Skip to content

Commit 6cb824e

Browse files
committed
Implemented tonemapping.
To use tonemapping, the user needs to supply one or more functions computing the effective output data from the raw data: One or three functions to manipulate the colour data, and optionally a second or fourth function to manipulate the transparency. By default, each function takes the corresponding channel's raw data as a single parameter, but the user can specify a different set of data to be passed to all functions. The syntax is `global_settings { tonemapping { parameters { CHANNEL ... } FUNCTION ... } }`, where each `CHANNEL` may be any of `channel` (for the channel's raw data), `red`, `green`, `blue`, `filter` (for the named channel's raw data), `gray`, `grey` (for the raw grayscale value), 'x', 'y' (for the screen coordinate ranging from left/top = 0 to right/bottom = 1). each `FUNCTION` may take either the form `function { EXPRESSION }` or `function(IDENTIFIERS) { EXPRESSION }`, with the latter form allowing to specify the identifiers by which the chosen data channels will be referred to in EXPRESSION (defaulting to `x`, `y` and `z`).
1 parent 0a062cc commit 6cb824e

File tree

10 files changed

+211
-6
lines changed

10 files changed

+211
-6
lines changed

source/base/version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
#define OFFICIAL_VERSION_STRING "3.7.1"
4646
#define OFFICIAL_VERSION_NUMBER 371
4747

48-
#define POV_RAY_PRERELEASE "alpha.8514084"
48+
#define POV_RAY_PRERELEASE "alpha.8558038"
4949

5050
#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
5151
#ifdef POV_RAY_PRERELEASE

source/core/render/tracepixel.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include "core/render/trace.h"
5555
#include "core/scene/object.h"
5656
#include "core/scene/scenedata.h"
57+
#include "core/scene/tracethreaddata.h"
5758
#include "core/shape/mesh.h"
5859

5960
// this must be the last file included
@@ -308,6 +309,55 @@ void TracePixel::operator()(DBL x, DBL y, DBL width, DBL height, RGBTColour& col
308309
}
309310
else
310311
TraceRayWithFocalBlur(colour, x, y, width, height);
312+
313+
RGBTColour computedColour(colour);
314+
for (int iResultChannel = 0; iResultChannel < kResultChannelIdCount; ++iResultChannel)
315+
{
316+
if (sceneData->tonemappingFunctions[iResultChannel])
317+
{
318+
sceneData->tonemappingFunctions[iResultChannel]->InitArguments(threadData->functionContext);
319+
for (vector<DataChannelId>::iterator iParameter = sceneData->tonemappingParameters.begin(); iParameter != sceneData->tonemappingParameters.end(); ++iParameter)
320+
{
321+
COLC data;
322+
switch (*iParameter)
323+
{
324+
case kDataChannelRed:
325+
case kDataChannelGreen:
326+
case kDataChannelBlue:
327+
data = computedColour.rgb()[*iParameter];
328+
break;
329+
case kDataChannelTransmit:
330+
data = computedColour.transm();
331+
break;
332+
case kDataChannelCurrent:
333+
data = computedColour.rgb()[iResultChannel];
334+
break;
335+
case kDataChannelGray:
336+
data = computedColour.Greyscale();
337+
break;
338+
case kDataChannelX:
339+
data = x/width;
340+
break;
341+
case kDataChannelY:
342+
data = y/height;
343+
break;
344+
}
345+
sceneData->tonemappingFunctions[iResultChannel]->PushArgument(threadData->functionContext, data);
346+
}
347+
COLC result = sceneData->tonemappingFunctions[iResultChannel]->Execute(threadData->functionContext);
348+
switch (iResultChannel)
349+
{
350+
case kDataChannelRed:
351+
case kDataChannelGreen:
352+
case kDataChannelBlue:
353+
colour.rgb()[iResultChannel] = result;
354+
break;
355+
case kDataChannelTransmit:
356+
colour.transm() = result;
357+
break;
358+
}
359+
}
360+
}
311361
}
312362

