diff --git a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml index ff653b6457..4fa29de9a3 100644 --- a/interface/resources/qml/hifi/tablet/TabletMenuStack.qml +++ b/interface/resources/qml/hifi/tablet/TabletMenuStack.qml @@ -22,7 +22,6 @@ Item { anchors.fill: parent id: d objectName: "stack" - initialItem: topMenu property var menuStack: [] property var topMenu: null; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e081e80360..449b014c13 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6178,7 +6178,7 @@ void Application::showAssetServerWidget(QString filePath) { if (!hmd->getShouldShowTablet() && !isHMDMode()) { DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload); } else { - static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); + static const QUrl url("../dialogs/TabletAssetServer.qml"); tablet->pushOntoStack(url); } } diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index af9c03a218..bfad5644bf 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -42,7 +42,7 @@ void CustomPromptResultFromScriptValue(const QScriptValue& object, CustomPromptR * @property {number} innerWidth - The width of the drawable area of the Interface window (i.e., without borders or other * chrome), in pixels. <em>Read-only.</em> * @property {number} innerHeight - The height of the drawable area of the Interface window (i.e., without borders or other - * chrome) plus the height of the menu bar, in pixels. <em>Read-only.</em> + * chrome), in pixels. <em>Read-only.</em> * @property {object} location - Provides facilities for working with your current metaverse location. See {@link location}. * @property {number} x - The x coordinate of the top left corner of the Interface window on the display. <em>Read-only.</em> * @property {number} y - The y coordinate of the top left corner of the Interface window on the display. <em>Read-only.</em> @@ -301,7 +301,7 @@ public slots: /**jsdoc * Get Interface's build number. * @function Window.checkVersion - * @returns {string} - Interface's build number. + * @returns {string} Interface's build number. */ QString checkVersion(); @@ -327,7 +327,7 @@ public slots: * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. * @example <caption>Using the snapshot function and signals.</caption> - * function onStillSnapshottaken(path, notify) { + * function onStillSnapshotTaken(path, notify) { * print("Still snapshot taken: " + path); * print("Notify: " + notify); * } @@ -340,7 +340,7 @@ public slots: * print("Animated snapshot taken: " + animatedPath); * } * - * Window.stillSnapshotTaken.connect(onStillSnapshottaken); + * Window.stillSnapshotTaken.connect(onStillSnapshotTaken); * Window.processingGifStarted.connect(onProcessingGifStarted); * Window.processingGifCompleted.connect(onProcessingGifCompleted); * @@ -555,7 +555,7 @@ signals: /**jsdoc * Triggered when a still snapshot has been taken by calling {@link Window.takeSnapshot|takeSnapshot} with - * <code>includeAnimated = false</code>. + * <code>includeAnimated = false</code> or {@link Window.takeSecondaryCameraSnapshot|takeSecondaryCameraSnapshot}. * @function Window.stillSnapshotTaken * @param {string} pathStillSnapshot - The path and name of the snapshot image file. * @param {boolean} notify - The value of the <code>notify</code> parameter that {@link Window.takeSnapshot|takeSnapshot} diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh index fbca241bb9..3cbed3fcef 100644 --- a/libraries/render-utils/src/DeferredBufferRead.slh +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -46,6 +46,15 @@ struct DeferredFragment { float depthVal; }; +<@if not GETFRESNEL0@> +<@def GETFRESNEL0@> +vec3 getFresnelF0(float metallic, vec3 metalF0) { + // Enable continuous metallness value by lerping between dielectric + // and metal fresnel F0 value based on the "metallic" parameter + return mix(vec3(0.03), metalF0, metallic); +} +<@endif@> + DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { vec4 normalVal; vec4 diffuseVal; @@ -73,13 +82,7 @@ DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { frag.scattering = specularVal.x; } - if (frag.metallic <= 0.5) { - frag.metallic = 0.0; - frag.fresnel = vec3(0.03); // Default Di-electric fresnel value - } else { - frag.fresnel = vec3(diffuseVal.xyz); - frag.metallic = 1.0; - } + frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz); return frag; } @@ -106,14 +109,7 @@ DeferredFragment unpackDeferredFragmentNoPositionNoAmbient(vec2 texcoord) { //frag.emissive = specularVal.xyz; frag.obscurance = 1.0; - - if (frag.metallic <= 0.5) { - frag.metallic = 0.0; - frag.fresnel = vec3(0.03); // Default Di-electric fresnel value - } else { - frag.fresnel = vec3(diffuseVal.xyz); - frag.metallic = 1.0; - } + frag.fresnel = getFresnelF0(frag.metallic, diffuseVal.xyz); return frag; } diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 02ab97b825..ab26f95482 100644 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -65,10 +65,12 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <$prepareGlobalLight($supportScattering$)$> + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -79,7 +81,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -110,10 +112,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu ) { <$prepareGlobalLight($supportScattering$)$> + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -123,7 +127,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -174,21 +178,22 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity, vec3 prevLighting) { <$prepareGlobalLight()$> - color = prevLighting; + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + color = prevLighting; color += emissive * isEmissiveEnabled(); // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance); color += ambientDiffuse; color += ambientSpecular / opacity; // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse; color += directionalSpecular / opacity; @@ -201,19 +206,20 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze( { <$prepareGlobalLight()$> - color = prevLighting; + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + color = prevLighting; color += emissive * isEmissiveEnabled(); // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance); // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); color += ambientDiffuse + directionalDiffuse; color += (ambientSpecular + directionalSpecular) / opacity; diff --git a/libraries/render-utils/src/ForwardGlobalLight.slh b/libraries/render-utils/src/ForwardGlobalLight.slh index cde37e0ba7..dd4aa88836 100644 --- a/libraries/render-utils/src/ForwardGlobalLight.slh +++ b/libraries/render-utils/src/ForwardGlobalLight.slh @@ -65,10 +65,12 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness <$prepareGlobalLight($supportScattering$)$> + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -79,7 +81,7 @@ vec3 albedo, vec3 fresnel, float metallic, float roughness // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); @@ -109,10 +111,12 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu ) { <$prepareGlobalLight($supportScattering$)$> + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -124,7 +128,7 @@ vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscu // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> @@ -173,19 +177,21 @@ vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscur vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, vec3 fresnel, float metallic, vec3 emissive, float roughness, float opacity) { <$prepareGlobalLight()$> + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + color += emissive * isEmissiveEnabled(); // Ambient vec3 ambientDiffuse; vec3 ambientSpecular; - evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, obscurance); + evalLightingAmbient(ambientDiffuse, ambientSpecular, lightAmbient, surface, metallic, fresnel, albedo, obscurance); color += ambientDiffuse; color += ambientSpecular / opacity; // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse; color += directionalSpecular / opacity; diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 5f74b46d3e..eb565d60e4 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -16,22 +16,27 @@ uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { // textureQueryLevels is not available until #430, so we require explicit lod // float mipmapLevel = lod * textureQueryLevels(skyboxMap); + float filterLod = textureQueryLod(skyboxMap, direction).x; + // Keep texture filtering LOD as limit to prevent aliasing on specular reflection + lod = max(lod, filterLod); return textureLod(skyboxMap, direction, lod); } <@endfunc@> <@func declareEvalAmbientSpecularIrradiance(supportAmbientSphere, supportAmbientMap, supportIfAmbientMapElseAmbientSphere)@> -vec3 fresnelSchlickAmbient(vec3 fresnelColor, vec3 lightDir, vec3 halfDir, float gloss) { - return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * pow(1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0), 5.0); +vec3 fresnelSchlickAmbient(vec3 fresnelColor, float ndotd, float gloss) { + float f = pow(1.0 - ndotd, 5.0); + return fresnelColor + (max(vec3(gloss), fresnelColor) - fresnelColor) * f; +// return fresnelColor + (vec3(1.0) - fresnelColor) * f; } <@if supportAmbientMap@> <$declareSkyboxMap()$> <@endif@> -vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 fragNormal, float roughness) { - vec3 direction = -reflect(fragEyeDir, fragNormal); +vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, SurfaceData surface) { + vec3 lightDir = -reflect(surface.eyeDir, surface.normal); vec3 specularLight; <@if supportIfAmbientMapElseAmbientSphere@> if (getLightHasAmbientMap(ambient)) @@ -39,8 +44,10 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f <@if supportAmbientMap@> { float levels = getLightAmbientMapNumMips(ambient); - float lod = min(((roughness)* levels), levels); - specularLight = evalSkyboxLight(direction, lod).xyz; + float m = 12.0 / (1.0+11.0*surface.roughness); + float lod = levels - m; + lod = max(lod, 0); + specularLight = evalSkyboxLight(lightDir, lod).xyz; } <@endif@> <@if supportIfAmbientMapElseAmbientSphere@> @@ -48,11 +55,11 @@ vec3 evalAmbientSpecularIrradiance(LightAmbient ambient, vec3 fragEyeDir, vec3 f <@endif@> <@if supportAmbientSphere@> { - specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), direction).xyz; + specularLight = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lightDir).xyz; } <@endif@> - return specularLight; + return specularLight; } <@endfunc@> @@ -66,21 +73,21 @@ float curvatureAO(in float k) { } <@endif@> -void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, vec3 eyeDir, vec3 normal, - float roughness, float metallic, vec3 fresnel, vec3 albedo, float obscurance +void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambient, SurfaceData surface, + float metallic, vec3 fresnelF0, vec3 albedo, float obscurance <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature <@endif@> ) { // Fresnel - vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, eyeDir, normal, 1.0 - roughness); + vec3 ambientFresnel = fresnelSchlickAmbient(fresnelF0, surface.ndotv, 1.0-surface.roughness); // Diffuse from ambient - diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), normal).xyz; + diffuse = (1.0 - metallic) * (vec3(1.0) - ambientFresnel) * sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), surface.normal).xyz; // Specular highlight from ambient - specular = evalAmbientSpecularIrradiance(ambient, eyeDir, normal, roughness) * ambientFresnel; + specular = evalAmbientSpecularIrradiance(ambient, surface) * ambientFresnel; <@if supportScattering@> if (scattering * isScatteringEnabled() > 0.0) { @@ -92,7 +99,7 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie // Diffuse from ambient diffuse = sphericalHarmonics_evalSphericalLight(getLightAmbientSphere(ambient), lowNormalCurvature.xyz).xyz; - + diffuse /= 3.1415926; specular = vec3(0.0); } <@endif@> @@ -107,8 +114,9 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie diffuse *= albedo; } - diffuse *= lightEnergy * isDiffuseEnabled() * isAmbientEnabled(); - specular *= lightEnergy * isSpecularEnabled() * isAmbientEnabled(); + lightEnergy *= isAmbientEnabled(); + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); } <@endfunc@> diff --git a/libraries/render-utils/src/LightDirectional.slh b/libraries/render-utils/src/LightDirectional.slh index 749709c600..b6e1720a2c 100644 --- a/libraries/render-utils/src/LightDirectional.slh +++ b/libraries/render-utils/src/LightDirectional.slh @@ -12,7 +12,7 @@ <@func declareLightingDirectional(supportScattering)@> void evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, vec3 lightIrradiance, - vec3 eyeDir, vec3 normal, float roughness, + SurfaceData surface, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature @@ -22,14 +22,17 @@ void evalLightingDirectional(out vec3 diffuse, out vec3 specular, vec3 lightDir, // Attenuation vec3 lightEnergy = shadow * lightIrradiance; - evalFragShading(diffuse, specular, normal, -lightDir, eyeDir, metallic, fresnel, roughness, albedo + updateSurfaceDataWithLight(surface, -lightDir); + + evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); - diffuse *= lightEnergy * isDiffuseEnabled() * isDirectionalEnabled(); - specular *= lightEnergy * isSpecularEnabled() * isDirectionalEnabled(); + lightEnergy *= isDirectionalEnabled(); + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); } <@endfunc@> diff --git a/libraries/render-utils/src/LightLocal.slh b/libraries/render-utils/src/LightLocal.slh index 895955269d..d988fc0a8d 100644 --- a/libraries/render-utils/src/LightLocal.slh +++ b/libraries/render-utils/src/LightLocal.slh @@ -20,17 +20,15 @@ <@include LightClusterGrid.slh@> -vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fragNormal, vec3 fragEyeDir, - vec4 midNormalCurvature, vec4 lowNormalCurvature, - float fragRoughness, float fragScattering, float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, - float opacity) { +vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceData surface, + float fragMetallic, vec3 fragFresnel, vec3 fragAlbedo, float fragScattering, + vec4 midNormalCurvature, vec4 lowNormalCurvature, float opacity) { vec4 fragColor = vec4(0.0); vec3 fragSpecular = vec3(0.0); vec3 fragDiffuse = vec3(0.0); int lightClusterOffset = cluster.z; // Compute the rougness into gloss2 once: - float fragGloss2 = pow(fragRoughness + 0.001, 4.0); bool withScattering = (fragScattering * isScatteringEnabled() > 0.0); int numLightTouching = 0; @@ -50,7 +48,7 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fra // Allright we re in the light sphere volume fragLightDirLen.w = length(fragLightVecLen2.xyz); fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - if (dot(fragNormal, fragLightDirLen.xyz) < 0.0) { + if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) { continue; } @@ -63,16 +61,18 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fra float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + updateSurfaceDataWithLight(surface, fragLightDir); + // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); vec3 lightEnergy = radialAttenuation * getLightIrradiance(light); // Eval shading if (withScattering) { - evalFragShadingScattering(diffuse, specular, fragNormal, fragLightDir, fragEyeDir, fragMetallic, fragFresnel, fragRoughness, fragAlbedo - ,fragScattering, midNormalCurvature, lowNormalCurvature ); + evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo, + fragScattering, midNormalCurvature, lowNormalCurvature ); } else { - evalFragShadingGloss(diffuse, specular, fragNormal, fragLightDir, fragEyeDir, fragMetallic, fragFresnel, fragGloss2, fragAlbedo); + evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo); } diffuse *= lightEnergy; @@ -99,7 +99,7 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fra // Allright we re in the light sphere volume fragLightDirLen.w = length(fragLightVecLen2.xyz); fragLightDirLen.xyz = fragLightVecLen2.xyz / fragLightDirLen.w; - if (dot(fragNormal, fragLightDirLen.xyz) < 0.0) { + if (dot(surface.normal, fragLightDirLen.xyz) < 0.0) { continue; } @@ -117,6 +117,8 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fra float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + updateSurfaceDataWithLight(surface, fragLightDir); + // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); float angularAttenuation = lightIrradiance_evalLightSpotAttenuation(light.irradiance, cosSpotAngle); @@ -124,10 +126,10 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, vec3 fra // Eval shading if (withScattering) { - evalFragShadingScattering(diffuse, specular, fragNormal, fragLightDir, fragEyeDir, fragMetallic, fragFresnel, fragRoughness, fragAlbedo - ,fragScattering, midNormalCurvature, lowNormalCurvature ); + evalFragShadingScattering(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo, + fragScattering, midNormalCurvature, lowNormalCurvature ); } else { - evalFragShadingGloss(diffuse, specular, fragNormal, fragLightDir, fragEyeDir, fragMetallic, fragFresnel, fragGloss2, fragAlbedo); + evalFragShadingGloss(diffuse, specular, fragMetallic, fragFresnel, surface, fragAlbedo); } diffuse *= lightEnergy; diff --git a/libraries/render-utils/src/LightPoint.slh b/libraries/render-utils/src/LightPoint.slh index 7e389e11f6..91a1260fcc 100644 --- a/libraries/render-utils/src/LightPoint.slh +++ b/libraries/render-utils/src/LightPoint.slh @@ -12,7 +12,7 @@ <@func declareLightingPoint(supportScattering)@> void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, - vec4 fragLightDirLen, vec3 fragEyeDir, vec3 normal, float roughness, + vec4 fragLightDirLen, SurfaceData surface, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature @@ -23,19 +23,22 @@ void evalLightingPoint(out vec3 diffuse, out vec3 specular, Light light, float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + updateSurfaceDataWithLight(surface, fragLightDir); + // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); vec3 lightEnergy = radialAttenuation * shadow * getLightIrradiance(light); // Eval shading - evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo + evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); - diffuse *= lightEnergy * isDiffuseEnabled() * isPointEnabled(); - specular *= lightEnergy * isSpecularEnabled() * isPointEnabled(); + lightEnergy *= isPointEnabled(); + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); if (isShowLightContour() > 0.0) { // Show edge diff --git a/libraries/render-utils/src/LightSpot.slh b/libraries/render-utils/src/LightSpot.slh index 8627dae0eb..73c5bd9559 100644 --- a/libraries/render-utils/src/LightSpot.slh +++ b/libraries/render-utils/src/LightSpot.slh @@ -12,7 +12,7 @@ <@func declareLightingSpot(supportScattering)@> void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, - vec4 fragLightDirLen, float cosSpotAngle, vec3 fragEyeDir, vec3 normal, float roughness, + vec4 fragLightDirLen, float cosSpotAngle, SurfaceData surface, float metallic, vec3 fresnel, vec3 albedo, float shadow <@if supportScattering@> , float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature @@ -23,6 +23,7 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, float fragLightDistance = fragLightDirLen.w; vec3 fragLightDir = fragLightDirLen.xyz; + updateSurfaceDataWithLight(surface, fragLightDir); // Eval attenuation float radialAttenuation = lightIrradiance_evalLightAttenuation(light.irradiance, fragLightDistance); @@ -30,14 +31,15 @@ void evalLightingSpot(out vec3 diffuse, out vec3 specular, Light light, vec3 lightEnergy = angularAttenuation * radialAttenuation * shadow *getLightIrradiance(light); // Eval shading - evalFragShading(diffuse, specular, normal, fragLightDir, fragEyeDir, metallic, fresnel, roughness, albedo + evalFragShading(diffuse, specular, metallic, fresnel, surface, albedo <@if supportScattering@> ,scattering, midNormalCurvature, lowNormalCurvature <@endif@> ); - diffuse *= lightEnergy * isDiffuseEnabled() * isSpotEnabled(); - specular *= lightEnergy * isSpecularEnabled() * isSpotEnabled(); + lightEnergy *= isSpotEnabled(); + diffuse *= lightEnergy * isDiffuseEnabled(); + specular *= lightEnergy * isSpecularEnabled(); if (isShowLightContour() > 0.0) { // Show edges diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 521c4894dc..1247e7e096 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -77,6 +77,30 @@ float isWireframeEnabled() { <@endfunc@> <$declareLightingModel()$> +struct SurfaceData { + vec3 normal; + vec3 eyeDir; + vec3 lightDir; + vec3 halfDir; + float roughness; + float roughness2; + float roughness4; + float ndotv; + float ndotl; + float ndoth; + float ldoth; + float smithInvG1NdotV; +}; + +<@if not GETFRESNEL0@> +<@def GETFRESNEL0@> +vec3 getFresnelF0(float metallic, vec3 metalF0) { + // Enable continuous metallness value by lerping between dielectric + // and metal fresnel F0 value based on the "metallic" parameter + return mix(vec3(0.03), metalF0, metallic); +} +<@endif@> + <@func declareBeckmannSpecular()@> uniform sampler2D scatteringSpecularBeckmann; @@ -85,17 +109,13 @@ float fetchSpecularBeckmann(float ndoth, float roughness) { return pow(2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0); } -vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { +vec2 skinSpecular(SurfaceData surface, float intensity) { vec2 result = vec2(0.0, 1.0); - float ndotl = dot(N, L); - if (ndotl > 0.0) { - vec3 h = L + V; - vec3 H = normalize(h); - float ndoth = dot(N, H); - float PH = fetchSpecularBeckmann(ndoth, roughness); - float F = fresnelSchlickScalar(0.028, H, V); - float frSpec = max(PH * F / dot(h, h), 0.0); - result.x = ndotl * intensity * frSpec; + if (surface.ndotl > 0.0) { + float PH = fetchSpecularBeckmann(surface.ndoth, surface.roughness); + float F = fresnelSchlickScalar(0.028, surface); + float frSpec = max(PH * F / dot(surface.halfDir, surface.halfDir), 0.0); + result.x = surface.ndotl * intensity * frSpec; result.y -= F; } @@ -105,117 +125,136 @@ vec2 skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { <@func declareEvalPBRShading()@> -vec3 fresnelSchlickColor(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) { - float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); +float evalSmithInvG1(float roughness4, float ndotd) { + return ndotd + sqrt(roughness4+ndotd*ndotd*(1.0-roughness4)); +} + +SurfaceData initSurfaceData(float roughness, vec3 normal, vec3 eyeDir) { + SurfaceData surface; + surface.eyeDir = eyeDir; + surface.normal = normal; + surface.roughness = mix(0.001, 1.0, roughness); + surface.roughness2 = surface.roughness * surface.roughness; + surface.roughness4 = surface.roughness2 * surface.roughness2; + surface.ndotv = clamp(dot(normal, eyeDir), 0.0, 1.0); + surface.smithInvG1NdotV = evalSmithInvG1(surface.roughness4, surface.ndotv); + + // These values will be set when we know the light direction, in updateSurfaceDataWithLight + surface.ndoth = 0.0; + surface.ndotl = 0.0; + surface.ldoth = 0.0; + surface.lightDir = vec3(0,0,1); + surface.halfDir = vec3(0,0,1); + + return surface; +} + +void updateSurfaceDataWithLight(inout SurfaceData surface, vec3 lightDir) { + surface.lightDir = lightDir; + surface.halfDir = normalize(surface.eyeDir + lightDir); + vec3 dots; + dots.x = dot(surface.normal, surface.halfDir); + dots.y = dot(surface.normal, surface.lightDir); + dots.z = dot(surface.halfDir, surface.lightDir); + dots = clamp(dots, vec3(0), vec3(1)); + surface.ndoth = dots.x; + surface.ndotl = dots.y; + surface.ldoth = dots.z; +} + +vec3 fresnelSchlickColor(vec3 fresnelColor, SurfaceData surface) { + float base = 1.0 - surface.ldoth; //float exponential = pow(base, 5.0); float base2 = base * base; float exponential = base * base2 * base2; return vec3(exponential) + fresnelColor * (1.0 - exponential); } -float fresnelSchlickScalar(float fresnelScalar, vec3 lightDir, vec3 halfDir) { - float base = 1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0); +float fresnelSchlickScalar(float fresnelScalar, SurfaceData surface) { + float base = 1.0 - surface.ldoth; //float exponential = pow(base, 5.0); float base2 = base * base; float exponential = base * base2 * base2; return (exponential) + fresnelScalar * (1.0 - exponential); } -float specularDistribution(float roughness, vec3 normal, vec3 halfDir) { - float ndoth = clamp(dot(halfDir, normal), 0.0, 1.0); -// float gloss2 = pow(0.001 + roughness, 4); - float gloss2 = (0.001 + roughness); - gloss2 *= gloss2; // pow 2 - gloss2 *= gloss2; // pow 4 - float denom = (ndoth * ndoth*(gloss2 - 1.0) + 1.0); - float power = gloss2 / (3.14159 * denom * denom); +float specularDistribution(SurfaceData surface) { + // See https://www.khronos.org/assets/uploads/developers/library/2017-web3d/glTF-2.0-Launch_Jun17.pdf + // for details of equations, especially page 20 + float denom = (surface.ndoth*surface.ndoth * (surface.roughness2 - 1.0) + 1.0); + denom *= denom; + // Add geometric factors G1(n,l) and G1(n,v) + float smithInvG1NdotL = evalSmithInvG1(surface.roughness4, surface.ndotl); + denom *= surface.smithInvG1NdotV * smithInvG1NdotL; + // Don't divide by PI as it will be done later + float power = surface.roughness4 / denom; return power; } -float specularDistributionGloss(float gloss2, vec3 normal, vec3 halfDir) { - float ndoth = clamp(dot(halfDir, normal), 0.0, 1.0); -// float gloss2 = pow(0.001 + roughness, 4); - float denom = (ndoth * ndoth*(gloss2 - 1.0) + 1.0); - float power = gloss2 / (3.14159 * denom * denom); - return power; -} -<! //NOTE: ANother implementation for specularDistribution - float specularDistribution(float roughness, vec3 normal, vec3 halfDir) { - float gloss = exp2(10 * (1.0 - roughness) + 1); - float power = pow(clamp(dot(halfDir, normal), 0.0, 1.0), gloss); - power *= (gloss * 0.125 + 0.25); - return power; -} -!> -// Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) { - // Diffuse Lighting - float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); - - // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); - float power = specularDistribution(roughness, fragNormal, halfDir); - vec3 specular = fresnelColor * power * diffuse; - - return vec4(specular, (1.0 - metallic) * diffuse * (1.0 - fresnelColor.x)); -} // Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShadingDielectric(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, float fresnel) { - // Diffuse Lighting - float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); +vec4 evalPBRShading(float metallic, vec3 fresnel, SurfaceData surface) { + // Incident angle attenuation + float angleAttenuation = surface.ndotl; // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - float fresnelScalar = fresnelSchlickScalar(fresnel, fragLightDir, halfDir); - float power = specularDistribution(roughness, fragNormal, halfDir); - vec3 specular = vec3(fresnelScalar) * power * diffuse; + vec3 fresnelColor = fresnelSchlickColor(fresnel, surface); + float power = specularDistribution(surface); + vec3 specular = fresnelColor * power * angleAttenuation; + float diffuse = (1.0 - metallic) * angleAttenuation * (1.0 - fresnelColor.x); - return vec4(specular, diffuse * (1.0 - fresnelScalar)); + diffuse /= 3.1415926; + // Diffuse is divided by PI but specular isn't because an infinitesimal volume light source + // has a multiplier of PI, says Naty Hoffman. + // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf + // page 23 paragraph "Punctual light sources") + + return vec4(specular, diffuse); } -vec4 evalPBRShadingMetallic(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float roughness, vec3 fresnel) { - // Diffuse Lighting - float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); +// Frag Shading returns the diffuse amount as W and the specular rgb as xyz +vec4 evalPBRShadingDielectric(SurfaceData surface, float fresnel) { + // Incident angle attenuation + float angleAttenuation = surface.ndotl; // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); - float power = specularDistribution(roughness, fragNormal, halfDir); - vec3 specular = fresnelColor * power * diffuse; + float fresnelScalar = fresnelSchlickScalar(fresnel, surface); + float power = specularDistribution(surface); + vec3 specular = vec3(fresnelScalar) * power * angleAttenuation; + float diffuse = angleAttenuation * (1.0 - fresnelScalar); + diffuse /= 3.1415926; + // Diffuse is divided by PI but specular isn't because an infinitesimal volume light source + // has a multiplier of PI, says Naty Hoffman. + // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf + // page 23 paragraph "Punctual light sources") + return vec4(specular, diffuse); +} + +vec4 evalPBRShadingMetallic(SurfaceData surface, vec3 fresnel) { + // Incident angle attenuation + float angleAttenuation = surface.ndotl; + + // Specular Lighting + vec3 fresnelColor = fresnelSchlickColor(fresnel, surface); + float power = specularDistribution(surface); + vec3 specular = fresnelColor * power * angleAttenuation; + + // Specular isn't divided by PI because an infinitesimal volume light source + // has a multiplier of PI, says Naty Hoffman. + // (see http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf + // page 23 paragraph "Punctual light sources") return vec4(specular, 0.f); } -// Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShadingGloss(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float gloss2) { - // Diffuse Lighting - float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); - - // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - vec3 fresnelColor = fresnelSchlickColor(fresnel, fragLightDir, halfDir); - float power = specularDistributionGloss(gloss2, fragNormal, halfDir); - vec3 specular = fresnelColor * power * diffuse; - - return vec4(specular, (1.0 - metallic) * diffuse * (1.0 - fresnelColor.x)); -} - <@endfunc@> <$declareEvalPBRShading()$> -// Return xyz the specular/reflection component and w the diffuse component -//vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) { -// return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); -//} - void evalFragShading(out vec3 diffuse, out vec3 specular, - vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, - float metallic, vec3 fresnel, float roughness, vec3 albedo) { - vec4 shading = evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) { + vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); if (isAlbedoEnabled() > 0.0) { diffuse *= albedo; @@ -229,22 +268,19 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, void evalFragShading(out vec3 diffuse, out vec3 specular, - vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, - float metallic, vec3 fresnel, float roughness, vec3 albedo, + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo, float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) { if (scattering * isScatteringEnabled() > 0.0) { - vec3 brdf = evalSkinBRDF(fragLightDir, fragNormal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); - float NdotL = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); - diffuse = mix(vec3(NdotL), brdf, scattering); + vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); + diffuse = mix(vec3(surface.ndotl), brdf, scattering); // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - vec2 specularBrdf = skinSpecular(fragNormal, fragLightDir, fragEyeDir, roughness, 1.0); + vec2 specularBrdf = skinSpecular(surface, 1.0); diffuse *= specularBrdf.y; specular = vec3(specularBrdf.x); } else { - vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, roughness); + vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); specular = shading.xyz; } @@ -253,17 +289,14 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, - vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, - float metallic, vec3 fresnel, float roughness, vec3 albedo - ,float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature -) { - vec3 brdf = evalSkinBRDF(fragLightDir, fragNormal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); - float NdotL = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo, + float scattering, vec4 midNormalCurvature, vec4 lowNormalCurvature) { + vec3 brdf = evalSkinBRDF(surface.lightDir, surface.normal, midNormalCurvature.xyz, lowNormalCurvature.xyz, lowNormalCurvature.w); + float NdotL = surface.ndotl; diffuse = mix(vec3(NdotL), brdf, scattering); // Specular Lighting - vec3 halfDir = normalize(fragEyeDir + fragLightDir); - vec2 specularBrdf = skinSpecular(fragNormal, fragLightDir, fragEyeDir, roughness, 1.0); + vec2 specularBrdf = skinSpecular(surface, 1.0); diffuse *= specularBrdf.y; specular = vec3(specularBrdf.x); @@ -271,10 +304,8 @@ void evalFragShadingScattering(out vec3 diffuse, out vec3 specular, } void evalFragShadingGloss(out vec3 diffuse, out vec3 specular, - vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, - float metallic, vec3 fresnel, float gloss, vec3 albedo -) { - vec4 shading = evalPBRShadingGloss(fragNormal, fragLightDir, fragEyeDir, metallic, fresnel, gloss); + float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) { + vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); specular = shading.xyz; diff --git a/libraries/render-utils/src/SubsurfaceScattering.slh b/libraries/render-utils/src/SubsurfaceScattering.slh index 201ec2291a..233dfd7a0c 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.slh +++ b/libraries/render-utils/src/SubsurfaceScattering.slh @@ -63,38 +63,6 @@ vec3 scatter(float r) { <@endfunc@> -<@func declareSkinSpecularLighting()@> - -uniform sampler2D scatteringSpecularBeckmann; - -float fetchSpecularBeckmann(float ndoth, float roughness) { - return pow( 2.0 * texture(scatteringSpecularBeckmann, vec2(ndoth, roughness)).r, 10.0); -} - -float fresnelReflectance(vec3 H, vec3 V, float Fo) { - float base = 1.0 - dot(V, H); - float exponential = pow(base, 5.0); - return exponential + Fo * (1.0 - exponential); -} - -float skinSpecular(vec3 N, vec3 L, vec3 V, float roughness, float intensity) { - float result = 0.0; - float ndotl = dot(N, L); - if (ndotl > 0.0) { - vec3 h = L + V; - vec3 H = normalize(h); - float ndoth = dot(N, H); - float PH = fetchSpecularBeckmann(ndoth, roughness); - float F = fresnelReflectance(H, V, 0.028); - float frSpec = max(PH * F / dot(h, h), 0.0); - result = ndotl * intensity * frSpec; - } - - return result; -} - -<@endfunc@> - <@func declareSubsurfaceScatteringIntegrate(NumIntegrationSteps)@> diff --git a/libraries/render-utils/src/local_lights_shading.slf b/libraries/render-utils/src/local_lights_shading.slf index b9c57b82cb..8ae8f3fb5b 100644 --- a/libraries/render-utils/src/local_lights_shading.slf +++ b/libraries/render-utils/src/local_lights_shading.slf @@ -55,10 +55,11 @@ void main(void) { // Frag to eye vec vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); + SurfaceData surface = initSurfaceData(frag.roughness, frag.normal, fragEyeDir); - _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, frag.normal, fragEyeDir, - midNormalCurvature, lowNormalCurvature, frag.roughness, frag.scattering, - frag.metallic, frag.fresnel, frag.albedo, 1.0); + _fragColor = evalLocalLighting(cluster, numLights, fragWorldPos.xyz, surface, + frag.metallic, frag.fresnel, frag.albedo, frag.scattering, + midNormalCurvature, lowNormalCurvature, 1.0); } diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index c054a5c096..9b6913fe1c 100644 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -53,13 +53,7 @@ void main(void) { <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } + vec3 fresnel = getFresnelF0(metallic, albedo); vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; @@ -68,16 +62,17 @@ void main(void) { vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + vec4 localLighting = vec4(0.0); <$fetchClusterInfo(_worldPosition)$>; if (hasLocalLights(numLights, clusterPos, dims)) { - vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); - vec3 fragEyeDir = normalize(fragEyeVector); - - localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, fragNormal, fragEyeDir, - vec4(0), vec4(0), roughness, 0.0, - metallic, fresnel, albedo, opacity); + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); } _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( diff --git a/libraries/render-utils/src/model_translucent_fade.slf b/libraries/render-utils/src/model_translucent_fade.slf index c6bfd1659d..ea8774fd4e 100644 --- a/libraries/render-utils/src/model_translucent_fade.slf +++ b/libraries/render-utils/src/model_translucent_fade.slf @@ -62,13 +62,7 @@ void main(void) { <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } + vec3 fresnel = getFresnelF0(metallic, albedo); vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; @@ -77,16 +71,17 @@ void main(void) { vec3 fragNormal = normalize(_normal); TransformCamera cam = getTransformCamera(); + vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + SurfaceData surface = initSurfaceData(roughness, fragNormal, fragEyeDir); + vec4 localLighting = vec4(0.0); <$fetchClusterInfo(_worldPosition)$>; if (hasLocalLights(numLights, clusterPos, dims)) { - vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); - vec3 fragEyeDir = normalize(fragEyeVector); - - localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, fragNormal, fragEyeDir, - vec4(0), vec4(0), roughness, 0.0, - metallic, fresnel, albedo, opacity); + localLighting = evalLocalLighting(cluster, numLights, _worldPosition.xyz, surface, + metallic, fresnel, albedo, 0.0, + vec4(0), vec4(0), opacity); } _fragColor = vec4(evalGlobalLightingAlphaBlendedWithHaze( diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 683e1420bc..9b9e419d37 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -40,12 +40,14 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> + SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse * isDiffuseEnabled() * isDirectionalEnabled(); color += directionalSpecular * isSpecularEnabled() * isDirectionalEnabled(); diff --git a/libraries/render-utils/src/overlay3D_model.slf b/libraries/render-utils/src/overlay3D_model.slf index bb0d84a513..ea61c2bb75 100644 --- a/libraries/render-utils/src/overlay3D_model.slf +++ b/libraries/render-utils/src/overlay3D_model.slf @@ -46,13 +46,7 @@ void main(void) { albedo *= _color; float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } + vec3 fresnel = getFresnelF0(metallic, albedo); float roughness = getMaterialRoughness(mat); <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; diff --git a/libraries/render-utils/src/overlay3D_model_translucent.slf b/libraries/render-utils/src/overlay3D_model_translucent.slf index 18f40a37b4..6f1d34926e 100644 --- a/libraries/render-utils/src/overlay3D_model_translucent.slf +++ b/libraries/render-utils/src/overlay3D_model_translucent.slf @@ -44,13 +44,7 @@ void main(void) { albedo *= _color; float metallic = getMaterialMetallic(mat); - vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value - if (metallic <= 0.5) { - metallic = 0.0; - } else { - fresnel = albedo; - metallic = 1.0; - } + vec3 fresnel = getFresnelF0(metallic, albedo); float roughness = getMaterialRoughness(mat); <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index c39d4b0c3b..b780de7d8e 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -40,12 +40,14 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 a vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> + SurfaceData surface = initSurfaceData(roughness, normal, fragEyeDir); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(ambient); // Directional vec3 directionalDiffuse; vec3 directionalSpecular; - evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, fragEyeDir, fragNormal, roughness, metallic, fresnel, albedo, shadowAttenuation); + evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); color += directionalDiffuse; color += directionalSpecular / opacity; diff --git a/libraries/script-engine/src/AssetScriptingInterface.cpp b/libraries/script-engine/src/AssetScriptingInterface.cpp index 25e8c0dcf3..e0e04a1e25 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.cpp +++ b/libraries/script-engine/src/AssetScriptingInterface.cpp @@ -16,9 +16,11 @@ #include <AssetRequest.h> #include <AssetUpload.h> #include <MappingRequest.h> -#include <NetworkLogging.h> #include <NodeList.h> +#include "ScriptEngineLogging.h" + + AssetScriptingInterface::AssetScriptingInterface(QScriptEngine* engine) : _engine(engine) { @@ -53,10 +55,32 @@ void AssetScriptingInterface::setMapping(QString path, QString hash, QScriptValu setMappingRequest->start(); } +void AssetScriptingInterface::getMapping(QString path, QScriptValue callback) { + auto request = DependencyManager::get<AssetClient>()->createGetMappingRequest(path); + QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { + auto result = request->getError(); + if (callback.isFunction()) { + if (result == GetMappingRequest::NotFound) { + QScriptValueList args { "", true }; + callback.call(_engine->currentContext()->thisObject(), args); + } else if (result == GetMappingRequest::NoError) { + QScriptValueList args { request->getHash(), true }; + callback.call(_engine->currentContext()->thisObject(), args); + } else { + qCDebug(scriptengine) << "error -- " << request->getError() << " -- " << request->getErrorString(); + QScriptValueList args { "", false }; + callback.call(_engine->currentContext()->thisObject(), args); + } + request->deleteLater(); + } + }); + request->start(); +} void AssetScriptingInterface::downloadData(QString urlString, QScriptValue callback) { if (!urlString.startsWith(ATP_SCHEME)) { + qCDebug(scriptengine) << "AssetScriptingInterface::downloadData url must be of form atp:<hash-value>"; return; } diff --git a/libraries/script-engine/src/AssetScriptingInterface.h b/libraries/script-engine/src/AssetScriptingInterface.h index 2812be65f9..dded2ef21d 100644 --- a/libraries/script-engine/src/AssetScriptingInterface.h +++ b/libraries/script-engine/src/AssetScriptingInterface.h @@ -75,7 +75,24 @@ public: * @param {string} error */ Q_INVOKABLE void setMapping(QString path, QString hash, QScriptValue callback); - + + /**jsdoc + * Look up a path to hash mapping within the connected domain's asset server + * @function Assets.getMapping + * @static + * @param path {string} + * @param callback {Assets~getMappingCallback} + */ + + /**jsdoc + * Called when getMapping is complete. + * @callback Assets~getMappingCallback + * @param assetID {string} hash value if found, else an empty string + * @param success {boolean} false for errors other than "not found", else true + */ + Q_INVOKABLE void getMapping(QString path, QScriptValue callback); + + Q_INVOKABLE void setBakingEnabled(QString path, bool enabled, QScriptValue callback); #if (PR_BUILD || DEV_BUILD)