diff --git a/examples/utilities/tools/render/debugFramebuffer.js b/examples/utilities/tools/render/debugFramebuffer.js new file mode 100644 index 0000000000..e764cf52d8 --- /dev/null +++ b/examples/utilities/tools/render/debugFramebuffer.js @@ -0,0 +1,51 @@ +// +// ddebugFramBuffer.js +// examples/utilities/tools/render +// +// Sam Gateau created on 2/18/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var DDB = Render.RenderDeferredTask.DebugDeferredBuffer; +oldConfig = DDB.toJSON(); +DDB.enabled = true; + + +// Set up the qml ui +var qml = Script.resolvePath('framebuffer.qml'); +var window = new OverlayWindow({ + title: 'Framebuffer Debug', + source: qml, + width: 400, height: 400, +}); +window.setPosition(25, 50); +window.closed.connect(function() { Script.stop(); }); + +// Debug buffer sizing +var resizing = false; + +Controller.mousePressEvent.connect(function (e) { + if (shouldStartResizing(e.x)) { + resizing = true; + } +}); +Controller.mouseReleaseEvent.connect(function() { resizing = false; }); +Controller.mouseMoveEvent.connect(function (e) { resizing && setDebugBufferSize(e.x); }); + + +function shouldStartResizing(eventX) { + var x = Math.abs(eventX - Window.innerWidth * (1.0 + DDB.size.x) / 2.0); + var mode = DDB.mode; + return mode !== -1 && x < 20; +} + +function setDebugBufferSize(x) { + x = (2.0 * (x / Window.innerWidth) - 1.0); // scale + x = Math.min(Math.max(-1, x), 1); // clamp + DDB.size = { x: x, y: -1, z: 1, w: 1 }; +} + +Script.scriptEnding.connect(function () { DDB.fromJSON(oldConfig); }); diff --git a/examples/utilities/tools/render/framebuffer.qml b/examples/utilities/tools/render/framebuffer.qml new file mode 100644 index 0000000000..d6f4ea7915 --- /dev/null +++ b/examples/utilities/tools/render/framebuffer.qml @@ -0,0 +1,52 @@ +// +// main.qml +// examples/utilities/tools/render +// +// Created by Zach Pomerantz on 2/8/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.5 +import QtQuick.Controls 1.4 + +Column { + spacing: 8 + Column { + id: debug + property var config: Render.getConfig("DebugDeferredBuffer") + + function setDebugMode(mode) { + debug.config.enabled = (mode != -1); + debug.config.mode = mode; + } + + Label { text: qsTr("Debug Buffer") } + ExclusiveGroup { id: bufferGroup } + Repeater { + model: [ + "Off", + "Depth", + "Albedo", + "Normal", + "Roughness", + "Metallic", + "Emissive", + "Occlusion", + "Lightmap", + "Lighting", + "Shadow", + "Pyramid Depth", + "Ambient Occlusion", + "Custom Shader" + ] + RadioButton { + text: qsTr(modelData) + exclusiveGroup: bufferGroup + checked: index == 0 + onCheckedChanged: if (checked) debug.setDebugMode(index - 1); + } + } + } +} diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fe1e0bbbcd..b786e3b82d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3816,7 +3816,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se // Setup the current Zone Entity lighting { auto stage = DependencyManager::get()->getSkyStage(); - DependencyManager::get()->setGlobalLight(stage->getSunLight(), stage->getSkybox()->getCubemap()); + DependencyManager::get()->setGlobalLight(stage->getSunLight()); } { diff --git a/interface/src/ModelPackager.cpp b/interface/src/ModelPackager.cpp index 64ab76c64c..fa87a5f657 100644 --- a/interface/src/ModelPackager.cpp +++ b/interface/src/ModelPackager.cpp @@ -342,9 +342,9 @@ void ModelPackager::populateBasicMapping(QVariantHash& mapping, QString filename void ModelPackager::listTextures() { _textures.clear(); foreach (const FBXMaterial mat, _geometry->materials) { - if (!mat.diffuseTexture.filename.isEmpty() && mat.diffuseTexture.content.isEmpty() && - !_textures.contains(mat.diffuseTexture.filename)) { - _textures << mat.diffuseTexture.filename; + if (!mat.albedoTexture.filename.isEmpty() && mat.albedoTexture.content.isEmpty() && + !_textures.contains(mat.albedoTexture.filename)) { + _textures << mat.albedoTexture.filename; } if (!mat.normalTexture.filename.isEmpty() && mat.normalTexture.content.isEmpty() && !_textures.contains(mat.normalTexture.filename)) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index bc1f614f79..44c3146b41 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -273,6 +273,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrresetAmbientSphere(); + sceneKeyLight->setAmbientMap(nullptr); sceneKeyLight->setColor(_previousKeyLightColor); sceneKeyLight->setIntensity(_previousKeyLightIntensity); sceneKeyLight->setAmbientIntensity(_previousKeyLightAmbientIntensity); @@ -321,10 +322,11 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetTexture(zone->getKeyLightProperties().getAmbientURL(), CUBE_TEXTURE); - if (_ambientTexture->getGPUTexture()) { + if (_ambientTexture && _ambientTexture->isLoaded() && _ambientTexture->getGPUTexture()) { _pendingAmbientTexture = false; if (_ambientTexture->getGPUTexture()->getIrradiance()) { sceneKeyLight->setAmbientSphere(_ambientTexture->getGPUTexture()->getIrradiance()); + sceneKeyLight->setAmbientMap(_ambientTexture->getGPUTexture()); isAmbientTextureSet = true; } } else { @@ -354,12 +356,13 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrgetTexture(zone->getSkyboxProperties().getURL(), CUBE_TEXTURE); - if (_skyboxTexture->getGPUTexture()) { + if (_skyboxTexture && _skyboxTexture->isLoaded() && _skyboxTexture->getGPUTexture()) { auto texture = _skyboxTexture->getGPUTexture(); skybox->setCubemap(texture); _pendingSkyboxTexture = false; if (!isAmbientTextureSet && texture->getIrradiance()) { sceneKeyLight->setAmbientSphere(texture->getIrradiance()); + sceneKeyLight->setAmbientMap(texture); isAmbientTextureSet = true; } } else { @@ -381,6 +384,7 @@ void EntityTreeRenderer::applyZonePropertiesToScene(std::shared_ptrresetAmbientSphere(); + sceneKeyLight->setAmbientMap(nullptr); } } diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index fc659d5928..9b7193bbfc 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -15,7 +15,7 @@ <@include DeferredBufferWrite.slh@> -// the diffuse texture +// the albedo texture uniform sampler2D originalTexture; // the interpolated normal diff --git a/libraries/entities-renderer/src/polyvox.slf b/libraries/entities-renderer/src/polyvox.slf index 2bdecbf9fe..38d9494a61 100644 --- a/libraries/entities-renderer/src/polyvox.slf +++ b/libraries/entities-renderer/src/polyvox.slf @@ -28,9 +28,6 @@ void main(void) { vec3 worldNormal = cross(dFdy(_worldPosition.xyz), dFdx(_worldPosition.xyz)); worldNormal = normalize(worldNormal); - vec3 specular = DEFAULT_SPECULAR; - float shininess = DEFAULT_SHININESS; - float inPositionX = (_worldPosition.x - 0.5) / voxelVolumeSize.x; float inPositionY = (_worldPosition.y - 0.5) / voxelVolumeSize.y; float inPositionZ = (_worldPosition.z - 0.5) / voxelVolumeSize.z; @@ -44,5 +41,5 @@ void main(void) { vec3 yzDiffuseScaled = yzDiffuse.rgb * abs(worldNormal.x); vec4 diffuse = vec4(xyDiffuseScaled + xzDiffuseScaled + yzDiffuseScaled, 1.0); - packDeferredFragment(_normal, 1.0, vec3(diffuse), specular, shininess); + packDeferredFragment(_normal, 1.0, vec3(diffuse), DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_SPECULAR); } diff --git a/libraries/entities-renderer/src/untextured_particle.slv b/libraries/entities-renderer/src/untextured_particle.slv index ab0ea15219..85f9d438bf 100644 --- a/libraries/entities-renderer/src/untextured_particle.slv +++ b/libraries/entities-renderer/src/untextured_particle.slv @@ -16,7 +16,7 @@ out vec4 _color; void main(void) { - // pass along the diffuse color + // pass along the color _color = colorToLinearRGBA(inColor); TransformCamera cam = getTransformCamera(); diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 1be3bbb5f6..500f856450 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -865,6 +865,9 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } } else if (object.name == "Material") { FBXMaterial material; + if (object.properties.at(1).toByteArray().contains("StingrayPBS")) { + material.isPBSMaterial = true; + } foreach (const FBXNode& subobject, object.children) { bool properties = false; QByteArray propertyName; @@ -879,7 +882,7 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS propertyName = "P"; index = 4; } - if (properties) { + if (!material.isPBSMaterial && properties) { foreach (const FBXNode& property, subobject.children) { if (property.name == propertyName) { if (property.properties.at(0) == "DiffuseColor") { @@ -914,6 +917,44 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS #endif } } + } else if (material.isPBSMaterial && properties) { + std::vector unknowns; + foreach(const FBXNode& property, subobject.children) { + if (property.name == propertyName) { + if (property.properties.at(0) == "Maya|use_normal_map") { + material.useNormalMap = (bool)property.properties.at(index).value(); + + } else if (property.properties.at(0) == "Maya|base_color") { + material.diffuseColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "Maya|use_color_map") { + material.useAlbedoMap = (bool) property.properties.at(index).value(); + + } else if (property.properties.at(0) == "Maya|roughness") { + material.roughness = property.properties.at(index).value(); + } else if (property.properties.at(0) == "Maya|use_roughness_map") { + material.useRoughnessMap = (bool)property.properties.at(index).value(); + + } else if (property.properties.at(0) == "Maya|metallic") { + material.metallic = property.properties.at(index).value(); + } else if (property.properties.at(0) == "Maya|use_metallic_map") { + material.useMetallicMap = (bool)property.properties.at(index).value(); + + } else if (property.properties.at(0) == "Maya|emissive") { + material.emissiveColor = getVec3(property.properties, index); + } else if (property.properties.at(0) == "Maya|emissive_intensity") { + material.emissiveIntensity = property.properties.at(index).value(); + } else if (property.properties.at(0) == "Maya|use_emissive_map") { + material.useEmissiveMap = (bool)property.properties.at(index).value(); + + } else if (property.properties.at(0) == "Maya|use_ao_map") { + material.useOcclusionMap = (bool)property.properties.at(index).value(); + + } else { + const QString propname = property.properties.at(0).toString(); + unknowns.push_back(propname.toStdString()); + } + } + } } #if defined(DEBUG_FBXREADER) else { @@ -1030,18 +1071,35 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS if (connection.properties.at(0) == "OP") { int counter = 0; QByteArray type = connection.properties.at(3).toByteArray().toLower(); - if (type.contains("diffuse")) { + if ((type.contains("diffuse") && !type.contains("tex_global_diffuse"))) { + diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("tex_color_map")) { diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("transparentcolor")) { // it should be TransparentColor... // THis is how Maya assign a texture that affect diffuse color AND transparency ? - diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + transparentTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("bump")) { bumpTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type.contains("normal")) { normalTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("specular") || type.contains("reflection")) { + } else if (type.contains("tex_normal_map")) { + normalTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if ((type.contains("specular") && !type.contains("tex_global_specular")) || type.contains("reflection")) { specularTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("tex_metallic_map")) { + metallicTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("shininess")) { + shininessTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("tex_roughness_map")) { + roughnessTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("emissive")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("tex_emissive_map")) { + emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("ambient")) { + ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); + } else if (type.contains("tex_ao_map")) { + occlusionTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else if (type == "lcl rotation") { localRotations.insert(getID(connection.properties, 2), getID(connection.properties, 1)); @@ -1055,14 +1113,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS } else if (type == "d|z") { zComponents.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - } else if (type.contains("shininess")) { - counter++; - - } else if (_loadLightmaps && type.contains("emissive")) { - emissiveTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); - - } else if (_loadLightmaps && type.contains("ambient")) { - ambientTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1)); } else { QString typenam = type.data(); counter++; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 51cb5baf9f..3fefd837f3 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -111,7 +111,7 @@ public: QString texcoordSetName; bool isBumpmap{ false }; - + bool isNull() const { return name.isEmpty() && filename.isEmpty() && content.isEmpty(); } }; @@ -130,11 +130,10 @@ class FBXMaterial { public: FBXMaterial() {}; FBXMaterial(const glm::vec3& diffuseColor, const glm::vec3& specularColor, const glm::vec3& emissiveColor, - const glm::vec2& emissiveParams, float shininess, float opacity) : + float shininess, float opacity) : diffuseColor(diffuseColor), specularColor(specularColor), emissiveColor(emissiveColor), - emissiveParams(emissiveParams), shininess(shininess), opacity(opacity) {} @@ -144,18 +143,39 @@ public: float specularFactor = 1.0f; glm::vec3 emissiveColor{ 0.0f }; - glm::vec2 emissiveParams{ 0.0f, 1.0f }; float shininess = 23.0f; float opacity = 1.0f; + float metallic{ 0.0f }; + float roughness{ 1.0f }; + float emissiveIntensity{ 1.0f }; + QString materialID; model::MaterialPointer _material; - FBXTexture diffuseTexture; - FBXTexture opacityTexture; FBXTexture normalTexture; + FBXTexture albedoTexture; + FBXTexture opacityTexture; + FBXTexture glossTexture; + FBXTexture roughnessTexture; FBXTexture specularTexture; + FBXTexture metallicTexture; FBXTexture emissiveTexture; + FBXTexture occlusionTexture; + FBXTexture lightmapTexture; + glm::vec2 lightmapParams{ 0.0f, 1.0f }; + + + bool isPBSMaterial{ false }; + // THe use XXXMap are not really used to drive which map are going or not, debug only + bool useNormalMap{ false }; + bool useAlbedoMap{ false }; + bool useOpacityMap{ false }; + bool useRoughnessMap{ false }; + bool useSpecularMap{ false }; + bool useMetallicMap{ false }; + bool useEmissiveMap{ false }; + bool useOcclusionMap{ false }; bool needTangentSpace() const; }; @@ -397,11 +417,16 @@ public: QHash diffuseTextures; + QHash transparentTextures; QHash bumpTextures; QHash normalTextures; QHash specularTextures; + QHash metallicTextures; + QHash roughnessTextures; + QHash shininessTextures; QHash emissiveTextures; QHash ambientTextures; + QHash occlusionTextures; QHash _fbxMaterials; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index e947a0356e..d87eac405f 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -79,11 +79,20 @@ void FBXReader::consolidateFBXMaterials() { } } - material.diffuseTexture = diffuseTexture; - + material.albedoTexture = diffuseTexture; detectDifferentUVs = (diffuseTexture.texcoordSet != 0) || (!diffuseTexture.transform.isIdentity()); } - + + + FBXTexture transparentTexture; + QString transparentTextureID = transparentTextures.value(material.materialID); + if (!transparentTextureID.isNull()) { + transparentTexture = getTexture(transparentTextureID); + + material.opacityTexture = transparentTexture; + detectDifferentUVs |= (transparentTexture.texcoordSet != 0) || (!transparentTexture.transform.isIdentity()); + } + FBXTexture normalTexture; QString bumpTextureID = bumpTextures.value(material.materialID); QString normalTextureID = normalTextures.value(material.materialID); @@ -100,37 +109,66 @@ void FBXReader::consolidateFBXMaterials() { material.normalTexture = normalTexture; detectDifferentUVs |= (normalTexture.texcoordSet != 0) || (!normalTexture.transform.isIdentity()); } - - + FBXTexture specularTexture; QString specularTextureID = specularTextures.value(material.materialID); if (!specularTextureID.isNull()) { specularTexture = getTexture(specularTextureID); detectDifferentUVs |= (specularTexture.texcoordSet != 0) || (!specularTexture.transform.isIdentity()); - material.specularTexture = specularTexture; } + FBXTexture metallicTexture; + QString metallicTextureID = metallicTextures.value(material.materialID); + if (!metallicTextureID.isNull()) { + metallicTexture = getTexture(metallicTextureID); + detectDifferentUVs |= (metallicTexture.texcoordSet != 0) || (!metallicTexture.transform.isIdentity()); + material.metallicTexture = metallicTexture; + } + + FBXTexture roughnessTexture; + QString roughnessTextureID = roughnessTextures.value(material.materialID); + if (!roughnessTextureID.isNull()) { + roughnessTexture = getTexture(roughnessTextureID); + material.roughnessTexture = roughnessTexture; + detectDifferentUVs |= (roughnessTexture.texcoordSet != 0) || (!roughnessTexture.transform.isIdentity()); + } + + FBXTexture shininessTexture; + QString shininessTextureID = shininessTextures.value(material.materialID); + if (!shininessTextureID.isNull()) { + shininessTexture = getTexture(shininessTextureID); + material.glossTexture = shininessTexture; + detectDifferentUVs |= (shininessTexture.texcoordSet != 0) || (!shininessTexture.transform.isIdentity()); + } + FBXTexture emissiveTexture; - glm::vec2 emissiveParams(0.f, 1.f); - emissiveParams.x = _lightmapOffset; - emissiveParams.y = _lightmapLevel; - QString emissiveTextureID = emissiveTextures.value(material.materialID); - QString ambientTextureID = ambientTextures.value(material.materialID); - if (_loadLightmaps && (!emissiveTextureID.isNull() || !ambientTextureID.isNull())) { - - if (!emissiveTextureID.isNull()) { - emissiveTexture = getTexture(emissiveTextureID); - emissiveParams.y = 4.0f; - } else if (!ambientTextureID.isNull()) { - emissiveTexture = getTexture(ambientTextureID); - } - - material.emissiveParams = emissiveParams; - material.emissiveTexture = emissiveTexture; - + if (!emissiveTextureID.isNull()) { + emissiveTexture = getTexture(emissiveTextureID); detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); + material.emissiveTexture = emissiveTexture; + } + + FBXTexture occlusionTexture; + QString occlusionTextureID = occlusionTextures.value(material.materialID); + if (!occlusionTextureID.isNull()) { + occlusionTexture = getTexture(occlusionTextureID); + detectDifferentUVs |= (occlusionTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); + material.occlusionTexture = occlusionTexture; + } + + glm::vec2 lightmapParams(0.f, 1.f); + lightmapParams.x = _lightmapOffset; + lightmapParams.y = _lightmapLevel; + + FBXTexture ambientTexture; + QString ambientTextureID = ambientTextures.value(material.materialID); + if (_loadLightmaps && !ambientTextureID.isNull()) { + ambientTexture = getTexture(ambientTextureID); + detectDifferentUVs |= (ambientTexture.texcoordSet != 0) || (!ambientTexture.transform.isIdentity()); + material.lightmapTexture = ambientTexture; + material.lightmapParams = lightmapParams; } // Finally create the true material representation @@ -140,13 +178,16 @@ void FBXReader::consolidateFBXMaterials() { auto diffuse = material.diffuseColor; // FIXME: Do not use the Diffuse Factor yet as some FBX models have it set to 0 // diffuse *= material.diffuseFactor; - material._material->setDiffuse(diffuse); + material._material->setAlbedo(diffuse); - float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); - // FIXME: Do not use the Specular Factor yet as some FBX models have it set to 0 - // metallic *= material.specularFactor; - material._material->setMetallic(metallic); - material._material->setGloss(material.shininess); + if (material.isPBSMaterial) { + material._material->setRoughness(material.roughness); + material._material->setMetallic(material.metallic); + } else { + material._material->setRoughness(model::Material::shininessToRoughness(material.shininess)); + float metallic = std::max(material.specularColor.x, std::max(material.specularColor.y, material.specularColor.z)); + material._material->setMetallic(metallic); + } if (material.opacity <= 0.0f) { material._material->setOpacity(1.0f); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index ff33246b3f..e735ba06d9 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -558,7 +558,6 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor, objMaterial.specularColor, glm::vec3(0.0f), - glm::vec2(0.0f, 1.0f), objMaterial.shininess, objMaterial.opacity); FBXMaterial& fbxMaterial = geometry.materials[materialID]; @@ -567,13 +566,13 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, model::MaterialPointer modelMaterial = fbxMaterial._material; if (!objMaterial.diffuseTextureFilename.isEmpty()) { - fbxMaterial.diffuseTexture.filename = objMaterial.diffuseTextureFilename; + fbxMaterial.albedoTexture.filename = objMaterial.diffuseTextureFilename; } modelMaterial->setEmissive(fbxMaterial.emissiveColor); - modelMaterial->setDiffuse(fbxMaterial.diffuseColor); + modelMaterial->setAlbedo(fbxMaterial.diffuseColor); modelMaterial->setMetallic(glm::length(fbxMaterial.specularColor)); - modelMaterial->setGloss(fbxMaterial.shininess); + modelMaterial->setRoughness(model::Material::shininessToRoughness(fbxMaterial.shininess)); if (fbxMaterial.opacity <= 0.0f) { modelMaterial->setOpacity(1.0f); @@ -617,7 +616,7 @@ void fbxDebugDump(const FBXGeometry& fbxgeo) { qCDebug(modelformat) << " specularColor =" << meshPart.specularColor << "mat =" << meshPart._material->getMetallic(); qCDebug(modelformat) << " emissiveColor =" << meshPart.emissiveColor << "mat =" << meshPart._material->getEmissive(); qCDebug(modelformat) << " emissiveParams =" << meshPart.emissiveParams; - qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getGloss(); + qCDebug(modelformat) << " gloss =" << meshPart.shininess << "mat =" << meshPart._material->getRoughness(); qCDebug(modelformat) << " opacity =" << meshPart.opacity << "mat =" << meshPart._material->getOpacity(); */ qCDebug(modelformat) << " materialID =" << meshPart.materialID; diff --git a/libraries/gpu/src/gpu/Format.cpp b/libraries/gpu/src/gpu/Format.cpp index a66fc19458..7c603919fd 100644 --- a/libraries/gpu/src/gpu/Format.cpp +++ b/libraries/gpu/src/gpu/Format.cpp @@ -11,7 +11,7 @@ using namespace gpu; const Element Element::COLOR_RGBA_32{ VEC4, NUINT8, RGBA }; -const Element Element::COLOR_RGBA{ VEC4, FLOAT, RGBA }; +const Element Element::VEC4F_COLOR_RGBA{ VEC4, FLOAT, RGBA }; const Element Element::VEC2F_UV{ VEC2, FLOAT, UV }; const Element Element::VEC2F_XY{ VEC2, FLOAT, XY }; const Element Element::VEC3F_XYZ{ VEC3, FLOAT, XYZ }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 54d40c3e12..625ca6cec3 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -247,7 +247,7 @@ public: } static const Element COLOR_RGBA_32; - static const Element COLOR_RGBA; + static const Element VEC4F_COLOR_RGBA; static const Element VEC2F_UV; static const Element VEC2F_XY; static const Element VEC3F_XYZ; diff --git a/libraries/gpu/src/gpu/GLBackendShader.cpp b/libraries/gpu/src/gpu/GLBackendShader.cpp index ca9c014c00..c27c5dd97d 100755 --- a/libraries/gpu/src/gpu/GLBackendShader.cpp +++ b/libraries/gpu/src/gpu/GLBackendShader.cpp @@ -162,8 +162,6 @@ GLBackend::GLShader* compileShader(const Shader& shader) { char* temp = new char[infoLength] ; glGetShaderInfoLog(glshader, infoLength, NULL, temp); - qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; - qCWarning(gpulogging) << temp; /* filestream.open("debugshader.glsl.info.txt"); @@ -172,6 +170,11 @@ GLBackend::GLShader* compileShader(const Shader& shader) { filestream.close(); } */ + + qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:"; + qCWarning(gpulogging) << srcstr; + qCWarning(gpulogging) << "GLShader::compileShader - errors:"; + qCWarning(gpulogging) << temp; delete[] temp; glDeleteShader(glshader); diff --git a/libraries/gpu/src/gpu/GLBackendTexture.cpp b/libraries/gpu/src/gpu/GLBackendTexture.cpp index d84d3e3967..efcafc9d60 100755 --- a/libraries/gpu/src/gpu/GLBackendTexture.cpp +++ b/libraries/gpu/src/gpu/GLBackendTexture.cpp @@ -145,6 +145,8 @@ public: switch(dstFormat.getSemantic()) { case gpu::RGB: case gpu::RGBA: + case gpu::SRGB: + case gpu::SRGBA: texel.internalFormat = GL_RED; switch (dstFormat.getType()) { case gpu::UINT32: { @@ -196,7 +198,11 @@ public: break; } case gpu::NUINT8: { - texel.internalFormat = GL_R8; + if ((dstFormat.getSemantic() == gpu::SRGB || dstFormat.getSemantic() == gpu::SRGBA)) { + texel.internalFormat = GL_SLUMINANCE; + } else { + texel.internalFormat = GL_R8; + } break; } case gpu::NINT8: { @@ -209,6 +215,7 @@ public: } break; + case gpu::DEPTH: texel.format = GL_DEPTH_COMPONENT; // It's depth component to load it texel.internalFormat = GL_DEPTH_COMPONENT; diff --git a/libraries/gpu/src/gpu/Texture.h b/libraries/gpu/src/gpu/Texture.h index 378f49c2f4..e05dc84c25 100755 --- a/libraries/gpu/src/gpu/Texture.h +++ b/libraries/gpu/src/gpu/Texture.h @@ -14,6 +14,7 @@ #include "Resource.h" #include //min max and more +#include #include @@ -139,6 +140,53 @@ protected: class Texture : public Resource { public: + class Usage { + public: + enum FlagBit { + COLOR = 0, // Texture is a color map + NORMAL, // Texture is a normal map + ALPHA, // Texture has an alpha channel + ALPHA_MASK, // Texture alpha channel is a Mask 0/1 + + NUM_FLAGS, + }; + typedef std::bitset Flags; + + // The key is the Flags + Flags _flags; + + Usage() : _flags(0) {} + Usage(const Flags& flags) : _flags(flags) {} + + bool operator== (const Usage& rhs) const { return _flags == rhs._flags; } + bool operator!= (const Usage& rhs) const { return _flags != rhs._flags; } + + class Builder { + friend class Usage; + Flags _flags{ 0 }; + public: + Builder() {} + + Usage build() const { return Usage(_flags); } + + Builder& withColor() { _flags.set(COLOR); return (*this); } + Builder& withNormal() { _flags.set(NORMAL); return (*this); } + Builder& withAlpha() { _flags.set(ALPHA); return (*this); } + Builder& withAlphaMask() { _flags.set(ALPHA_MASK); return (*this); } + }; + Usage(const Builder& builder) : Usage(builder._flags) {} + + bool isColor() const { return _flags[COLOR]; } + bool isNormal() const { return _flags[NORMAL]; } + + bool isAlpha() const { return _flags[ALPHA]; } + bool isAlphaMask() const { return _flags[ALPHA_MASK]; } + + + bool operator==(const Usage& usage) { return (_flags == usage._flags); } + bool operator!=(const Usage& usage) { return (_flags != usage._flags); } + }; + class Pixels { public: Pixels() {} @@ -343,6 +391,10 @@ public: bool isDefined() const { return _defined; } + // Usage is a a set of flags providing Semantic about the usage of the Texture. + void setUsage(const Usage& usage) { _usage = usage; } + Usage getUsage() const { return _usage; } + // For Cube Texture, it's possible to generate the irradiance spherical harmonics and make them availalbe with the texture bool generateIrradiance(); const SHPointer& getIrradiance(uint16 slice = 0) const { return _irradiance; } @@ -380,6 +432,8 @@ protected: Type _type = TEX_1D; + Usage _usage; + SHPointer _irradiance; bool _autoGenerateMips = false; bool _isIrradianceValid = false; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index a3cc920a40..21eed5f59f 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -136,10 +136,13 @@ bool NetworkGeometry::isLoadedWithTextures() const { if (!_isLoadedWithTextures) { for (auto&& material : _materials) { - if ((material->diffuseTexture && !material->diffuseTexture->isLoaded()) || + if ((material->albedoTexture && !material->albedoTexture->isLoaded()) || (material->normalTexture && !material->normalTexture->isLoaded()) || - (material->specularTexture && !material->specularTexture->isLoaded()) || - (material->emissiveTexture && !material->emissiveTexture->isLoaded())) { + (material->roughnessTexture && !material->roughnessTexture->isLoaded()) || + (material->metallicTexture && !material->metallicTexture->isLoaded()) || + (material->occlusionTexture && !material->occlusionTexture->isLoaded()) || + (material->emissiveTexture && !material->emissiveTexture->isLoaded()) || + (material->lightmapTexture && !material->lightmapTexture->isLoaded())) { return false; } } @@ -154,15 +157,15 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u for (auto&& material : _materials) { auto networkMaterial = material->_material; auto oldTextureMaps = networkMaterial->getTextureMaps(); - if (material->diffuseTextureName == name) { - material->diffuseTexture = textureCache->getTexture(url, DEFAULT_TEXTURE); + if (material->albedoTextureName == name) { + material->albedoTexture = textureCache->getTexture(url, DEFAULT_TEXTURE); - auto diffuseMap = model::TextureMapPointer(new model::TextureMap()); - diffuseMap->setTextureSource(material->diffuseTexture->_textureSource); - diffuseMap->setTextureTransform( - oldTextureMaps[model::MaterialKey::DIFFUSE_MAP]->getTextureTransform()); + auto albedoMap = model::TextureMapPointer(new model::TextureMap()); + albedoMap->setTextureSource(material->albedoTexture->_textureSource); + albedoMap->setTextureTransform( + oldTextureMaps[model::MaterialKey::ALBEDO_MAP]->getTextureTransform()); - networkMaterial->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap); + networkMaterial->setTextureMap(model::MaterialKey::ALBEDO_MAP, albedoMap); } else if (material->normalTextureName == name) { material->normalTexture = textureCache->getTexture(url); @@ -170,15 +173,31 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u normalMap->setTextureSource(material->normalTexture->_textureSource); networkMaterial->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap); - } else if (material->specularTextureName == name) { - material->specularTexture = textureCache->getTexture(url); + } else if (material->roughnessTextureName == name) { + // FIXME: If passing a gloss map instead of a roughmap how to say that ? looking for gloss in the name ? + material->roughnessTexture = textureCache->getTexture(url, ROUGHNESS_TEXTURE); + + auto roughnessMap = model::TextureMapPointer(new model::TextureMap()); + roughnessMap->setTextureSource(material->roughnessTexture->_textureSource); + + networkMaterial->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap); + } else if (material->metallicTextureName == name) { + // FIXME: If passing a specular map instead of a metallic how to say that ? looking for wtf in the name ? + material->metallicTexture = textureCache->getTexture(url, METALLIC_TEXTURE); auto glossMap = model::TextureMapPointer(new model::TextureMap()); - glossMap->setTextureSource(material->specularTexture->_textureSource); + glossMap->setTextureSource(material->metallicTexture->_textureSource); - networkMaterial->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap); + networkMaterial->setTextureMap(model::MaterialKey::METALLIC_MAP, glossMap); } else if (material->emissiveTextureName == name) { - material->emissiveTexture = textureCache->getTexture(url); + material->emissiveTexture = textureCache->getTexture(url, EMISSIVE_TEXTURE); + + auto emissiveMap = model::TextureMapPointer(new model::TextureMap()); + emissiveMap->setTextureSource(material->emissiveTexture->_textureSource); + + networkMaterial->setTextureMap(model::MaterialKey::EMISSIVE_MAP, emissiveMap); + } else if (material->lightmapTextureName == name) { + material->emissiveTexture = textureCache->getTexture(url, LIGHTMAP_TEXTURE); auto lightmapMap = model::TextureMapPointer(new model::TextureMap()); lightmapMap->setTextureSource(material->emissiveTexture->_textureSource); @@ -200,9 +219,14 @@ void NetworkGeometry::setTextureWithNameToURL(const QString& name, const QUrl& u QStringList NetworkGeometry::getTextureNames() const { QStringList result; for (auto&& material : _materials) { - if (!material->diffuseTextureName.isEmpty() && material->diffuseTexture) { - QString textureURL = material->diffuseTexture->getURL().toString(); - result << material->diffuseTextureName + ":\"" + textureURL + "\""; + if (!material->emissiveTextureName.isEmpty() && material->emissiveTexture) { + QString textureURL = material->emissiveTexture->getURL().toString(); + result << material->emissiveTextureName + ":\"" + textureURL + "\""; + } + + if (!material->albedoTextureName.isEmpty() && material->albedoTexture) { + QString textureURL = material->albedoTexture->getURL().toString(); + result << material->albedoTextureName + ":\"" + textureURL + "\""; } if (!material->normalTextureName.isEmpty() && material->normalTexture) { @@ -210,14 +234,24 @@ QStringList NetworkGeometry::getTextureNames() const { result << material->normalTextureName + ":\"" + textureURL + "\""; } - if (!material->specularTextureName.isEmpty() && material->specularTexture) { - QString textureURL = material->specularTexture->getURL().toString(); - result << material->specularTextureName + ":\"" + textureURL + "\""; + if (!material->roughnessTextureName.isEmpty() && material->roughnessTexture) { + QString textureURL = material->roughnessTexture->getURL().toString(); + result << material->roughnessTextureName + ":\"" + textureURL + "\""; } - if (!material->emissiveTextureName.isEmpty() && material->emissiveTexture) { - QString textureURL = material->emissiveTexture->getURL().toString(); - result << material->emissiveTextureName + ":\"" + textureURL + "\""; + if (!material->metallicTextureName.isEmpty() && material->metallicTexture) { + QString textureURL = material->metallicTexture->getURL().toString(); + result << material->metallicTextureName + ":\"" + textureURL + "\""; + } + + if (!material->occlusionTextureName.isEmpty() && material->occlusionTexture) { + QString textureURL = material->occlusionTexture->getURL().toString(); + result << material->occlusionTextureName + ":\"" + textureURL + "\""; + } + + if (!material->lightmapTextureName.isEmpty() && material->lightmapTexture) { + QString textureURL = material->lightmapTexture->getURL().toString(); + result << material->lightmapTextureName + ":\"" + textureURL + "\""; } } @@ -304,7 +338,8 @@ static NetworkMesh* buildNetworkMesh(const FBXMesh& mesh, const QUrl& textureBas return networkMesh; } -static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUrl, + +static model::TextureMapPointer setupNetworkTextureMap(NetworkGeometry* geometry, const QUrl& textureBaseUrl, const FBXTexture& texture, TextureType type, NetworkTexturePointer& networkTexture, QString& networkTextureName) { auto textureCache = DependencyManager::get(); @@ -314,6 +349,7 @@ static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUr const auto filename = baseUrl.resolved(QUrl(texture.filename)); networkTexture = textureCache->getTexture(filename, type, texture.content); + QObject::connect(networkTexture.data(), &NetworkTexture::networkTextureCreated, geometry, &NetworkGeometry::textureLoaded); networkTextureName = texture.name; auto map = std::make_shared(); @@ -321,33 +357,66 @@ static model::TextureMapPointer setupNetworkTextureMap(const QUrl& textureBaseUr return map; } -static NetworkMaterial* buildNetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl) { +static NetworkMaterial* buildNetworkMaterial(NetworkGeometry* geometry, const FBXMaterial& material, const QUrl& textureBaseUrl) { NetworkMaterial* networkMaterial = new NetworkMaterial(); networkMaterial->_material = material._material; - if (!material.diffuseTexture.filename.isEmpty()) { - auto diffuseMap = setupNetworkTextureMap(textureBaseUrl, material.diffuseTexture, DEFAULT_TEXTURE, - networkMaterial->diffuseTexture, networkMaterial->diffuseTextureName); - diffuseMap->setTextureTransform(material.diffuseTexture.transform); - networkMaterial->_material->setTextureMap(model::MaterialKey::DIFFUSE_MAP, diffuseMap); + if (!material.albedoTexture.filename.isEmpty()) { + auto albedoMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.albedoTexture, DEFAULT_TEXTURE, + networkMaterial->albedoTexture, networkMaterial->albedoTextureName); + albedoMap->setTextureTransform(material.albedoTexture.transform); + material._material->setTextureMap(model::MaterialKey::ALBEDO_MAP, albedoMap); } + if (!material.normalTexture.filename.isEmpty()) { - auto normalMap = setupNetworkTextureMap(textureBaseUrl, material.normalTexture, + auto normalMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.normalTexture, (material.normalTexture.isBumpmap ? BUMP_TEXTURE : NORMAL_TEXTURE), networkMaterial->normalTexture, networkMaterial->normalTextureName); networkMaterial->_material->setTextureMap(model::MaterialKey::NORMAL_MAP, normalMap); } - if (!material.specularTexture.filename.isEmpty()) { - auto glossMap = setupNetworkTextureMap(textureBaseUrl, material.specularTexture, SPECULAR_TEXTURE, - networkMaterial->specularTexture, networkMaterial->specularTextureName); - networkMaterial->_material->setTextureMap(model::MaterialKey::GLOSS_MAP, glossMap); + + // Roughness first or gloss maybe + if (!material.roughnessTexture.filename.isEmpty()) { + auto roughnessMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.roughnessTexture, ROUGHNESS_TEXTURE, + networkMaterial->roughnessTexture, networkMaterial->roughnessTextureName); + material._material->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap); + } else if (!material.glossTexture.filename.isEmpty()) { + auto roughnessMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.glossTexture, GLOSS_TEXTURE, + networkMaterial->roughnessTexture, networkMaterial->roughnessTextureName); + material._material->setTextureMap(model::MaterialKey::ROUGHNESS_MAP, roughnessMap); } + + // Metallic first or specular maybe + + if (!material.metallicTexture.filename.isEmpty()) { + auto metallicMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.metallicTexture, METALLIC_TEXTURE, + networkMaterial->metallicTexture, networkMaterial->metallicTextureName); + material._material->setTextureMap(model::MaterialKey::METALLIC_MAP, metallicMap); + } else if (!material.specularTexture.filename.isEmpty()) { + + auto metallicMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.specularTexture, SPECULAR_TEXTURE, + networkMaterial->metallicTexture, networkMaterial->metallicTextureName); + material._material->setTextureMap(model::MaterialKey::METALLIC_MAP, metallicMap); + } + + if (!material.occlusionTexture.filename.isEmpty()) { + auto occlusionMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.occlusionTexture, OCCLUSION_TEXTURE, + networkMaterial->occlusionTexture, networkMaterial->occlusionTextureName); + material._material->setTextureMap(model::MaterialKey::OCCLUSION_MAP, occlusionMap); + } + if (!material.emissiveTexture.filename.isEmpty()) { - auto lightmapMap = setupNetworkTextureMap(textureBaseUrl, material.emissiveTexture, LIGHTMAP_TEXTURE, + auto emissiveMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.emissiveTexture, EMISSIVE_TEXTURE, networkMaterial->emissiveTexture, networkMaterial->emissiveTextureName); - lightmapMap->setTextureTransform(material.emissiveTexture.transform); - lightmapMap->setLightmapOffsetScale(material.emissiveParams.x, material.emissiveParams.y); - networkMaterial->_material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap); + material._material->setTextureMap(model::MaterialKey::EMISSIVE_MAP, emissiveMap); + } + + if (!material.lightmapTexture.filename.isEmpty()) { + auto lightmapMap = setupNetworkTextureMap(geometry, textureBaseUrl, material.lightmapTexture, LIGHTMAP_TEXTURE, + networkMaterial->lightmapTexture, networkMaterial->lightmapTextureName); + lightmapMap->setTextureTransform(material.lightmapTexture.transform); + lightmapMap->setLightmapOffsetScale(material.lightmapParams.x, material.lightmapParams.y); + material._material->setTextureMap(model::MaterialKey::LIGHTMAP_MAP, lightmapMap); } return networkMaterial; @@ -367,7 +436,7 @@ void NetworkGeometry::modelParseSuccess(FBXGeometry* geometry) { QHash fbxMatIDToMatID; foreach(const FBXMaterial& material, _geometry->materials) { fbxMatIDToMatID[material.materialID] = _materials.size(); - _materials.emplace_back(buildNetworkMaterial(material, _textureBaseUrl)); + _materials.emplace_back(buildNetworkMaterial(this, material, _textureBaseUrl)); } @@ -413,3 +482,6 @@ const NetworkMaterial* NetworkGeometry::getShapeMaterial(int shapeID) { } } +void NetworkGeometry::textureLoaded(const QWeakPointer& networkTexture) { + numTextureLoaded++; +} diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index b2d81c5900..60f185f691 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -105,6 +105,9 @@ signals: // Fired when something went wrong. void onFailure(NetworkGeometry& networkGeometry, Error error); +public slots: + void textureLoaded(const QWeakPointer& networkTexture); + protected slots: void mappingRequestDone(const QByteArray& data); void mappingRequestError(QNetworkReply::NetworkError error); @@ -115,6 +118,7 @@ protected slots: void modelParseSuccess(FBXGeometry* geometry); void modelParseError(int error, QString str); + protected: void attemptRequestInternal(); void requestMapping(const QUrl& url); @@ -133,6 +137,7 @@ protected: QUrl _modelUrl; QVariantHash _mapping; QUrl _textureBaseUrl; + int numTextureLoaded = 0; Resource* _resource = nullptr; std::unique_ptr _geometry; // This should go away evenutally once we can put everything we need in the model::AssetPointer @@ -173,15 +178,23 @@ public: class NetworkMaterial { public: + model::MaterialPointer _material; - QString diffuseTextureName; - QSharedPointer diffuseTexture; - QString normalTextureName; - QSharedPointer normalTexture; - QString specularTextureName; - QSharedPointer specularTexture; QString emissiveTextureName; QSharedPointer emissiveTexture; + QString albedoTextureName; + QSharedPointer albedoTexture; + QString normalTextureName; + QSharedPointer normalTexture; + QString roughnessTextureName; + QSharedPointer roughnessTexture; + QString metallicTextureName; + QSharedPointer metallicTexture; + QString occlusionTextureName; + QSharedPointer occlusionTexture; + QString lightmapTextureName; + QSharedPointer lightmapTexture; + }; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 8201339e93..d49ff91abf 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -212,12 +212,23 @@ NetworkTexture::TextureLoaderFunc NetworkTexture::getTextureLoader() const { return TextureLoaderFunc(model::TextureUsage::createNormalTextureFromNormalImage); break; } + case ROUGHNESS_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromImage); + break; + } + case GLOSS_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createRoughnessTextureFromGlossImage); + break; + } + case SPECULAR_TEXTURE: { + return TextureLoaderFunc(model::TextureUsage::createMetallicTextureFromImage); + break; + } case CUSTOM_TEXTURE: { return _textureLoader; break; } case DEFAULT_TEXTURE: - case SPECULAR_TEXTURE: case EMISSIVE_TEXTURE: default: { return TextureLoaderFunc(model::TextureUsage::create2DTextureFromImage); @@ -335,10 +346,6 @@ void NetworkTexture::setImage(const QImage& image, void* voidTexture, int origin finishedLoading(true); - imageLoaded(image); -} - -void NetworkTexture::imageLoaded(const QImage& image) { - // nothing by default + emit networkTextureCreated(qWeakPointerCast (_self)); } diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 033b4bede6..af82d2a1ad 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -29,7 +29,20 @@ class NetworkTexture; typedef QSharedPointer NetworkTexturePointer; -enum TextureType { DEFAULT_TEXTURE, NORMAL_TEXTURE, BUMP_TEXTURE, SPECULAR_TEXTURE, EMISSIVE_TEXTURE, CUBE_TEXTURE, LIGHTMAP_TEXTURE, CUSTOM_TEXTURE }; +enum TextureType { + DEFAULT_TEXTURE, + NORMAL_TEXTURE, + BUMP_TEXTURE, + SPECULAR_TEXTURE, + METALLIC_TEXTURE = SPECULAR_TEXTURE, // for now spec and metallic texture are the same, converted to grey + ROUGHNESS_TEXTURE, + GLOSS_TEXTURE, + EMISSIVE_TEXTURE, + CUBE_TEXTURE, + OCCLUSION_TEXTURE, + LIGHTMAP_TEXTURE, + CUSTOM_TEXTURE +}; /// Stores cached textures, including render-to-texture targets. class TextureCache : public ResourceCache, public Dependency { @@ -83,8 +96,6 @@ private: gpu::TexturePointer _blueTexture; gpu::TexturePointer _blackTexture; gpu::TexturePointer _normalFittingTexture; - - QHash > _dilatableNetworkTextures; }; /// A simple object wrapper for an OpenGL texture. @@ -114,7 +125,11 @@ public: int getHeight() const { return _height; } TextureLoaderFunc getTextureLoader() const; - + +signals: + void networkTextureCreated(const QWeakPointer& self); + + protected: virtual void downloadFinished(const QByteArray& data) override; @@ -123,8 +138,6 @@ protected: // FIXME: This void* should be a gpu::Texture* but i cannot get it to work for now, moving on... Q_INVOKABLE void setImage(const QImage& image, void* texture, int originalWidth, int originalHeight); - virtual void imageLoaded(const QImage& image); - private: TextureType _type; diff --git a/libraries/model/src/model/Light.cpp b/libraries/model/src/model/Light.cpp index 8a016c4d77..1762b0a9fb 100755 --- a/libraries/model/src/model/Light.cpp +++ b/libraries/model/src/model/Light.cpp @@ -130,7 +130,7 @@ void Light::setShowContour(float show) { if (show <= 0.f) { show = 0.0f; } - editSchema()._control.w = show; + editSchema()._control.z = show; } void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) { @@ -140,3 +140,16 @@ void Light::setAmbientSphere(const gpu::SphericalHarmonics& sphere) { void Light::setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset) { editSchema()._ambientSphere.assignPreset(preset); } + +void Light::setAmbientMap(gpu::TexturePointer ambientMap) { + _ambientMap = ambientMap; + if (ambientMap) { + setAmbientMapNumMips(_ambientMap->evalNumMips()); + } else { + setAmbientMapNumMips(0); + } +} + +void Light::setAmbientMapNumMips(uint16_t numMips) { + editSchema()._ambientMapNumMips = (float)numMips; +} diff --git a/libraries/model/src/model/Light.h b/libraries/model/src/model/Light.h index dafbf90397..3b320e08fd 100755 --- a/libraries/model/src/model/Light.h +++ b/libraries/model/src/model/Light.h @@ -97,7 +97,7 @@ public: // For editing purpose, show the light volume contour. // Set to non 0 to show it, the value is used as the intensity of the contour color void setShowContour(float show); - float getShowContour() const { return getSchema()._control.w; } + float getShowContour() const { return getSchema()._control.z; } // If the light has an ambient (Indirect) component, then the Ambientintensity can be used to control its contribution to the lighting void setAmbientIntensity(float intensity); @@ -108,6 +108,12 @@ public: const gpu::SphericalHarmonics& getAmbientSphere() const { return getSchema()._ambientSphere; } void setAmbientSpherePreset(gpu::SphericalHarmonics::Preset preset); + void setAmbientMap(gpu::TexturePointer ambientMap); + gpu::TexturePointer getAmbientMap() const { return _ambientMap; } + + void setAmbientMapNumMips(uint16_t numMips); + uint16_t getAmbientMapNumMips() const { return (uint16_t) getSchema()._ambientMapNumMips; } + // Schema to access the attribute values of the light class Schema { public: @@ -120,7 +126,8 @@ public: Vec4 _spot{0.0f, 0.0f, 0.0f, 0.0f}; Vec4 _shadow{0.0f}; - Vec4 _control{0.0f, 0.0f, 0.0f, 0.0f}; + float _ambientMapNumMips{ 0.0f }; + Vec3 _control{ 0.0f, 0.0f, 0.0f }; gpu::SphericalHarmonics _ambientSphere; }; @@ -133,6 +140,8 @@ protected: UniformBufferView _schemaBuffer; Transform _transform; + gpu::TexturePointer _ambientMap; + const Schema& getSchema() const { return _schemaBuffer.get(); } Schema& editSchema() { return _schemaBuffer.edit(); } diff --git a/libraries/model/src/model/Light.slh b/libraries/model/src/model/Light.slh index af1c251ccb..80804e3cf5 100644 --- a/libraries/model/src/model/Light.slh +++ b/libraries/model/src/model/Light.slh @@ -109,6 +109,10 @@ SphericalHarmonics getLightAmbientSphere(Light l) { return l._ambientSphere; } +float getLightAmbientMapNumMips(Light l) { + return l._control.x; +} + <@if GPU_FEATURE_PROFILE == GPU_CORE @> uniform lightBuffer { Light light; diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index 1d0f6ee5d9..10fa15edd5 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -44,37 +44,51 @@ Material& Material::operator= (const Material& material) { Material::~Material() { } -void Material::setDiffuse(const Color& diffuse, bool isSRGB) { - _key.setDiffuse(glm::any(glm::greaterThan(diffuse, Color(0.0f)))); - _schemaBuffer.edit()._diffuse = (isSRGB ? ColorUtils::toLinearVec3(diffuse) : diffuse); -} - -void Material::setMetallic(float metallic) { - _key.setMetallic(metallic > 0.0f); - _schemaBuffer.edit()._metallic = glm::vec3(metallic); -} - void Material::setEmissive(const Color& emissive, bool isSRGB) { _key.setEmissive(glm::any(glm::greaterThan(emissive, Color(0.0f)))); + _schemaBuffer.edit()._key = (uint32) _key._flags.to_ulong(); _schemaBuffer.edit()._emissive = (isSRGB ? ColorUtils::toLinearVec3(emissive) : emissive); } -void Material::setGloss(float gloss) { - _key.setGloss((gloss > 0.0f)); - _schemaBuffer.edit()._gloss = gloss; -} - void Material::setOpacity(float opacity) { _key.setTransparent((opacity < 1.0f)); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); _schemaBuffer.edit()._opacity = opacity; } +void Material::setAlbedo(const Color& albedo, bool isSRGB) { + _key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f)))); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); + _schemaBuffer.edit()._albedo = (isSRGB ? ColorUtils::toLinearVec3(albedo) : albedo); +} + +void Material::setRoughness(float roughness) { + roughness = std::min(1.0f, std::max(roughness, 0.0f)); + _key.setGlossy((roughness < 1.0f)); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); + _schemaBuffer.edit()._roughness = roughness; +} + +void Material::setFresnel(const Color& fresnel, bool isSRGB) { + //_key.setAlbedo(glm::any(glm::greaterThan(albedo, Color(0.0f)))); + _schemaBuffer.edit()._fresnel = (isSRGB ? ColorUtils::toLinearVec3(fresnel) : fresnel); +} + +void Material::setMetallic(float metallic) { + _key.setMetallic(metallic > 0.0f); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); + _schemaBuffer.edit()._metallic = metallic; +} + + void Material::setTextureMap(MapChannel channel, const TextureMapPointer& textureMap) { if (textureMap) { _key.setMapChannel(channel, (true)); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); _textureMaps[channel] = textureMap; } else { _key.setMapChannel(channel, (false)); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); _textureMaps.erase(channel); } } diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index cb5a285dba..b22f8a3f42 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -28,17 +28,18 @@ class MaterialKey { public: enum FlagBit { EMISSIVE_VAL_BIT = 0, - DIFFUSE_VAL_BIT, + ALBEDO_VAL_BIT, METALLIC_VAL_BIT, - GLOSS_VAL_BIT, + GLOSSY_VAL_BIT, TRANSPARENT_VAL_BIT, EMISSIVE_MAP_BIT, - DIFFUSE_MAP_BIT, + ALBEDO_MAP_BIT, METALLIC_MAP_BIT, - GLOSS_MAP_BIT, + ROUGHNESS_MAP_BIT, TRANSPARENT_MAP_BIT, NORMAL_MAP_BIT, + OCCLUSION_MAP_BIT, LIGHTMAP_MAP_BIT, NUM_FLAGS, @@ -47,11 +48,12 @@ public: enum MapChannel { EMISSIVE_MAP = 0, - DIFFUSE_MAP, + ALBEDO_MAP, METALLIC_MAP, - GLOSS_MAP, + ROUGHNESS_MAP, TRANSPARENT_MAP, NORMAL_MAP, + OCCLUSION_MAP, LIGHTMAP_MAP, NUM_MAP_CHANNELS, @@ -71,22 +73,23 @@ public: MaterialKey build() const { return MaterialKey(_flags); } Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT); return (*this); } - Builder& withDiffuse() { _flags.set(DIFFUSE_VAL_BIT); return (*this); } + Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT); return (*this); } Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); } - Builder& withGloss() { _flags.set(GLOSS_VAL_BIT); return (*this); } + Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); } Builder& withTransparent() { _flags.set(TRANSPARENT_VAL_BIT); return (*this); } Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); } - Builder& withDiffuseMap() { _flags.set(DIFFUSE_MAP_BIT); return (*this); } + Builder& withAlbedoMap() { _flags.set(ALBEDO_MAP_BIT); return (*this); } Builder& withMetallicMap() { _flags.set(METALLIC_MAP_BIT); return (*this); } - Builder& withGlossMap() { _flags.set(GLOSS_MAP_BIT); return (*this); } + Builder& withRoughnessMap() { _flags.set(ROUGHNESS_MAP_BIT); return (*this); } Builder& withTransparentMap() { _flags.set(TRANSPARENT_MAP_BIT); return (*this); } Builder& withNormalMap() { _flags.set(NORMAL_MAP_BIT); return (*this); } + Builder& withOcclusionMap() { _flags.set(OCCLUSION_MAP_BIT); return (*this); } Builder& withLightmapMap() { _flags.set(LIGHTMAP_MAP_BIT); return (*this); } // Convenient standard keys that we will keep on using all over the place - static MaterialKey opaqueDiffuse() { return Builder().withDiffuse().build(); } + static MaterialKey opaqueAlbedo() { return Builder().withAlbedo().build(); } }; void setEmissive(bool value) { _flags.set(EMISSIVE_VAL_BIT, value); } @@ -95,11 +98,11 @@ public: void setEmissiveMap(bool value) { _flags.set(EMISSIVE_MAP_BIT, value); } bool isEmissiveMap() const { return _flags[EMISSIVE_MAP_BIT]; } - void setDiffuse(bool value) { _flags.set(DIFFUSE_VAL_BIT, value); } - bool isDiffuse() const { return _flags[DIFFUSE_VAL_BIT]; } + void setAlbedo(bool value) { _flags.set(ALBEDO_VAL_BIT, value); } + bool isAlbedo() const { return _flags[ALBEDO_VAL_BIT]; } - void setDiffuseMap(bool value) { _flags.set(DIFFUSE_MAP_BIT, value); } - bool isDiffuseMap() const { return _flags[DIFFUSE_MAP_BIT]; } + void setAlbedoMap(bool value) { _flags.set(ALBEDO_MAP_BIT, value); } + bool isAlbedoMap() const { return _flags[ALBEDO_MAP_BIT]; } void setMetallic(bool value) { _flags.set(METALLIC_VAL_BIT, value); } bool isMetallic() const { return _flags[METALLIC_VAL_BIT]; } @@ -107,11 +110,12 @@ public: void setMetallicMap(bool value) { _flags.set(METALLIC_MAP_BIT, value); } bool isMetallicMap() const { return _flags[METALLIC_MAP_BIT]; } - void setGloss(bool value) { _flags.set(GLOSS_VAL_BIT, value); } - bool isGloss() const { return _flags[GLOSS_VAL_BIT]; } + void setGlossy(bool value) { _flags.set(GLOSSY_VAL_BIT, value); } + bool isGlossy() const { return _flags[GLOSSY_VAL_BIT]; } + bool isRough() const { return !_flags[GLOSSY_VAL_BIT]; } - void setGlossMap(bool value) { _flags.set(GLOSS_MAP_BIT, value); } - bool isGlossMap() const { return _flags[GLOSS_MAP_BIT]; } + void setRoughnessMap(bool value) { _flags.set(ROUGHNESS_MAP_BIT, value); } + bool isRoughnessMap() const { return _flags[ROUGHNESS_MAP_BIT]; } void setTransparent(bool value) { _flags.set(TRANSPARENT_VAL_BIT, value); } bool isTransparent() const { return _flags[TRANSPARENT_VAL_BIT]; } @@ -123,6 +127,9 @@ public: void setNormalMap(bool value) { _flags.set(NORMAL_MAP_BIT, value); } bool isNormalMap() const { return _flags[NORMAL_MAP_BIT]; } + void setOcclusionMap(bool value) { _flags.set(OCCLUSION_MAP_BIT, value); } + bool isOcclusionMap() const { return _flags[OCCLUSION_MAP_BIT]; } + void setLightmapMap(bool value) { _flags.set(LIGHTMAP_MAP_BIT, value); } bool isLightmapMap() const { return _flags[LIGHTMAP_MAP_BIT]; } @@ -154,11 +161,11 @@ public: Builder& withoutEmissiveMap() { _value.reset(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } Builder& withEmissiveMap() { _value.set(MaterialKey::EMISSIVE_MAP_BIT); _mask.set(MaterialKey::EMISSIVE_MAP_BIT); return (*this); } - Builder& withoutDiffuse() { _value.reset(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); } - Builder& withDiffuse() { _value.set(MaterialKey::DIFFUSE_VAL_BIT); _mask.set(MaterialKey::DIFFUSE_VAL_BIT); return (*this); } + Builder& withoutAlbedo() { _value.reset(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } + Builder& withAlbedo() { _value.set(MaterialKey::ALBEDO_VAL_BIT); _mask.set(MaterialKey::ALBEDO_VAL_BIT); return (*this); } - Builder& withoutDiffuseMap() { _value.reset(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); } - Builder& withDiffuseMap() { _value.set(MaterialKey::DIFFUSE_MAP_BIT); _mask.set(MaterialKey::DIFFUSE_MAP_BIT); return (*this); } + Builder& withoutAlbedoMap() { _value.reset(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } + Builder& withAlbedoMap() { _value.set(MaterialKey::ALBEDO_MAP_BIT); _mask.set(MaterialKey::ALBEDO_MAP_BIT); return (*this); } Builder& withoutMetallic() { _value.reset(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); } Builder& withMetallic() { _value.set(MaterialKey::METALLIC_VAL_BIT); _mask.set(MaterialKey::METALLIC_VAL_BIT); return (*this); } @@ -166,11 +173,11 @@ public: Builder& withoutMetallicMap() { _value.reset(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); } Builder& withMetallicMap() { _value.set(MaterialKey::METALLIC_MAP_BIT); _mask.set(MaterialKey::METALLIC_MAP_BIT); return (*this); } - Builder& withoutGloss() { _value.reset(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); } - Builder& withGloss() { _value.set(MaterialKey::GLOSS_VAL_BIT); _mask.set(MaterialKey::GLOSS_VAL_BIT); return (*this); } + Builder& withoutGlossy() { _value.reset(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT); return (*this); } + Builder& withGlossy() { _value.set(MaterialKey::GLOSSY_VAL_BIT); _mask.set(MaterialKey::GLOSSY_VAL_BIT); return (*this); } - Builder& withoutGlossMap() { _value.reset(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); } - Builder& withGlossMap() { _value.set(MaterialKey::GLOSS_MAP_BIT); _mask.set(MaterialKey::GLOSS_MAP_BIT); return (*this); } + Builder& withoutRoughnessMap() { _value.reset(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); } + Builder& withRoughnessMap() { _value.set(MaterialKey::ROUGHNESS_MAP_BIT); _mask.set(MaterialKey::ROUGHNESS_MAP_BIT); return (*this); } Builder& withoutTransparent() { _value.reset(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } Builder& withTransparent() { _value.set(MaterialKey::TRANSPARENT_VAL_BIT); _mask.set(MaterialKey::TRANSPARENT_VAL_BIT); return (*this); } @@ -181,11 +188,14 @@ public: Builder& withoutNormalMap() { _value.reset(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } Builder& withNormalMap() { _value.set(MaterialKey::NORMAL_MAP_BIT); _mask.set(MaterialKey::NORMAL_MAP_BIT); return (*this); } + Builder& withoutOcclusionMap() { _value.reset(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); } + Builder& withOcclusionMap() { _value.set(MaterialKey::OCCLUSION_MAP_BIT); _mask.set(MaterialKey::OCCLUSION_MAP_BIT); return (*this); } + Builder& withoutLightmapMap() { _value.reset(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); } Builder& withLightmapMap() { _value.set(MaterialKey::LIGHTMAP_MAP_BIT); _mask.set(MaterialKey::LIGHTMAP_MAP_BIT); return (*this); } // Convenient standard keys that we will keep on using all over the place - static MaterialFilter opaqueDiffuse() { return Builder().withDiffuse().withoutTransparent().build(); } + static MaterialFilter opaqueAlbedo() { return Builder().withAlbedo().withoutTransparent().build(); } }; // Item Filter operator testing if a key pass the filter @@ -223,29 +233,39 @@ public: void setEmissive(const Color& emissive, bool isSRGB = true); Color getEmissive(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._emissive) : _schemaBuffer.get()._emissive); } - void setDiffuse(const Color& diffuse, bool isSRGB = true); - Color getDiffuse(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._diffuse) : _schemaBuffer.get()._diffuse); } - - void setMetallic(float metallic); - float getMetallic() const { return _schemaBuffer.get()._metallic.x; } - - void setGloss(float gloss); - float getGloss() const { return _schemaBuffer.get()._gloss; } - void setOpacity(float opacity); float getOpacity() const { return _schemaBuffer.get()._opacity; } + void setAlbedo(const Color& albedo, bool isSRGB = true); + Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._albedo) : _schemaBuffer.get()._albedo); } + + void setFresnel(const Color& fresnel, bool isSRGB = true); + Color getFresnel(bool SRGB = true) const { return (SRGB ? ColorUtils::toGamma22Vec3(_schemaBuffer.get()._fresnel) : _schemaBuffer.get()._fresnel); } + + void setMetallic(float metallic); + float getMetallic() const { return _schemaBuffer.get()._metallic; } + + void setRoughness(float roughness); + float getRoughness() const { return _schemaBuffer.get()._roughness; } + // Schema to access the attribute values of the material class Schema { public: - - glm::vec3 _diffuse{ 0.5f }; - float _opacity{1.f}; - glm::vec3 _metallic{ 0.03f }; - float _gloss{0.1f}; - glm::vec3 _emissive{ 0.0f }; - float _spare0{0.0f}; - glm::vec4 _spareVec4{0.0f}; // for alignment beauty, Material size == Mat4x4 + glm::vec3 _emissive{ 0.0f }; // No Emissive + float _opacity{ 1.0f }; // Opacity = 1 => Not Transparent + + glm::vec3 _albedo{ 0.5f }; // Grey albedo => isAlbedo + float _roughness{ 1.0f }; // Roughness = 1 => Not Glossy + + glm::vec3 _fresnel{ 0.03f }; // Fresnel value for a default non metallic + float _metallic{ 0.0f }; // Not Metallic + + + glm::vec3 _spare0{ 0.0f }; + + uint32_t _key{ 0 }; // a copy of the materialKey + + // for alignment beauty, Material size == Mat4x4 Schema() {} }; @@ -256,6 +276,9 @@ public: void setTextureMap(MapChannel channel, const TextureMapPointer& textureMap); const TextureMaps& getTextureMaps() const { return _textureMaps; } + // conversion from legacy material properties to PBR equivalent + static float shininessToRoughness(float shininess) { return 1.0f - shininess / 100.0f; } + protected: MaterialKey _key; diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index f48bdfa8f1..d75f3df5e0 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -12,9 +12,9 @@ <@def MODEL_MATERIAL_SLH@> struct Material { - vec4 _diffuse; - vec4 _specular; - vec4 _emissive; + vec4 _emissiveOpacity; + vec4 _albedoRoughness; + vec4 _fresnelMetallic; vec4 _spare; }; @@ -26,41 +26,36 @@ Material getMaterial() { return _mat; } - 0.04045 - // constants: - // T = 0.04045 - // A = 1 / 1.055 = 0.94786729857 - // B = 0.055 * A = 0.05213270142 - // C = 1 / 12.92 = 0.0773993808 - // G = 2.4 - const float T = 0.04045; - const float A = 0.947867; - const float B = 0.052132; - const float C = 0.077399; - const float G = 2.4; +vec3 getMaterialEmissive(Material m) { return m._emissiveOpacity.rgb; } +float getMaterialOpacity(Material m) { return m._emissiveOpacity.a; } - if (cs > T) { - return pow((cs * A + B), G); - } else { - return cs * C; - } -} +vec3 getMaterialAlbedo(Material m) { return m._albedoRoughness.rgb; } +float getMaterialRoughness(Material m) { return m._albedoRoughness.a; } + +vec3 getMaterialFresnel(Material m) { return m._fresnelMetallic.rgb; } +float getMaterialMetallic(Material m) { return m._fresnelMetallic.a; } + +float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } + +int getMaterialKey(Material m) { return floatBitsToInt(m._spare.w); } + +const int EMISSIVE_VAL_BIT = 0x00000001; +const int ALBEDO_VAL_BIT = 0x00000002; +const int METALLIC_VAL_BIT = 0x00000004; +const int GLOSSY_VAL_BIT = 0x00000008; +const int TRANSPARENT_VAL_BIT = 0x00000010; + + +const int EMISSIVE_MAP_BIT = 0x00000020; +const int ALBEDO_MAP_BIT = 0x00000040; +const int METALLIC_MAP_BIT = 0x00000080; +const int ROUGHNESS_MAP_BIT = 0x00000100; +const int TRANSPARENT_MAP_BIT = 0x00000200; +const int NORMAL_MAP_BIT = 0x00000400; +const int OCCLUSION_MAP_BIT = 0x00000800; + +const int LIGHTMAP_MAP_BIT = 0x00001000; -vec3 SRGBToLinear(vec3 srgb) { - return vec3(componentSRGBToLinear(srgb.x),componentSRGBToLinear(srgb.y),componentSRGBToLinear(srgb.z)); -} -vec3 getMaterialDiffuse(Material m) { return (gl_FragCoord.x < 800 ? SRGBToLinear(m._diffuse.rgb) : m._diffuse.rgb); } -*/!> -float getMaterialOpacity(Material m) { return m._diffuse.a; } -vec3 getMaterialDiffuse(Material m) { return m._diffuse.rgb; } -vec3 getMaterialSpecular(Material m) { return m._specular.rgb; } -float getMaterialShininess(Material m) { return m._specular.a; } <@endif@> diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index c976e5c396..23503ef6fb 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -212,6 +212,9 @@ void SunSkyStage::setSunAmbientSphere(const gpu::SHPointer& sphere) { _sunLight->setAmbientSpherePreset(DEFAULT_AMBIENT_SPHERE); } } +void SunSkyStage::setSunAmbientMap(const gpu::TexturePointer& map) { + _sunLight->setAmbientMap(map); +} void SunSkyStage::setSunDirection(const Vec3& direction) { if (!isSunModelEnabled()) { diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 31772d5e48..d9fa81b16f 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -150,6 +150,7 @@ public: void setSunAmbientIntensity(float intensity) { _sunLight->setAmbientIntensity(intensity); } float getSunAmbientIntensity() const { return getSunLight()->getAmbientIntensity(); } void setSunAmbientSphere(const gpu::SHPointer& sphere); + void setSunAmbientMap(const gpu::TexturePointer& map); // The sun direction is expressed in the world space void setSunDirection(const Vec3& direction); diff --git a/libraries/model/src/model/TextureMap.cpp b/libraries/model/src/model/TextureMap.cpp index cd42419f6a..d0416ec3b5 100755 --- a/libraries/model/src/model/TextureMap.cpp +++ b/libraries/model/src/model/TextureMap.cpp @@ -54,22 +54,38 @@ void TextureMap::setLightmapOffsetScale(float offset, float scale) { gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { QImage image = srcImage; bool validAlpha = false; + bool alphaAsMask = true; + const uint8 OPAQUE_ALPHA = 255; + const uint8 TRANSLUCENT_ALPHA = 0; if (image.hasAlphaChannel()) { + std::map alphaHistogram; + if (image.format() != QImage::Format_ARGB32) { image = image.convertToFormat(QImage::Format_ARGB32); } - // Actual alpha channel? + // Actual alpha channel? create the histogram for (int y = 0; y < image.height(); ++y) { const QRgb* data = reinterpret_cast(image.constScanLine(y)); for (int x = 0; x < image.width(); ++x) { auto alpha = qAlpha(data[x]); - if (alpha != 255) { + alphaHistogram[alpha] ++; + if (alpha != OPAQUE_ALPHA) { validAlpha = true; break; } } } + + // If alpha was meaningfull refine + if (validAlpha && (alphaHistogram.size() > 1)) { + auto totalNumPixels = image.height() * image.width(); + auto numOpaques = alphaHistogram[OPAQUE_ALPHA]; + auto numTranslucents = alphaHistogram[TRANSLUCENT_ALPHA]; + auto numTransparents = totalNumPixels - numOpaques - numTranslucents; + + alphaAsMask = ((numTransparents / (double)totalNumPixels) < 0.05); + } } if (!validAlpha && image.format() != QImage::Format_RGB888) { @@ -89,10 +105,21 @@ gpu::Texture* TextureUsage::create2DTextureFromImage(const QImage& srcImage, con } theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + + auto usage = gpu::Texture::Usage::Builder().withColor(); + if (validAlpha) { + usage.withAlpha(); + if (alphaAsMask) { + usage.withAlphaMask(); + } + } + theTexture->setUsage(usage.build()); + theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); theTexture->autoGenerateMips(-1); // FIXME queue for transfer to GPU and block on completion + } return theTexture; @@ -223,6 +250,99 @@ gpu::Texture* TextureUsage::createNormalTextureFromBumpImage(const QImage& srcIm return theTexture; } +gpu::Texture* TextureUsage::createRoughnessTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + QImage image = srcImage; + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + } + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); + theTexture->autoGenerateMips(-1); + + // FIXME queue for transfer to GPU and block on completion + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createRoughnessTextureFromGlossImage(const QImage& srcImage, const std::string& srcImageName) { + QImage image = srcImage; + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + } + + // Gloss turned into Rough + image.invertPixels(QImage::InvertRgba); + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); + theTexture->autoGenerateMips(-1); + + // FIXME queue for transfer to GPU and block on completion + } + + return theTexture; +} + +gpu::Texture* TextureUsage::createMetallicTextureFromImage(const QImage& srcImage, const std::string& srcImageName) { + QImage image = srcImage; + if (!image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGB888) { + image = image.convertToFormat(QImage::Format_RGB888); + } + } else { + if (image.format() != QImage::Format_ARGB32) { + image = image.convertToFormat(QImage::Format_ARGB32); + } + } + + image = image.convertToFormat(QImage::Format_Grayscale8); + + gpu::Texture* theTexture = nullptr; + if ((image.width() > 0) && (image.height() > 0)) { + + gpu::Element formatGPU = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + gpu::Element formatMip = gpu::Element(gpu::SCALAR, gpu::NUINT8, gpu::RGB); + + theTexture = (gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR))); + theTexture->assignStoredMip(0, formatMip, image.byteCount(), image.constBits()); + theTexture->autoGenerateMips(-1); + + // FIXME queue for transfer to GPU and block on completion + } + + return theTexture; +} + class CubeLayout { public: int _widthRatio = 1; @@ -473,8 +593,8 @@ gpu::Texture* TextureUsage::createCubeTextureFromImage(const QImage& srcImage, c theTexture->assignStoredMipFace(0, formatMip, face.byteCount(), face.constBits(), f); f++; } - - // GEnerate irradiance while we are at it + + // Generate irradiance while we are at it theTexture->generateIrradiance(); } } diff --git a/libraries/model/src/model/TextureMap.h b/libraries/model/src/model/TextureMap.h index 6bc5b8228c..228adb25e6 100755 --- a/libraries/model/src/model/TextureMap.h +++ b/libraries/model/src/model/TextureMap.h @@ -27,13 +27,16 @@ typedef glm::vec3 Color; class TextureUsage { public: gpu::Texture::Type _type{ gpu::Texture::TEX_2D }; - Material::MapFlags _materialUsage{ MaterialKey::DIFFUSE_MAP }; + Material::MapFlags _materialUsage{ MaterialKey::ALBEDO_MAP }; int _environmentUsage = 0; static gpu::Texture* create2DTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createNormalTextureFromNormalImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createNormalTextureFromBumpImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createRoughnessTextureFromImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createRoughnessTextureFromGlossImage(const QImage& image, const std::string& srcImageName); + static gpu::Texture* createMetallicTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createCubeTextureFromImage(const QImage& image, const std::string& srcImageName); static gpu::Texture* createLightmapTextureFromImage(const QImage& image, const std::string& srcImageName); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 06d8709dc5..c9ea223b3f 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -20,6 +20,7 @@ #include "GeometryCache.h" #include "FramebufferCache.h" +#include "TextureCache.h" #include "DeferredLightingEffect.h" #include "debug_deferred_buffer_vert.h" @@ -39,7 +40,7 @@ void DebugDeferredBufferConfig::setMode(int newMode) { } enum Slot { - Diffuse = 0, + Albedo = 0, Normal, Specular, Depth, @@ -52,27 +53,54 @@ enum Slot { -static const std::string DEFAULT_DIFFUSE_SHADER { +static const std::string DEFAULT_ALBEDO_SHADER { "vec4 getFragmentColor() {" - " return vec4(pow(texture(diffuseMap, uv).xyz, vec3(1.0 / 2.2)), 1.0);" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(pow(frag.diffuse, vec3(1.0 / 2.2)), 1.0);" " }" }; -static const std::string DEFAULT_SPECULAR_SHADER { +static const std::string DEFAULT_METALLIC_SHADER { "vec4 getFragmentColor() {" - " return vec4(texture(specularMap, uv).xyz, 1.0);" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(vec3(pow(frag.metallic, 1.0 / 2.2)), 1.0);" " }" }; + static const std::string DEFAULT_ROUGHNESS_SHADER { "vec4 getFragmentColor() {" - " return vec4(vec3(texture(specularMap, uv).a), 1.0);" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(vec3(pow(frag.roughness, 1.0 / 2.2)), 1.0);" " }" }; static const std::string DEFAULT_NORMAL_SHADER { "vec4 getFragmentColor() {" - " return vec4(normalize(texture(normalMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(vec3(0.5) + (frag.normal * 0.5), 1.0);" " }" }; + +static const std::string DEFAULT_OCCLUSION_SHADER{ + "vec4 getFragmentColor() {" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return vec4(vec3(frag.obscurance), 1.0);" + " }" +}; + +static const std::string DEFAULT_EMISSIVE_SHADER{ + "vec4 getFragmentColor() {" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return (frag.mode != LIGHT_MAPPED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" + " }" +}; + +static const std::string DEFAULT_LIGHTMAP_SHADER{ + "vec4 getFragmentColor() {" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return (frag.mode == LIGHT_MAPPED ? vec4(frag.emissive, 1.0) : vec4(vec3(0.0), 1.0));" + " }" +}; + static const std::string DEFAULT_DEPTH_SHADER { "vec4 getFragmentColor() {" " return vec4(vec3(texture(depthMap, uv).x), 1.0);" @@ -105,7 +133,7 @@ static const std::string DEFAULT_PYRAMID_DEPTH_SHADER { static const std::string DEFAULT_AMBIENT_OCCLUSION_SHADER{ "vec4 getFragmentColor() {" - " return vec4(vec3(texture(occlusionMap, uv).x), 1.0);" + " return vec4(vec3(texture(obscuranceMap, uv).x), 1.0);" // When drawing color " return vec4(vec3(texture(occlusionMap, uv).xyz), 1.0);" // when drawing normal " return vec4(normalize(texture(occlusionMap, uv).xyz * 2.0 - vec3(1.0)), 1.0);" " }" @@ -144,16 +172,22 @@ DebugDeferredBuffer::DebugDeferredBuffer() { std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string customFile) { switch (mode) { - case DiffuseMode: - return DEFAULT_DIFFUSE_SHADER; - case SpecularMode: - return DEFAULT_SPECULAR_SHADER; + case AlbedoMode: + return DEFAULT_ALBEDO_SHADER; + case MetallicMode: + return DEFAULT_METALLIC_SHADER; case RoughnessMode: return DEFAULT_ROUGHNESS_SHADER; case NormalMode: return DEFAULT_NORMAL_SHADER; case DepthMode: return DEFAULT_DEPTH_SHADER; + case EmissiveMode: + return DEFAULT_EMISSIVE_SHADER; + case OcclusionMode: + return DEFAULT_OCCLUSION_SHADER; + case LightmapMode: + return DEFAULT_LIGHTMAP_SHADER; case LightingMode: return DEFAULT_LIGHTING_SHADER; case ShadowMode: @@ -206,14 +240,14 @@ const gpu::PipelinePointer& DebugDeferredBuffer::getPipeline(Mode mode, std::str const auto program = gpu::Shader::createProgram(vs, ps); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding("diffuseMap", Diffuse)); + slotBindings.insert(gpu::Shader::Binding("albedoMap", Albedo)); slotBindings.insert(gpu::Shader::Binding("normalMap", Normal)); slotBindings.insert(gpu::Shader::Binding("specularMap", Specular)); slotBindings.insert(gpu::Shader::Binding("depthMap", Depth)); + slotBindings.insert(gpu::Shader::Binding("obscuranceMap", AmbientOcclusion)); slotBindings.insert(gpu::Shader::Binding("lightingMap", Lighting)); slotBindings.insert(gpu::Shader::Binding("shadowMap", Shadow)); slotBindings.insert(gpu::Shader::Binding("pyramidMap", Pyramid)); - slotBindings.insert(gpu::Shader::Binding("occlusionMap", AmbientOcclusion)); slotBindings.insert(gpu::Shader::Binding("occlusionBlurredMap", AmbientOcclusionBlurred)); gpu::Shader::makeProgram(*program, slotBindings); @@ -247,6 +281,7 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { const auto geometryBuffer = DependencyManager::get(); const auto framebufferCache = DependencyManager::get(); + const auto textureCache = DependencyManager::get(); const auto& lightStage = DependencyManager::get()->getLightStage(); glm::mat4 projMat; @@ -262,14 +297,19 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren batch.setPipeline(getPipeline(_mode, first)); - batch.setResourceTexture(Diffuse, framebufferCache->getDeferredColorTexture()); + batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture()); batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture()); batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture()); batch.setResourceTexture(Depth, framebufferCache->getPrimaryDepthTexture()); batch.setResourceTexture(Lighting, framebufferCache->getLightingTexture()); batch.setResourceTexture(Shadow, lightStage.lights[0]->shadow.framebuffer->getDepthStencilBuffer()); batch.setResourceTexture(Pyramid, framebufferCache->getDepthPyramidTexture()); - batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture()); + if (DependencyManager::get()->isAmbientOcclusionEnabled()) { + batch.setResourceTexture(AmbientOcclusion, framebufferCache->getOcclusionTexture()); + } else { + // need to assign the white texture if ao is off + batch.setResourceTexture(AmbientOcclusion, textureCache->getWhiteTexture()); + } batch.setResourceTexture(AmbientOcclusionBlurred, framebufferCache->getOcclusionBlurredTexture()); const glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index b31985d6a3..f00dd58f0e 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -47,11 +47,14 @@ protected: enum Mode : uint8_t { // Use Mode suffix to avoid collisions - DiffuseMode = 0, - SpecularMode, - RoughnessMode, + DepthMode = 0, + AlbedoMode, NormalMode, - DepthMode, + RoughnessMode, + MetallicMode, + EmissiveMode, + OcclusionMode, + LightmapMode, LightingMode, ShadowMode, PyramidDepthMode, diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 3f9aef6dd1..5a3c941ce3 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -12,8 +12,8 @@ <@def DEFERRED_BUFFER_SLH@> -// the diffuse texture -uniform sampler2D diffuseMap; +// the albedo texture +uniform sampler2D albedoMap; // the normal texture uniform sampler2D normalMap; @@ -34,8 +34,8 @@ uniform sampler2D lightingMap; struct DeferredTransform { mat4 projection; mat4 viewInverse; - - vec4 stereoSide_spareABC; + float stereoSide; + vec3 _spareABC; }; layout(std140) uniform deferredTransformBuffer { @@ -46,10 +46,10 @@ DeferredTransform getDeferredTransform() { } bool getStereoMode(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide_spareABC.x != 0.0); + return (deferredTransform.stereoSide != 0.0); } float getStereoSide(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide_spareABC.x); + return (deferredTransform.stereoSide); } vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { @@ -64,52 +64,82 @@ vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, v } struct DeferredFragment { - float depthVal; vec4 normalVal; vec4 diffuseVal; vec4 specularVal; vec4 position; vec3 normal; + float metallic; vec3 diffuse; float obscurance; vec3 specular; - float gloss; + float roughness; + vec3 emissive; int mode; + float depthVal; }; const int LIGHT_MAPPED = 1; -DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) { - DeferredFragment frag; - frag.depthVal = texture(depthMap, texcoord).r; - frag.normalVal = texture(normalMap, texcoord); - frag.diffuseVal = texture(diffuseMap, texcoord); - frag.specularVal = texture(specularMap, texcoord); - frag.obscurance = texture(obscuranceMap, texcoord).x; - +vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) { if (getStereoMode(deferredTransform)) { if (texcoord.x > 0.5) { texcoord.x -= 0.5; } texcoord.x *= 2.0; } - frag.position = evalEyePositionFromZ(deferredTransform, frag.depthVal, texcoord); + return evalEyePositionFromZ(deferredTransform, depthValue, texcoord); +} + +DeferredFragment unpackDeferredFragmentNoPosition(vec2 texcoord) { + + DeferredFragment frag; + frag.depthVal = -1; + frag.normalVal = texture(normalMap, texcoord); + frag.diffuseVal = texture(albedoMap, texcoord); + frag.specularVal = texture(specularMap, texcoord); + frag.obscurance = texture(obscuranceMap, texcoord).x; // Unpack the normal from the map frag.normal = normalize(frag.normalVal.xyz * 2.0 - vec3(1.0)); frag.mode = 0; - if ((frag.normalVal.a >= 0.45) && (frag.normalVal.a <= 0.55)) { + frag.emissive = frag.specularVal.xyz; + if (frag.normalVal.a < 0.5) { + frag.mode = 0; + frag.roughness = 2.0 * frag.normalVal.a; + } else { frag.mode = LIGHT_MAPPED; + frag.roughness = 2.0 * frag.normalVal.a - 1.0; } + frag.metallic = frag.diffuseVal.a; frag.diffuse = frag.diffuseVal.xyz; - frag.specular = frag.specularVal.xyz; - frag.gloss = frag.specularVal.w; + if (frag.metallic <= 0.5) { + frag.metallic = 0.0; + frag.specular = vec3(0.03); // Default Di-electric fresnel value + } else { + frag.specular = vec3(frag.diffuseVal.xyz); + frag.metallic = 1.0; + } + frag.obscurance = min(frag.specularVal.w, frag.obscurance); + return frag; +} + +DeferredFragment unpackDeferredFragment(DeferredTransform deferredTransform, vec2 texcoord) { + + float depthValue = texture(depthMap, texcoord).r; + + DeferredFragment frag = unpackDeferredFragmentNoPosition(texcoord); + + frag.depthVal = depthValue; + frag.position = unpackDeferredPosition(deferredTransform, frag.depthVal, texcoord); return frag; } + + <@endif@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 1045c4afc7..2a2c2883d3 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -40,37 +40,41 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold)); } -const vec3 DEFAULT_SPECULAR = vec3(0.1); +const float DEFAULT_ROUGHNESS = 0.9; const float DEFAULT_SHININESS = 10; +const float DEFAULT_METALLIC = 0; +const vec3 DEFAULT_SPECULAR = vec3(0.1); +const vec3 DEFAULT_EMISSIVE = vec3(0.0); +const float DEFAULT_OCCLUSION = 1.0; -void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { + +void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) { if (alpha != 1.0) { discard; } - - _fragColor0 = vec4(diffuse.rgb, 1.0); // Opaque - _fragColor1 = vec4(bestFitNormal(normal), 1.0); - _fragColor2 = vec4(specular, shininess / 128.0); + _fragColor0 = vec4(albedo, metallic); + _fragColor1 = vec4(bestFitNormal(normal), 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor2 = vec4(emissive, occlusion); } -void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) { + +void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 fresnel, vec3 emissive) { if (alpha != 1.0) { discard; } - - _fragColor0 = vec4(diffuse.rgb, 0.5); - _fragColor1 = vec4(bestFitNormal(normal), 0.5); - _fragColor2 = vec4(emissive, shininess / 128.0); + _fragColor0 = vec4(albedo, metallic); + _fragColor1 = vec4(bestFitNormal(normal), 0.5 + 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor2 = vec4(emissive, 1.0); } -void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { +void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) { if (alpha <= 0.0) { discard; } - _fragColor0 = vec4(diffuse.rgb, alpha); + _fragColor0 = vec4(albedo.rgb, alpha); // _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - // _fragColor2 = vec4(specular, shininess / 128.0); + // _fragColor2 = vec4(fresnel, roughness); } <@endif@> diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 71c533de24..71bc2dc6d0 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -11,109 +11,116 @@ <@if not DEFERRED_GLOBAL_LIGHT_SLH@> <@def DEFERRED_GLOBAL_LIGHT_SLH@> +<@include model/Light.slh@> <@include DeferredLighting.slh@> <@func declareSkyboxMap()@> - +// declareSkyboxMap uniform samplerCube skyboxMap; vec4 evalSkyboxLight(vec3 direction, float lod) { - // FIXME - //vec4 skytexel = textureLod(skyboxMap, direction, lod * textureQueryLevels(skyboxMap)); - vec4 skytexel = texture(skyboxMap, direction); - return skytexel; + // textureQueryLevels is not available until #430, so we require explicit lod + // float mipmapLevel = lod * textureQueryLevels(skyboxMap); + return textureLod(skyboxMap, direction, lod); } - <@endfunc@> -// Everything about light -<@include model/Light.slh@> +<@func prepareGlobalLight()@> + // prepareGlobalLight + + // Transform directions to worldspace + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + vec3 fragEyeVector = vec3(invViewMat * vec4(-position, 0.0)); + vec3 fragEyeDir = normalize(fragEyeVector); + + // Get light + Light light = getLight(); + vec3 fresnel = vec3(0.03); // Default Di-electric fresnel value + if (metallic > 0.5) { + fresnel = albedo; + metallic = 1.0; + } + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, fresnel, roughness); + vec3 color = vec3(albedo * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light); + color += emissive; +<@endfunc@> + +<@func declareAmbientFresnel()@> +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); +} +<@endfunc@> <@func declareEvalAmbientGlobalColor()@> -vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { - - // Need the light now - Light light = getLight(); - - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); - vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); - vec3 fragEyeDir = normalize(fragEyeVector.xyz); - - vec3 color = diffuse.rgb * getLightColor(light) * obscurance * getLightAmbientIntensity(light); - - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - - color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light); - +vec3 evalAmbientGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { + <$prepareGlobalLight()$> + color += albedo * getLightColor(light) * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalAmbientSphereGlobalColor()@> +<$declareAmbientFresnel()$> -vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { - // Need the light now - Light light = getLight(); - - vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0))); - vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); - vec3 fragEyeDir = normalize(fragEyeVector.xyz); - - vec3 ambientNormal = fragNormal.xyz; - vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), ambientNormal).xyz * obscurance * getLightAmbientIntensity(light); +vec3 evalAmbientSphereGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { + <$prepareGlobalLight()$> - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + // Diffuse from ambient + color += (1 - metallic) * albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light); - color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light); + // Specular highlight from ambient + vec3 direction = -reflect(fragEyeDir, fragNormal); + vec3 skyboxLight = evalSphericalLight(getLightAmbientSphere(light), direction).xyz; + vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, fragEyeDir, fragNormal, 1 - roughness); + color += ambientFresnel * skyboxLight.rgb * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalSkyboxGlobalColor()@> - <$declareSkyboxMap()$> +<$declareAmbientFresnel()$> -vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { - // Need the light now - Light light = getLight(); - - vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0))); - vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); - vec3 fragEyeDir = normalize(fragEyeVector.xyz); - - vec3 color = diffuse.rgb * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light); +vec3 evalSkyboxGlobalColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 emissive, float roughness) { + <$prepareGlobalLight()$> - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + // Diffuse from ambient + color += (1 - metallic) * albedo * evalSphericalLight(getLightAmbientSphere(light), fragNormal).xyz * obscurance * getLightAmbientIntensity(light); - color += vec3(diffuse * shading.w + shading.rgb) * min(shadowAttenuation, obscurance) * getLightColor(light) * getLightIntensity(light); + // Specular highlight from ambient + vec3 direction = -reflect(fragEyeDir, fragNormal); + float levels = getLightAmbientMapNumMips(light); + float lod = min(floor((roughness) * levels), levels); + vec4 skyboxLight = evalSkyboxLight(direction, lod); + vec3 ambientFresnel = fresnelSchlickAmbient(fresnel, fragEyeDir, fragNormal, 1 - roughness); + color += ambientFresnel * skyboxLight.rgb * obscurance * getLightAmbientIntensity(light); return color; } <@endfunc@> <@func declareEvalLightmappedColor()@> -vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 diffuse, vec3 lightmap) { - +vec3 evalLightmappedColor(mat4 invViewMat, float shadowAttenuation, float obscurance, vec3 normal, vec3 albedo, vec3 lightmap) { Light light = getLight(); - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); - float diffuseDot = dot(fragNormal, -getLightDirection(light)); - - // need to catch normals perpendicular to the projection plane hence the magic number for the threshold - // it should be just 0, but we have innacurracy so we need to overshoot + // Catch normals perpendicular to the projection plane, hence the magic number for the threshold + // It should be just 0, but we have inaccuracy so we overshoot const float PERPENDICULAR_THRESHOLD = -0.005; + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); // transform to worldspace + float diffuseDot = dot(fragNormal, -getLightDirection(light)); float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); - //float facingLight = step(PERPENDICULAR_THRESHOLD, diffuseDot); - // evaluate the shadow test but only relevant for light facing fragments + + // Reevaluate the shadow attenuation for light facing fragments float lightAttenuation = (1 - facingLight) + facingLight * shadowAttenuation; - // diffuse light is the lightmap dimmed by shadow + + // Diffuse light is the lightmap dimmed by shadow vec3 diffuseLight = lightAttenuation * lightmap; - // ambient is a tiny percentage of the lightmap and only when in the shadow + // Ambient light is the lightmap when in shadow vec3 ambientLight = (1 - lightAttenuation) * lightmap * getLightAmbientIntensity(light); - return obscurance * diffuse * (ambientLight + diffuseLight); + return obscurance * albedo * (diffuseLight + ambientLight); } <@endfunc@> diff --git a/libraries/render-utils/src/DeferredLighting.slh b/libraries/render-utils/src/DeferredLighting.slh index cf03861c2f..2e06deb0af 100755 --- a/libraries/render-utils/src/DeferredLighting.slh +++ b/libraries/render-utils/src/DeferredLighting.slh @@ -13,41 +13,55 @@ <@func declareEvalPBRShading()@> + +vec3 fresnelSchlick(vec3 fresnelColor, vec3 lightDir, vec3 halfDir) { + return fresnelColor + (1.0 - fresnelColor) * pow(1.0 - clamp(dot(lightDir, halfDir), 0.0, 1.0), 5); +} + +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 denom = (ndoth * ndoth*(gloss2 - 1) + 1); + float power = gloss2 / (3.14159 * denom * denom); + return power; +} + // Frag Shading returns the diffuse amount as W and the specular rgb as xyz -vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { +vec4 evalPBRShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 fresnel, float roughness) { // Diffuse Lighting - float diffuseDot = dot(fragNormal, fragLightDir); - float facingLight = step(0.0, diffuseDot); - float diffuse = diffuseDot * facingLight; - - // Specular Lighting depends on the half vector and the gloss + float diffuse = clamp(dot(fragNormal, fragLightDir), 0.0, 1.0); + + // Specular Lighting vec3 halfDir = normalize(fragEyeDir + fragLightDir); + vec3 fresnelColor = fresnelSchlick(fresnel, fragLightDir,halfDir); + float power = specularDistribution(roughness, fragNormal, halfDir); + vec3 specular = power * fresnelColor * diffuse; - float specularPower = pow(max(0.0, dot(halfDir, fragNormal)), gloss * 128.0); - specularPower *= (gloss * 128.0 * 0.125 + 0.25); - - float shlickPower = (1.0 - dot(fragLightDir,halfDir)); - float shlickPower2 = shlickPower * shlickPower; - float shlickPower5 = shlickPower2 * shlickPower2 * shlickPower; - vec3 fresnel = specular * (1.0 - shlickPower5) + vec3(shlickPower5); - vec3 reflect = specularPower * fresnel * diffuse; - - return vec4(reflect, diffuse * (1 - fresnel.x)); + return vec4(specular, (1.0 - metallic) * diffuse * (1 - fresnelColor.x)); } <@endfunc@> <@func declareEvalBlinnRShading()@> -vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { +vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float roughness) { // Diffuse Lighting float diffuseDot = dot(fragNormal, fragLightDir); float facingLight = step(0.0, diffuseDot); float diffuse = diffuseDot * facingLight; - // Specular Lighting depends on the half vector and the gloss + // Specular Lighting depends on the half vector and the roughness vec3 halfDir = normalize(fragEyeDir + fragLightDir); - float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss * 128.0); + float gloss = (1.0 - roughness) * 128.0; + glos *= gloss; + float specularPower = pow(facingLight * max(0.0, dot(halfDir, fragNormal)), gloss); vec3 reflect = specularPower * specular * diffuse; return vec4(reflect, diffuse); @@ -59,8 +73,8 @@ vec4 evalBlinnShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 <$declareEvalPBRShading()$> // Return xyz the specular/reflection component and w the diffuse component -vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, vec3 specular, float gloss) { - return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, specular, gloss); +vec4 evalFragShading(vec3 fragNormal, vec3 fragLightDir, vec3 fragEyeDir, float metallic, vec3 specular, float roughness) { + return evalPBRShading(fragNormal, fragLightDir, fragEyeDir, metallic, specular, roughness); } <@endif@> diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index c1c7240f20..82bd0e73d0 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -92,6 +92,11 @@ void DeferredLightingEffect::init() { // Add the global light to the light stage (for later shadow rendering) _lightStage.addLight(lp); + lp->setDirection(glm::vec3(-1.0f)); + lp->setColor(glm::vec3(1.0f)); + lp->setIntensity(1.0f); + lp->setType(model::Light::SUN); + lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE); } void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color, @@ -311,22 +316,23 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo { auto& program = _shadowMapEnabled ? _directionalLightShadow : _directionalLight; LightLocationsPtr locations = _shadowMapEnabled ? _directionalLightShadowLocations : _directionalLightLocations; + const auto& keyLight = _allocatedLights[_globalLights.front()]; // Setup the global directional pass pipeline { if (_shadowMapEnabled) { - if (_skyboxTexture) { + if (keyLight->getAmbientMap()) { program = _directionalSkyboxLightShadow; locations = _directionalSkyboxLightShadowLocations; - } else if (_ambientLightMode > -1) { + } else { program = _directionalAmbientSphereLightShadow; locations = _directionalAmbientSphereLightShadowLocations; } } else { - if (_skyboxTexture) { + if (keyLight->getAmbientMap()) { program = _directionalSkyboxLight; locations = _directionalSkyboxLightLocations; - } else if (_ambientLightMode > -1) { + } else { program = _directionalAmbientSphereLight; locations = _directionalAmbientSphereLightLocations; } @@ -351,7 +357,7 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo geometryCache->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color); } - if (_skyboxTexture) { + if (keyLight->getAmbientMap()) { batch.setResourceTexture(SKYBOX_MAP_UNIT, nullptr); } } @@ -490,14 +496,14 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit) { PerformanceTimer perfTimer("DLE->setupBatch()"); - auto globalLight = _allocatedLights[_globalLights.front()]; + auto keyLight = _allocatedLights[_globalLights.front()]; if (lightBufferUnit >= 0) { - batch.setUniformBuffer(lightBufferUnit, globalLight->getSchemaBuffer()); + batch.setUniformBuffer(lightBufferUnit, keyLight->getSchemaBuffer()); } - if (_skyboxTexture && (skyboxCubemapUnit >= 0)) { - batch.setResourceTexture(skyboxCubemapUnit, _skyboxTexture); + if (keyLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { + batch.setResourceTexture(skyboxCubemapUnit, keyLight->getAmbientMap()); } } @@ -508,7 +514,7 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo gpu::ShaderPointer program = gpu::Shader::createProgram(VS, PS); gpu::Shader::BindingSet slotBindings; - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), DEFERRED_BUFFER_COLOR_UNIT)); + slotBindings.insert(gpu::Shader::Binding(std::string("colorMap"), DEFERRED_BUFFER_COLOR_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), DEFERRED_BUFFER_NORMAL_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), DEFERRED_BUFFER_EMISSIVE_UNIT)); slotBindings.insert(gpu::Shader::Binding(std::string("depthMap"), DEFERRED_BUFFER_DEPTH_UNIT)); @@ -556,15 +562,14 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo } -void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light, const gpu::TexturePointer& skyboxTexture) { +void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { auto globalLight = _allocatedLights.front(); globalLight->setDirection(light->getDirection()); globalLight->setColor(light->getColor()); globalLight->setIntensity(light->getIntensity()); globalLight->setAmbientIntensity(light->getAmbientIntensity()); globalLight->setAmbientSphere(light->getAmbientSphere()); - - _skyboxTexture = skyboxTexture; + globalLight->setAmbientMap(light->getAmbientMap()); } model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 75cefc277d..63d8f4d175 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -49,11 +49,12 @@ public: void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int skyboxCubemapUnit); // update global lighting - void setGlobalLight(const model::LightPointer& light, const gpu::TexturePointer& skyboxTexture); + void setGlobalLight(const model::LightPointer& light); const LightStage& getLightStage() { return _lightStage; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } + bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } private: DeferredLightingEffect() = default; @@ -95,15 +96,12 @@ private: std::vector _pointLights; std::vector _spotLights; - int _ambientLightMode = 0; - gpu::TexturePointer _skyboxTexture; - // Class describing the uniform buffer with all the parameters common to the deferred shaders class DeferredTransform { public: glm::mat4 projection; glm::mat4 viewInverse; - float stereoSide{ 0.f }; + float stereoSide { 0.f }; float spareA, spareB, spareC; DeferredTransform() {} diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 756e18dc8b..82a92f572e 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -506,7 +506,7 @@ GeometryCache::GeometryCache() : std::make_shared(getSimplePipeline(), nullptr, [](const render::ShapePipeline&, gpu::Batch& batch) { // Set the defaults needed for a simple program - batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP, + batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP, DependencyManager::get()->getWhiteTexture()); batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP, DependencyManager::get()->getNormalFittingTexture()); @@ -1734,9 +1734,9 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emissive, bool depthBiased) { batch.setPipeline(getSimplePipeline(textured, culled, emissive, depthBiased)); - // If not textured, set a default diffuse map + // If not textured, set a default albedo map if (!textured) { - batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP, + batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP, DependencyManager::get()->getWhiteTexture()); } // Set a default normal map diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh new file mode 100644 index 0000000000..8904ae34b2 --- /dev/null +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -0,0 +1,139 @@ + +<@if not MODEL_MATERIAL_TEXTURES_SLH@> +<@def MODEL_MATERIAL_TEXTURES_SLH@> + +<@func declareMaterialTextures(withAlbedo, withRoughness, withNormal, withMetallic, withEmissive, withOcclusion)@> + +<@if withAlbedo@> +uniform sampler2D albedoMap; +vec4 fetchAlbedoMap(vec2 uv) { + return texture(albedoMap, uv); +} +<@endif@> + +<@if withRoughness@> +uniform sampler2D roughnessMap; +float fetchRoughnessMap(vec2 uv) { + return (texture(roughnessMap, uv).r); +} +<@endif@> + +<@if withNormal@> +uniform sampler2D normalMap; +vec3 fetchNormalMap(vec2 uv) { + return texture(normalMap, uv).xyz; +} +<@endif@> + +<@if withMetallic@> +uniform sampler2D metallicMap; +float fetchMetallicMap(vec2 uv) { + return (texture(metallicMap, uv).r); +} +<@endif@> + +<@if withEmissive@> +uniform sampler2D emissiveMap; +vec3 fetchEmissiveMap(vec2 uv) { + return texture(emissiveMap, uv).rgb; +} +<@endif@> + +<@if withOcclusion@> +uniform sampler2D occlusionMap; +float fetchOcclusionMap(vec2 uv) { + return texture(occlusionMap, uv).r; +} +<@endif@> +<@endfunc@> + + +<@func fetchMaterialTextures(matKey, texcoord0, albedo, roughness, normal, metallic, emissive, occlusion)@> +<@if albedo@> + vec4 <$albedo$> = (((<$matKey$> & ALBEDO_MAP_BIT) != 0) ? fetchAlbedoMap(<$texcoord0$>) : vec4(1.0)); +<@endif@> +<@if roughness@> + float <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? fetchRoughnessMap(<$texcoord0$>) : 1.0); +<@endif@> +<@if normal@> + vec3 <$normal$> = (((<$matKey$> & NORMAL_MAP_BIT) != 0) ? fetchNormalMap(<$texcoord0$>) : vec3(0.0, 1.0, 0.0)); +<@endif@> +<@if metallic@> + float <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? fetchMetallicMap(<$texcoord0$>) : 0.0); +<@endif@> +<@if emissive@> + vec3 <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? fetchEmissiveMap(<$texcoord0$>) : vec3(0.0)); +<@endif@> +<@if occlusion@> + float <$occlusion$> = (((<$matKey$> & OCCLUSION_MAP_BIT) != 0) ? fetchOcclusionMap(<$texcoord0$>) : 1.0); +<@endif@> +<@endfunc@> + + +<@func declareMaterialLightmap()@> +uniform sampler2D emissiveMap; +uniform vec2 emissiveParams; +vec3 fetchLightmapMap(vec2 uv) { + return (vec3(emissiveParams.x) + emissiveParams.y * texture(emissiveMap, uv).rgb); +} +<@endfunc@> + +<@func fetchMaterialLightmap(texcoord1, lightmapVal)@> + vec3 <$lightmapVal$> = fetchLightmapMap(<$texcoord1$>); +<@endfunc@> + + +<@func tangentToViewSpace(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> +{ + vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz); + vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz); + vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 localNormal = normalize(<$fetchedNormal$> - vec3(0.5, 0.5, 0.5)); + <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z); +} +<@endfunc@> + +<@func evalMaterialAlbedo(fetchedAlbedo, materialAlbedo, matKey, albedo)@> +{ + <$albedo$>.xyz = (((<$matKey$> & ALBEDO_VAL_BIT) != 0) ? <$materialAlbedo$> : vec3(1.0)); + + if (((<$matKey$> & ALBEDO_MAP_BIT) != 0)) { + <$albedo$>.xyz *= <$fetchedAlbedo$>.xyz; + } +} +<@endfunc@> + +<@func evalMaterialRoughness(fetchedRoughness, materialRoughness, matKey, roughness)@> +{ + <$roughness$> = (((<$matKey$> & ROUGHNESS_MAP_BIT) != 0) ? <$fetchedRoughness$> : <$materialRoughness$>); +} +<@endfunc@> + +<@func evalMaterialMetallic(fetchedMetallic, materialMetallic, matKey, metallic)@> +{ + <$metallic$> = (((<$matKey$> & METALLIC_MAP_BIT) != 0) ? <$fetchedMetallic$> : <$materialMetallic$>); +} +<@endfunc@> + +<@func evalMaterialEmissive(fetchedEmissive, materialEmissive, matKey, emissive)@> +{ + <$emissive$> = (((<$matKey$> & EMISSIVE_MAP_BIT) != 0) ? <$fetchedEmissive$> : <$materialEmissive$>); +} +<@endfunc@> + +<@func evalMaterialOcclusion(fetchedOcclusion, matKey, occlusion)@> +{ + <$occlusion$> = <$fetchedOcclusion$>; +} +<@endfunc@> + +<@endif@> \ No newline at end of file diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e5a313e3b1..166b14333f 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -106,7 +106,7 @@ ShapeKey MeshPartPayload::getShapeKey() const { if (drawMaterialKey.isNormalMap()) { builder.withTangents(); } - if (drawMaterialKey.isGlossMap()) { + if (drawMaterialKey.isMetallicMap()) { builder.withSpecular(); } if (drawMaterialKey.isLightmapMap()) { @@ -145,20 +145,34 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto textureMaps = _drawMaterial->getTextureMaps(); glm::mat4 texcoordTransform[2]; - // Diffuse - if (materialKey.isDiffuseMap()) { - auto diffuseMap = textureMaps[model::MaterialKey::DIFFUSE_MAP]; - if (diffuseMap && diffuseMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, diffuseMap->getTextureView()); + // Albedo + if (materialKey.isAlbedoMap()) { + auto albedoMap = textureMaps[model::MaterialKey::ALBEDO_MAP]; + if (albedoMap && albedoMap->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, albedoMap->getTextureView()); - if (!diffuseMap->getTextureTransform().isIdentity()) { - diffuseMap->getTextureTransform().getMatrix(texcoordTransform[0]); + if (!albedoMap->getTextureTransform().isIdentity()) { + albedoMap->getTextureTransform().getMatrix(texcoordTransform[0]); } } else { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, textureCache->getGrayTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::DIFFUSE_MAP, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO_MAP, textureCache->getWhiteTexture()); + } + + // Roughness map + if (materialKey.isRoughnessMap()) { + auto roughnessMap = textureMaps[model::MaterialKey::ROUGHNESS_MAP]; + if (roughnessMap && roughnessMap->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, roughnessMap->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, textureCache->getWhiteTexture()); + } + } else { + batch.setResourceTexture(ShapePipeline::Slot::ROUGHNESS_MAP, textureCache->getWhiteTexture()); } // Normal map @@ -167,7 +181,7 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat if (normalMap && normalMap->isDefined()) { batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, normalMap->getTextureView()); - // texcoord are assumed to be the same has diffuse + // texcoord are assumed to be the same has albedo } else { batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, textureCache->getBlueTexture()); } @@ -175,26 +189,40 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat batch.setResourceTexture(ShapePipeline::Slot::NORMAL_MAP, nullptr); } - // TODO: For now gloss map is used as the "specular map in the shading, we ll need to fix that - if (materialKey.isGlossMap()) { - auto specularMap = textureMaps[model::MaterialKey::GLOSS_MAP]; + // Metallic map + if (materialKey.isMetallicMap()) { + auto specularMap = textureMaps[model::MaterialKey::METALLIC_MAP]; if (specularMap && specularMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, specularMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, specularMap->getTextureView()); - // texcoord are assumed to be the same has diffuse + // texcoord are assumed to be the same has albedo } else { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, textureCache->getBlackTexture()); + batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::SPECULAR_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::METALLIC_MAP, nullptr); } - // TODO: For now lightmaop is piped into the emissive map unit, we need to fix that and support for real emissive too + // Occlusion map + if (materialKey.isOcclusionMap()) { + auto specularMap = textureMaps[model::MaterialKey::OCCLUSION_MAP]; + if (specularMap && specularMap->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, specularMap->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, textureCache->getWhiteTexture()); + } + } else { + batch.setResourceTexture(ShapePipeline::Slot::OCCLUSION_MAP, nullptr); + } + + // Emissive / Lightmap if (materialKey.isLightmapMap()) { auto lightmapMap = textureMaps[model::MaterialKey::LIGHTMAP_MAP]; if (lightmapMap && lightmapMap->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, lightmapMap->getTextureView()); + batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, lightmapMap->getTextureView()); auto lightmapOffsetScale = lightmapMap->getLightmapOffsetScale(); batch._glUniform2f(locations->emissiveParams, lightmapOffsetScale.x, lightmapOffsetScale.y); @@ -203,10 +231,18 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat lightmapMap->getTextureTransform().getMatrix(texcoordTransform[1]); } } else { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, textureCache->getGrayTexture()); + batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getGrayTexture()); + } + } else if (materialKey.isEmissiveMap()) { + auto emissiveMap = textureMaps[model::MaterialKey::EMISSIVE_MAP]; + + if (emissiveMap && emissiveMap->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, emissiveMap->getTextureView()); + } else { + batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, textureCache->getBlackTexture()); } } else { - batch.setResourceTexture(ShapePipeline::Slot::LIGHTMAP_MAP, nullptr); + batch.setResourceTexture(ShapePipeline::Slot::EMISSIVE_LIGHTMAP_MAP, nullptr); } // Texcoord transforms ? @@ -378,7 +414,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { bool isTranslucent = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap(); bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); - bool hasSpecular = drawMaterialKey.isGlossMap(); + bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isSkinned = _isSkinned; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c29c37140e..ce6dfd6849 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1205,9 +1205,9 @@ void Model::segregateMeshGroups() { if (showingCollisionHull) { if (!_collisionHullMaterial) { _collisionHullMaterial = std::make_shared(); - _collisionHullMaterial->setDiffuse(glm::vec3(1.0f, 0.5f, 0.0f)); + _collisionHullMaterial->setAlbedo(glm::vec3(1.0f, 0.5f, 0.0f)); _collisionHullMaterial->setMetallic(0.02f); - _collisionHullMaterial->setGloss(1.0f); + _collisionHullMaterial->setRoughness(0.5f); } _renderItemsSet << std::make_shared(networkMesh._mesh, partIndex, _collisionHullMaterial, transform, offset); } else { diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 0954c7ef83..aa0f9dc7d9 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -66,16 +66,16 @@ void initStencilPipeline(gpu::PipelinePointer& pipeline) { gpu::BufferView getDefaultMaterialBuffer() { model::Material::Schema schema; - schema._diffuse = vec3(1.0f); + schema._albedo = vec3(1.0f); schema._opacity = 1.0f; - schema._metallic = vec3(0.1f); - schema._gloss = 10.0f; + schema._metallic = 0.1f; + schema._roughness = 0.9f; return gpu::BufferView(std::make_shared(sizeof(model::Material::Schema), (const gpu::Byte*) &schema)); } void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { - // Set a default diffuse map - batch.setResourceTexture(render::ShapePipeline::Slot::DIFFUSE_MAP, + // Set a default albedo map + batch.setResourceTexture(render::ShapePipeline::Slot::ALBEDO_MAP, DependencyManager::get()->getWhiteTexture()); // Set a default normal map batch.setResourceTexture(render::ShapePipeline::Slot::NORMAL_FITTING_MAP, diff --git a/libraries/render-utils/src/animdebugdraw.slv b/libraries/render-utils/src/animdebugdraw.slv index 3cb356c055..ffa44b6cee 100644 --- a/libraries/render-utils/src/animdebugdraw.slv +++ b/libraries/render-utils/src/animdebugdraw.slv @@ -16,7 +16,7 @@ out vec4 _color; void main(void) { - // pass along the diffuse color + // pass along the color _color = colorToLinearRGBA(inColor.rgba); TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index 3d1b9db46c..e1ec0d3ef0 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -44,8 +44,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index ffe0e21851..963a10d579 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -46,8 +46,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index e07c57a905..1a739f9389 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -45,8 +45,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_light_shadow.slf b/libraries/render-utils/src/directional_light_shadow.slf index 4aa041b847..3b9b4d22c6 100644 --- a/libraries/render-utils/src/directional_light_shadow.slf +++ b/libraries/render-utils/src/directional_light_shadow.slf @@ -47,8 +47,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } } diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 78fdc4e234..9e24a5f585 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -45,8 +45,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index bbce15be68..c3008b5509 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -47,8 +47,9 @@ void main(void) { frag.position.xyz, frag.normal, frag.diffuse, - frag.specular, - frag.gloss); + frag.metallic, + frag.emissive, + frag.roughness); _fragColor = vec4(color, frag.normalVal.a); } diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index f455030f6f..c9ca6d9eb7 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -15,8 +15,8 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> in vec4 _position; in vec3 _normal; @@ -25,15 +25,26 @@ in vec2 _texCoord0; void main(void) { - // Fetch diffuse map - vec4 diffuse = texture(diffuseMap, _texCoord0); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; packDeferredFragment( normalize(_normal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - getMaterialSpecular(mat), - getMaterialShininess(mat)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex); } diff --git a/libraries/render-utils/src/model_emissive.slf b/libraries/render-utils/src/model_emissive.slf index 25239691cd..471e613eb4 100644 --- a/libraries/render-utils/src/model_emissive.slf +++ b/libraries/render-utils/src/model_emissive.slf @@ -15,7 +15,7 @@ <@include DeferredBufferWrite.slh@> <@include model/Material.slh@> -uniform sampler2D diffuseMap; +uniform sampler2D albedoMap; in vec2 _texCoord0; in vec3 _normal; @@ -23,16 +23,17 @@ in vec3 _color; in float _alpha; void main(void) { - vec4 texel = texture(diffuseMap, _texCoord0); + vec4 texel = texture(albedoMap, _texCoord0); Material mat = getMaterial(); - vec3 fragColor = getMaterialDiffuse(mat) * texel.rgb * _color; + vec3 fragColor = getMaterialAlbedo(mat) * texel.rgb * _color; packDeferredFragmentLightmap( normalize(_normal), texel.a, vec3(1.0), - getMaterialSpecular(mat), - getMaterialShininess(mat), + getMaterialRoughness(mat), + getMaterialMetallic(mat), + getMaterialFresnel(mat), fragColor); } diff --git a/libraries/render-utils/src/model_lightmap.slf b/libraries/render-utils/src/model_lightmap.slf index ab92d2bf4c..46d81d39e1 100755 --- a/libraries/render-utils/src/model_lightmap.slf +++ b/libraries/render-utils/src/model_lightmap.slf @@ -16,12 +16,9 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the emissive map texture and parameters -uniform sampler2D emissiveMap; -uniform vec2 emissiveParams; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS)$> +<$declareMaterialLightmap()$> in vec4 _position; in vec2 _texCoord0; @@ -30,16 +27,18 @@ in vec3 _normal; in vec3 _color; void main(void) { - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec4 emissive = texture(emissiveMap, _texCoord1); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness)$> + <$fetchMaterialLightmap(_texCoord1, emissive)$> + packDeferredFragmentLightmap( normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - getMaterialSpecular(mat), - getMaterialShininess(mat), + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat), + getMaterialFresnel(mat), (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); } diff --git a/libraries/render-utils/src/model_lightmap.slv b/libraries/render-utils/src/model_lightmap.slv index eacc91245c..8696b70373 100755 --- a/libraries/render-utils/src/model_lightmap.slv +++ b/libraries/render-utils/src/model_lightmap.slv @@ -28,7 +28,7 @@ out vec3 _normal; out vec3 _color; void main(void) { - // pass along the diffuse color in linear space + // pass along the color in linear space _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 78c802be51..9ccc6e5352 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -16,15 +16,9 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal map texture -uniform sampler2D normalMap; - -// the emissive map texture and parameters -uniform sampler2D emissiveMap; -uniform vec2 emissiveParams; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL)$> +<$declareMaterialLightmap()$> in vec4 _position; in vec2 _texCoord0; @@ -34,25 +28,20 @@ in vec3 _tangent; in vec3 _color; void main(void) { - // compute the view normal from the various bits - vec3 normalizedNormal = normalize(_normal); - vec3 normalizedTangent = normalize(_tangent); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5); - vec4 viewNormal = vec4(normalizedTangent * localNormal.x + - normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); - - // set the diffuse, normal, specular data - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec4 emissive = texture(emissiveMap, _texCoord1); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel)$> + <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + + vec3 viewNormal; + <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$> packDeferredFragmentLightmap( normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - getMaterialSpecular(mat), - getMaterialShininess(mat), - (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat), + getMaterialMetallic(mat), + getMaterialFresnel(mat), + lightmapVal); } diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slv b/libraries/render-utils/src/model_lightmap_normal_map.slv index 6046a67e10..eb8f80656d 100755 --- a/libraries/render-utils/src/model_lightmap_normal_map.slv +++ b/libraries/render-utils/src/model_lightmap_normal_map.slv @@ -29,7 +29,7 @@ out vec3 _tangent; out vec3 _color; void main(void) { - // pass along the diffuse color in linear space + // pass along the color in linear space _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates diff --git a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf index 1b7416baa5..71909a789f 100755 --- a/libraries/render-utils/src/model_lightmap_normal_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_specular_map.slf @@ -16,18 +16,9 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the emissive map texture and parameters -uniform sampler2D emissiveMap; -uniform vec2 emissiveParams; - -// the normal map texture -uniform sampler2D normalMap; - -// the specular map texture -uniform sampler2D specularMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC)$> +<$declareMaterialLightmap()$> in vec4 _position; in vec2 _texCoord0; @@ -37,26 +28,20 @@ in vec3 _tangent; in vec3 _color; void main(void) { - // compute the view normal from the various bits - vec3 normalizedNormal = normalize(_normal); - vec3 normalizedTangent = normalize(_tangent); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5); - vec4 viewNormal = vec4(normalizedTangent * localNormal.x + - normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); - - // set the diffuse, normal, specular data - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec3 specular = texture(specularMap, _texCoord0).rgb; - vec4 emissive = texture(emissiveMap, _texCoord1); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> + <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> + + vec3 viewNormal; + <$tangentToViewSpace(normalTexel, _normal, _tangent, viewNormal)$> packDeferredFragmentLightmap( normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - specular, // no use of getMaterialSpecular(mat) - getMaterialShininess(mat), - (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*specular, // no use of */ getMaterialFresnel(mat), + lightmapVal); } diff --git a/libraries/render-utils/src/model_lightmap_specular_map.slf b/libraries/render-utils/src/model_lightmap_specular_map.slf index efdfcd6be9..5eefefdc29 100755 --- a/libraries/render-utils/src/model_lightmap_specular_map.slf +++ b/libraries/render-utils/src/model_lightmap_specular_map.slf @@ -16,15 +16,9 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the emissive map texture and parameters -uniform sampler2D emissiveMap; -uniform vec2 emissiveParams; - -// the specular texture -uniform sampler2D specularMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC)$> +<$declareMaterialLightmap()$> in vec4 _position; in vec2 _texCoord0; @@ -33,18 +27,17 @@ in vec3 _normal; in vec3 _color; void main(void) { - // set the diffuse, normal, specular data - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec3 specular = texture(specularMap, _texCoord0).rgb; - vec4 emissive = texture(emissiveMap, _texCoord1); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedo, roughness, _SCRIBE_NULL, metallicTex)$> + <$fetchMaterialLightmap(_texCoord1, lightmapVal)$> packDeferredFragmentLightmap( normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - specular, // no use of getMaterialSpecular(mat) - getMaterialShininess(mat), - (vec3(emissiveParams.x) + emissiveParams.y * emissive.rgb)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), + getMaterialAlbedo(mat) * albedo.rgb * _color, + getMaterialRoughness(mat) * roughness, + getMaterialMetallic(mat) * metallicTex, + /*metallicTex, // no use of */getMaterialFresnel(mat), + lightmapVal); } diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 5479cec8eb..a584427005 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -16,11 +16,8 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal map texture -uniform sampler2D normalMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> in vec4 _position; in vec2 _texCoord0; @@ -29,22 +26,29 @@ in vec3 _tangent; in vec3 _color; void main(void) { - // compute the view normal from the various bits - vec3 normalizedNormal = normalize(_normal.xyz); - vec3 normalizedTangent = normalize(_tangent.xyz); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = normalize(vec3(texture(normalMap, _texCoord0.st)) - vec3(0.5, 0.5, 0.5)); - vec4 viewNormal = vec4(normalizedTangent * localNormal.x + - normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); - - vec4 diffuse = texture(diffuseMap, _texCoord0.st); - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$> + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 viewNormal; + <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$> packDeferredFragment( - normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - getMaterialSpecular(mat), - getMaterialShininess(mat)); + viewNormal, + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + albedo, + roughness, + getMaterialMetallic(mat), + emissive, + occlusionTex); } diff --git a/libraries/render-utils/src/model_normal_map.slv b/libraries/render-utils/src/model_normal_map.slv index 5ed4e37278..f7711cd326 100755 --- a/libraries/render-utils/src/model_normal_map.slv +++ b/libraries/render-utils/src/model_normal_map.slv @@ -28,7 +28,7 @@ out vec3 _tangent; out vec3 _color; void main(void) { - // pass along the diffuse color + // pass along the color _color = colorToLinearRGB(inColor.xyz); // and the texture coordinates diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index 2ebcdaae44..cf461db7ef 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -16,14 +16,8 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the normal map texture -uniform sampler2D normalMap; - -// the specular map texture -uniform sampler2D specularMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, NORMAL, METALLIC, EMISSIVE, OCCLUSION)$> in vec4 _position; in vec2 _texCoord0; @@ -32,24 +26,33 @@ in vec3 _tangent; in vec3 _color; void main(void) { - // compute the view normal from the various bits - vec3 normalizedNormal = normalize(_normal); - vec3 normalizedTangent = normalize(_tangent); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = normalize(vec3(texture(normalMap, _texCoord0)) - vec3(0.5, 0.5, 0.5)); - vec4 viewNormal = vec4(normalizedTangent * localNormal.x + - normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); - - // set the diffuse, normal, specular data - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec3 specular = texture(specularMap, _texCoord0).rgb; - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, metallicTex, emissiveTex, occlusionTex)$> + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + vec3 viewNormal; + <$tangentToViewSpace(normalTex, _normal, _tangent, viewNormal)$> + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; + packDeferredFragment( normalize(viewNormal.xyz), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - specular, //getMaterialSpecular(mat), - getMaterialShininess(mat)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + albedo, + roughness, + metallic, + emissive, + occlusionTex); } diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index e7f639194d..32e5823430 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -16,11 +16,8 @@ <@include model/Material.slh@> -// the diffuse texture -uniform sampler2D diffuseMap; - -// the specular texture -uniform sampler2D specularMap; +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, METALLIC, EMISSIVE, OCCLUSION)$> in vec4 _position; in vec2 _texCoord0; @@ -29,16 +26,29 @@ in vec3 _color; void main(void) { - // set the diffuse, normal, specular data - vec4 diffuse = texture(diffuseMap, _texCoord0); - vec3 specular = texture(specularMap, _texCoord0).rgb; - Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$> + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + float roughness = getMaterialRoughness(mat); + <$evalMaterialRoughness(roughnessTex, roughness, matKey, roughness)$>; + + vec3 emissive = getMaterialEmissive(mat); + <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; + + float metallic = getMaterialMetallic(mat); + <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; packDeferredFragment( normalize(_normal), - evalOpaqueFinalAlpha(getMaterialOpacity(mat), diffuse.a), - getMaterialDiffuse(mat) * diffuse.rgb * _color, - specular, //getMaterialSpecular(mat), - getMaterialShininess(mat)); + evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedoTex.a), + albedo, + roughness, + metallic, + emissive, + occlusionTex); } diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 481cb942b3..086f9fe168 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -20,9 +20,7 @@ <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> - - -uniform sampler2D diffuseMap; +uniform sampler2D albedoMap; in vec2 _texCoord0; in vec4 _position; @@ -33,15 +31,16 @@ in float _alpha; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(diffuseMap, _texCoord0); + vec4 albedo = texture(albedoMap, _texCoord0); Material mat = getMaterial(); vec3 fragPosition = _position.xyz; vec3 fragNormal = normalize(_normal); - vec3 fragDiffuse = getMaterialDiffuse(mat) * diffuse.rgb * _color; - vec3 fragSpecular = getMaterialSpecular(mat); - float fragGloss = getMaterialShininess(mat) / 128; - float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha; + vec3 fragAlbedo = getMaterialAlbedo(mat) * albedo.rgb * _color; + float fragMetallic = getMaterialMetallic(mat); + vec3 fragEmissive = getMaterialEmissive(mat); + float fragRoughness = getMaterialRoughness(mat); + float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha; TransformCamera cam = getTransformCamera(); @@ -51,8 +50,9 @@ void main(void) { 1.0, fragPosition, fragNormal, - fragDiffuse, - fragSpecular, - fragGloss), + fragAlbedo, + fragMetallic, + fragEmissive, + fragRoughness), fragOpacity); } diff --git a/libraries/render-utils/src/model_translucent_emissive.slf b/libraries/render-utils/src/model_translucent_emissive.slf index a2c7186f6f..82faf7cf45 100644 --- a/libraries/render-utils/src/model_translucent_emissive.slf +++ b/libraries/render-utils/src/model_translucent_emissive.slf @@ -14,7 +14,7 @@ <@include model/Material.slh@> -uniform sampler2D diffuseMap; +uniform sampler2D albedoMap; in vec2 _texCoord0; in vec3 _color; @@ -23,11 +23,11 @@ in float _alpha; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(diffuseMap, _texCoord0); + vec4 albedo = texture(albedoMap, _texCoord0); Material mat = getMaterial(); - vec3 fragColor = getMaterialDiffuse(mat) * diffuse.rgb * _color; - float fragOpacity = getMaterialOpacity(mat) * diffuse.a * _alpha; + vec3 fragColor = getMaterialAlbedo(mat) * albedo.rgb * _color; + float fragOpacity = getMaterialOpacity(mat) * albedo.a * _alpha; _fragColor = vec4(fragColor, fragOpacity); } diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 66a48e95f4..38199a7a82 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -17,7 +17,7 @@ <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> -vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) { +vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 specular, float roughness, float opacity) { // Need the light now Light light = getLight(); @@ -28,11 +28,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light); - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, specular, roughness); - color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(albedo * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return vec4(color, opacity); } @@ -48,14 +48,15 @@ in float _alpha; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(originalTexture, _texCoord0); + vec4 albedo = texture(originalTexture, _texCoord0); vec3 fragPosition = _position.xyz; vec3 fragNormal = normalize(_normal); - vec3 fragDiffuse = diffuse.rgb * _color; + vec3 fragAlbedo = albedo.rgb * _color; + float fragMetallic = 0.0; vec3 fragSpecular = vec3(0.1); - float fragGloss = 10.0 / 128.0; - float fragOpacity = diffuse.a; + float fragRoughness = 0.9; + float fragOpacity = albedo.a; if (fragOpacity <= 0.1) { discard; @@ -64,9 +65,10 @@ void main(void) { vec4 color = evalGlobalColor(1.0, fragPosition, fragNormal, - fragDiffuse, + fragAlbedo, + fragMetallic, fragSpecular, - fragGloss, + fragRoughness, fragOpacity); // Apply standard tone mapping diff --git a/libraries/render-utils/src/overlay3D_emissive.slf b/libraries/render-utils/src/overlay3D_emissive.slf index ad689baf91..727eb0f317 100644 --- a/libraries/render-utils/src/overlay3D_emissive.slf +++ b/libraries/render-utils/src/overlay3D_emissive.slf @@ -20,12 +20,12 @@ in vec3 _color; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(originalTexture, _texCoord0); + vec4 albedo = texture(originalTexture, _texCoord0); - if (diffuse.a <= 0.1) { + if (albedo.a <= 0.1) { discard; } - vec4 color = vec4(diffuse.rgb * _color, diffuse.a); + vec4 color = vec4(albedo.rgb * _color, albedo.a); // Apply standard tone mapping _fragColor = vec4(pow(color.xyz, vec3(1.0 / 2.2)), color.w); diff --git a/libraries/render-utils/src/overlay3D_translucent.slf b/libraries/render-utils/src/overlay3D_translucent.slf index dcc15ba25b..f8c18abf20 100644 --- a/libraries/render-utils/src/overlay3D_translucent.slf +++ b/libraries/render-utils/src/overlay3D_translucent.slf @@ -18,7 +18,7 @@ <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> -vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss, float opacity) { +vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 albedo, float metallic, vec3 specular, float roughness, float opacity) { // Need the light now Light light = getLight(); @@ -29,11 +29,11 @@ vec4 evalGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 d vec3 fragEyeDir; <$transformEyeToWorldDir(cam, fragEyeVectorView, fragEyeDir)$> - vec3 color = opacity * diffuse.rgb * getLightColor(light) * getLightAmbientIntensity(light); + vec3 color = opacity * albedo * getLightColor(light) * getLightAmbientIntensity(light); - vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); + vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, metallic, specular, roughness); - color += vec3(diffuse * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(albedo * shading.w * opacity + shading.rgb) * shadowAttenuation * getLightColor(light) * getLightIntensity(light); return vec4(color, opacity); } @@ -49,21 +49,23 @@ in float _alpha; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(originalTexture, _texCoord0); + vec4 albedo = texture(originalTexture, _texCoord0); vec3 fragPosition = _position.xyz; vec3 fragNormal = normalize(_normal); - vec3 fragDiffuse = diffuse.rgb * _color; + vec3 fragAlbedo = albedo.rgb * _color; + float fragMetallic = 0.0; vec3 fragSpecular = vec3(0.1); - float fragGloss = 10.0 / 128.0; - float fragOpacity = diffuse.a * _alpha; + float fragRoughness = 0.9; + float fragOpacity = albedo.a * _alpha; vec4 color = evalGlobalColor(1.0, fragPosition, fragNormal, - fragDiffuse, + fragAlbedo, + fragMetallic, fragSpecular, - fragGloss, + fragRoughness, fragOpacity); // Apply standard tone mapping diff --git a/libraries/render-utils/src/overlay3D_translucent_emissive.slf b/libraries/render-utils/src/overlay3D_translucent_emissive.slf index bcfec7d588..61935f3c67 100644 --- a/libraries/render-utils/src/overlay3D_translucent_emissive.slf +++ b/libraries/render-utils/src/overlay3D_translucent_emissive.slf @@ -21,7 +21,7 @@ in float _alpha; out vec4 _fragColor; void main(void) { - vec4 diffuse = texture(originalTexture, _texCoord0); + vec4 albedo = texture(originalTexture, _texCoord0); - _fragColor = vec4(diffuse.rgb * _color, diffuse.a * _alpha); + _fragColor = vec4(albedo.rgb * _color, albedo.a * _alpha); } diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index a64d4a81a8..0cadf3a760 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -60,7 +60,7 @@ void main(void) { vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss); + vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness); // Eval attenuation float radialAttenuation = evalLightAttenuation(light, fragLightDistance); diff --git a/libraries/render-utils/src/sdf_text3D.slf b/libraries/render-utils/src/sdf_text3D.slf index 69fec0042b..faa4d02bfa 100644 --- a/libraries/render-utils/src/sdf_text3D.slf +++ b/libraries/render-utils/src/sdf_text3D.slf @@ -10,6 +10,8 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +<@include DeferredBufferWrite.slh@> + uniform sampler2D Font; uniform bool Outline; uniform vec4 Color; @@ -17,12 +19,11 @@ uniform vec4 Color; // the interpolated normal in vec3 _normal; in vec2 _texCoord0; - +/* layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; - -const float DEFAULT_SHININESS = 10; +*/ const float gamma = 2.2; const float smoothing = 256.0; @@ -53,7 +54,16 @@ void main() { } // final color - _fragColor0 = vec4(Color.rgb, Color.a * a); + /* _fragColor0 = vec4(Color.rgb, Color.a * a); _fragColor1 = vec4(normalize(_normal.xyz), 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); - _fragColor2 = vec4(Color.rgb, DEFAULT_SHININESS / 128.0); + _fragColor2 = vec4(Color.rgb, 10 / 128.0); + */ + packDeferredFragmentLightmap( + normalize(_normal), + Color.a * a, + Color.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_SPECULAR, + Color.rgb); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index b24e4f92ff..5ad9dc174f 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -51,9 +51,9 @@ void main(void) { if (emissiveAmount > 0.0) { packDeferredFragmentLightmap( - normal, 1.0, diffuse, specular, shininess, specular); + normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), DEFAULT_METALLIC, specular, specular); } else { packDeferredFragment( - normal, 1.0, diffuse, specular, shininess); + normal, 1.0, diffuse, max(0, 1.0 - shininess / 128.0), length(specular), DEFAULT_EMISSIVE, DEFAULT_OCCLUSION); } } diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 727c029bbe..0832b22214 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// simple.frag +// simple_textured.slf // fragment shader // // Created by Clément Brisset on 5/29/15. @@ -15,7 +15,7 @@ <@include DeferredBufferWrite.slh@> <@include model/Material.slh@> -// the diffuse texture +// the albedo texture uniform sampler2D originalTexture; // the interpolated normal @@ -31,5 +31,8 @@ void main(void) { normalize(_normal.xyz), texel.a, _color.rgb * texel.rgb, - DEFAULT_SPECULAR, DEFAULT_SHININESS); + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_textured_emisive.slf b/libraries/render-utils/src/simple_textured_emisive.slf index 1dd3d667a6..92bdee8d02 100644 --- a/libraries/render-utils/src/simple_textured_emisive.slf +++ b/libraries/render-utils/src/simple_textured_emisive.slf @@ -14,7 +14,7 @@ <@include DeferredBufferWrite.slh@> -// the diffuse texture +// the albedo texture uniform sampler2D originalTexture; // the interpolated normal @@ -29,6 +29,8 @@ void main(void) { normalize(_normal), texel.a, _color.rgb, - DEFAULT_SPECULAR, DEFAULT_SHININESS, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_SPECULAR, texel.rgb); } \ No newline at end of file diff --git a/libraries/render-utils/src/skin_model.slv b/libraries/render-utils/src/skin_model.slv index 8ab475e1fd..199b97ba53 100755 --- a/libraries/render-utils/src/skin_model.slv +++ b/libraries/render-utils/src/skin_model.slv @@ -32,7 +32,7 @@ void main(void) { skinPositionNormal(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, position, interpolatedNormal); - // pass along the diffuse color + // pass along the color _color = colorToLinearRGB(inColor.rgb); // and the texture coordinates diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index cec93a024e..003b35b79b 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -34,7 +34,7 @@ void main(void) { skinPositionNormalTangent(inSkinClusterIndex, inSkinClusterWeight, inPosition, inNormal.xyz, inTangent.xyz, position, interpolatedNormal.xyz, interpolatedTangent.xyz); - // pass along the diffuse color + // pass along the color _color = colorToLinearRGB(inColor.rgb); // and the texture coordinates diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index b72598f810..69f8e836aa 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -66,7 +66,7 @@ void main(void) { vec3 fragNormal = vec3(invViewMat * vec4(frag.normal, 0.0)); vec4 fragEyeVector = invViewMat * vec4(-frag.position.xyz, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.specular, frag.gloss); + vec4 shading = evalFragShading(fragNormal, fragLightDir, fragEyeDir, frag.metallic, frag.specular, frag.roughness); // Eval attenuation float radialAttenuation = evalLightAttenuation(light, fragLightDistance); diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index b77c9c3451..6974a7e385 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -53,10 +53,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("skinClusterBuffer"), Slot::SKINNING_GPU)); slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), Slot::MATERIAL_GPU)); - slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), Slot::DIFFUSE_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("albedoMap"), Slot::ALBEDO_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("roughnessMap"), Slot::ROUGHNESS_MAP)); slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), Slot::NORMAL_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), Slot::SPECULAR_MAP)); - slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::LIGHTMAP_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("metallicMap"), Slot::METALLIC_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), Slot::EMISSIVE_LIGHTMAP_MAP)); + slotBindings.insert(gpu::Shader::Binding(std::string("occlusionMap"), Slot::OCCLUSION_MAP)); slotBindings.insert(gpu::Shader::Binding(std::string("lightBuffer"), Slot::LIGHT_BUFFER)); slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), Slot::NORMAL_FITTING_MAP)); @@ -66,10 +68,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); locations->emissiveParams = program->getUniforms().findLocation("emissiveParams"); locations->normalFittingMapUnit = program->getTextures().findLocation("normalFittingMap"); - locations->diffuseTextureUnit = program->getTextures().findLocation("diffuseMap"); + locations->albedoTextureUnit = program->getTextures().findLocation("albedoMap"); + locations->roughnessTextureUnit = program->getTextures().findLocation("roughnessMap"); locations->normalTextureUnit = program->getTextures().findLocation("normalMap"); - locations->specularTextureUnit = program->getTextures().findLocation("specularMap"); + locations->metallicTextureUnit = program->getTextures().findLocation("metallicMap"); locations->emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); + locations->occlusionTextureUnit = program->getTextures().findLocation("occlusionMap"); locations->skinClusterBufferUnit = program->getBuffers().findLocation("skinClusterBuffer"); locations->materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); locations->lightBufferUnit = program->getBuffers().findLocation("lightBuffer"); diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 4fd1dc22c5..0f795aadde 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -195,10 +195,13 @@ public: public: static const int SKINNING_GPU = 2; static const int MATERIAL_GPU = 3; - static const int DIFFUSE_MAP = 0; + static const int ALBEDO_MAP = 0; static const int NORMAL_MAP = 1; - static const int SPECULAR_MAP = 2; - static const int LIGHTMAP_MAP = 3; + static const int METALLIC_MAP = 2; + static const int EMISSIVE_LIGHTMAP_MAP = 3; + static const int ROUGHNESS_MAP = 4; + static const int OCCLUSION_MAP = 5; + static const int LIGHT_BUFFER = 4; static const int NORMAL_FITTING_MAP = 10; }; @@ -206,10 +209,12 @@ public: class Locations { public: int texcoordMatrices; - int diffuseTextureUnit; + int albedoTextureUnit; int normalTextureUnit; - int specularTextureUnit; + int roughnessTextureUnit; + int metallicTextureUnit; int emissiveTextureUnit; + int occlusionTextureUnit; int emissiveParams; int normalFittingMapUnit; int skinClusterBufferUnit; diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index 079cfff2c7..3883b948df 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -81,6 +81,11 @@ void SceneScripting::KeyLight::setAmbientSphere(const gpu::SHPointer& sphere) { _skyStage->setSunAmbientSphere(sphere); } +void SceneScripting::KeyLight::setAmbientMap(const gpu::TexturePointer& map) { + _skyStage->setSunAmbientMap(map); +} + + glm::vec3 SceneScripting::KeyLight::getDirection() const { return _skyStage->getSunDirection(); } diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 12681b1887..e8ea2e0217 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -84,6 +84,7 @@ namespace SceneScripting { // AmbientTexture is unscriptable - it must be set through the zone entity void setAmbientSphere(const gpu::SHPointer& sphere); void resetAmbientSphere() { setAmbientSphere(nullptr); } + void setAmbientMap(const gpu::TexturePointer& map); protected: model::SunSkyStagePointer _skyStage; diff --git a/tests/gpu-test/src/unlit.slf b/tests/gpu-test/src/unlit.slf index 77d28aa7e9..f88fcb510b 100644 --- a/tests/gpu-test/src/unlit.slf +++ b/tests/gpu-test/src/unlit.slf @@ -24,5 +24,5 @@ void main(void) { normalize(_normal.xyz), 1.0, _color.rgb, - DEFAULT_SPECULAR, DEFAULT_SHININESS); + DEFAULT_ROUGHNESS, DEFAULT_METALLIC, DEFAULT_EMISSIVE, DEFAULT_OCCLUSION); } diff --git a/tools/scribe/src/TextTemplate.cpp b/tools/scribe/src/TextTemplate.cpp index 3ccb0baea0..741ddb6846 100755 --- a/tools/scribe/src/TextTemplate.cpp +++ b/tools/scribe/src/TextTemplate.cpp @@ -18,6 +18,8 @@ typedef TextTemplate::Block::Pointer BlockPointer; typedef TextTemplate::Config::Pointer ConfigPointer; typedef TextTemplate::Pointer TextTemplatePointer; +const std::string TextTemplate::Tag::NULL_VAR = "_SCRIBE_NULL"; + //----------------------------------------------------------------------------- TextTemplate::Config::Config() : _includes(), @@ -370,7 +372,11 @@ bool TextTemplate::convertExpressionToFuncArguments(String& src, std::vector< St token += c; } else if (c == ',') { if (!token.empty()) { - arguments.push_back(token); + if (token == Tag::NULL_VAR) { + arguments.push_back(Tag::NULL_VAR); + } else { + arguments.push_back(token); + } nbTokens++; } token.clear(); @@ -750,7 +756,9 @@ int TextTemplate::evalBlockGeneration(std::ostream& dst, const BlockPointer& blo paramCache.push_back((*it).second); (*it).second = val; } else { - vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); + if (val != Tag::NULL_VAR) { + vars.insert(Vars::value_type(funcBlock->command.arguments[i], val)); + } paramCache.push_back(""); } } diff --git a/tools/scribe/src/TextTemplate.h b/tools/scribe/src/TextTemplate.h index a6fd04da5c..44edc23c12 100755 --- a/tools/scribe/src/TextTemplate.h +++ b/tools/scribe/src/TextTemplate.h @@ -42,6 +42,8 @@ public: static const char VAR = '$'; static const char COM = '@'; static const char REM = '!'; + + static const std::string NULL_VAR; }; class Command {