313363
bool TracePixel::CreateCameraRay(Ray& ray, DBL x, DBL y, DBL width, DBL height, size_t ray_number)

source/core/scene/scenedata.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ SceneData::SceneData() :
100100
removeBounds = true;
101101

102102
tree = NULL;
103+
104+
for (unsigned int i = 0; i < kResultChannelIdCount; ++i)
105+
tonemappingFunctions[i] = NULL;
103106
}
104107

105108
SceneData::~SceneData()
@@ -130,6 +133,10 @@ SceneData::~SceneData()
130133

131134
if(tree != NULL)
132135
delete tree;
136+
137+
for (unsigned int i = 0; i < kResultChannelIdCount; ++i)
138+
if (tonemappingFunctions[i])
139+
delete tonemappingFunctions[i];
133140
}
134141

135142
}

source/core/scene/scenedata.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,30 @@ namespace pov
5050

5151
using namespace pov_base;
5252

53+
enum ResultChannelId
54+
{
55+
// first three must match RGBColour channels
56+
kResultChannelRed,
57+
kResultChannelGreen,
58+
kResultChannelBlue,
59+
kResultChannelTransmit,
60+
kResultChannelIdCount
61+
};
62+
63+
enum DataChannelId
64+
{
65+
// first three must match RGBColour channels
66+
kDataChannelRed,
67+
kDataChannelGreen,
68+
kDataChannelBlue,
69+
kDataChannelTransmit,
70+
kDataChannelCurrent,
71+
kDataChannelGray,
72+
kDataChannelX,
73+
kDataChannelY,
74+
kDataChannelIdCount
75+
};
76+
5377
class BSPTree;
5478

5579
struct Fog_Struct;
@@ -219,6 +243,9 @@ class SceneData
219243
unsigned int nodes, splitNodes, objectNodes, emptyNodes, maxObjects, maxDepth, aborts;
220244
float averageObjects, averageDepth, averageAborts, averageAbortObjects;
221245

246+
GenericScalarFunctionPtr tonemappingFunctions[kResultChannelIdCount];
247+
vector<DataChannelId> tonemappingParameters;
248+
222249
// ********************************************************************************
223250
// ********************************************************************************
224251

source/parser/parser.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ void Parser::Run()
290290
strcat(str, str [0] ? ", function '.hf'" : "function '.hf'");
291291
if(mExperimentalFlags.meshCamera)
292292
strcat(str, str [0] ? ", mesh camera" : "mesh camera");
293+
if(mExperimentalFlags.tonemapping)
294+
strcat(str, str [0] ? ", tonemapping" : "tonemapping");
293295
if(mExperimentalFlags.slopeAltitude)
294296
strcat(str, str [0] ? ", slope pattern altitude" : "slope pattern altitude");
295297
if(mExperimentalFlags.spline)
@@ -7416,6 +7418,115 @@ void Parser::Parse_Global_Settings()
74167418
Parse_End();
74177419
END_CASE
74187420

