Compositor: Full frame Mix node
Adds full frame implementation to this node operations. No functional changes. 2.3x faster than tiled fallback on average. Reviewed By: jbakker Differential Revision: https://developer.blender.org/D11686
This commit is contained in:
parent
300fe84bf0
commit
b35efa932e
|
@ -35,6 +35,7 @@ MixBaseOperation::MixBaseOperation()
|
|||
this->m_inputColor2Operation = nullptr;
|
||||
this->setUseValueAlphaMultiply(false);
|
||||
this->setUseClamp(false);
|
||||
flags.can_be_constant = true;
|
||||
}
|
||||
|
||||
void MixBaseOperation::initExecution()
|
||||
|
@ -97,6 +98,45 @@ void MixBaseOperation::deinitExecution()
|
|||
this->m_inputColor2Operation = nullptr;
|
||||
}
|
||||
|
||||
void MixBaseOperation::update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs)
|
||||
{
|
||||
const MemoryBuffer *input_value = inputs[0];
|
||||
const MemoryBuffer *input_color1 = inputs[1];
|
||||
const MemoryBuffer *input_color2 = inputs[2];
|
||||
const int width = BLI_rcti_size_x(&area);
|
||||
PixelCursor p;
|
||||
p.out_stride = output->elem_stride;
|
||||
p.value_stride = input_value->elem_stride;
|
||||
p.color1_stride = input_color1->elem_stride;
|
||||
p.color2_stride = input_color2->elem_stride;
|
||||
for (const int y : YRange(area)) {
|
||||
p.out = output->get_elem(area.xmin, y);
|
||||
p.row_end = p.out + width * output->elem_stride;
|
||||
p.value = input_value->get_elem(area.xmin, y);
|
||||
p.color1 = input_color1->get_elem(area.xmin, y);
|
||||
p.color2 = input_color2->get_elem(area.xmin, y);
|
||||
update_memory_buffer_row(p);
|
||||
}
|
||||
}
|
||||
|
||||
void MixBaseOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
p.out[0] = value_m * p.color1[0] + value * p.color2[0];
|
||||
p.out[1] = value_m * p.color1[1] + value * p.color2[1];
|
||||
p.out[2] = value_m * p.color1[2] + value * p.color2[2];
|
||||
p.out[3] = p.color1[3];
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Add Operation ******** */
|
||||
|
||||
void MixAddOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
|
||||
|
@ -121,6 +161,23 @@ void MixAddOperation::executePixelSampled(float output[4], float x, float y, Pix
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixAddOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
p.out[0] = p.color1[0] + value * p.color2[0];
|
||||
p.out[1] = p.color1[1] + value * p.color2[1];
|
||||
p.out[2] = p.color1[2] + value * p.color2[2];
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Blend Operation ******** */
|
||||
|
||||
void MixBlendOperation::executePixelSampled(float output[4],
|
||||
|
@ -150,6 +207,24 @@ void MixBlendOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixBlendOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
float value_m = 1.0f - value;
|
||||
p.out[0] = value_m * p.color1[0] + value * p.color2[0];
|
||||
p.out[1] = value_m * p.color1[1] + value * p.color2[1];
|
||||
p.out[2] = value_m * p.color1[2] + value * p.color2[2];
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Burn Operation ******** */
|
||||
|
||||
void MixColorBurnOperation::executePixelSampled(float output[4],
|
||||
|
@ -228,6 +303,48 @@ void MixColorBurnOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixColorBurnOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
float tmp = value_m + value * p.color2[0];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[0] = 0.0f;
|
||||
}
|
||||
else {
|
||||
tmp = 1.0f - (1.0f - p.color1[0]) / tmp;
|
||||
p.out[0] = CLAMPIS(tmp, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
tmp = value_m + value * p.color2[1];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[1] = 0.0f;
|
||||
}
|
||||
else {
|
||||
tmp = 1.0f - (1.0f - p.color1[1]) / tmp;
|
||||
p.out[1] = CLAMPIS(tmp, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
tmp = value_m + value * p.color2[2];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[2] = 0.0f;
|
||||
}
|
||||
else {
|
||||
tmp = 1.0f - (1.0f - p.color1[2]) / tmp;
|
||||
p.out[2] = CLAMPIS(tmp, 0.0f, 1.0f);
|
||||
}
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Color Operation ******** */
|
||||
|
||||
void MixColorOperation::executePixelSampled(float output[4],
|
||||
|
@ -268,6 +385,36 @@ void MixColorOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixColorOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
float colH, colS, colV;
|
||||
rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
|
||||
if (colS != 0.0f) {
|
||||
float rH, rS, rV;
|
||||
float tmpr, tmpg, tmpb;
|
||||
rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
|
||||
hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb);
|
||||
p.out[0] = (value_m * p.color1[0]) + (value * tmpr);
|
||||
p.out[1] = (value_m * p.color1[1]) + (value * tmpg);
|
||||
p.out[2] = (value_m * p.color1[2]) + (value * tmpb);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(p.out, p.color1);
|
||||
}
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Darken Operation ******** */
|
||||
|
||||
void MixDarkenOperation::executePixelSampled(float output[4],
|
||||
|
@ -296,6 +443,24 @@ void MixDarkenOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixDarkenOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
float value_m = 1.0f - value;
|
||||
p.out[0] = min_ff(p.color1[0], p.color2[0]) * value + p.color1[0] * value_m;
|
||||
p.out[1] = min_ff(p.color1[1], p.color2[1]) * value + p.color1[1] * value_m;
|
||||
p.out[2] = min_ff(p.color1[2], p.color2[2]) * value + p.color1[2] * value_m;
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Difference Operation ******** */
|
||||
|
||||
void MixDifferenceOperation::executePixelSampled(float output[4],
|
||||
|
@ -324,6 +489,24 @@ void MixDifferenceOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixDifferenceOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
p.out[0] = value_m * p.color1[0] + value * fabsf(p.color1[0] - p.color2[0]);
|
||||
p.out[1] = value_m * p.color1[1] + value * fabsf(p.color1[1] - p.color2[1]);
|
||||
p.out[2] = value_m * p.color1[2] + value * fabsf(p.color1[2] - p.color2[2]);
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Difference Operation ******** */
|
||||
|
||||
void MixDivideOperation::executePixelSampled(float output[4],
|
||||
|
@ -369,6 +552,41 @@ void MixDivideOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixDivideOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
if (p.color2[0] != 0.0f) {
|
||||
p.out[0] = value_m * (p.color1[0]) + value * (p.color1[0]) / p.color2[0];
|
||||
}
|
||||
else {
|
||||
p.out[0] = 0.0f;
|
||||
}
|
||||
if (p.color2[1] != 0.0f) {
|
||||
p.out[1] = value_m * (p.color1[1]) + value * (p.color1[1]) / p.color2[1];
|
||||
}
|
||||
else {
|
||||
p.out[1] = 0.0f;
|
||||
}
|
||||
if (p.color2[2] != 0.0f) {
|
||||
p.out[2] = value_m * (p.color1[2]) + value * (p.color1[2]) / p.color2[2];
|
||||
}
|
||||
else {
|
||||
p.out[2] = 0.0f;
|
||||
}
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Dodge Operation ******** */
|
||||
|
||||
void MixDodgeOperation::executePixelSampled(float output[4],
|
||||
|
@ -452,6 +670,64 @@ void MixDodgeOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixDodgeOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
|
||||
float tmp;
|
||||
if (p.color1[0] != 0.0f) {
|
||||
tmp = 1.0f - value * p.color2[0];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[0] = 1.0f;
|
||||
}
|
||||
else {
|
||||
p.out[0] = p.color1[0] / tmp;
|
||||
CLAMP_MAX(p.out[0], 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.out[0] = 0.0f;
|
||||
}
|
||||
|
||||
if (p.color1[1] != 0.0f) {
|
||||
tmp = 1.0f - value * p.color2[1];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[1] = 1.0f;
|
||||
}
|
||||
else {
|
||||
p.out[1] = p.color1[1] / tmp;
|
||||
CLAMP_MAX(p.out[1], 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.out[1] = 0.0f;
|
||||
}
|
||||
|
||||
if (p.color1[2] != 0.0f) {
|
||||
tmp = 1.0f - value * p.color2[2];
|
||||
if (tmp <= 0.0f) {
|
||||
p.out[2] = 1.0f;
|
||||
}
|
||||
else {
|
||||
p.out[2] = p.color1[2] / tmp;
|
||||
CLAMP_MAX(p.out[2], 1.0f);
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.out[2] = 0.0f;
|
||||
}
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Glare Operation ******** */
|
||||
|
||||
void MixGlareOperation::executePixelSampled(float output[4],
|
||||
|
@ -487,6 +763,33 @@ void MixGlareOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixGlareOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
const float value = p.value[0];
|
||||
/* Linear interpolation between 3 cases:
|
||||
* value=-1:output=input value=0:output=input+glare value=1:output=glare
|
||||
*/
|
||||
float input_weight;
|
||||
float glare_weight;
|
||||
if (value < 0.0f) {
|
||||
input_weight = 1.0f;
|
||||
glare_weight = 1.0f + value;
|
||||
}
|
||||
else {
|
||||
input_weight = 1.0f - value;
|
||||
glare_weight = 1.0f;
|
||||
}
|
||||
p.out[0] = input_weight * MAX2(p.color1[0], 0.0f) + glare_weight * p.color2[0];
|
||||
p.out[1] = input_weight * MAX2(p.color1[1], 0.0f) + glare_weight * p.color2[1];
|
||||
p.out[2] = input_weight * MAX2(p.color1[2], 0.0f) + glare_weight * p.color2[2];
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Hue Operation ******** */
|
||||
|
||||
void MixHueOperation::executePixelSampled(float output[4], float x, float y, PixelSampler sampler)
|
||||
|
@ -524,6 +827,36 @@ void MixHueOperation::executePixelSampled(float output[4], float x, float y, Pix
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixHueOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
float colH, colS, colV;
|
||||
rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
|
||||
if (colS != 0.0f) {
|
||||
float rH, rS, rV;
|
||||
float tmpr, tmpg, tmpb;
|
||||
rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
|
||||
hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb);
|
||||
p.out[0] = value_m * p.color1[0] + value * tmpr;
|
||||
p.out[1] = value_m * p.color1[1] + value * tmpg;
|
||||
p.out[2] = value_m * p.color1[2] + value * tmpb;
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(p.out, p.color1);
|
||||
}
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Lighten Operation ******** */
|
||||
|
||||
void MixLightenOperation::executePixelSampled(float output[4],
|
||||
|
@ -570,6 +903,30 @@ void MixLightenOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixLightenOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
|
||||
float tmp = value * p.color2[0];
|
||||
p.out[0] = MAX2(tmp, p.color1[0]);
|
||||
|
||||
tmp = value * p.color2[1];
|
||||
p.out[1] = MAX2(tmp, p.color1[1]);
|
||||
|
||||
tmp = value * p.color2[2];
|
||||
p.out[2] = MAX2(tmp, p.color1[2]);
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Linear Light Operation ******** */
|
||||
|
||||
void MixLinearLightOperation::executePixelSampled(float output[4],
|
||||
|
@ -613,6 +970,39 @@ void MixLinearLightOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixLinearLightOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
if (p.color2[0] > 0.5f) {
|
||||
p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0] - 0.5f));
|
||||
}
|
||||
else {
|
||||
p.out[0] = p.color1[0] + value * (2.0f * (p.color2[0]) - 1.0f);
|
||||
}
|
||||
if (p.color2[1] > 0.5f) {
|
||||
p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1] - 0.5f));
|
||||
}
|
||||
else {
|
||||
p.out[1] = p.color1[1] + value * (2.0f * (p.color2[1]) - 1.0f);
|
||||
}
|
||||
if (p.color2[2] > 0.5f) {
|
||||
p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2] - 0.5f));
|
||||
}
|
||||
else {
|
||||
p.out[2] = p.color1[2] + value * (2.0f * (p.color2[2]) - 1.0f);
|
||||
}
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Multiply Operation ******** */
|
||||
|
||||
void MixMultiplyOperation::executePixelSampled(float output[4],
|
||||
|
@ -641,6 +1031,25 @@ void MixMultiplyOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixMultiplyOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
p.out[0] = p.color1[0] * (value_m + value * p.color2[0]);
|
||||
p.out[1] = p.color1[1] * (value_m + value * p.color2[1]);
|
||||
p.out[2] = p.color1[2] * (value_m + value * p.color2[2]);
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Overlay Operation ******** */
|
||||
|
||||
void MixOverlayOperation::executePixelSampled(float output[4],
|
||||
|
@ -686,6 +1095,40 @@ void MixOverlayOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixOverlayOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
if (p.color1[0] < 0.5f) {
|
||||
p.out[0] = p.color1[0] * (value_m + 2.0f * value * p.color2[0]);
|
||||
}
|
||||
else {
|
||||
p.out[0] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]);
|
||||
}
|
||||
if (p.color1[1] < 0.5f) {
|
||||
p.out[1] = p.color1[1] * (value_m + 2.0f * value * p.color2[1]);
|
||||
}
|
||||
else {
|
||||
p.out[1] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]);
|
||||
}
|
||||
if (p.color1[2] < 0.5f) {
|
||||
p.out[2] = p.color1[2] * (value_m + 2.0f * value * p.color2[2]);
|
||||
}
|
||||
else {
|
||||
p.out[2] = 1.0f - (value_m + 2.0f * value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]);
|
||||
}
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Saturation Operation ******** */
|
||||
|
||||
void MixSaturationOperation::executePixelSampled(float output[4],
|
||||
|
@ -723,6 +1166,33 @@ void MixSaturationOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixSaturationOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
float rH, rS, rV;
|
||||
rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
|
||||
if (rS != 0.0f) {
|
||||
float colH, colS, colV;
|
||||
rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
|
||||
hsv_to_rgb(rH, (value_m * rS + value * colS), rV, &p.out[0], &p.out[1], &p.out[2]);
|
||||
}
|
||||
else {
|
||||
copy_v3_v3(p.out, p.color1);
|
||||
}
|
||||
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Screen Operation ******** */
|
||||
|
||||
void MixScreenOperation::executePixelSampled(float output[4],
|
||||
|
@ -752,6 +1222,25 @@ void MixScreenOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixScreenOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
|
||||
p.out[0] = 1.0f - (value_m + value * (1.0f - p.color2[0])) * (1.0f - p.color1[0]);
|
||||
p.out[1] = 1.0f - (value_m + value * (1.0f - p.color2[1])) * (1.0f - p.color1[1]);
|
||||
p.out[2] = 1.0f - (value_m + value * (1.0f - p.color2[2])) * (1.0f - p.color1[2]);
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Soft Light Operation ******** */
|
||||
|
||||
void MixSoftLightOperation::executePixelSampled(float output[4],
|
||||
|
@ -793,6 +1282,34 @@ void MixSoftLightOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixSoftLightOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
const float value_m = 1.0f - value;
|
||||
float scr, scg, scb;
|
||||
|
||||
/* First calculate non-fac based Screen mix. */
|
||||
scr = 1.0f - (1.0f - p.color2[0]) * (1.0f - p.color1[0]);
|
||||
scg = 1.0f - (1.0f - p.color2[1]) * (1.0f - p.color1[1]);
|
||||
scb = 1.0f - (1.0f - p.color2[2]) * (1.0f - p.color1[2]);
|
||||
|
||||
p.out[0] = value_m * p.color1[0] +
|
||||
value * ((1.0f - p.color1[0]) * p.color2[0] * p.color1[0] + p.color1[0] * scr);
|
||||
p.out[1] = value_m * p.color1[1] +
|
||||
value * ((1.0f - p.color1[1]) * p.color2[1] * p.color1[1] + p.color1[1] * scg);
|
||||
p.out[2] = value_m * p.color1[2] +
|
||||
value * ((1.0f - p.color1[2]) * p.color2[2] * p.color1[2] + p.color1[2] * scb);
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Subtract Operation ******** */
|
||||
|
||||
void MixSubtractOperation::executePixelSampled(float output[4],
|
||||
|
@ -820,6 +1337,23 @@ void MixSubtractOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixSubtractOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
p.out[0] = p.color1[0] - value * p.color2[0];
|
||||
p.out[1] = p.color1[1] - value * p.color2[1];
|
||||
p.out[2] = p.color1[2] - value * p.color2[2];
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
/* ******** Mix Value Operation ******** */
|
||||
|
||||
void MixValueOperation::executePixelSampled(float output[4],
|
||||
|
@ -851,4 +1385,25 @@ void MixValueOperation::executePixelSampled(float output[4],
|
|||
clampIfNeeded(output);
|
||||
}
|
||||
|
||||
void MixValueOperation::update_memory_buffer_row(PixelCursor &p)
|
||||
{
|
||||
while (p.out < p.row_end) {
|
||||
float value = p.value[0];
|
||||
if (this->useValueAlphaMultiply()) {
|
||||
value *= p.color2[3];
|
||||
}
|
||||
float value_m = 1.0f - value;
|
||||
|
||||
float rH, rS, rV;
|
||||
float colH, colS, colV;
|
||||
rgb_to_hsv(p.color1[0], p.color1[1], p.color1[2], &rH, &rS, &rV);
|
||||
rgb_to_hsv(p.color2[0], p.color2[1], p.color2[2], &colH, &colS, &colV);
|
||||
hsv_to_rgb(rH, rS, (value_m * rV + value * colV), &p.out[0], &p.out[1], &p.out[2]);
|
||||
p.out[3] = p.color1[3];
|
||||
|
||||
clampIfNeeded(p.out);
|
||||
p.next();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "COM_MultiThreadedOperation.h"
|
||||
|
||||
namespace blender::compositor {
|
||||
|
||||
|
@ -27,8 +27,29 @@ namespace blender::compositor {
|
|||
* it assumes we are in sRGB color space.
|
||||
*/
|
||||
|
||||
class MixBaseOperation : public NodeOperation {
|
||||
class MixBaseOperation : public MultiThreadedOperation {
|
||||
protected:
|
||||
struct PixelCursor {
|
||||
float *out;
|
||||
const float *row_end;
|
||||
const float *value;
|
||||
const float *color1;
|
||||
const float *color2;
|
||||
int out_stride;
|
||||
int value_stride;
|
||||
int color1_stride;
|
||||
int color2_stride;
|
||||
|
||||
void next()
|
||||
{
|
||||
BLI_assert(out < row_end);
|
||||
out += out_stride;
|
||||
value += value_stride;
|
||||
color1 += color1_stride;
|
||||
color2 += color2_stride;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Prefetched reference to the inputProgram
|
||||
*/
|
||||
|
@ -81,101 +102,165 @@ class MixBaseOperation : public NodeOperation {
|
|||
{
|
||||
this->m_useClamp = value;
|
||||
}
|
||||
|
||||
void update_memory_buffer_partial(MemoryBuffer *output,
|
||||
const rcti &area,
|
||||
Span<MemoryBuffer *> inputs) final;
|
||||
|
||||
protected:
|
||||
virtual void update_memory_buffer_row(PixelCursor &p);
|
||||
};
|
||||
|
||||
class MixAddOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixBlendOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixColorBurnOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixColorOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixDarkenOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixDifferenceOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixDivideOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixDodgeOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixGlareOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixHueOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixLightenOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixLinearLightOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixMultiplyOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixOverlayOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixSaturationOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixScreenOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixSoftLightOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixSubtractOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
class MixValueOperation : public MixBaseOperation {
|
||||
public:
|
||||
void executePixelSampled(float output[4], float x, float y, PixelSampler sampler) override;
|
||||
|
||||
protected:
|
||||
void update_memory_buffer_row(PixelCursor &p) override;
|
||||
};
|
||||
|
||||
} // namespace blender::compositor
|
||||
|
|
Loading…
Reference in New Issue