diff --git a/source/MaterialXRender/Image.cpp b/source/MaterialXRender/Image.cpp index e3b0e4365c..07144b4300 100644 --- a/source/MaterialXRender/Image.cpp +++ b/source/MaterialXRender/Image.cpp @@ -89,11 +89,12 @@ UnsignedIntPair getMaxDimensions(const vector& imageVec) // Image methods // -Image::Image(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType) : +Image::Image(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType, bool useCustomMipMaps) : _width(width), _height(height), _channelCount(channelCount), _baseType(baseType), + _useCustomMipMaps(useCustomMipMaps), _resourceBuffer(nullptr), _resourceBufferDeallocator(nullptr), _resourceId(0) @@ -505,7 +506,22 @@ void Image::writeTable(const FilePath& filePath, unsigned int channel) void Image::createResourceBuffer() { releaseResourceBuffer(); - _resourceBuffer = malloc(_width * _height * _channelCount * getBaseStride()); + size_t numTexels = 0; + if (_useCustomMipMaps) + { + int w = _width; + int h = _height; + while (w > 0 && h > 0) { + numTexels += w * h; + w /= 2; + h /= 2; + } + } + else + { + numTexels = _width * _height; + } + _resourceBuffer = malloc(numTexels * _channelCount * getBaseStride()); _resourceBufferDeallocator = nullptr; } diff --git a/source/MaterialXRender/Image.h b/source/MaterialXRender/Image.h index e5857d2af8..140ae8f9a0 100644 --- a/source/MaterialXRender/Image.h +++ b/source/MaterialXRender/Image.h @@ -55,9 +55,15 @@ class MX_RENDER_API Image public: /// Create an empty image with the given properties. - static ImagePtr create(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType = BaseType::UINT8) + static ImagePtr create( + unsigned int width, + unsigned int height, + unsigned int channelCount, + BaseType baseType = BaseType::UINT8, + bool useCustomMipMaps = false + ) { - return ImagePtr(new Image(width, height, channelCount, baseType)); + return ImagePtr(new Image(width, height, channelCount, baseType, useCustomMipMaps)); } ~Image(); @@ -89,6 +95,11 @@ class MX_RENDER_API Image return _baseType; } + bool getUseCustomMipMaps() const + { + return _useCustomMipMaps; + } + /// Return the stride of our base type in bytes. unsigned int getBaseStride() const; @@ -207,13 +218,14 @@ class MX_RENDER_API Image /// @} protected: - Image(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType); + Image(unsigned int width, unsigned int height, unsigned int channelCount, BaseType baseType, bool useCustomMipMaps); protected: unsigned int _width; unsigned int _height; unsigned int _channelCount; BaseType _baseType; + bool _useCustomMipMaps; void* _resourceBuffer; ImageBufferDeallocator _resourceBufferDeallocator; diff --git a/source/MaterialXRenderMsl/MetalTextureHandler.mm b/source/MaterialXRenderMsl/MetalTextureHandler.mm index 745019ac92..b80e8da540 100644 --- a/source/MaterialXRenderMsl/MetalTextureHandler.mm +++ b/source/MaterialXRenderMsl/MetalTextureHandler.mm @@ -154,7 +154,7 @@ (!generateMipMaps ? MTLTextureUsageRenderTarget : 0); texDesc.resourceOptions = MTLResourceStorageModePrivate; texDesc.pixelFormat = pixelFormat; - if(generateMipMaps) + if(generateMipMaps && !image->getUseCustomMipMaps()) { if(image->getChannelCount() == 1) { @@ -193,30 +193,40 @@ NSUInteger channelCount = image->getChannelCount(); - NSUInteger sourceBytesPerRow = - image->getWidth() * - channelCount * - getTextureBaseTypeSize(image->getBaseType()); - NSUInteger sourceBytesPerImage = - sourceBytesPerRow * - image->getHeight(); + int numBytesPerTexel = channelCount * getTextureBaseTypeSize(image->getBaseType()); + int numUploadMips = image->getUseCustomMipMaps() ? image->getMaxMipCount() : 1; + size_t numTexelsAcrossMips = 0; + if (image->getUseCustomMipMaps()) + { + int w = image->getWidth(); + int h = image->getHeight(); + while (w > 0 && h > 0) { + numTexelsAcrossMips += w * h; + w /= 2; + h /= 2; + } + } + else + { + numTexelsAcrossMips = image->getWidth() * image->getHeight(); + } std::vector rearrangedDataF; std::vector rearrangedDataC; void* imageData = image->getResourceBuffer(); + if ((pixelFormat == MTLPixelFormatRGBA32Float || pixelFormat == MTLPixelFormatRGBA8Unorm) && channelCount == 3) { bool isFloat = pixelFormat == MTLPixelFormatRGBA32Float; - sourceBytesPerRow = sourceBytesPerRow / 3 * 4; - sourceBytesPerImage = sourceBytesPerImage / 3 * 4; + numBytesPerTexel = numBytesPerTexel / 3 * 4; size_t srcIdx = 0; if(isFloat) { - rearrangedDataF.resize(sourceBytesPerImage / sizeof(float)); + rearrangedDataF.resize(numTexelsAcrossMips * numBytesPerTexel / sizeof(float)); for(size_t dstIdx = 0; dstIdx < rearrangedDataF.size(); ++dstIdx) { if((dstIdx & 0x3) == 3) @@ -232,7 +242,7 @@ } else { - rearrangedDataC.resize(sourceBytesPerImage); + rearrangedDataC.resize(numTexelsAcrossMips * numBytesPerTexel); for(size_t dstIdx = 0; dstIdx < rearrangedDataC.size(); ++dstIdx) { if((dstIdx & 0x3) == 3) @@ -253,22 +263,36 @@ id buffer = nil; if(imageData) { - buffer = [_device newBufferWithBytes:imageData - length:sourceBytesPerImage - options:MTLStorageModeShared]; - [blitCmdEncoder copyFromBuffer:buffer sourceOffset:0 - sourceBytesPerRow:sourceBytesPerRow - sourceBytesPerImage:sourceBytesPerImage - sourceSize:MTLSizeMake(image->getWidth(), image->getHeight(), 1) - toTexture:texture - destinationSlice:0 - destinationLevel:0 - destinationOrigin:MTLOriginMake(0, 0, 0)]; + buffer = [_device + newBufferWithBytes:imageData + length:(numTexelsAcrossMips * numBytesPerTexel) + options:MTLStorageModeShared]; + int width = image->getWidth(); + int height = image->getHeight(); + int sourceOffset = 0; + for (int mipLevel = 0; mipLevel < numUploadMips; mipLevel++) + { + NSUInteger sourceBytesPerRow = width * numBytesPerTexel; + NSUInteger sourceBytesPerImage = height * sourceBytesPerRow; + [blitCmdEncoder + copyFromBuffer:buffer + sourceOffset:sourceOffset + sourceBytesPerRow:sourceBytesPerRow + sourceBytesPerImage:sourceBytesPerImage + sourceSize:MTLSizeMake(width, height, 1) + toTexture:texture + destinationSlice:0 + destinationLevel:mipLevel + destinationOrigin:MTLOriginMake(0, 0, 0)]; + sourceOffset += width * height * numBytesPerTexel; + width = width / 2; + height = height / 2; + } } - if(generateMipMaps && image->getMaxMipCount() > 1) + if(generateMipMaps && !image->getUseCustomMipMaps() && image->getMaxMipCount() > 1) [blitCmdEncoder generateMipmapsForTexture:texture]; - + [blitCmdEncoder endEncoding]; [cmdBuffer commit]; diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 6346658d07..bed36fd8b3 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -445,12 +445,68 @@ void Viewer::initialize() void Viewer::loadEnvironmentLight() { // Load the requested radiance map. - mx::ImagePtr envRadianceMap = _imageHandler->acquireImage(_envRadianceFilename); - if (!envRadianceMap) - { - new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Failed to load environment light"); - return; + // mx::ImagePtr envRadianceMap = _imageHandler->acquireImage(_envRadianceFilename); + // if (!envRadianceMap) + // { + // new ng::MessageDialog(this, ng::MessageDialog::Type::Warning, "Failed to load environment light"); + // return; + // } + mx::ImagePtr envRadianceMap = mx::Image::create(1024, 1024, 4, mx::Image::BaseType::UINT8, true); + envRadianceMap->createResourceBuffer(); + { + int numMips = envRadianceMap->getMaxMipCount(); + int w = envRadianceMap->getWidth(); + int h = envRadianceMap->getHeight(); + char* writePtr = (char*)envRadianceMap->getResourceBuffer(); + for (int i = 0; i < numMips; i++) + { + uint8_t color[4] = { 0, 0, 0, 255}; + switch (i) + { + case 0: + color[0] = 255; + break; + case 1: + color[1] = 255; + break; + case 2: + color[2] = 255; + break; + case 3: + color[0] = 255; + color[1] = 255; + break; + case 4: + color[0] = 255; + color[2] = 255; + break; + case 5: + color[1] = 255; + color[2] = 255; + break; + case 6: + color[0] = 255; + color[1] = 255; + color[2] = 255; + break; + } + + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + writePtr[0] = color[0]; + writePtr[1] = color[1]; + writePtr[2] = color[2]; + writePtr[3] = color[3]; + writePtr += 4; + } + } + w = w/2; + h = h/2; + } } +// envRadianceMap->setUniformColor(mx::Color4(0.0f, 1.0f, 0.0f, 1.0f)); // If requested, normalize the environment upon loading. if (_normalizeEnvironment) @@ -837,12 +893,10 @@ void Viewer::createAdvancedSettings(Widget* parent) lightingLabel->set_font_size(20); lightingLabel->set_font("sans-bold"); - ng::CheckBox* directLightingBox = new ng::CheckBox(advancedPopup, "Direct Lighting"); - directLightingBox->set_checked(_lightHandler->getDirectLighting()); - directLightingBox->set_callback([this](bool enable) - { - _lightHandler->setDirectLighting(enable); - }); + // --------- + // Don't commit this + _lightHandler->setDirectLighting(false); + // --------- ng::CheckBox* indirectLightingBox = new ng::CheckBox(advancedPopup, "Indirect Lighting"); indirectLightingBox->set_checked(_lightHandler->getIndirectLighting());