7421+
CASE (TONEMAPPING_TOKEN)
7422+
mExperimentalFlags.tonemapping = true;
7423+
Parse_Begin();
7424+
{
7425+
unsigned int numChannels = 0;
7426+
unsigned int numParameters;
7427+
DataChannelId parameterId;
7428+
sceneData->tonemappingParameters.clear();
7429+
sceneData->tonemappingParameters.push_back(kDataChannelCurrent);
7430+
GenericScalarFunctionPtr pFn = NULL;
7431+
vector<GenericScalarFunctionPtr> apFn;
7432+
EXPECT
7433+
CASE (PARAMETERS_TOKEN)
7434+
sceneData->tonemappingParameters.clear();
7435+
Parse_Begin();
7436+
EXPECT
7437+
CASE (COLOUR_KEY_TOKEN)
7438+
switch(Token.Function_Id)
7439+
{
7440+
case RED_TOKEN: parameterId = kDataChannelRed; break;
7441+
case GREEN_TOKEN: parameterId = kDataChannelGreen; break;
7442+
case BLUE_TOKEN: parameterId = kDataChannelBlue; break;
7443+
case GRAY_TOKEN: parameterId = kDataChannelGray; break;
7444+
case TRANSMIT_TOKEN: parameterId = kDataChannelTransmit; break;
7445+
default: parameterId = kDataChannelIdCount; break; // indicates an invalid keyword
7446+
}
7447+
if (parameterId == kDataChannelIdCount)
7448+
{
7449+
UNGET
7450+
EXIT
7451+
}
7452+
sceneData->tonemappingParameters.push_back(parameterId);
7453+
Parse_Comma();
7454+
END_CASE
7455+
CASE (VECTOR_FUNCT_TOKEN)
7456+
switch(Token.Function_Id)
7457+
{
7458+
case X_TOKEN: parameterId = kDataChannelX; break;
7459+
case Y_TOKEN: parameterId = kDataChannelY; break;
7460+
default: parameterId = kDataChannelIdCount; break; // indicates an invalid keyword
7461+
}
7462+
if (parameterId == kDataChannelIdCount)
7463+
{
7464+
UNGET
7465+
EXIT
7466+
}
7467+
sceneData->tonemappingParameters.push_back(parameterId);
7468+
Parse_Comma();
7469+
END_CASE
7470+
CASE (CHANNEL_TOKEN)
7471+
sceneData->tonemappingParameters.push_back(kDataChannelCurrent);
7472+
Parse_Comma();
7473+
END_CASE
7474+
OTHERWISE
7475+
UNGET
7476+
EXIT
7477+
END_CASE
7478+
END_EXPECT
7479+
Parse_End();
7480+
END_CASE
7481+
CASE (FUNCTION_TOKEN)
7482+
apFn.push_back(new FunctionVM::CustomFunction(fnVMContext->functionvm, Parse_Function(true)));
7483+
END_CASE
7484+
OTHERWISE
7485+
UNGET
7486+
EXIT
7487+
END_CASE
7488+
END_EXPECT
7489+
switch (apFn.size())
7490+
{
7491+
case 0:
7492+
Error("Must have at least one function in tonemapping.");
7493+
break;
7494+
case 1:
7495+
// If a single function is supplied, it is applied to all colour channels.
7496+
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
7497+
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[0]->Clone();
7498+
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[0]->Clone();
7499+
sceneData->tonemappingFunctions[kResultChannelTransmit] = NULL;
7500+
break;
7501+
case 2:
7502+
// If two functions are supplied, the first one is applied to all colour channels and the second to the transmit channel.
7503+
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
7504+
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[0]->Clone();
7505+
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[0]->Clone();
7506+
sceneData->tonemappingFunctions[kResultChannelTransmit] = apFn[1];
7507+
break;
7508+
case 3:
7509+
// If three functions are supplied, they are applied to the colour channels.
7510+
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
7511+
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[1];
7512+
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[2];
7513+
sceneData->tonemappingFunctions[kResultChannelTransmit] = NULL;
7514+
break;
7515+
case 4:
7516+
// If four functions are supplied, the first three are applied to the colour channels and the last one to the transmit channel.
7517+
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
7518+
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[1];
7519+
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[2];
7520+
sceneData->tonemappingFunctions[kResultChannelTransmit] = apFn[3];
7521+
break;
7522+
default:
7523+
Error("Too many functions in tonemapping.");
7524+
break;
7525+
}
7526+
}
7527+
Parse_End();
7528+
END_CASE
7529+
74197530
OTHERWISE
74207531
UNGET
74217532
EXIT

source/parser/parser.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ struct ExperimentalFlags
157157
bool backsideIllumination : 1;
158158
bool functionHf : 1;
159159
bool meshCamera : 1;
160+
bool tonemapping : 1;
160161
bool slopeAltitude : 1;
161162
bool spline : 1;
162163
bool subsurface : 1;
@@ -167,6 +168,7 @@ struct ExperimentalFlags
167168
backsideIllumination(false),
168169
functionHf(false),
169170
meshCamera(false),
171+
tonemapping(false),
170172
slopeAltitude(false),
171173
spline(false),
172174
subsurface(false),
@@ -415,7 +417,7 @@ class Parser : public SceneTask
415417
DBL Parse_Signed_Float(void);
416418

