Skip to content
Snippets Groups Projects
Commit d8f04c76 authored by Ben Heasly's avatar Ben Heasly
Browse files

new example about luminance scaling across renderings

parent 42444891
No related branches found
No related tags found
No related merge requests found
......@@ -29,9 +29,4 @@ else
originalMappings = {};
end
if ~iscell(originalMappings)
error('parseJsonMappings:invalidJson', ...
'Could not load mappings cell from JSON <%s>\n', fileName);
end
mappings = rtbValidateMappings(originalMappings);
File added
File added
%%% RenderToolbox4 Copyright (c) 2012-2016 The RenderToolbox Team{1}.
%%% About Us://github.com/RenderToolbox/RenderToolbox4/wiki/About-Us
%%% RenderToolbox4 is released under the MIT License. See LICENSE file.
%
%% Render the LuminanceScaling scene.
clear;
%% Choose example file.
parentSceneFile = 'LuminanceScaling.blend';
%% Choose batch renderer options.
hints.imageWidth = 320;
hints.imageHeight = 240;
hints.fov = deg2rad(36);
hints.recipeName = 'rtbMakeLuminanceScaling';
hints.renderer = 'Mitsuba';
recipeFolder = rtbWorkingFolder('hints', hints);
%% Mappings to turn spheres into area lights.
m{1}.broadType = 'meshes';
m{1}.name = 'LeftSphere';
m{1}.operation = 'blessAsAreaLight';
m{1}.properties = rtbMappingProperty( ...
'name', 'intensity', ...
'valueType', 'spectrum', ...
'value', '300:0 800:(intensity)');
m{2}.broadType = 'meshes';
m{2}.name = 'RightSphere';
m{2}.operation = 'blessAsAreaLight';
m{2}.properties = rtbMappingProperty( ...
'name', 'intensity', ...
'valueType', 'spectrum', ...
'value', '300:100 800:0');
m{3}.broadType = 'materials';
m{3}.specificType = 'matte';
m{3}.name = 'Backdrop';
m{3}.operation = 'update';
m{3}.properties = rtbMappingProperty( ...
'name', 'diffuseReflectance', ...
'valueType', 'spectrum', ...
'value', 'mccBabel-1.spd');
mappingsFile = fullfile(recipeFolder, 'LuminanceScalingMappings.json');
rtbWriteJson(m, 'fileName', mappingsFile);
%% Conditions to vary the intensity of one light.
names = {'intensity'};
intensities = {1, 10, 100, 1000}';
conditionsFile = fullfile(recipeFolder, 'LuminanceScalingConditions.txt');
rtbWriteConditionsFile(conditionsFile, names, intensities);
%% Render.
nativeSceneFiles = rtbMakeSceneFiles(parentSceneFile, ...
'mappingsFile', mappingsFile, ...
'conditionsFile', conditionsFile, ...
'hints', hints);
radianceDataFiles = rtbBatchRender(nativeSceneFiles, 'hints', hints);
%% Choose scaling and tone mapping based on the last rendering.
calibrationRendering = load(radianceDataFiles{end});
% convert to sRGB with scaling by max luminance
% obtain the XYZ image and scaling facotr used internally
[~, XYZImage, ~, scaleFactor] = rtbMultispectralToSRGB( ...
calibrationRendering.multispectralImage, ...
calibrationRendering.S, ...
'isScale', true);
% choose a tone mapping threshold from the returned XYZ image
luminance = XYZImage(:,:,2);
toneMapThreshold = 100 * mean(luminance(:));
%% Convert each rendering to sRGB with constant scaling and tone mapping.
nRenderings = numel(radianceDataFiles);
nRows = 2;
nColumns = ceil(nRenderings / nRows);
for rr = 1:nRenderings
rendering = load(radianceDataFiles{rr});
sRGBImage = rtbMultispectralToSRGB( ...
rendering.multispectralImage, ...
rendering.S, ...
'scaleFactor', scaleFactor, ...
'toneMapThreshold', toneMapThreshold);
subplot(nRows, nColumns, rr);
imshow(uint8(sRGBImage));
title(sprintf('left %d, right 100', intensities{rr}))
end
function [sRGBImage, XYZImage, rawRGBImage] = rtbMultispectralToSRGB(multispectralImage, S, varargin)
function [sRGBImage, XYZImage, rawRGBImage, scaleFactor] = rtbMultispectralToSRGB(multispectralImage, S, varargin)
% Convert multi-spectral image data to XYZ and sRGB.
%
% sRGBImage = rtbMultispectralToSRGB(multispectralImage, S)
......@@ -14,14 +14,29 @@ function [sRGBImage, XYZImage, rawRGBImage] = rtbMultispectralToSRGB(multispectr
% this factor times the mean luminance. The default is 0, don't truncate
% luminances.
%
% sRGBImage = rtbMultispectralToSRGB( ... 'toneMapThreshold', toneMapThreshold)
% specifies a simple tone mapping threshold. Truncates lumininces above
% the given toneMapThreshold. The default is 0, don't truncate luminances.
%
% If toneMapFactor and toneMapThreshold are both supplied, toneMapThreshold
% is used and toneMapFactor is ignored.
%
% sRGBImage = rtbMultispectralToSRGB( ... 'isScale', isScale)
% specifies whether to scale the gamma-corrected image to the display
% maximum (true) or not (false). The default is false, don't scale the
% image.
%
% sRGBImage = rtbMultispectralToSRGB( ... 'scaleFactor', scaleFactor)
% specifies a constant to scale the sRGB image. The default is 0, don't
% scale the image.
%
% If isScale and scaleFactor are both supplied, scaleFactor
% is used and toneMapFactor is isScale.
%
% Returns a gamma-corrected sRGB image of size [height width 3]. Also
% returns the intermediate XYZ image and the uncorrected RGB image, which
% have the same size.
% have the same size. Also returns the scale factor that was used to
% scale the sRGB image, if any.
%
%%% RenderToolbox4 Copyright (c) 2012-2016 The RenderToolbox Team.
%%% About Us://github.com/RenderToolbox/RenderToolbox4/wiki/About-Us
......@@ -31,12 +46,16 @@ parser = inputParser();
parser.addRequired('multispectralImage', @isnumeric);
parser.addRequired('S', @isnumeric);
parser.addParameter('toneMapFactor', 0, @isnumeric);
parser.addParameter('toneMapThreshold', 0, @isnumeric);
parser.addParameter('isScale', false, @islogical);
parser.addParameter('scaleFactor', 0, @isnumeric);
parser.parse(multispectralImage, S, varargin{:});
multispectralImage = parser.Results.multispectralImage;
S = parser.Results.S;
toneMapFactor = parser.Results.toneMapFactor;
toneMapThreshold = parser.Results.toneMapThreshold;
isScale = parser.Results.isScale;
scaleFactor = parser.Results.scaleFactor;
% convert to CIE XYZ image using CIE 1931 standard weighting functions
% 683 converts watt-valued spectra to lumen-valued luminances (Y-values)
......@@ -49,6 +68,8 @@ XYZImage = rtbMultispectralToSensorImage(multispectralImage, S, ...
% convert to sRGB with a very simple tone mapping algorithm that truncates
% luminance above a factor times the mean luminance
[sRGBImage, rawRGBImage] = rtbXYZToSRGB(XYZImage, ...
[sRGBImage, rawRGBImage, scaleFactor] = rtbXYZToSRGB(XYZImage, ...
'toneMapFactor', toneMapFactor, ...
'isScale', isScale);
'toneMapThreshold', toneMapThreshold, ...
'isScale', isScale, ...
'scaleFactor', scaleFactor);
......@@ -10,14 +10,23 @@ function [gammaImage, rawImage, scaleFactor] = rtbXYZToSRGB(image, varargin)
% for simple tone mapping -- luminance will be trncated above this factor
% times the mean luminance. The default is 0, don't do this tone mapping.
%
% rtbXYZToSRGB( ... 'toneMapMax', toneMapMax) specifies a threshold for an
% even simpler tone mapping -- truncate luminance above this value. The
% default is 0, don't do this tone mapping.
% sRGBImage = rtbXYZToSRGB( ... 'toneMapThreshold', toneMapThreshold)
% specifies a simple tone mapping threshold. Truncates lumininces above
% the given toneMapThreshold. The default is 0, don't truncate luminances.
%
% If toneMapFactor and toneMapThreshold are both supplied, toneMapThreshold
% is used and toneMapFactor is ignored.
%
% rtbXYZToSRGB( ... 'isScale', isScale) specifies whether to scale the
% gamma-corrected image. If isScale is logical and true, the image will be
% scaled by its maximum. If isScale is a number, the image will be scaled
% by this number. The default is false, don't do any scaling.
% scaled by its maximum. The default is false, don't do any scaling.
%
% sRGBImage = rtbXYZToSRGB( ... 'scaleFactor', scaleFactor)
% specifies a constant to scale the sRGB image. The default is 0, don't
% scale the image.
%
% If isScale and scaleFactor are both supplied, scaleFactor
% is used and toneMapFactor is isScale.
%
% Returns a matrix of size [height width n] with gamma corrected sRGB color
% data. Also returns a matrix of the same size with uncorrected sRGB color
......@@ -32,13 +41,15 @@ function [gammaImage, rawImage, scaleFactor] = rtbXYZToSRGB(image, varargin)
parser = inputParser();
parser.addRequired('image', @isnumeric);
parser.addParameter('toneMapFactor', 0, @isnumeric);
parser.addParameter('toneMapMax', 0, @isnumeric);
parser.addParameter('isScale', false);
parser.addParameter('toneMapThreshold', 0, @isnumeric);
parser.addParameter('isScale', false, @islogical);
parser.addParameter('scaleFactor', 0, @isnumeric);
parser.parse(image, varargin{:});
image = parser.Results.image;
toneMapFactor = parser.Results.toneMapFactor;
toneMapMax = parser.Results.toneMapMax;
toneMapThreshold = parser.Results.toneMapThreshold;
isScale = parser.Results.isScale;
scaleFactor = parser.Results.scaleFactor;
%% Convert XYZ to sRGB
%
......@@ -53,30 +64,25 @@ isScale = parser.Results.isScale;
[XYZCalFormat,m,n] = ImageToCalFormat(image);
% Tone map. This is a very simple algorithm that truncates
% luminance above a factor times the mean luminance.
if (toneMapFactor > 0)
% luminance above threshold.
if (toneMapThreshold > 0)
XYZCalFormat = BasicToneMapCalFormat(XYZCalFormat, toneMapThreshold);
elseif (toneMapFactor > 0)
meanLuminance = mean(XYZCalFormat(2,:));
maxLum = toneMapFactor * meanLuminance;
XYZCalFormat = BasicToneMapCalFormat(XYZCalFormat, maxLum);
end
% Tone map again. This is an even simpler algorithm
% that truncates luminance above a fixed value.
if (toneMapMax > 0)
XYZCalFormat = BasicToneMapCalFormat(XYZCalFormat, toneMapMax);
end
% Convert to sRGB
% may allow code to scale input max to output max.
SRGBPrimaryCalFormat = XYZToSRGBPrimary(XYZCalFormat);
if islogical(isScale)
scaleFactor = 1/max(SRGBPrimaryCalFormat(:));
SRGBCalFormat = SRGBGammaCorrect(SRGBPrimaryCalFormat, isScale);
else
scaleFactor = isScale;
if scaleFactor > 0
SRGBPrimaryCalFormat = SRGBPrimaryCalFormat .* scaleFactor;
SRGBCalFormat = SRGBGammaCorrect(SRGBPrimaryCalFormat, false);
elseif islogical(isScale)
scaleFactor = 1/max(SRGBPrimaryCalFormat(:));
SRGBCalFormat = SRGBGammaCorrect(SRGBPrimaryCalFormat, isScale);
end
% Back to image plane format
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment