diff --git a/libraries/stdlib/genglsl/mx_image_color3.glsl b/libraries/stdlib/genglsl/mx_image_color3.glsl index 802318f475..8c4c039554 100644 --- a/libraries/stdlib/genglsl/mx_image_color3.glsl +++ b/libraries/stdlib/genglsl/mx_image_color3.glsl @@ -2,13 +2,6 @@ void mx_image_color3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv).rgb; - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).rgb; } diff --git a/libraries/stdlib/genglsl/mx_image_color4.glsl b/libraries/stdlib/genglsl/mx_image_color4.glsl index e74ad9445f..7541b9da04 100644 --- a/libraries/stdlib/genglsl/mx_image_color4.glsl +++ b/libraries/stdlib/genglsl/mx_image_color4.glsl @@ -2,13 +2,6 @@ void mx_image_color4(sampler2D tex_sampler, int layer, vec4 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec4 result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv); - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv); } diff --git a/libraries/stdlib/genglsl/mx_image_float.glsl b/libraries/stdlib/genglsl/mx_image_float.glsl index 9b831035d2..0a402a101c 100644 --- a/libraries/stdlib/genglsl/mx_image_float.glsl +++ b/libraries/stdlib/genglsl/mx_image_float.glsl @@ -2,13 +2,6 @@ void mx_image_float(sampler2D tex_sampler, int layer, float defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out float result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv).r; - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).r; } diff --git a/libraries/stdlib/genglsl/mx_image_vector2.glsl b/libraries/stdlib/genglsl/mx_image_vector2.glsl index 124cb09287..42a7235297 100644 --- a/libraries/stdlib/genglsl/mx_image_vector2.glsl +++ b/libraries/stdlib/genglsl/mx_image_vector2.glsl @@ -2,13 +2,6 @@ void mx_image_vector2(sampler2D tex_sampler, int layer, vec2 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec2 result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv).rg; - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).rg; } diff --git a/libraries/stdlib/genglsl/mx_image_vector3.glsl b/libraries/stdlib/genglsl/mx_image_vector3.glsl index 840e60fe6f..d49eab735e 100644 --- a/libraries/stdlib/genglsl/mx_image_vector3.glsl +++ b/libraries/stdlib/genglsl/mx_image_vector3.glsl @@ -2,13 +2,6 @@ void mx_image_vector3(sampler2D tex_sampler, int layer, vec3 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec3 result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv).rgb; - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv).rgb; } diff --git a/libraries/stdlib/genglsl/mx_image_vector4.glsl b/libraries/stdlib/genglsl/mx_image_vector4.glsl index f4b61d83f0..c8bdc66fc4 100644 --- a/libraries/stdlib/genglsl/mx_image_vector4.glsl +++ b/libraries/stdlib/genglsl/mx_image_vector4.glsl @@ -2,13 +2,6 @@ void mx_image_vector4(sampler2D tex_sampler, int layer, vec4 defaultval, vec2 texcoord, int uaddressmode, int vaddressmode, int filtertype, int framerange, int frameoffset, int frameendaction, vec2 uv_scale, vec2 uv_offset, out vec4 result) { - if (textureSize(tex_sampler, 0).x > 1) - { - vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); - result = texture(tex_sampler, uv); - } - else - { - result = defaultval; - } + vec2 uv = mx_transform_uv(texcoord, uv_scale, uv_offset); + result = texture(tex_sampler, uv); } diff --git a/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx b/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx new file mode 100644 index 0000000000..89b99c3c39 --- /dev/null +++ b/resources/Materials/TestSuite/stdlib/texture/image_default.mtlx @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MaterialXGraphEditor/RenderView.cpp b/source/MaterialXGraphEditor/RenderView.cpp index faf48f543a..f36a492502 100644 --- a/source/MaterialXGraphEditor/RenderView.cpp +++ b/source/MaterialXGraphEditor/RenderView.cpp @@ -720,7 +720,7 @@ void RenderView::loadEnvironmentLight() envIrradianceMap = _imageHandler->acquireImage(envIrradiancePath); // If not found, then generate an irradiance map via spherical harmonics. - if (envIrradianceMap == _imageHandler->getInvalidImage()) + if (envIrradianceMap == _imageHandler->getZeroImage()) { mx::Sh3ColorCoeffs shIrradiance = mx::projectEnvironment(envRadianceMap, true); envIrradianceMap = mx::renderEnvironment(shIrradiance, IRRADIANCE_MAP_WIDTH, IRRADIANCE_MAP_HEIGHT); diff --git a/source/MaterialXRender/ImageHandler.cpp b/source/MaterialXRender/ImageHandler.cpp index bc43b617ff..d54a18fedd 100644 --- a/source/MaterialXRender/ImageHandler.cpp +++ b/source/MaterialXRender/ImageHandler.cpp @@ -56,9 +56,6 @@ ImageHandler::ImageHandler(ImageLoaderPtr imageLoader) { addLoader(imageLoader); _zeroImage = createUniformImage(2, 2, 4, Image::BaseType::UINT8, Color4(0.0f)); - - // Generated shaders interpret 1x1 textures as invalid images. - _invalidImage = createUniformImage(1, 1, 4, Image::BaseType::UINT8, Color4(0.0f)); } void ImageHandler::addLoader(ImageLoaderPtr loader) @@ -118,7 +115,7 @@ bool ImageHandler::saveImage(const FilePath& filePath, return false; } -ImagePtr ImageHandler::acquireImage(const FilePath& filePath) +ImagePtr ImageHandler::acquireImage(const FilePath& filePath, const Color4& defaultColor) { // Resolve the input filepath. FilePath resolvedFilePath = filePath; @@ -142,9 +139,12 @@ ImagePtr ImageHandler::acquireImage(const FilePath& filePath) return image; } - // No valid image was found, so cache the sentinel invalid image. - cacheImage(resolvedFilePath, _invalidImage); - return _invalidImage; + // No valid image was found, so generate a uniform texture with the given default color. + // TODO: This step assumes that the missing image and its default color are in the same + // color space, which is not always the case. + ImagePtr defaultImage = createUniformImage(1, 1, 4, Image::BaseType::UINT8, defaultColor); + cacheImage(resolvedFilePath, defaultImage); + return defaultImage; } bool ImageHandler::bindImage(ImagePtr, const ImageSamplingProperties&) @@ -189,7 +189,7 @@ ImageVec ImageHandler::getReferencedImages(ConstDocumentPtr doc) if (file) { ImagePtr image = acquireImage(file->getResolvedValueString()); - if (image && image != _invalidImage) + if (image) { imageVec.push_back(image); } @@ -214,14 +214,6 @@ ImagePtr ImageHandler::loadImage(const FilePath& filePath) } if (image) { - // Generated shaders interpret 1x1 textures as invalid images, so valid 1x1 - // images must be resized. - if (image->getWidth() == 1 && image->getHeight() == 1) - { - image = createUniformImage(2, 2, image->getChannelCount(), - image->getBaseType(), image->getTexelColor(0, 0)); - } - return image; } } @@ -288,23 +280,23 @@ void ImageSamplingProperties::setProperties(const string& fileNameUniform, root = root.substr(0, pos); } - const string uaddressmodeStr = root + UADDRESS_MODE_SUFFIX; - const ShaderPort* port = uniformBlock.find(uaddressmodeStr); + const ShaderPort* port = uniformBlock.find(root + UADDRESS_MODE_SUFFIX); ValuePtr intValue = port ? port->getValue() : nullptr; uaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE); - const string vaddressmodeStr = root + VADDRESS_MODE_SUFFIX; - port = uniformBlock.find(vaddressmodeStr); + port = uniformBlock.find(root + VADDRESS_MODE_SUFFIX); intValue = port ? port->getValue() : nullptr; vaddressMode = ImageSamplingProperties::AddressMode(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE); - const string filtertypeStr = root + FILTER_TYPE_SUFFIX; - port = uniformBlock.find(filtertypeStr); + port = uniformBlock.find(root + FILTER_TYPE_SUFFIX); intValue = port ? port->getValue() : nullptr; filterType = ImageSamplingProperties::FilterType(intValue && intValue->isA() ? intValue->asA() : INVALID_MAPPED_INT_VALUE); - const string defaultColorStr = root + DEFAULT_COLOR_SUFFIX; - port = uniformBlock.find(defaultColorStr); + port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX); + if (!port) + { + port = uniformBlock.find(root + DEFAULT_COLOR_SUFFIX + "_cm_in"); + } ValuePtr colorValue = port ? port->getValue() : nullptr; if (colorValue) { diff --git a/source/MaterialXRender/ImageHandler.h b/source/MaterialXRender/ImageHandler.h index ee1fe127c4..c744eb2f6a 100644 --- a/source/MaterialXRender/ImageHandler.h +++ b/source/MaterialXRender/ImageHandler.h @@ -188,7 +188,7 @@ class MX_RENDER_API ImageHandler /// found in the cache, then each image loader will be applied in turn. /// @param filePath File path of the image. /// @return On success, a shared pointer to the acquired image. - ImagePtr acquireImage(const FilePath& filePath); + ImagePtr acquireImage(const FilePath& filePath, const Color4& defaultColor = Color4(0.0f)); /// Bind an image for rendering. /// @param image The image to bind. @@ -247,13 +247,6 @@ class MX_RENDER_API ImageHandler return _zeroImage; } - /// Return the sentinel invalid image, representing images that cannot be loaded - /// and should be replaced with their declared default value. - ImagePtr getInvalidImage() const - { - return _invalidImage; - } - /// Acquire all images referenced by the given document, and return the /// images in a vector. ImageVec getReferencedImages(ConstDocumentPtr doc); @@ -278,7 +271,6 @@ class MX_RENDER_API ImageHandler FileSearchPath _searchPath; StringResolverPtr _resolver; ImagePtr _zeroImage; - ImagePtr _invalidImage; }; MATERIALX_NAMESPACE_END diff --git a/source/MaterialXRenderGlsl/GlslMaterial.cpp b/source/MaterialXRenderGlsl/GlslMaterial.cpp index ef7a0ed0c2..ce4582d44f 100644 --- a/source/MaterialXRenderGlsl/GlslMaterial.cpp +++ b/source/MaterialXRenderGlsl/GlslMaterial.cpp @@ -209,7 +209,7 @@ ImagePtr GlslMaterial::bindImage(const FilePath& filePath, const std::string& un imageHandler->setFilenameResolver(resolver); // Acquire the given image. - ImagePtr image = imageHandler->acquireImage(filePath); + ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor); if (!image) { return nullptr; diff --git a/source/MaterialXRenderGlsl/GlslProgram.cpp b/source/MaterialXRenderGlsl/GlslProgram.cpp index a60997716a..900cac0ef1 100644 --- a/source/MaterialXRenderGlsl/GlslProgram.cpp +++ b/source/MaterialXRenderGlsl/GlslProgram.cpp @@ -491,7 +491,7 @@ ImagePtr GlslProgram::bindTexture(unsigned int uniformType, int uniformLocation, uniformType >= GL_SAMPLER_1D && uniformType <= GL_SAMPLER_CUBE) { // Acquire the image. - ImagePtr image = imageHandler->acquireImage(filePath); + ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor); if (imageHandler->bindImage(image, samplingProperties)) { GLTextureHandlerPtr textureHandler = std::static_pointer_cast(imageHandler); diff --git a/source/MaterialXRenderMsl/MslMaterial.mm b/source/MaterialXRenderMsl/MslMaterial.mm index 7e9cd38adc..66fc0462f2 100644 --- a/source/MaterialXRenderMsl/MslMaterial.mm +++ b/source/MaterialXRenderMsl/MslMaterial.mm @@ -199,7 +199,7 @@ imageHandler->setFilenameResolver(resolver); // Acquire the given image. - return imageHandler->acquireImage(filePath); + return imageHandler->acquireImage(filePath, samplingProperties.defaultColor); } void MslMaterial::bindLighting(LightHandlerPtr lightHandler, diff --git a/source/MaterialXRenderMsl/MslPipelineStateObject.mm b/source/MaterialXRenderMsl/MslPipelineStateObject.mm index 84a615fd61..4f8378ae46 100644 --- a/source/MaterialXRenderMsl/MslPipelineStateObject.mm +++ b/source/MaterialXRenderMsl/MslPipelineStateObject.mm @@ -542,7 +542,7 @@ int GetStrideOfMetalType(MTLDataType type) { // Acquire the image. string error; - ImagePtr image = imageHandler->acquireImage(filePath); + ImagePtr image = imageHandler->acquireImage(filePath, samplingProperties.defaultColor); imageHandler->bindImage(image, samplingProperties); return bindTexture(renderCmdEncoder, uniformLocation, image, imageHandler); } diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index ecbb4352fc..6346658d07 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -474,7 +474,7 @@ void Viewer::loadEnvironmentLight() } // Look for an irradiance map using an expected filename convention. - mx::ImagePtr envIrradianceMap = _imageHandler->getInvalidImage(); + mx::ImagePtr envIrradianceMap = _imageHandler->getZeroImage(); if (!_normalizeEnvironment && !_splitDirectLight) { mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName(); @@ -482,7 +482,7 @@ void Viewer::loadEnvironmentLight() } // If not found, then generate an irradiance map via spherical harmonics. - if (envIrradianceMap == _imageHandler->getInvalidImage()) + if (envIrradianceMap == _imageHandler->getZeroImage()) { if (_generateReferenceIrradiance) { diff --git a/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp b/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp index 7ece49d60b..d261bc7306 100644 --- a/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp +++ b/source/PyMaterialX/PyMaterialXRender/PyImageHandler.cpp @@ -41,7 +41,8 @@ void bindPyImageHandler(py::module& mod) .def("addLoader", &mx::ImageHandler::addLoader) .def("saveImage", &mx::ImageHandler::saveImage, py::arg("filePath"), py::arg("image"), py::arg("verticalFlip") = false) - .def("acquireImage", &mx::ImageHandler::acquireImage) + .def("acquireImage", &mx::ImageHandler::acquireImage, + py::arg("filePath"), py::arg("defaultColor") = mx::Color4(0.0f)) .def("bindImage", &mx::ImageHandler::bindImage) .def("unbindImage", &mx::ImageHandler::unbindImage) .def("unbindImages", &mx::ImageHandler::unbindImages) @@ -54,6 +55,5 @@ void bindPyImageHandler(py::module& mod) py::arg("image") = nullptr) .def("clearImageCache", &mx::ImageHandler::clearImageCache) .def("getZeroImage", &mx::ImageHandler::getZeroImage) - .def("getInvalidImage", &mx::ImageHandler::getInvalidImage) .def("getReferencedImages", &mx::ImageHandler::getReferencedImages); }