417419
// function.h/function.cpp
418-
FUNCTION_PTR Parse_Function(void);
420+
FUNCTION_PTR Parse_Function(bool allowParameters = false);
419421
FUNCTION_PTR Parse_FunctionContent(void);
420422
FUNCTION_PTR Parse_FunctionOrContent(void);
421423
void Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count);

source/parser/parser_functions_utilities.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,15 +82,17 @@ namespace pov
8282
*
8383
******************************************************************************/
8484

85-
FUNCTION_PTR Parser::Parse_Function(void)
85+
FUNCTION_PTR Parser::Parse_Function(bool allowParameters)
8686
{
8787
FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID");
8888
ExprNode *expression = NULL;
8989
FunctionCode function;
90+
FNCode f(this, &function, false, NULL);
9091

91-
Parse_Begin();
92+
if (allowParameters)
93+
f.Parameter();
9294

93-
FNCode f(this, &function, false, NULL);
95+
Parse_Begin();
9496

9597
expression = FNSyntax_ParseExpression();
9698
f.Compile(expression);

source/parser/reservedwords.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
127127
{CAUSTICS_TOKEN, "caustics"},
128128
{CEIL_TOKEN, "ceil"},
129129
{CELLS_TOKEN, "cells"},
130+
{CHANNEL_TOKEN, "channel"},
130131
{CHARSET_TOKEN, "charset"},
131132
{CHECKER_TOKEN, "checker"},
132133
{CHR_TOKEN, "chr"},
@@ -396,6 +397,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
396397
{PANORAMIC_TOKEN, "panoramic"},
397398
{PARALLEL_TOKEN, "parallel"},
398399
{PARAMETER_ID_TOKEN, "parameter identifier"},
400+
{PARAMETERS_TOKEN, "parameters"},
399401
{PARAMETRIC_TOKEN,"parametric"},
400402
{PASS_THROUGH_TOKEN, "pass_through"},
401403
{PATTERN_TOKEN, "pattern"},
@@ -573,6 +575,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
573575
{TNORMAL_ID_TOKEN, "normal identifier"},
574576
{TNORMAL_TOKEN, "normal"},
575577
{TOLERANCE_TOKEN, "tolerance"},
578+
{TONEMAPPING_TOKEN, "tonemapping"},
576579
{TOROIDAL_TOKEN, "toroidal"},
577580
{TORUS_TOKEN, "torus"},
578581
{TRACE_TOKEN, "trace"},

source/parser/reservedwords.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ enum TOKEN_IDS
186186
CAMERA_ID_TOKEN,
187187
CAMERA_TOKEN,
188188
CELLS_TOKEN,
189+
CHANNEL_TOKEN,
189190
CHECKER_TOKEN,
190191
CLIPPED_BY_TOKEN,
191192
COLON_TOKEN,
@@ -270,6 +271,7 @@ enum TOKEN_IDS
270271
ONION_TOKEN,
271272
OPTIONAL_TOKEN,
272273
OVUS_TOKEN,
274+
PARAMETERS_TOKEN,
273275
PERCENT_TOKEN,
274276
PHASE_TOKEN,
275277
PHONG_SIZE_TOKEN,
@@ -332,6 +334,7 @@ enum TOKEN_IDS
332334
TILES_TOKEN,
333335
TNORMAL_ID_TOKEN,
334336
TNORMAL_TOKEN,
337+
TONEMAPPING_TOKEN,
335338
TORUS_TOKEN,
336339
TRANSFORM_ID_TOKEN,
337340
TRANSFORM_TOKEN,

unix/VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.7.1-alpha.8514084
1+
3.7.1-alpha.8558038

0 commit comments

Comments
 (0)