diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index fe2fc5ddcd..fd0d2bcedf 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -104,7 +104,7 @@ void Image3DOverlay::render(RenderArgs* args) { const render::ShapeKey Image3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); if (_emissive) { - builder.withEmissive(); + builder.withUnlit(); } if (getAlpha() != 1.0f) { builder.withTranslucent(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 891e1dca3b..f0244d0e3f 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -210,7 +210,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } DependencyManager::get()->bindSimpleProgram(batch, textured, culled, emissive); - DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f)); + DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, 0.0f)); } void RenderableWebEntityItem::setSourceUrl(const QString& value) { diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2df388e1d4..2322a808c7 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -892,7 +892,10 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS properties = true; propertyName = "P"; index = 4; + } else if (subobject.name == "ShadingModel") { + material.shadingModel = subobject.properties.at(0).toString(); } + if (properties) { std::vector unknowns; foreach(const FBXNode& property, subobject.children) { @@ -988,7 +991,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS QString propname = subobject.name.data(); int unknown = 0; if ( (propname == "Version") - ||(propname == "ShadingModel") ||(propname == "Multilayer")) { } else { unknown++; @@ -1130,7 +1132,6 @@ FBXGeometry* FBXReader::extractFBXGeometry(const QVariantHash& mapping, const QS 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)); } else if (type == "lcl translation") { diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index c1952fc550..6ba1c5786b 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -154,6 +154,7 @@ public: QString materialID; QString name; + QString shadingModel; model::MaterialPointer _material; FBXTexture normalTexture; diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index 11c6dad2f2..22a577072d 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -72,6 +72,10 @@ void FBXReader::consolidateFBXMaterials() { // foreach (const QString& materialID, materials) { for (QHash::iterator it = _fbxMaterials.begin(); it != _fbxMaterials.end(); it++) { FBXMaterial& material = (*it); + + // Maya is the exporting the shading model and we aretrying to use it + bool isMaterialLambert = (material.shadingModel.toLower() == "lambert"); + // the pure material associated with this part bool detectDifferentUVs = false; FBXTexture diffuseTexture; @@ -171,6 +175,13 @@ void FBXReader::consolidateFBXMaterials() { emissiveTexture = getTexture(emissiveTextureID); detectDifferentUVs |= (emissiveTexture.texcoordSet != 0) || (!emissiveTexture.transform.isIdentity()); material.emissiveTexture = emissiveTexture; + + if (isMaterialLambert) { + // If the emissiveTextureID comes from the Texture bound to Emissive when material is lambert, we know it s exported from maya + // And the EMissiveColor is forced to 0.5 by Maya which is bad + // So we need to force it to 1.0 + material.emissiveColor = vec3(1.0); + } } FBXTexture occlusionTexture; @@ -198,7 +209,7 @@ void FBXReader::consolidateFBXMaterials() { material._material = std::make_shared(); // Emissive color is the mix of emissiveColor with emissiveFactor - auto emissive = material.emissiveColor * material.emissiveFactor; + auto emissive = material.emissiveColor * (isMaterialLambert ? 1.0f : material.emissiveFactor); // In lambert there is not emissiveFactor material._material->setEmissive(emissive); // Final diffuse color is the mix of diffuseColor with diffuseFactor @@ -212,6 +223,18 @@ void FBXReader::consolidateFBXMaterials() { 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 (isMaterialLambert) { + if (!material._material->getKey().isAlbedo()) { + // switch emissive to material albedo as we tag the material to unlit + material._material->setUnlit(true); + material._material->setAlbedo(emissive); + + if (!material.emissiveTexture.isNull()) { + material.albedoTexture = material.emissiveTexture; + } + } + } } if (material.opacity <= 0.0f) { diff --git a/libraries/model/src/model/Material.cpp b/libraries/model/src/model/Material.cpp index d700a191c4..ba61732237 100755 --- a/libraries/model/src/model/Material.cpp +++ b/libraries/model/src/model/Material.cpp @@ -74,6 +74,11 @@ void Material::setOpacity(float opacity) { _schemaBuffer.edit()._opacity = opacity; } +void Material::setUnlit(bool value) { + _key.setUnlit(value); + _schemaBuffer.edit()._key = (uint32)_key._flags.to_ulong(); +} + 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(); diff --git a/libraries/model/src/model/Material.h b/libraries/model/src/model/Material.h index cf6b48f257..8dd9dd7960 100755 --- a/libraries/model/src/model/Material.h +++ b/libraries/model/src/model/Material.h @@ -28,14 +28,15 @@ class MaterialKey { public: enum FlagBit { EMISSIVE_VAL_BIT = 0, + UNLIT_VAL_BIT, ALBEDO_VAL_BIT, METALLIC_VAL_BIT, GLOSSY_VAL_BIT, OPACITY_VAL_BIT, - OPACITY_MASK_MAP_BIT, // OPacity Map and Opacity MASK map are mutually exclusive + OPACITY_MASK_MAP_BIT, // Opacity Map and Opacity MASK map are mutually exclusive OPACITY_TRANSLUCENT_MAP_BIT, - // THe map bits must be in the smae sequence as the enum names for the map channels + // THe map bits must be in the same sequence as the enum names for the map channels EMISSIVE_MAP_BIT, ALBEDO_MAP_BIT, METALLIC_MAP_BIT, @@ -74,9 +75,12 @@ public: MaterialKey build() const { return MaterialKey(_flags); } Builder& withEmissive() { _flags.set(EMISSIVE_VAL_BIT); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT_VAL_BIT); return (*this); } + Builder& withAlbedo() { _flags.set(ALBEDO_VAL_BIT); return (*this); } Builder& withMetallic() { _flags.set(METALLIC_VAL_BIT); return (*this); } Builder& withGlossy() { _flags.set(GLOSSY_VAL_BIT); return (*this); } + Builder& withTranslucentFactor() { _flags.set(OPACITY_VAL_BIT); return (*this); } Builder& withEmissiveMap() { _flags.set(EMISSIVE_MAP_BIT); return (*this); } @@ -98,6 +102,9 @@ public: void setEmissive(bool value) { _flags.set(EMISSIVE_VAL_BIT, value); } bool isEmissive() const { return _flags[EMISSIVE_VAL_BIT]; } + void setUnlit(bool value) { _flags.set(UNLIT_VAL_BIT, value); } + bool isUnlit() const { return _flags[UNLIT_VAL_BIT]; } + void setEmissiveMap(bool value) { _flags.set(EMISSIVE_MAP_BIT, value); } bool isEmissiveMap() const { return _flags[EMISSIVE_MAP_BIT]; } @@ -172,6 +179,9 @@ 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& withoutUnlit() { _value.reset(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_VAL_BIT); return (*this); } + Builder& withUnlit() { _value.set(MaterialKey::UNLIT_VAL_BIT); _mask.set(MaterialKey::UNLIT_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); } @@ -250,6 +260,9 @@ public: void setOpacity(float opacity); float getOpacity() const { return _schemaBuffer.get()._opacity; } + void setUnlit(bool value); + bool isUnlit() const { return _key.isUnlit(); } + void setAlbedo(const Color& albedo, bool isSRGB = true); Color getAlbedo(bool SRGB = true) const { return (SRGB ? ColorUtils::tosRGBVec3(_schemaBuffer.get()._albedo) : _schemaBuffer.get()._albedo); } diff --git a/libraries/model/src/model/Material.slh b/libraries/model/src/model/Material.slh index 28f9769a8b..4a6139c664 100644 --- a/libraries/model/src/model/Material.slh +++ b/libraries/model/src/model/Material.slh @@ -40,20 +40,21 @@ float getMaterialShininess(Material m) { return 1.0 - getMaterialRoughness(m); } int getMaterialKey(Material m) { return floatBitsToInt(m._spareKey.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 OPACITY_VAL_BIT = 0x00000010; -const int OPACITY_MASK_MAP_BIT = 0x00000020; -const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000040; +const int UNLIT_VAL_BIT = 0x00000002; +const int ALBEDO_VAL_BIT = 0x00000004; +const int METALLIC_VAL_BIT = 0x00000008; +const int GLOSSY_VAL_BIT = 0x00000010; +const int OPACITY_VAL_BIT = 0x00000020; +const int OPACITY_MASK_MAP_BIT = 0x00000040; +const int OPACITY_TRANSLUCENT_MAP_BIT = 0x00000080; -const int EMISSIVE_MAP_BIT = 0x00000080; -const int ALBEDO_MAP_BIT = 0x00000100; -const int METALLIC_MAP_BIT = 0x00000200; -const int ROUGHNESS_MAP_BIT = 0x00000400; -const int NORMAL_MAP_BIT = 0x00000800; -const int OCCLUSION_MAP_BIT = 0x00001000; -const int LIGHTMAP_MAP_BIT = 0x00002000; +const int EMISSIVE_MAP_BIT = 0x00000100; +const int ALBEDO_MAP_BIT = 0x00000200; +const int METALLIC_MAP_BIT = 0x00000400; +const int ROUGHNESS_MAP_BIT = 0x00000800; +const int NORMAL_MAP_BIT = 0x00001000; +const int OCCLUSION_MAP_BIT = 0x00002000; +const int LIGHTMAP_MAP_BIT = 0x00004000; <@endif@> diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 12d3774ffd..6dfec30b16 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -90,14 +90,21 @@ static const std::string DEFAULT_OCCLUSION_SHADER{ 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));" + " return (frag.mode == FRAG_MODE_SHADED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" + " }" +}; + +static const std::string DEFAULT_UNLIT_SHADER{ + "vec4 getFragmentColor() {" + " DeferredFragment frag = unpackDeferredFragmentNoPosition(uv);" + " return (frag.mode == FRAG_MODE_UNLIT ? vec4(pow(frag.diffuse, 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));" + " return (frag.mode == FRAG_MODE_LIGHTMAPPED ? vec4(pow(frag.emissive, vec3(1.0 / 2.2)), 1.0) : vec4(vec3(0.0), 1.0));" " }" }; @@ -184,6 +191,8 @@ std::string DebugDeferredBuffer::getShaderSourceCode(Mode mode, std::string cust return DEFAULT_DEPTH_SHADER; case EmissiveMode: return DEFAULT_EMISSIVE_SHADER; + case UnlitMode: + return DEFAULT_UNLIT_SHADER; case OcclusionMode: return DEFAULT_OCCLUSION_SHADER; case LightmapMode: diff --git a/libraries/render-utils/src/DebugDeferredBuffer.h b/libraries/render-utils/src/DebugDeferredBuffer.h index f00dd58f0e..521dc13e0a 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.h +++ b/libraries/render-utils/src/DebugDeferredBuffer.h @@ -53,6 +53,7 @@ protected: RoughnessMode, MetallicMode, EmissiveMode, + UnlitMode, OcclusionMode, LightmapMode, LightingMode, diff --git a/libraries/render-utils/src/DeferredBuffer.slh b/libraries/render-utils/src/DeferredBuffer.slh index 5a3c941ce3..aed89b30d0 100755 --- a/libraries/render-utils/src/DeferredBuffer.slh +++ b/libraries/render-utils/src/DeferredBuffer.slh @@ -11,135 +11,44 @@ <@if not DEFERRED_BUFFER_SLH@> <@def DEFERRED_BUFFER_SLH@> +// Unpack the metallic-mode value +const float FRAG_PACK_SHADED_NON_METALLIC = 0.0; +const float FRAG_PACK_SHADED_METALLIC = 0.1; +const float FRAG_PACK_SHADED_RANGE_INV = 1.0 / (FRAG_PACK_SHADED_METALLIC - FRAG_PACK_SHADED_NON_METALLIC); -// the albedo texture -uniform sampler2D albedoMap; +const float FRAG_PACK_LIGHTMAPPED_NON_METALLIC = 0.2; +const float FRAG_PACK_LIGHTMAPPED_METALLIC = 0.3; +const float FRAG_PACK_LIGHTMAPPED_RANGE_INV = 1.0 / (FRAG_PACK_LIGHTMAPPED_METALLIC - FRAG_PACK_LIGHTMAPPED_NON_METALLIC); -// the normal texture -uniform sampler2D normalMap; +const float FRAG_PACK_UNLIT = 0.5; -// the specular texture -uniform sampler2D specularMap; +const int FRAG_MODE_UNLIT = 0; +const int FRAG_MODE_SHADED = 1; +const int FRAG_MODE_LIGHTMAPPED = 2; -// the depth texture -uniform sampler2D depthMap; - -// the obscurance texture -uniform sampler2D obscuranceMap; - -// the lighting texture -uniform sampler2D lightingMap; - - -struct DeferredTransform { - mat4 projection; - mat4 viewInverse; - float stereoSide; - vec3 _spareABC; -}; - -layout(std140) uniform deferredTransformBuffer { - DeferredTransform _deferredTransform; -}; -DeferredTransform getDeferredTransform() { - return _deferredTransform; -} - -bool getStereoMode(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide != 0.0); -} -float getStereoSide(DeferredTransform deferredTransform) { - return (deferredTransform.stereoSide); -} - -vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { - vec3 nPos = vec3(texcoord.xy * 2.0f - 1.0f, depthVal * 2.0f - 1.0f); - - // compute the view space position using the depth - // basically manually pick the proj matrix components to do the inverse - float Ze = -deferredTransform.projection[3][2] / (nPos.z + deferredTransform.projection[2][2]); - float Xe = (-Ze * nPos.x - Ze * deferredTransform.projection[2][0] - deferredTransform.projection[3][0]) / deferredTransform.projection[0][0]; - float Ye = (-Ze * nPos.y - Ze * deferredTransform.projection[2][1] - deferredTransform.projection[3][1]) / deferredTransform.projection[1][1]; - return vec4(Xe, Ye, Ze, 1.0f); -} - -struct DeferredFragment { - vec4 normalVal; - vec4 diffuseVal; - vec4 specularVal; - vec4 position; - vec3 normal; - float metallic; - vec3 diffuse; - float obscurance; - vec3 specular; - float roughness; - vec3 emissive; - int mode; - float depthVal; -}; - -const int LIGHT_MAPPED = 1; - -vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) { - if (getStereoMode(deferredTransform)) { - if (texcoord.x > 0.5) { - texcoord.x -= 0.5; - } - texcoord.x *= 2.0; +void unpackModeMetallic(float rawValue, out int mode, out float metallic) { + if (rawValue <= FRAG_PACK_SHADED_METALLIC) { + mode = FRAG_MODE_SHADED; + metallic = clamp((rawValue - FRAG_PACK_SHADED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0); + } else if (rawValue <= FRAG_PACK_LIGHTMAPPED_METALLIC) { + mode = FRAG_MODE_LIGHTMAPPED; + metallic = clamp((rawValue - FRAG_PACK_LIGHTMAPPED_NON_METALLIC) * FRAG_PACK_SHADED_RANGE_INV, 0.0, 1.0); + } else if (rawValue >= FRAG_PACK_UNLIT) { + mode = FRAG_MODE_UNLIT; + metallic = 0.0; } - 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; - 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; - 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; +float packShadedMetallic(float metallic) { + return mix(FRAG_PACK_SHADED_NON_METALLIC, FRAG_PACK_SHADED_METALLIC, metallic); } -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; +float packLightmappedMetallic(float metallic) { + return mix(FRAG_PACK_LIGHTMAPPED_NON_METALLIC, FRAG_PACK_LIGHTMAPPED_METALLIC, metallic); } - - +float packUnlit() { + return FRAG_PACK_UNLIT; +} <@endif@> diff --git a/libraries/render-utils/src/DeferredBufferRead.slh b/libraries/render-utils/src/DeferredBufferRead.slh new file mode 100644 index 0000000000..fa166300ae --- /dev/null +++ b/libraries/render-utils/src/DeferredBufferRead.slh @@ -0,0 +1,140 @@ + +<@if not DEFERRED_BUFFER_READ_SLH@> +<@def DEFERRED_BUFFER_READ_SLH@> + +<@include DeferredBuffer.slh@> + +// the albedo texture +uniform sampler2D albedoMap; + +// the normal texture +uniform sampler2D normalMap; + +// the specular texture +uniform sampler2D specularMap; + +// the depth texture +uniform sampler2D depthMap; + +// the obscurance texture +uniform sampler2D obscuranceMap; + +// the lighting texture +uniform sampler2D lightingMap; + + +struct DeferredTransform { + mat4 projection; + mat4 viewInverse; + float stereoSide; + vec3 _spareABC; +}; + +layout(std140) uniform deferredTransformBuffer { + DeferredTransform _deferredTransform; +}; +DeferredTransform getDeferredTransform() { + return _deferredTransform; +} + +bool getStereoMode(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide != 0.0); +} +float getStereoSide(DeferredTransform deferredTransform) { + return (deferredTransform.stereoSide); +} + +vec4 evalEyePositionFromZ(DeferredTransform deferredTransform, float depthVal, vec2 texcoord) { + vec3 nPos = vec3(texcoord.xy * 2.0f - 1.0f, depthVal * 2.0f - 1.0f); + + // compute the view space position using the depth + // basically manually pick the proj matrix components to do the inverse + float Ze = -deferredTransform.projection[3][2] / (nPos.z + deferredTransform.projection[2][2]); + float Xe = (-Ze * nPos.x - Ze * deferredTransform.projection[2][0] - deferredTransform.projection[3][0]) / deferredTransform.projection[0][0]; + float Ye = (-Ze * nPos.y - Ze * deferredTransform.projection[2][1] - deferredTransform.projection[3][1]) / deferredTransform.projection[1][1]; + return vec4(Xe, Ye, Ze, 1.0f); +} + +struct DeferredFragment { + vec4 normalVal; + vec4 diffuseVal; + vec4 specularVal; + vec4 position; + vec3 normal; + float metallic; + vec3 diffuse; + float obscurance; + vec3 specular; + float roughness; + vec3 emissive; + int mode; + float depthVal; +}; + +vec4 unpackDeferredPosition(DeferredTransform deferredTransform, float depthValue, vec2 texcoord) { + if (getStereoMode(deferredTransform)) { + if (texcoord.x > 0.5) { + texcoord.x -= 0.5; + } + texcoord.x *= 2.0; + } + 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.roughness = 2.0 * frag.normalVal.a; + + // Diffuse color and unpack the mode and the metallicness + frag.diffuse = frag.diffuseVal.xyz; + unpackModeMetallic(frag.diffuseVal.w, frag.mode, frag.metallic); + + + 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.emissive = frag.specularVal.xyz; + 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 24a2f0d8a5..2be38fbea3 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -11,6 +11,8 @@ <@if not DEFERRED_BUFFER_WRITE_SLH@> <@def DEFERRED_BUFFER_WRITE_SLH@> +<@include DeferredBuffer.slh@> + layout(location = 0) out vec4 _fragColor0; layout(location = 1) out vec4 _fragColor1; layout(location = 2) out vec4 _fragColor2; @@ -48,13 +50,12 @@ const vec3 DEFAULT_EMISSIVE = vec3(0.0); const float DEFAULT_OCCLUSION = 1.0; const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; - void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion) { if (alpha != 1.0) { discard; } - _fragColor0 = vec4(albedo, metallic); - _fragColor1 = vec4(bestFitNormal(normal), 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor0 = vec4(albedo, packShadedMetallic(metallic)); + _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, occlusion); } @@ -63,19 +64,25 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 albedo, float r if (alpha != 1.0) { discard; } - _fragColor0 = vec4(albedo, metallic); - _fragColor1 = vec4(bestFitNormal(normal), 0.5 + 0.5 * clamp(roughness, 0.0, 1.0)); + _fragColor0 = vec4(albedo, packLightmappedMetallic(metallic)); + _fragColor1 = vec4(bestFitNormal(normal), clamp(roughness, 0.0, 1.0)); _fragColor2 = vec4(emissive, 1.0); } +void packDeferredFragmentUnlit(vec3 normal, float alpha, vec3 color) { + if (alpha != 1.0) { + discard; + } + _fragColor0 = vec4(color, packUnlit()); + _fragColor1 = vec4(bestFitNormal(normal), 1.0); + //_fragColor2 = vec4(vec3(0.0), 1.0); // If unlit, do not worry about the emissive color target +} + void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 albedo, vec3 fresnel, float roughness) { if (alpha <= 0.0) { discard; - } - + } _fragColor0 = vec4(albedo.rgb, alpha); - // _fragColor1 = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); - // _fragColor2 = vec4(fresnel, roughness); } <@endif@> diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 550baa6946..15bf44744c 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -31,7 +31,7 @@ #include "simple_vert.h" #include "simple_textured_frag.h" -#include "simple_textured_emisive_frag.h" +#include "simple_textured_unlit_frag.h" #include "grid_frag.h" @@ -1687,7 +1687,7 @@ public: enum FlagBit { IS_TEXTURED_FLAG = 0, IS_CULLED_FLAG, - IS_EMISSIVE_FLAG, + IS_UNLIT_FLAG, HAS_DEPTH_BIAS_FLAG, NUM_FLAGS, @@ -1696,7 +1696,7 @@ public: enum Flag { IS_TEXTURED = (1 << IS_TEXTURED_FLAG), IS_CULLED = (1 << IS_CULLED_FLAG), - IS_EMISSIVE = (1 << IS_EMISSIVE_FLAG), + IS_UNLIT = (1 << IS_UNLIT_FLAG), HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG), }; typedef unsigned short Flags; @@ -1705,7 +1705,7 @@ public: bool isTextured() const { return isFlag(IS_TEXTURED); } bool isCulled() const { return isFlag(IS_CULLED); } - bool isEmissive() const { return isFlag(IS_EMISSIVE); } + bool isUnlit() const { return isFlag(IS_UNLIT); } bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); } Flags _flags = 0; @@ -1715,9 +1715,9 @@ public: SimpleProgramKey(bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false) { + bool unlit = false, bool depthBias = false) { _flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) | - (emissive ? IS_EMISSIVE : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); + (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0); } SimpleProgramKey(int bitmask) : _flags(bitmask) {} @@ -1731,8 +1731,8 @@ inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) { return a.getRaw() == b.getRaw(); } -void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool emissive, bool depthBiased) { - batch.setPipeline(getSimplePipeline(textured, culled, emissive, depthBiased)); +void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool unlit, bool depthBiased) { + batch.setPipeline(getSimplePipeline(textured, culled, unlit, depthBiased)); // If not textured, set a default albedo map if (!textured) { @@ -1744,23 +1744,23 @@ void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool cul DependencyManager::get()->getNormalFittingTexture()); } -gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool emissive, bool depthBiased) { - SimpleProgramKey config{textured, culled, emissive, depthBiased}; +gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) { + SimpleProgramKey config{ textured, culled, unlit, depthBiased }; // Compile the shaders static std::once_flag once; std::call_once(once, [&]() { auto VS = gpu::Shader::createVertex(std::string(simple_vert)); auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag)); - auto PSEmissive = gpu::Shader::createPixel(std::string(simple_textured_emisive_frag)); + auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag)); _simpleShader = gpu::Shader::createProgram(VS, PS); - _emissiveShader = gpu::Shader::createProgram(VS, PSEmissive); + _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); - gpu::Shader::makeProgram(*_emissiveShader, slotBindings); + gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); // If the pipeline already exists, return it @@ -1785,7 +1785,7 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - gpu::ShaderPointer program = (config.isEmissive()) ? _emissiveShader : _simpleShader; + gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _simpleShader; gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b69ebf8531..c4531aa102 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -153,10 +153,10 @@ public: // Bind the pipeline and get the state to render static geometry void bindSimpleProgram(gpu::Batch& batch, bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false); + bool unlit = false, bool depthBias = false); // Get the pipeline to render static geometry gpu::PipelinePointer getSimplePipeline(bool textured = false, bool culled = true, - bool emissive = false, bool depthBias = false); + bool unlit = false, bool depthBias = false); render::ShapePipelinePointer getShapePipeline() { return GeometryCache::_simplePipeline; } // Static (instanced) geometry @@ -393,7 +393,7 @@ private: QHash > _networkGeometry; gpu::ShaderPointer _simpleShader; - gpu::ShaderPointer _emissiveShader; + gpu::ShaderPointer _unlitShader; static render::ShapePipelinePointer _simplePipeline; QHash _simplePrograms; }; diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index 512b7a533c..f9b1c76104 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -157,7 +157,7 @@ vec3 fetchLightmapMap(vec2 uv) { } <@endfunc@> -<@func $discardTransparent(opacity)@> +<@func discardTransparent(opacity)@> { if (<$opacity$> < 1.0) { discard; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 03c1ac9eda..08c8dc23b4 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -144,6 +144,11 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::Locat auto materialKey = _drawMaterial->getKey(); auto textureMaps = _drawMaterial->getTextureMaps(); + int numUnlit = 0; + if (materialKey.isUnlit()) { + numUnlit++; + } + // Albedo if (materialKey.isAlbedoMap()) { auto albedoMap = textureMaps[model::MaterialKey::ALBEDO_MAP]; @@ -414,6 +419,7 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isUnlit = drawMaterialKey.isUnlit(); bool isSkinned = _isSkinned; bool wireframe = _model->isWireframe(); @@ -435,6 +441,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (hasLightmap) { builder.withLightmap(); } + if (isUnlit) { + builder.withUnlit(); + } if (isSkinned) { builder.withSkinned(); } diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index ada5a66c39..16681fd363 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -27,7 +27,7 @@ #include "skin_model_normal_map_vert.h" #include "model_frag.h" -#include "model_emissive_frag.h" +#include "model_unlit_frag.h" #include "model_shadow_frag.h" #include "model_normal_map_frag.h" #include "model_normal_specular_map_frag.h" @@ -37,13 +37,13 @@ #include "model_lightmap_normal_specular_map_frag.h" #include "model_lightmap_specular_map_frag.h" #include "model_translucent_frag.h" -#include "model_translucent_emissive_frag.h" +#include "model_translucent_unlit_frag.h" #include "overlay3D_vert.h" #include "overlay3D_frag.h" #include "overlay3D_translucent_frag.h" -#include "overlay3D_emissive_frag.h" -#include "overlay3D_translucent_emissive_frag.h" +#include "overlay3D_unlit_frag.h" +#include "overlay3D_translucent_unlit_frag.h" #include "drawOpaqueStencil_frag.h" @@ -102,13 +102,13 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); auto pixel = gpu::Shader::createPixel(std::string(overlay3D_frag)); auto pixelTranslucent = gpu::Shader::createPixel(std::string(overlay3D_translucent_frag)); - auto pixelEmissive = gpu::Shader::createPixel(std::string(overlay3D_emissive_frag)); - auto pixelTranslucentEmissive = gpu::Shader::createPixel(std::string(overlay3D_translucent_emissive_frag)); + auto pixelUnlit = gpu::Shader::createPixel(std::string(overlay3D_unlit_frag)); + auto pixelTranslucentUnlit = gpu::Shader::createPixel(std::string(overlay3D_translucent_unlit_frag)); auto opaqueProgram = gpu::Shader::createProgram(vertex, pixel); auto translucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucent); - auto emissiveOpaqueProgram = gpu::Shader::createProgram(vertex, pixelEmissive); - auto emissiveTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentEmissive); + auto unlitOpaqueProgram = gpu::Shader::createProgram(vertex, pixelUnlit); + auto unlitTranslucentProgram = gpu::Shader::createProgram(vertex, pixelTranslucentUnlit); for (int i = 0; i < 8; i++) { bool isCulled = (i & 1); @@ -138,9 +138,9 @@ void initOverlay3DPipelines(ShapePlumber& plumber) { isOpaque ? builder.withOpaque() : builder.withTranslucent(); auto simpleProgram = isOpaque ? opaqueProgram : translucentProgram; - auto emissiveProgram = isOpaque ? emissiveOpaqueProgram : emissiveTranslucentProgram; - plumber.addPipeline(builder.withoutEmissive().build(), simpleProgram, state, &lightBatchSetter); - plumber.addPipeline(builder.withEmissive().build(), emissiveProgram, state, &batchSetter); + auto unlitProgram = isOpaque ? unlitOpaqueProgram : unlitTranslucentProgram; + plumber.addPipeline(builder.withoutUnlit().build(), simpleProgram, state, &lightBatchSetter); + plumber.addPipeline(builder.withUnlit().build(), unlitProgram, state, &batchSetter); } } @@ -201,12 +201,12 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { // Pixel shaders auto modelPixel = gpu::Shader::createPixel(std::string(model_frag)); - auto modelEmissivePixel = gpu::Shader::createPixel(std::string(model_emissive_frag)); + auto modelUnlitPixel = gpu::Shader::createPixel(std::string(model_unlit_frag)); auto modelNormalMapPixel = gpu::Shader::createPixel(std::string(model_normal_map_frag)); auto modelSpecularMapPixel = gpu::Shader::createPixel(std::string(model_specular_map_frag)); auto modelNormalSpecularMapPixel = gpu::Shader::createPixel(std::string(model_normal_specular_map_frag)); auto modelTranslucentPixel = gpu::Shader::createPixel(std::string(model_translucent_frag)); - auto modelTranslucentEmissivePixel = gpu::Shader::createPixel(std::string(model_translucent_emissive_frag)); + auto modelTranslucentUnlitPixel = gpu::Shader::createPixel(std::string(model_translucent_unlit_frag)); auto modelShadowPixel = gpu::Shader::createPixel(std::string(model_shadow_frag)); auto modelLightmapPixel = gpu::Shader::createPixel(std::string(model_lightmap_frag)); auto modelLightmapNormalMapPixel = gpu::Shader::createPixel(std::string(model_lightmap_normal_map_frag)); @@ -219,8 +219,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { Key::Builder(), modelVertex, modelPixel); addPipeline( - Key::Builder().withEmissive(), - modelVertex, modelEmissivePixel); + Key::Builder().withUnlit(), + modelVertex, modelUnlitPixel); addPipeline( Key::Builder().withTangents(), modelNormalMapVertex, modelNormalMapPixel); @@ -235,8 +235,8 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { Key::Builder().withTranslucent(), modelVertex, modelTranslucentPixel); addPipeline( - Key::Builder().withTranslucent().withEmissive(), - modelVertex, modelTranslucentEmissivePixel); + Key::Builder().withTranslucent().withUnlit(), + modelVertex, modelTranslucentUnlitPixel); addPipeline( Key::Builder().withTranslucent().withTangents(), modelNormalMapVertex, modelTranslucentPixel); @@ -296,4 +296,5 @@ void initDeferredPipelines(render::ShapePlumber& plumber) { addPipeline( Key::Builder().withSkinned().withDepthOnly(), skinModelShadowVertex, modelShadowPixel); + } diff --git a/libraries/render-utils/src/debug_deferred_buffer.slf b/libraries/render-utils/src/debug_deferred_buffer.slf index bbc50fa97a..b323836657 100644 --- a/libraries/render-utils/src/debug_deferred_buffer.slf +++ b/libraries/render-utils/src/debug_deferred_buffer.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> uniform sampler2D pyramidMap; uniform sampler2D occlusionMap; diff --git a/libraries/render-utils/src/directional_ambient_light.slf b/libraries/render-utils/src/directional_ambient_light.slf index e1ec0d3ef0..2ee818fdba 100755 --- a/libraries/render-utils/src/directional_ambient_light.slf +++ b/libraries/render-utils/src/directional_ambient_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -27,7 +27,9 @@ void main(void) { float shadowAttenuation = 1.0; - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_ambient_light_shadow.slf b/libraries/render-utils/src/directional_ambient_light_shadow.slf index 963a10d579..20ceea9379 100644 --- a/libraries/render-utils/src/directional_ambient_light_shadow.slf +++ b/libraries/render-utils/src/directional_ambient_light_shadow.slf @@ -13,7 +13,7 @@ // <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -29,7 +29,9 @@ void main(void) { vec4 worldPos = deferredTransform.viewInverse * vec4(frag.position.xyz, 1.0); float shadowAttenuation = evalShadowAttenuation(worldPos); - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_light.slf b/libraries/render-utils/src/directional_light.slf index 1a739f9389..ef61e9a030 100644 --- a/libraries/render-utils/src/directional_light.slf +++ b/libraries/render-utils/src/directional_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -28,7 +28,9 @@ void main(void) { float shadowAttenuation = 1.0; // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_light_shadow.slf b/libraries/render-utils/src/directional_light_shadow.slf index 3b9b4d22c6..5b09d47e80 100644 --- a/libraries/render-utils/src/directional_light_shadow.slf +++ b/libraries/render-utils/src/directional_light_shadow.slf @@ -13,7 +13,7 @@ // <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -30,7 +30,9 @@ void main(void) { float shadowAttenuation = evalShadowAttenuation(worldPos); // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light.slf b/libraries/render-utils/src/directional_skybox_light.slf index 9e24a5f585..f0c7bb476f 100755 --- a/libraries/render-utils/src/directional_skybox_light.slf +++ b/libraries/render-utils/src/directional_skybox_light.slf @@ -12,7 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -28,7 +28,9 @@ void main(void) { float shadowAttenuation = 1.0; // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/directional_skybox_light_shadow.slf b/libraries/render-utils/src/directional_skybox_light_shadow.slf index c3008b5509..6a233e5985 100644 --- a/libraries/render-utils/src/directional_skybox_light_shadow.slf +++ b/libraries/render-utils/src/directional_skybox_light_shadow.slf @@ -13,7 +13,7 @@ //!> <@include Shadow.slh@> -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> <@include DeferredGlobalLight.slh@> <$declareEvalLightmappedColor()$> @@ -30,7 +30,9 @@ void main(void) { float shadowAttenuation = evalShadowAttenuation(worldPos); // Light mapped or not ? - if (frag.mode == LIGHT_MAPPED) { + if (frag.mode == FRAG_MODE_UNLIT) { + _fragColor = vec4(frag.diffuse, 1.0); + } else if (frag.mode == FRAG_MODE_LIGHTMAPPED) { vec3 color = evalLightmappedColor( deferredTransform.viewInverse, shadowAttenuation, diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index ddfd83d1d4..f1dcc942c9 100755 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -30,7 +30,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_emissive.slf b/libraries/render-utils/src/model_emissive.slf deleted file mode 100644 index 471e613eb4..0000000000 --- a/libraries/render-utils/src/model_emissive.slf +++ /dev/null @@ -1,39 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_emissive.frag -// fragment shader -// -// Created by Zach Pomerantz on 2/3/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 -// - -<@include DeferredBufferWrite.slh@> -<@include model/Material.slh@> - -uniform sampler2D albedoMap; - -in vec2 _texCoord0; -in vec3 _normal; -in vec3 _color; -in float _alpha; - -void main(void) { - vec4 texel = texture(albedoMap, _texCoord0); - - Material mat = getMaterial(); - vec3 fragColor = getMaterialAlbedo(mat) * texel.rgb * _color; - - packDeferredFragmentLightmap( - normalize(_normal), - texel.a, - vec3(1.0), - getMaterialRoughness(mat), - getMaterialMetallic(mat), - getMaterialFresnel(mat), - fragColor); -} diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 10ae6ee880..519b41e17f 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -31,7 +31,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, normalTex, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_specular_map.slf b/libraries/render-utils/src/model_specular_map.slf index 9b2f4ae640..3cbb060ab5 100755 --- a/libraries/render-utils/src/model_specular_map.slf +++ b/libraries/render-utils/src/model_specular_map.slf @@ -31,7 +31,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, metallicTex, emissiveTex, occlusionTex)$> float opacity = 1.0; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$discardTransparent(opacity)$>; vec3 albedo = getMaterialAlbedo(mat); diff --git a/libraries/render-utils/src/model_translucent.slf b/libraries/render-utils/src/model_translucent.slf index 1a807c5703..27a22a9763 100755 --- a/libraries/render-utils/src/model_translucent.slf +++ b/libraries/render-utils/src/model_translucent.slf @@ -38,8 +38,7 @@ void main(void) { <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, roughnessTex, _SCRIBE_NULL, _SCRIBE_NULL, emissiveTex, occlusionTex)$> float opacity = getMaterialOpacity(mat) * _alpha; - <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)&>; - <$discardTransparent(opacity)$>; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; vec3 albedo = getMaterialAlbedo(mat); <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; diff --git a/libraries/render-utils/src/model_translucent_emissive.slf b/libraries/render-utils/src/model_translucent_emissive.slf deleted file mode 100644 index 82faf7cf45..0000000000 --- a/libraries/render-utils/src/model_translucent_emissive.slf +++ /dev/null @@ -1,33 +0,0 @@ -<@include gpu/Config.slh@> -<$VERSION_HEADER$> -// Generated on <$_SCRIBE_DATE$> -// -// model_translucent_emissive.frag -// fragment shader -// -// Created by Zach Pomerantz on 2/3/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 -// - -<@include model/Material.slh@> - -uniform sampler2D albedoMap; - -in vec2 _texCoord0; -in vec3 _color; -in float _alpha; - -out vec4 _fragColor; - -void main(void) { - vec4 albedo = texture(albedoMap, _texCoord0); - - Material mat = getMaterial(); - 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/model_translucent_unlit.slf b/libraries/render-utils/src/model_translucent_unlit.slf new file mode 100644 index 0000000000..b9d6c64d6f --- /dev/null +++ b/libraries/render-utils/src/model_translucent_unlit.slf @@ -0,0 +1,39 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// model_translucent_unlit.frag +// fragment shader +// +// Created by Zach Pomerantz on 2/3/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 +// + +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, ROUGHNESS, _SCRIBE_NULL, _SCRIBE_NULL, EMISSIVE, OCCLUSION)$> + +in vec2 _texCoord0; +in vec3 _color; +in float _alpha; + +out vec4 _fragColor; + +void main(void) { + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + + float opacity = getMaterialOpacity(mat) * _alpha; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + _fragColor = vec4(albedo, opacity); +} diff --git a/libraries/render-utils/src/model_unlit.slf b/libraries/render-utils/src/model_unlit.slf new file mode 100644 index 0000000000..50778153fb --- /dev/null +++ b/libraries/render-utils/src/model_unlit.slf @@ -0,0 +1,44 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// material_opaque_unlit.frag +// fragment shader +// +// Created by Sam Gateau on 5/5/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 +// + +<@include DeferredBufferWrite.slh@> +<@include model/Material.slh@> + +<@include MaterialTextures.slh@> +<$declareMaterialTextures(ALBEDO, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + +in vec2 _texCoord0; +in vec3 _normal; +in vec3 _color; +in float _alpha; + +void main(void) { + + Material mat = getMaterial(); + int matKey = getMaterialKey(mat); + <$fetchMaterialTextures(matKey, _texCoord0, albedoTex, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL, _SCRIBE_NULL)$> + + float opacity = 1.0; + <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; + <$discardTransparent(opacity)$>; + + vec3 albedo = getMaterialAlbedo(mat); + <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; + albedo *= _color; + + packDeferredFragmentUnlit( + normalize(_normal), + opacity, + albedo); +} diff --git a/libraries/render-utils/src/overlay3D.slf b/libraries/render-utils/src/overlay3D.slf index 38199a7a82..38f236e0b3 100644 --- a/libraries/render-utils/src/overlay3D.slf +++ b/libraries/render-utils/src/overlay3D.slf @@ -71,6 +71,7 @@ void main(void) { fragRoughness, fragOpacity); + // 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_emissive.slf b/libraries/render-utils/src/overlay3D_translucent_unlit.slf similarity index 93% rename from libraries/render-utils/src/overlay3D_translucent_emissive.slf rename to libraries/render-utils/src/overlay3D_translucent_unlit.slf index 61935f3c67..18a26d0790 100644 --- a/libraries/render-utils/src/overlay3D_translucent_emissive.slf +++ b/libraries/render-utils/src/overlay3D_translucent_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// overlay3D_translucent_emissive.frag +// overlay3D_translucent_unlit.frag // fragment shader // // Created by Zach Pomerantz on 2/2/2016. diff --git a/libraries/render-utils/src/overlay3D_emissive.slf b/libraries/render-utils/src/overlay3D_unlit.slf similarity index 96% rename from libraries/render-utils/src/overlay3D_emissive.slf rename to libraries/render-utils/src/overlay3D_unlit.slf index 727eb0f317..42e51bdc25 100644 --- a/libraries/render-utils/src/overlay3D_emissive.slf +++ b/libraries/render-utils/src/overlay3D_unlit.slf @@ -2,7 +2,7 @@ <$VERSION_HEADER$> // Generated on <$_SCRIBE_DATE$> // -// overlay3D_emissive.frag +// overlay3D_unlit.frag // fragment shader // // Created by Zach Pomerantz on 2/2/2016. diff --git a/libraries/render-utils/src/point_light.slf b/libraries/render-utils/src/point_light.slf index 0cadf3a760..fc72f094e7 100644 --- a/libraries/render-utils/src/point_light.slf +++ b/libraries/render-utils/src/point_light.slf @@ -13,7 +13,7 @@ // // Everything about deferred buffer -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> //Everything about deferred lighting <@include DeferredLighting.slh@> @@ -32,6 +32,10 @@ void main(void) { vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + mat4 invViewMat = deferredTransform.viewInverse; // Kill if in front of the light volume diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 46127d6752..d56d1cc8e2 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -20,12 +20,12 @@ // the interpolated normal out vec3 _normal; out vec3 _modelNormal; -out vec3 _color; +out vec4 _color; out vec2 _texCoord0; out vec4 _position; void main(void) { - _color = colorToLinearRGB(inColor.rgb); + _color = colorToLinearRGBA(inColor); _texCoord0 = inTexCoord0.st; _position = inPosition; _modelNormal = inNormal.xyz; diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 0832b22214..062fb96f7d 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> <@include model/Material.slh@> @@ -20,13 +21,14 @@ uniform sampler2D originalTexture; // the interpolated normal in vec3 _normal; -in vec3 _color; +in vec4 _color; in vec2 _texCoord0; void main(void) { - Material material = getMaterial(); vec4 texel = texture(originalTexture, _texCoord0); - + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + } packDeferredFragment( normalize(_normal.xyz), texel.a, diff --git a/libraries/render-utils/src/simple_textured_emisive.slf b/libraries/render-utils/src/simple_textured_unlit.slf similarity index 77% rename from libraries/render-utils/src/simple_textured_emisive.slf rename to libraries/render-utils/src/simple_textured_unlit.slf index 92bdee8d02..cbfc7d7768 100644 --- a/libraries/render-utils/src/simple_textured_emisive.slf +++ b/libraries/render-utils/src/simple_textured_unlit.slf @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> // the albedo texture @@ -19,18 +20,17 @@ uniform sampler2D originalTexture; // the interpolated normal in vec3 _normal; -in vec3 _color; +in vec4 _color; in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); - - packDeferredFragmentLightmap( + if (_color.a <= 0.0) { + texel = colorToLinearRGBA(texel); + } + + packDeferredFragmentUnlit( normalize(_normal), texel.a, - _color.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_SPECULAR, - texel.rgb); + _color.rgb * texel.rgb); } \ No newline at end of file diff --git a/libraries/render-utils/src/spot_light.slf b/libraries/render-utils/src/spot_light.slf index 8355dcf91b..4191ba3f63 100644 --- a/libraries/render-utils/src/spot_light.slf +++ b/libraries/render-utils/src/spot_light.slf @@ -13,7 +13,7 @@ // // Everything about deferred buffer -<@include DeferredBuffer.slh@> +<@include DeferredBufferRead.slh@> //Everything about deferred lighting <@include DeferredLighting.slh@> @@ -32,6 +32,10 @@ void main(void) { vec2 texCoord = _texCoord0.st / _texCoord0.q; DeferredFragment frag = unpackDeferredFragment(deferredTransform, texCoord); + if (frag.mode == FRAG_MODE_UNLIT) { + discard; + } + mat4 invViewMat = deferredTransform.viewInverse; // Kill if in front of the light volume diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index aba4de6acf..bed3bd7c68 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -26,7 +26,7 @@ public: LIGHTMAP, TANGENTS, SPECULAR, - EMISSIVE, + UNLIT, SKINNED, STEREO, DEPTH_ONLY, @@ -57,7 +57,7 @@ public: Builder& withLightmap() { _flags.set(LIGHTMAP); return (*this); } Builder& withTangents() { _flags.set(TANGENTS); return (*this); } Builder& withSpecular() { _flags.set(SPECULAR); return (*this); } - Builder& withEmissive() { _flags.set(EMISSIVE); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); return (*this); } Builder& withStereo() { _flags.set(STEREO); return (*this); } Builder& withDepthOnly() { _flags.set(DEPTH_ONLY); return (*this); } @@ -101,8 +101,8 @@ public: Builder& withSpecular() { _flags.set(SPECULAR); _mask.set(SPECULAR); return (*this); } Builder& withoutSpecular() { _flags.reset(SPECULAR); _mask.set(SPECULAR); return (*this); } - Builder& withEmissive() { _flags.set(EMISSIVE); _mask.set(EMISSIVE); return (*this); } - Builder& withoutEmissive() { _flags.reset(EMISSIVE); _mask.set(EMISSIVE); return (*this); } + Builder& withUnlit() { _flags.set(UNLIT); _mask.set(UNLIT); return (*this); } + Builder& withoutUnlit() { _flags.reset(UNLIT); _mask.set(UNLIT); return (*this); } Builder& withSkinned() { _flags.set(SKINNED); _mask.set(SKINNED); return (*this); } Builder& withoutSkinned() { _flags.reset(SKINNED); _mask.set(SKINNED); return (*this); } @@ -137,7 +137,7 @@ public: bool hasLightmap() const { return _flags[LIGHTMAP]; } bool hasTangents() const { return _flags[TANGENTS]; } bool hasSpecular() const { return _flags[SPECULAR]; } - bool hasEmissive() const { return _flags[EMISSIVE]; } + bool isUnlit() const { return _flags[UNLIT]; } bool isTranslucent() const { return _flags[TRANSLUCENT]; } bool isSkinned() const { return _flags[SKINNED]; } bool isStereo() const { return _flags[STEREO]; } @@ -173,7 +173,7 @@ inline QDebug operator<<(QDebug debug, const ShapeKey& key) { << "hasLightmap:" << key.hasLightmap() << "hasTangents:" << key.hasTangents() << "hasSpecular:" << key.hasSpecular() - << "hasEmissive:" << key.hasEmissive() + << "isUnlit:" << key.isUnlit() << "isTranslucent:" << key.isTranslucent() << "isSkinned:" << key.isSkinned() << "isStereo:" << key.isStereo() diff --git a/scripts/developer/utilities/render/framebuffer.qml b/scripts/developer/utilities/render/framebuffer.qml index f13018142e..0d8d85cc32 100644 --- a/scripts/developer/utilities/render/framebuffer.qml +++ b/scripts/developer/utilities/render/framebuffer.qml @@ -33,6 +33,7 @@ Column { "Roughness", "Metallic", "Emissive", + "Shaded/Lightmapped/Unlit", "Occlusion", "Lightmap", "Lighting", diff --git a/tests/shaders/src/main.cpp b/tests/shaders/src/main.cpp index 2bc957b2d1..c50f5769e6 100644 --- a/tests/shaders/src/main.cpp +++ b/tests/shaders/src/main.cpp @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include @@ -160,7 +160,7 @@ void QTestWindow::draw() { testShaderBuild(skybox_vert, skybox_frag); testShaderBuild(simple_vert, simple_frag); testShaderBuild(simple_vert, simple_textured_frag); - testShaderBuild(simple_vert, simple_textured_emisive_frag); + testShaderBuild(simple_vert, simple_textured_unlit_frag); testShaderBuild(deferred_light_vert, directional_light_frag); testShaderBuild(deferred_light_vert, directional_ambient_light_frag); testShaderBuild(deferred_light_vert, directional_skybox_light_frag); diff --git a/tools/scribe/src/main.cpp b/tools/scribe/src/main.cpp index 13003f05cf..b7038e392e 100755 --- a/tools/scribe/src/main.cpp +++ b/tools/scribe/src/main.cpp @@ -12,6 +12,7 @@ #include "TextTemplate.h" #include +#include #include #include @@ -168,7 +169,7 @@ int main (int argc, char** argv) { auto scribe = std::make_shared(srcFilename, config); // ready to parse and generate - std::ostringstream destStringStream; + std::stringstream destStringStream; int numErrors = scribe->scribe(destStringStream, srcStream, vars); if (numErrors) { cerr << "Scribe " << srcFilename << "> failed: " << numErrors << " errors." << endl; @@ -187,14 +188,38 @@ int main (int argc, char** argv) { std::ostringstream targetStringStream; if (makeCPlusPlus) { + // Because there is a maximum size for literal strings declared in source we need to partition the + // full source string stream into pages that seems to be around that value... + const int MAX_STRING_LITERAL = 10000; + std::string lineToken; + auto pageSize = lineToken.length(); + std::vector> pages(1, std::make_shared()); + while (!destStringStream.eof()) { + std::getline(destStringStream, lineToken); + auto lineSize = lineToken.length() + 1; + + if (pageSize + lineSize > MAX_STRING_LITERAL) { + pages.push_back(std::make_shared()); + // reset pageStringStream + pageSize = 0; + } + + (*pages.back()) << lineToken << std::endl; + pageSize += lineSize; + } + targetStringStream << "// File generated by Scribe " << vars["_SCRIBE_DATE"] << std::endl; targetStringStream << "#ifndef scribe_" << targetName << "_h" << std::endl; targetStringStream << "#define scribe_" << targetName << "_h" << std::endl << std::endl; - // targetStringStream << "const char " << targetName << "[] = R\"XXXX(" << destStringStream.str() << ")XXXX\";"; - targetStringStream << "const char " << targetName << "[] = R\"SCRIBE("; - targetStringStream << destStringStream.str(); - targetStringStream << "\n)SCRIBE\";\n\n"; + targetStringStream << "const char " << targetName << "[] = \n"; + + // Write the pages content + for (auto page : pages) { + targetStringStream << "R\"SCRIBE(\n" << page->str() << "\n)SCRIBE\"\n"; + } + targetStringStream << ";\n" << std::endl << std::endl; + targetStringStream << "#endif" << std::endl; } else { targetStringStream << destStringStream.str();