Skip to content

Commit

Permalink
Implemented tonemapping.
Browse files Browse the repository at this point in the history
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`).
  • Loading branch information
c-lipka committed Apr 9, 2016
1 parent 0a062cc commit 6cb824e
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 6 deletions.
2 changes: 1 addition & 1 deletion source/base/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#define OFFICIAL_VERSION_STRING "3.7.1"
#define OFFICIAL_VERSION_NUMBER 371

#define POV_RAY_PRERELEASE "alpha.8514084"
#define POV_RAY_PRERELEASE "alpha.8558038"

#if (POV_RAY_IS_AUTOBUILD == 1) && ((POV_RAY_IS_OFFICIAL == 1) || (POV_RAY_IS_SEMI_OFFICIAL == 1))
#ifdef POV_RAY_PRERELEASE
Expand Down
50 changes: 50 additions & 0 deletions source/core/render/tracepixel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "core/render/trace.h"
#include "core/scene/object.h"
#include "core/scene/scenedata.h"
#include "core/scene/tracethreaddata.h"
#include "core/shape/mesh.h"

// this must be the last file included
Expand Down Expand Up @@ -308,6 +309,55 @@ void TracePixel::operator()(DBL x, DBL y, DBL width, DBL height, RGBTColour& col
}
else
TraceRayWithFocalBlur(colour, x, y, width, height);

RGBTColour computedColour(colour);
for (int iResultChannel = 0; iResultChannel < kResultChannelIdCount; ++iResultChannel)
{
if (sceneData->tonemappingFunctions[iResultChannel])
{
sceneData->tonemappingFunctions[iResultChannel]->InitArguments(threadData->functionContext);
for (vector<DataChannelId>::iterator iParameter = sceneData->tonemappingParameters.begin(); iParameter != sceneData->tonemappingParameters.end(); ++iParameter)
{
COLC data;
switch (*iParameter)
{
case kDataChannelRed:
case kDataChannelGreen:
case kDataChannelBlue:
data = computedColour.rgb()[*iParameter];
break;
case kDataChannelTransmit:
data = computedColour.transm();
break;
case kDataChannelCurrent:
data = computedColour.rgb()[iResultChannel];
break;
case kDataChannelGray:
data = computedColour.Greyscale();
break;
case kDataChannelX:
data = x/width;
break;
case kDataChannelY:
data = y/height;
break;
}
sceneData->tonemappingFunctions[iResultChannel]->PushArgument(threadData->functionContext, data);
}
COLC result = sceneData->tonemappingFunctions[iResultChannel]->Execute(threadData->functionContext);
switch (iResultChannel)
{
case kDataChannelRed:
case kDataChannelGreen:
case kDataChannelBlue:
colour.rgb()[iResultChannel] = result;
break;
case kDataChannelTransmit:
colour.transm() = result;
break;
}
}
}
}

bool TracePixel::CreateCameraRay(Ray& ray, DBL x, DBL y, DBL width, DBL height, size_t ray_number)
Expand Down
7 changes: 7 additions & 0 deletions source/core/scene/scenedata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ SceneData::SceneData() :
removeBounds = true;

tree = NULL;

for (unsigned int i = 0; i < kResultChannelIdCount; ++i)
tonemappingFunctions[i] = NULL;
}

SceneData::~SceneData()
Expand Down Expand Up @@ -130,6 +133,10 @@ SceneData::~SceneData()

if(tree != NULL)
delete tree;

for (unsigned int i = 0; i < kResultChannelIdCount; ++i)
if (tonemappingFunctions[i])
delete tonemappingFunctions[i];
}

}
27 changes: 27 additions & 0 deletions source/core/scene/scenedata.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ namespace pov

using namespace pov_base;

enum ResultChannelId
{
// first three must match RGBColour channels
kResultChannelRed,
kResultChannelGreen,
kResultChannelBlue,
kResultChannelTransmit,
kResultChannelIdCount
};

enum DataChannelId
{
// first three must match RGBColour channels
kDataChannelRed,
kDataChannelGreen,
kDataChannelBlue,
kDataChannelTransmit,
kDataChannelCurrent,
kDataChannelGray,
kDataChannelX,
kDataChannelY,
kDataChannelIdCount
};

class BSPTree;

struct Fog_Struct;
Expand Down Expand Up @@ -219,6 +243,9 @@ class SceneData
unsigned int nodes, splitNodes, objectNodes, emptyNodes, maxObjects, maxDepth, aborts;
float averageObjects, averageDepth, averageAborts, averageAbortObjects;

GenericScalarFunctionPtr tonemappingFunctions[kResultChannelIdCount];
vector<DataChannelId> tonemappingParameters;

// ********************************************************************************
// ********************************************************************************

Expand Down
111 changes: 111 additions & 0 deletions source/parser/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ void Parser::Run()
strcat(str, str [0] ? ", function '.hf'" : "function '.hf'");
if(mExperimentalFlags.meshCamera)
strcat(str, str [0] ? ", mesh camera" : "mesh camera");
if(mExperimentalFlags.tonemapping)
strcat(str, str [0] ? ", tonemapping" : "tonemapping");
if(mExperimentalFlags.slopeAltitude)
strcat(str, str [0] ? ", slope pattern altitude" : "slope pattern altitude");
if(mExperimentalFlags.spline)
Expand Down Expand Up @@ -7416,6 +7418,115 @@ void Parser::Parse_Global_Settings()
Parse_End();
END_CASE

CASE (TONEMAPPING_TOKEN)
mExperimentalFlags.tonemapping = true;
Parse_Begin();
{
unsigned int numChannels = 0;
unsigned int numParameters;
DataChannelId parameterId;
sceneData->tonemappingParameters.clear();
sceneData->tonemappingParameters.push_back(kDataChannelCurrent);
GenericScalarFunctionPtr pFn = NULL;
vector<GenericScalarFunctionPtr> apFn;
EXPECT
CASE (PARAMETERS_TOKEN)
sceneData->tonemappingParameters.clear();
Parse_Begin();
EXPECT
CASE (COLOUR_KEY_TOKEN)
switch(Token.Function_Id)
{
case RED_TOKEN: parameterId = kDataChannelRed; break;
case GREEN_TOKEN: parameterId = kDataChannelGreen; break;
case BLUE_TOKEN: parameterId = kDataChannelBlue; break;
case GRAY_TOKEN: parameterId = kDataChannelGray; break;
case TRANSMIT_TOKEN: parameterId = kDataChannelTransmit; break;
default: parameterId = kDataChannelIdCount; break; // indicates an invalid keyword
}
if (parameterId == kDataChannelIdCount)
{
UNGET
EXIT
}
sceneData->tonemappingParameters.push_back(parameterId);
Parse_Comma();
END_CASE
CASE (VECTOR_FUNCT_TOKEN)
switch(Token.Function_Id)
{
case X_TOKEN: parameterId = kDataChannelX; break;
case Y_TOKEN: parameterId = kDataChannelY; break;
default: parameterId = kDataChannelIdCount; break; // indicates an invalid keyword
}
if (parameterId == kDataChannelIdCount)
{
UNGET
EXIT
}
sceneData->tonemappingParameters.push_back(parameterId);
Parse_Comma();
END_CASE
CASE (CHANNEL_TOKEN)
sceneData->tonemappingParameters.push_back(kDataChannelCurrent);
Parse_Comma();
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
Parse_End();
END_CASE
CASE (FUNCTION_TOKEN)
apFn.push_back(new FunctionVM::CustomFunction(fnVMContext->functionvm, Parse_Function(true)));
END_CASE
OTHERWISE
UNGET
EXIT
END_CASE
END_EXPECT
switch (apFn.size())
{
case 0:
Error("Must have at least one function in tonemapping.");
break;
case 1:
// If a single function is supplied, it is applied to all colour channels.
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[0]->Clone();
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[0]->Clone();
sceneData->tonemappingFunctions[kResultChannelTransmit] = NULL;
break;
case 2:
// If two functions are supplied, the first one is applied to all colour channels and the second to the transmit channel.
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[0]->Clone();
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[0]->Clone();
sceneData->tonemappingFunctions[kResultChannelTransmit] = apFn[1];
break;
case 3:
// If three functions are supplied, they are applied to the colour channels.
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[1];
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[2];
sceneData->tonemappingFunctions[kResultChannelTransmit] = NULL;
break;
case 4:
// If four functions are supplied, the first three are applied to the colour channels and the last one to the transmit channel.
sceneData->tonemappingFunctions[kResultChannelRed] = apFn[0];
sceneData->tonemappingFunctions[kResultChannelGreen] = apFn[1];
sceneData->tonemappingFunctions[kResultChannelBlue] = apFn[2];
sceneData->tonemappingFunctions[kResultChannelTransmit] = apFn[3];
break;
default:
Error("Too many functions in tonemapping.");
break;
}
}
Parse_End();
END_CASE

OTHERWISE
UNGET
EXIT
Expand Down
4 changes: 3 additions & 1 deletion source/parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ struct ExperimentalFlags
bool backsideIllumination : 1;
bool functionHf : 1;
bool meshCamera : 1;
bool tonemapping : 1;
bool slopeAltitude : 1;
bool spline : 1;
bool subsurface : 1;
Expand All @@ -167,6 +168,7 @@ struct ExperimentalFlags
backsideIllumination(false),
functionHf(false),
meshCamera(false),
tonemapping(false),
slopeAltitude(false),
spline(false),
subsurface(false),
Expand Down Expand Up @@ -415,7 +417,7 @@ class Parser : public SceneTask
DBL Parse_Signed_Float(void);

// function.h/function.cpp
FUNCTION_PTR Parse_Function(void);
FUNCTION_PTR Parse_Function(bool allowParameters = false);
FUNCTION_PTR Parse_FunctionContent(void);
FUNCTION_PTR Parse_FunctionOrContent(void);
void Parse_FunctionOrContentList(GenericScalarFunctionPtr* apFn, unsigned int count);
Expand Down
8 changes: 5 additions & 3 deletions source/parser/parser_functions_utilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,17 @@ namespace pov
*
******************************************************************************/

FUNCTION_PTR Parser::Parse_Function(void)
FUNCTION_PTR Parser::Parse_Function(bool allowParameters)
{
FUNCTION_PTR ptr = (FUNCTION_PTR)POV_MALLOC(sizeof(FUNCTION), "Function ID");
ExprNode *expression = NULL;
FunctionCode function;
FNCode f(this, &function, false, NULL);

Parse_Begin();
if (allowParameters)
f.Parameter();

FNCode f(this, &function, false, NULL);
Parse_Begin();

expression = FNSyntax_ParseExpression();
f.Compile(expression);
Expand Down
3 changes: 3 additions & 0 deletions source/parser/reservedwords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
{CAUSTICS_TOKEN, "caustics"},
{CEIL_TOKEN, "ceil"},
{CELLS_TOKEN, "cells"},
{CHANNEL_TOKEN, "channel"},
{CHARSET_TOKEN, "charset"},
{CHECKER_TOKEN, "checker"},
{CHR_TOKEN, "chr"},
Expand Down Expand Up @@ -396,6 +397,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
{PANORAMIC_TOKEN, "panoramic"},
{PARALLEL_TOKEN, "parallel"},
{PARAMETER_ID_TOKEN, "parameter identifier"},
{PARAMETERS_TOKEN, "parameters"},
{PARAMETRIC_TOKEN,"parametric"},
{PASS_THROUGH_TOKEN, "pass_through"},
{PATTERN_TOKEN, "pattern"},
Expand Down Expand Up @@ -573,6 +575,7 @@ const RESERVED_WORD Reserved_Words[LAST_TOKEN] = {
{TNORMAL_ID_TOKEN, "normal identifier"},
{TNORMAL_TOKEN, "normal"},
{TOLERANCE_TOKEN, "tolerance"},
{TONEMAPPING_TOKEN, "tonemapping"},
{TOROIDAL_TOKEN, "toroidal"},
{TORUS_TOKEN, "torus"},
{TRACE_TOKEN, "trace"},
Expand Down
3 changes: 3 additions & 0 deletions source/parser/reservedwords.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ enum TOKEN_IDS
CAMERA_ID_TOKEN,
CAMERA_TOKEN,
CELLS_TOKEN,
CHANNEL_TOKEN,
CHECKER_TOKEN,
CLIPPED_BY_TOKEN,
COLON_TOKEN,
Expand Down Expand Up @@ -270,6 +271,7 @@ enum TOKEN_IDS
ONION_TOKEN,
OPTIONAL_TOKEN,
OVUS_TOKEN,
PARAMETERS_TOKEN,
PERCENT_TOKEN,
PHASE_TOKEN,
PHONG_SIZE_TOKEN,
Expand Down Expand Up @@ -332,6 +334,7 @@ enum TOKEN_IDS
TILES_TOKEN,
TNORMAL_ID_TOKEN,
TNORMAL_TOKEN,
TONEMAPPING_TOKEN,
TORUS_TOKEN,
TRANSFORM_ID_TOKEN,
TRANSFORM_TOKEN,
Expand Down
2 changes: 1 addition & 1 deletion unix/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.7.1-alpha.8514084
3.7.1-alpha.8558038

0 comments on commit 6cb824e

Please sign in to comment.