diff options
Diffstat (limited to 'source/blender/compositor/operations')
42 files changed, 885 insertions, 225 deletions
diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index bb915fec590..df64b7c8ddc 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -27,11 +27,11 @@ extern "C" { #include "RE_pipeline.h" } -BlurBaseOperation::BlurBaseOperation() : NodeOperation() +BlurBaseOperation::BlurBaseOperation(DataType data_type=COM_DT_COLOR) : NodeOperation() { - this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(data_type); this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); + this->addOutputSocket(data_type); this->setComplex(true); this->inputProgram = NULL; this->data = NULL; @@ -89,6 +89,46 @@ float *BlurBaseOperation::make_gausstab(int rad) return gausstab; } +/* normalized distance from the current (inverted so 1.0 is close and 0.0 is far) + * 'ease' is applied after, looks nicer */ +float *BlurBaseOperation::make_dist_fac_inverse(int rad, int falloff) +{ + float *dist_fac_invert, val; + int i, n; + + n = 2 * rad + 1; + + dist_fac_invert = new float[n]; + + for (i = -rad; i <= rad; i++) { + val = 1.0f - fabsf(((float)i / (float)rad)); + + /* keep in sync with proportional_falloff_curve_only_items */ + switch (falloff) { + case PROP_SMOOTH: + /* ease - gives less hard lines for dilate/erode feather */ + val = (3.0f * val * val - 2.0f * val * val * val); + break; + case PROP_SPHERE: + val = sqrtf(2.0f * val - val * val); + break; + case PROP_ROOT: + val = sqrtf(val); + break; + case PROP_SHARP: + val = val * val; + break; + case PROP_LIN: + default: + /* nothing */ + break; + } + dist_fac_invert[i + rad] = val; + } + + return dist_fac_invert; +} + void BlurBaseOperation::deinitExecution() { this->inputProgram = NULL; diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.h b/source/blender/compositor/operations/COM_BlurBaseOperation.h index 84fc243a5af..8f7208274db 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.h +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.h @@ -35,8 +35,9 @@ protected: SocketReader *inputProgram; SocketReader *inputSize; NodeBlurData *data; - BlurBaseOperation(); + BlurBaseOperation(DataType data_type); float *make_gausstab(int rad); + float *make_dist_fac_inverse(int rad, int falloff); float size; bool deleteData; bool sizeavailable; diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index dca087bb587..9fe5abcb075 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -22,6 +22,7 @@ #include "COM_BokehBlurOperation.h" #include "BLI_math.h" +#include "COM_OpenCLDevice.h" extern "C" { #include "RE_pipeline.h" @@ -73,13 +74,13 @@ void BokehBlurOperation::initExecution() void BokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - float tempColor[4]; + float color_accum[4]; float tempBoundingBox[4]; float bokeh[4]; inputBoundingBoxReader->read(tempBoundingBox, x, y, COM_PS_NEAREST, inputBuffers); if (tempBoundingBox[0] > 0.0f) { - float overallmultiplyer[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); @@ -96,7 +97,7 @@ void BokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer * maxy = min(maxy, inputBuffer->getRect()->ymax); maxx = min(maxx, inputBuffer->getRect()->xmax); - zero_v4(tempColor); + zero_v4(color_accum); int step = getStep(); int offsetadd = getOffsetAdd(); @@ -108,15 +109,15 @@ void BokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer * float u = this->bokehMidX - (nx - x) * m; float v = this->bokehMidY - (ny - y) * m; inputBokehProgram->read(bokeh, u, v, COM_PS_NEAREST, inputBuffers); - madd_v4_v4v4(tempColor, bokeh, &buffer[bufferindex]); - add_v4_v4(overallmultiplyer, bokeh); + madd_v4_v4v4(color_accum, bokeh, &buffer[bufferindex]); + add_v4_v4(multiplier_accum, bokeh); bufferindex += offsetadd; } } - color[0] = tempColor[0] * (1.0f / overallmultiplyer[0]); - color[1] = tempColor[1] * (1.0f / overallmultiplyer[1]); - color[2] = tempColor[2] * (1.0f / overallmultiplyer[2]); - color[3] = tempColor[3] * (1.0f / overallmultiplyer[3]); + color[0] = color_accum[0] * (1.0f / multiplier_accum[0]); + color[1] = color_accum[1] * (1.0f / multiplier_accum[1]); + color[2] = color_accum[2] * (1.0f / multiplier_accum[2]); + color[3] = color_accum[3] * (1.0f / multiplier_accum[3]); } else { inputProgram->read(color, x, y, COM_PS_NEAREST, inputBuffers); @@ -160,25 +161,25 @@ bool BokehBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBuffe } static cl_kernel kernel = 0; -void BokehBlurOperation::executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, +void BokehBlurOperation::executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp) { if (!kernel) { - kernel = COM_clCreateKernel(program, "bokehBlurKernel", NULL); + kernel = device->COM_clCreateKernel("bokehBlurKernel", NULL); } cl_int radius = this->getWidth() * this->size / 100.0f; cl_int step = this->getStep(); - COM_clAttachMemoryBufferToKernelParameter(context, kernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBoundingBoxReader); - COM_clAttachMemoryBufferToKernelParameter(context, kernel, 1, 4, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); - COM_clAttachMemoryBufferToKernelParameter(context, kernel, 2, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBokehProgram); - COM_clAttachOutputMemoryBufferToKernelParameter(kernel, 3, clOutputBuffer); - COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, 5, outputMemoryBuffer); + device->COM_clAttachMemoryBufferToKernelParameter(kernel, 0, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBoundingBoxReader); + device->COM_clAttachMemoryBufferToKernelParameter(kernel, 1, 4, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); + device->COM_clAttachMemoryBufferToKernelParameter(kernel, 2, -1, clMemToCleanUp, inputMemoryBuffers, this->inputBokehProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(kernel, 3, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(kernel, 5, outputMemoryBuffer); clSetKernelArg(kernel, 6, sizeof(cl_int), &radius); clSetKernelArg(kernel, 7, sizeof(cl_int), &step); - COM_clAttachSizeToKernelParameter(kernel, 8); + device->COM_clAttachSizeToKernelParameter(kernel, 8, this); - COM_clEnqueueRange(queue, kernel, outputMemoryBuffer, 9); + device->COM_clEnqueueRange(kernel, outputMemoryBuffer, 9, this); } diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.h b/source/blender/compositor/operations/COM_BokehBlurOperation.h index 3ec61c5ce01..853855d5c34 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.h @@ -57,6 +57,6 @@ public: void setSize(float size) { this->size = size; } - void executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp); + void executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp); }; #endif diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 3f9003b8c48..fe6be55e237 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -88,7 +88,7 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile) float *buffer = tile->getBuffer(); int size = tile->getWidth() * tile->getHeight(); int pixels = 0; - float sum; + float sum = 0.0f; for (int i = 0, offset = 0; i < size; i++, offset += 4) { if (buffer[offset + 3] > 0) { pixels++; @@ -97,7 +97,7 @@ void CalculateMeanOperation::calculateMean(MemoryBuffer *tile) { case 1: { - sum += buffer[offset] * 0.35f + buffer[offset + 1] * 0.45f + buffer[offset + 2] * 0.2f; + sum += rgb_to_bw(&buffer[offset]); break; } case 2: diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index b0739cd7567..811975c5e13 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -46,7 +46,7 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect, Memory float *buffer = tile->getBuffer(); int size = tile->getWidth() * tile->getHeight(); int pixels = 0; - float sum; + float sum = 0.0f; float mean = this->result; for (int i = 0, offset = 0; i < size; i++, offset += 4) { if (buffer[offset + 3] > 0) { @@ -56,7 +56,7 @@ void *CalculateStandardDeviationOperation::initializeTileData(rcti *rect, Memory { case 1: { - float value = buffer[offset] * 0.35f + buffer[offset + 1] * 0.45f + buffer[offset + 2] * 0.2f; + float value = rgb_to_bw(&buffer[offset]); sum += (value - mean) * (value - mean); break; } diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp index dff8ccf7e73..fb4e6f03e76 100644 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp +++ b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp @@ -21,7 +21,7 @@ */ #include "COM_CombineChannelsOperation.h" -#include <stdio.h> +#include "BLI_utildefines.h" CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() { @@ -36,6 +36,31 @@ CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() this->inputChannel3Operation = NULL; this->inputChannel4Operation = NULL; } + +bool CombineChannelsOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti tempOutput; + bool first = true; + for (int i = 0 ; i < 4 ; i ++) { + NodeOperation * inputOperation = this->getInputOperation(i); + if (inputOperation->determineDependingAreaOfInterest(input, readOperation, &tempOutput)) { + if (first) { + output->xmin = tempOutput.xmin; + output->ymin = tempOutput.ymin; + output->xmax = tempOutput.xmax; + output->ymax = tempOutput.ymax; + first = false; + } else { + output->xmin = MIN2(output->xmin, tempOutput.xmin); + output->ymin = MIN2(output->ymin, tempOutput.ymin); + output->xmax = MAX2(output->xmax, tempOutput.xmax); + output->ymax = MAX2(output->ymax, tempOutput.ymax); + } + } + } + return !first; +} + void CombineChannelsOperation::initExecution() { this->inputChannel1Operation = this->getInputSocketReader(0); diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.h b/source/blender/compositor/operations/COM_CombineChannelsOperation.h index d2977155e14..cc71f44b4f5 100644 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.h +++ b/source/blender/compositor/operations/COM_CombineChannelsOperation.h @@ -37,6 +37,8 @@ public: void initExecution(); void deinitExecution(); + + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); }; #endif diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index 2b1a804b432..936cbaadd84 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -41,7 +41,7 @@ CompositorOperation::CompositorOperation() : NodeOperation() this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); - this->setScene(NULL); + this->setRenderData(NULL); this->outputBuffer = NULL; this->imageInput = NULL; this->alphaInput = NULL; @@ -60,11 +60,11 @@ void CompositorOperation::initExecution() void CompositorOperation::deinitExecution() { if (!isBreaked()) { - const Scene *scene = this->scene; - Render *re = RE_GetRender(scene->id.name); + const RenderData *rd = this->rd; + Render *re = RE_GetRender_FromData(rd); RenderResult *rr = RE_AcquireResultWrite(re); if (rr) { - if (rr->rectf != NULL) { + if (rr->rectf != NULL) { MEM_freeN(rr->rectf); } rr->rectf = outputBuffer; @@ -127,12 +127,12 @@ void CompositorOperation::executeRegion(rcti *rect, unsigned int tileNumber, Mem void CompositorOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) { - int width = this->scene->r.xsch * this->scene->r.size / 100; - int height = this->scene->r.ysch * this->scene->r.size / 100; + int width = this->rd->xsch * this->rd->size / 100; + int height = this->rd->ysch * this->rd->size / 100; // check actual render resolution with cropping it may differ with cropped border.rendering // FIX for: [31777] Border Crop gives black (easy) - Render *re = RE_GetRender(this->scene->id.name); + Render *re = RE_GetRender_FromData(this->rd); if (re) { RenderResult *rr = RE_AcquireResultRead(re); if (rr) { diff --git a/source/blender/compositor/operations/COM_CompositorOperation.h b/source/blender/compositor/operations/COM_CompositorOperation.h index 0129c953946..280f39b7729 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.h +++ b/source/blender/compositor/operations/COM_CompositorOperation.h @@ -34,7 +34,7 @@ private: /** * @brief local reference to the scene */ - const Scene *scene; + const RenderData *rd; /** * @brief reference to the output float buffer @@ -53,7 +53,7 @@ private: public: CompositorOperation(); void executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer **memoryBuffers); - void setScene(const Scene *scene) { this->scene = scene; } + void setRenderData(const RenderData *rd) { this->rd = rd; } bool isOutputOperation(bool rendering) const { return true; } void initExecution(); void deinitExecution(); diff --git a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp index c66cb8df9be..0e2c1e29a1d 100644 --- a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp @@ -38,7 +38,7 @@ void ConvertColorToBWOperation::executePixel(float *outputValue, float x, float { float inputColor[4]; inputOperation->read(&inputColor[0], x, y, sampler, inputBuffers); - outputValue[0] = inputColor[0] * 0.35f + inputColor[1] * 0.45f + inputColor[2] * 0.2f; + outputValue[0] = rgb_to_bw(inputColor); } void ConvertColorToBWOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp index 306a2d96985..80d1c6444eb 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.cpp +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.cpp @@ -22,6 +22,7 @@ #include "COM_DilateErodeOperation.h" #include "BLI_math.h" +#include "COM_OpenCLDevice.h" // DilateErode Distance Threshold DilateErodeThresholdOperation::DilateErodeThresholdOperation() : NodeOperation() @@ -234,24 +235,24 @@ bool DilateDistanceOperation::determineDependingAreaOfInterest(rcti *input, Read } static cl_kernel dilateKernel = 0; -void DilateDistanceOperation::executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, +void DilateDistanceOperation::executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp) { if (!dilateKernel) { - dilateKernel = COM_clCreateKernel(program, "dilateKernel", NULL); + dilateKernel = device->COM_clCreateKernel("dilateKernel", NULL); } cl_int distanceSquared = this->distance * this->distance; cl_int scope = this->scope; - COM_clAttachMemoryBufferToKernelParameter(context, dilateKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); - COM_clAttachOutputMemoryBufferToKernelParameter(dilateKernel, 1, clOutputBuffer); - COM_clAttachMemoryBufferOffsetToKernelParameter(dilateKernel, 3, outputMemoryBuffer); + device->COM_clAttachMemoryBufferToKernelParameter(dilateKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(dilateKernel, 1, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(dilateKernel, 3, outputMemoryBuffer); clSetKernelArg(dilateKernel, 4, sizeof(cl_int), &scope); clSetKernelArg(dilateKernel, 5, sizeof(cl_int), &distanceSquared); - COM_clAttachSizeToKernelParameter(dilateKernel, 6); - COM_clEnqueueRange(queue, dilateKernel, outputMemoryBuffer, 7); + device->COM_clAttachSizeToKernelParameter(dilateKernel, 6, this); + device->COM_clEnqueueRange(dilateKernel, outputMemoryBuffer, 7, this); } // Erode Distance @@ -293,24 +294,24 @@ void ErodeDistanceOperation::executePixel(float *color, int x, int y, MemoryBuff } static cl_kernel erodeKernel = 0; -void ErodeDistanceOperation::executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, +void ErodeDistanceOperation::executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp) { if (!erodeKernel) { - erodeKernel = COM_clCreateKernel(program, "erodeKernel", NULL); + erodeKernel = device->COM_clCreateKernel("erodeKernel", NULL); } cl_int distanceSquared = this->distance * this->distance; cl_int scope = this->scope; - COM_clAttachMemoryBufferToKernelParameter(context, erodeKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); - COM_clAttachOutputMemoryBufferToKernelParameter(erodeKernel, 1, clOutputBuffer); - COM_clAttachMemoryBufferOffsetToKernelParameter(erodeKernel, 3, outputMemoryBuffer); + device->COM_clAttachMemoryBufferToKernelParameter(erodeKernel, 0, 2, clMemToCleanUp, inputMemoryBuffers, this->inputProgram); + device->COM_clAttachOutputMemoryBufferToKernelParameter(erodeKernel, 1, clOutputBuffer); + device->COM_clAttachMemoryBufferOffsetToKernelParameter(erodeKernel, 3, outputMemoryBuffer); clSetKernelArg(erodeKernel, 4, sizeof(cl_int), &scope); clSetKernelArg(erodeKernel, 5, sizeof(cl_int), &distanceSquared); - COM_clAttachSizeToKernelParameter(erodeKernel, 6); - COM_clEnqueueRange(queue, erodeKernel, outputMemoryBuffer, 7); + device->COM_clAttachSizeToKernelParameter(erodeKernel, 6, this); + device->COM_clEnqueueRange(erodeKernel, outputMemoryBuffer, 7, this); } // Dilate step diff --git a/source/blender/compositor/operations/COM_DilateErodeOperation.h b/source/blender/compositor/operations/COM_DilateErodeOperation.h index b11356129b4..4d0bf9de0ec 100644 --- a/source/blender/compositor/operations/COM_DilateErodeOperation.h +++ b/source/blender/compositor/operations/COM_DilateErodeOperation.h @@ -99,7 +99,7 @@ public: void setDistance(float distance) { this->distance = distance; } bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); - void executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, + void executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp); @@ -113,7 +113,7 @@ public: */ void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); - void executeOpenCL(cl_context context, cl_program program, cl_command_queue queue, + void executeOpenCL(OpenCLDevice* device, MemoryBuffer *outputMemoryBuffer, cl_mem clOutputBuffer, MemoryBuffer **inputMemoryBuffers, list<cl_mem> *clMemToCleanUp, list<cl_kernel> *clKernelsToCleanUp); diff --git a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp index ba54c8ad9d6..8344a4d248b 100644 --- a/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_DoubleEdgeMaskOperation.cpp @@ -1216,7 +1216,7 @@ void DoubleEdgeMaskOperation::doDoubleEdgeMask(float *imask, float *omask, float gsz = rsize[2]; // by the do_*EdgeDetection() function. fsz = gsz + isz + osz; // calculate size of pixel index buffer needed - gbuf = (unsigned short *)MEM_callocN(sizeof (unsigned short) * fsz * 2, "DEM"); // allocate edge/gradient pixel index buffer + gbuf = (unsigned short *)MEM_callocN(sizeof(unsigned short) * fsz * 2, "DEM"); // allocate edge/gradient pixel index buffer do_createEdgeLocationBuffer(t, rw, lres, res, gbuf, &innerEdgeOffset, &outerEdgeOffset, isz, gsz); do_fillGradientBuffer(rw, res, gbuf, isz, osz, gsz, innerEdgeOffset, outerEdgeOffset); diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp index 7830eef829c..7491b0f30dd 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.cpp @@ -20,11 +20,13 @@ * Monique Dewanchand */ +#include <limits.h> + #include "COM_FastGaussianBlurOperation.h" #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation() +FastGaussianBlurOperation::FastGaussianBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->iirgaus = NULL; } @@ -74,7 +76,7 @@ void FastGaussianBlurOperation::deinitExecution() delete this->iirgaus; this->iirgaus = NULL; } - BlurBaseOperation::deinitMutex(); + BlurBaseOperation::deinitMutex(); } void *FastGaussianBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) @@ -84,7 +86,7 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **m MemoryBuffer *newBuf = (MemoryBuffer *)this->inputProgram->initializeTileData(rect, memoryBuffers); MemoryBuffer *copy = newBuf->duplicate(); updateSize(memoryBuffers); - + int c; sx = data->sizex * this->size / 2.0f; sy = data->sizey * this->size / 2.0f; @@ -109,11 +111,14 @@ void *FastGaussianBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **m return iirgaus; } -void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, int chan, int xy) +void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, unsigned int chan, unsigned int xy) { double q, q2, sc, cf[4], tsM[9], tsu[3], tsv[3]; double *X, *Y, *W; - int i, x, y, sz; + const unsigned int src_width = src->getWidth(); + const unsigned int src_height = src->getHeight(); + unsigned int x, y, sz; + unsigned int i; float *buffer = src->getBuffer(); // <0.5 not valid, though can have a possibly useful sort of sharpening effect @@ -123,8 +128,8 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, int ch // XXX The YVV macro defined below explicitly expects sources of at least 3x3 pixels, // so just skiping blur along faulty direction if src's def is below that limit! - if (src->getWidth() < 3) xy &= ~(int) 1; - if (src->getHeight() < 3) xy &= ~(int) 2; + if (src_width < 3) xy &= ~(int) 1; + if (src_height < 3) xy &= ~(int) 2; if (xy < 1) return; // see "Recursive Gabor Filtering" by Young/VanVliet @@ -178,33 +183,34 @@ void FastGaussianBlurOperation::IIR_gauss(MemoryBuffer *src, float sigma, int ch Y[L - 1] = cf[0] * W[L - 1] + cf[1] * tsv[0] + cf[2] * tsv[1] + cf[3] * tsv[2]; \ Y[L - 2] = cf[0] * W[L - 2] + cf[1] * Y[L - 1] + cf[2] * tsv[0] + cf[3] * tsv[1]; \ Y[L - 3] = cf[0] * W[L - 3] + cf[1] * Y[L - 2] + cf[2] * Y[L - 1] + cf[3] * tsv[0]; \ - for (i = L - 4; i >= 0; i--) { \ + /* 'i != UINT_MAX' is really 'i >= 0', but necessary for unsigned int wrapping */ \ + for (i = L - 4; i != UINT_MAX; i--) { \ Y[i] = cf[0] * W[i] + cf[1] * Y[i + 1] + cf[2] * Y[i + 2] + cf[3] * Y[i + 3]; \ } \ } (void)0 // intermediate buffers - sz = MAX2(src->getWidth(), src->getHeight()); + sz = MAX2(src_width, src_height); X = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss X buf"); Y = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss Y buf"); W = (double *)MEM_callocN(sz * sizeof(double), "IIR_gauss W buf"); if (xy & 1) { // H - for (y = 0; y < src->getHeight(); ++y) { - const int yx = y * src->getWidth(); - for (x = 0; x < src->getWidth(); ++x) + for (y = 0; y < src_height; ++y) { + const int yx = y * src_width; + for (x = 0; x < src_width; ++x) X[x] = buffer[(x + yx) * COM_NUMBER_OF_CHANNELS + chan]; - YVV(src->getWidth()); - for (x = 0; x < src->getWidth(); ++x) + YVV(src_width); + for (x = 0; x < src_width; ++x) buffer[(x + yx) * COM_NUMBER_OF_CHANNELS + chan] = Y[x]; } } if (xy & 2) { // V - for (x = 0; x < src->getWidth(); ++x) { - for (y = 0; y < src->getHeight(); ++y) - X[y] = buffer[(x + y * src->getWidth()) * COM_NUMBER_OF_CHANNELS + chan]; - YVV(src->getHeight()); - for (y = 0; y < src->getHeight(); ++y) - buffer[(x + y * src->getWidth()) * COM_NUMBER_OF_CHANNELS + chan] = Y[y]; + for (x = 0; x < src_width; ++x) { + for (y = 0; y < src_height; ++y) + X[y] = buffer[(x + y * src_width) * COM_NUMBER_OF_CHANNELS + chan]; + YVV(src_height); + for (y = 0; y < src_height; ++y) + buffer[(x + y * src_width) * COM_NUMBER_OF_CHANNELS + chan] = Y[y]; } } diff --git a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h index f92e3dc68a5..0f3929f052c 100644 --- a/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h +++ b/source/blender/compositor/operations/COM_FastGaussianBlurOperation.h @@ -36,7 +36,7 @@ public: bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); - static void IIR_gauss(MemoryBuffer *src, float sigma, int channel, int xy); + static void IIR_gauss(MemoryBuffer *src, float sigma, unsigned int channel, unsigned int xy); void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); void deinitExecution(); void initExecution(); diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp new file mode 100644 index 00000000000..954aef7b916 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#include "COM_GaussianAlphaXBlurOperation.h" +#include "BLI_math.h" + +extern "C" { + #include "RE_pipeline.h" +} + +GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(COM_DT_VALUE) +{ + this->gausstab = NULL; + this->rad = 0; +} + +void *GaussianAlphaXBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (!this->sizeavailable) { + updateGauss(memoryBuffers); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers); + return buffer; +} + +void GaussianAlphaXBlurOperation::initExecution() +{ + /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + + if (this->sizeavailable) { + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, this->falloff); + } +} + +void GaussianAlphaXBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) +{ + if (this->gausstab == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + } + + if (this->distbuf_inv == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, this->falloff); + } +} + +BLI_INLINE float finv_test(const float f, const bool test) +{ + return (LIKELY(test == false)) ? f : 1.0f - f; +} + +void GaussianAlphaXBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + const bool do_invert = this->do_subtract; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + int miny = y; + int maxy = y; + int minx = x - this->rad; + int maxx = x + this->rad; + miny = max(miny, inputBuffer->getRect()->ymin); + minx = max(minx, inputBuffer->getRect()->xmin); + maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax); + + /* *** this is the main part which is different to 'GaussianXBlurOperation' *** */ + int step = getStep(); + int offsetadd = getOffsetAdd(); + int bufferindex = ((minx - bufferstartx) * 4) + ((miny - bufferstarty) * 4 * bufferwidth); + + /* gauss */ + float alpha_accum = 0.0f; + float multiplier_accum = 0.0f; + + /* dilate */ + float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int nx = minx; nx < maxx; nx += step) { + const int index = (nx - x) + this->rad; + float value = finv_test(buffer[bufferindex], do_invert); + float multiplier; + + /* gauss */ + { + multiplier = gausstab[index]; + alpha_accum += value * multiplier; + multiplier_accum += multiplier; + } + + /* dilate - find most extreme color */ + if (value > value_max) { + multiplier = distbuf_inv[index]; + value *= multiplier; + if (value > value_max) { + value_max = value; + distfacinv_max = multiplier; + } + } + bufferindex += offsetadd; + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_blur = alpha_accum / multiplier_accum; + const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); + color[0] = finv_test(value_final, do_invert); +} + +void GaussianAlphaXBlurOperation::deinitExecution() +{ + BlurBaseOperation::deinitExecution(); + delete [] this->gausstab; + this->gausstab = NULL; + delete [] this->distbuf_inv; + this->distbuf_inv = NULL; +} + +bool GaussianAlphaXBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; +#if 0 /* until we add size input */ + rcti sizeInput; + sizeInput.xmin = 0; + sizeInput.ymin = 0; + sizeInput.xmax = 5; + sizeInput.ymax = 5; + + NodeOperation *operation = this->getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) { + return true; + } + else +#endif + { + if (this->sizeavailable && this->gausstab != NULL) { + newInput.xmax = input->xmax + rad; + newInput.xmin = input->xmin - rad; + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h new file mode 100644 index 00000000000..38817ebef1d --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.h @@ -0,0 +1,64 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#ifndef _COM_GaussianAlphaXBlurOperation_h +#define _COM_GaussianAlphaXBlurOperation_h +#include "COM_NodeOperation.h" +#include "COM_BlurBaseOperation.h" + +class GaussianAlphaXBlurOperation : public BlurBaseOperation { +private: + float *gausstab; + float *distbuf_inv; + int falloff; /* falloff for distbuf_inv */ + bool do_subtract; + int rad; + void updateGauss(MemoryBuffer **memoryBuffers); +public: + GaussianAlphaXBlurOperation(); + + /** + * @brief the inner loop of this program + */ + void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); + + /** + * @brief initialize the execution + */ + void initExecution(); + + /** + * @brief Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + + /** + * Set subtract for Dilate/Erode functionality + */ + void setSubtract(bool subtract) { this->do_subtract = subtract; } + void setFalloff(int falloff) { this->falloff = falloff; } +}; +#endif diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp new file mode 100644 index 00000000000..e1105cf94b1 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -0,0 +1,190 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#include "COM_GaussianAlphaYBlurOperation.h" +#include "BLI_math.h" + +extern "C" { + #include "RE_pipeline.h" +} + +GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(COM_DT_VALUE) +{ + this->gausstab = NULL; + this->rad = 0; +} + +void *GaussianAlphaYBlurOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) +{ + if (!this->sizeavailable) { + updateGauss(memoryBuffers); + } + void *buffer = getInputOperation(0)->initializeTileData(NULL, memoryBuffers); + return buffer; +} + +void GaussianAlphaYBlurOperation::initExecution() +{ + /* BlurBaseOperation::initExecution(); */ /* until we suppoer size input - comment this */ + + if (this->sizeavailable) { + float rad = size * this->data->sizey; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, this->falloff); + } +} + +void GaussianAlphaYBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) +{ + if (this->gausstab == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizey; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->gausstab = BlurBaseOperation::make_gausstab(rad); + } + + if (this->distbuf_inv == NULL) { + updateSize(memoryBuffers); + float rad = size * this->data->sizex; + if (rad < 1) + rad = 1; + + this->rad = rad; + this->distbuf_inv = BlurBaseOperation::make_dist_fac_inverse(rad, this->falloff); + } +} + +BLI_INLINE float finv_test(const float f, const bool test) +{ + return (LIKELY(test == false)) ? f : 1.0f - f; +} + +void GaussianAlphaYBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) +{ + const bool do_invert = this->do_subtract; + MemoryBuffer *inputBuffer = (MemoryBuffer *)data; + float *buffer = inputBuffer->getBuffer(); + int bufferwidth = inputBuffer->getWidth(); + int bufferstartx = inputBuffer->getRect()->xmin; + int bufferstarty = inputBuffer->getRect()->ymin; + + int miny = y - this->rad; + int maxy = y + this->rad; + int minx = x; + int maxx = x; + miny = max(miny, inputBuffer->getRect()->ymin); + minx = max(minx, inputBuffer->getRect()->xmin); + maxy = min(maxy, inputBuffer->getRect()->ymax); + maxx = min(maxx, inputBuffer->getRect()->xmax); + + /* *** this is the main part which is different to 'GaussianYBlurOperation' *** */ + int step = getStep(); + + /* gauss */ + float alpha_accum = 0.0f; + float multiplier_accum = 0.0f; + + /* dilate */ + float value_max = finv_test(buffer[(x * 4) + (y * 4 * bufferwidth)], do_invert); /* init with the current color to avoid unneeded lookups */ + float distfacinv_max = 1.0f; /* 0 to 1 */ + + for (int ny = miny; ny < maxy; ny += step) { + int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); + + const int index = (ny - y) + this->rad; + float value = finv_test(buffer[bufferindex], do_invert); + float multiplier; + + /* gauss */ + { + multiplier = gausstab[index]; + alpha_accum += value * multiplier; + multiplier_accum += multiplier; + } + + /* dilate - find most extreme color */ + if (value > value_max) { + multiplier = distbuf_inv[index]; + value *= multiplier; + if (value > value_max) { + value_max = value; + distfacinv_max = multiplier; + } + } + + } + + /* blend between the max value and gauss blue - gives nice feather */ + const float value_blur = alpha_accum / multiplier_accum; + const float value_final = (value_max * distfacinv_max) + (value_blur * (1.0f - distfacinv_max)); + color[0] = finv_test(value_final, do_invert); +} + +void GaussianAlphaYBlurOperation::deinitExecution() +{ + BlurBaseOperation::deinitExecution(); + delete [] this->gausstab; + this->gausstab = NULL; + delete [] this->distbuf_inv; + this->distbuf_inv = NULL; +} + +bool GaussianAlphaYBlurOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) +{ + rcti newInput; +#if 0 /* until we add size input */ + rcti sizeInput; + sizeInput.xmin = 0; + sizeInput.ymin = 0; + sizeInput.xmax = 5; + sizeInput.ymax = 5; + + NodeOperation *operation = this->getInputOperation(1); + if (operation->determineDependingAreaOfInterest(&sizeInput, readOperation, output)) { + return true; + } + else +#endif + { + if (this->sizeavailable && this->gausstab != NULL) { + newInput.xmax = input->xmax; + newInput.xmin = input->xmin; + newInput.ymax = input->ymax + rad; + newInput.ymin = input->ymin - rad; + } + else { + newInput.xmax = this->getWidth(); + newInput.xmin = 0; + newInput.ymax = this->getHeight(); + newInput.ymin = 0; + } + return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + } +} diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h new file mode 100644 index 00000000000..67166be8241 --- /dev/null +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.h @@ -0,0 +1,64 @@ +/* + * Copyright 2011, Blender Foundation. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor: + * Jeroen Bakker + * Monique Dewanchand + * Campbell Barton + */ + +#ifndef _COM_GaussianAlphaYBlurOperation_h +#define _COM_GaussianAlphaYBlurOperation_h +#include "COM_NodeOperation.h" +#include "COM_BlurBaseOperation.h" + +class GaussianAlphaYBlurOperation : public BlurBaseOperation { +private: + float *gausstab; + float *distbuf_inv; + bool do_subtract; + int falloff; + int rad; + void updateGauss(MemoryBuffer **memoryBuffers); +public: + GaussianAlphaYBlurOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float *color, int x, int y, MemoryBuffer * inputBuffers[], void *data); + + /** + * @brief initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + void deinitExecution(); + + void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers); + bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + + /** + * Set subtract for Dilate/Erode functionality + */ + void setSubtract(bool subtract) { this->do_subtract = subtract; } + void setFalloff(int falloff) { this->falloff = falloff; } +}; +#endif diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index b38ed28cd6a..dc9e354b124 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation() +GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; } @@ -115,7 +115,7 @@ void GaussianBokehBlurOperation::executePixel(float *color, int x, int y, Memory tempColor[1] = 0; tempColor[2] = 0; tempColor[3] = 0; - float overallmultiplyer = 0; + float multiplier_accum = 0; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); @@ -138,15 +138,15 @@ void GaussianBokehBlurOperation::executePixel(float *color, int x, int y, Memory index = ((ny - y) + this->rady) * (this->radx * 2 + 1) + (minx - x + this->radx); int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); for (int nx = minx; nx < maxx; nx += step) { - const float multiplyer = gausstab[index]; - madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplyer); - overallmultiplyer += multiplyer; + const float multiplier = gausstab[index]; + madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplier); + multiplier_accum += multiplier; index += step; bufferindex += offsetadd; } } - mul_v4_v4fl(color, tempColor, 1.0f / overallmultiplyer); + mul_v4_v4fl(color, tempColor, 1.0f / multiplier_accum); } void GaussianBokehBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 09a2a70ead3..7a1964a4a63 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation() +GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; this->rad = 0; @@ -72,12 +72,8 @@ void GaussianXBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) void GaussianXBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - float tempColor[4]; - tempColor[0] = 0; - tempColor[1] = 0; - tempColor[2] = 0; - tempColor[3] = 0; - float overallmultiplyer = 0.0f; + float color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float multiplier_accum = 0.0f; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); @@ -99,12 +95,12 @@ void GaussianXBlurOperation::executePixel(float *color, int x, int y, MemoryBuff int bufferindex = ((minx - bufferstartx) * 4) + ((miny - bufferstarty) * 4 * bufferwidth); for (int nx = minx; nx < maxx; nx += step) { index = (nx - x) + this->rad; - const float multiplyer = gausstab[index]; - madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplyer); - overallmultiplyer += multiplyer; + const float multiplier = gausstab[index]; + madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); + multiplier_accum += multiplier; bufferindex += offsetadd; } - mul_v4_v4fl(color, tempColor, 1.0f / overallmultiplyer); + mul_v4_v4fl(color, color_accum, 1.0f / multiplier_accum); } void GaussianXBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index ace817194f3..06c1c78d85a 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -27,7 +27,7 @@ extern "C" { #include "RE_pipeline.h" } -GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation() +GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { this->gausstab = NULL; this->rad = 0; @@ -69,12 +69,8 @@ void GaussianYBlurOperation::updateGauss(MemoryBuffer **memoryBuffers) void GaussianYBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - float tempColor[4]; - tempColor[0] = 0; - tempColor[1] = 0; - tempColor[2] = 0; - tempColor[3] = 0; - float overallmultiplyer = 0; + float color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float multiplier_accum = 0.0f; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; float *buffer = inputBuffer->getBuffer(); int bufferwidth = inputBuffer->getWidth(); @@ -95,11 +91,11 @@ void GaussianYBlurOperation::executePixel(float *color, int x, int y, MemoryBuff for (int ny = miny; ny < maxy; ny += step) { index = (ny - y) + this->rad; int bufferindex = ((minx - bufferstartx) * 4) + ((ny - bufferstarty) * 4 * bufferwidth); - const float multiplyer = gausstab[index]; - madd_v4_v4fl(tempColor, &buffer[bufferindex], multiplyer); - overallmultiplyer += multiplyer; + const float multiplier = gausstab[index]; + madd_v4_v4fl(color_accum, &buffer[bufferindex], multiplier); + multiplier_accum += multiplier; } - mul_v4_v4fl(color, tempColor, 1.0f / overallmultiplyer); + mul_v4_v4fl(color, color_accum, 1.0f / multiplier_accum); } void GaussianYBlurOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_KeyingOperation.cpp b/source/blender/compositor/operations/COM_KeyingOperation.cpp index 0a450cc3bf8..ae2913350f9 100644 --- a/source/blender/compositor/operations/COM_KeyingOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingOperation.cpp @@ -98,23 +98,42 @@ void KeyingOperation::executePixel(float *color, float x, float y, PixelSampler int primary_channel = get_pixel_primary_channel(screenColor); - float saturation = get_pixel_saturation(pixelColor, this->screenBalance, primary_channel); - float screen_saturation = get_pixel_saturation(screenColor, this->screenBalance, primary_channel); - - if (saturation < 0) { + if (pixelColor[primary_channel] > 1.0f) { + /* overexposure doesn't happen on screen itself and usually happens + * on light sources in the shot, this need to be checked separately + * because saturation and falloff calculation is based on the fact + * that pixels are not overexposured + */ color[0] = 1.0f; } - else if (saturation >= screen_saturation) { - color[0] = 0.0f; - } else { - float distance = 1.0f - saturation / screen_saturation; - - color[0] = distance; + float saturation = get_pixel_saturation(pixelColor, this->screenBalance, primary_channel); + float screen_saturation = get_pixel_saturation(screenColor, this->screenBalance, primary_channel); + + if (saturation < 0) { + /* means main channel of pixel is different from screen, + * assume this is completely a foreground + */ + color[0] = 1.0f; + } + else if (saturation >= screen_saturation) { + /* matched main channels and higher saturation on pixel + * is treated as completely background + */ + color[0] = 0.0f; + } + else { + /* nice alpha falloff on edges */ + float distance = 1.0f - saturation / screen_saturation; + + color[0] = distance; + } } - color[0] *= (1.0f - garbageValue[0]); + /* apply garbage matte */ + color[0] = MIN2(color[0], 1.0f - garbageValue[0]); + /* apply core matte */ color[0] = MAX2(color[0], coreValue[0]); } diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index b728f6c5cca..9f7b69636ab 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -85,6 +85,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri int i; int width = this->getWidth(); int height = this->getHeight(); + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->movieClip, framenumber); if (this->trackingObject[0]) { MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, this->trackingObject); @@ -102,7 +103,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri if (!sites_total) return NULL; - BKE_movieclip_user_set_frame(&user, framenumber); + BKE_movieclip_user_set_frame(&user, clip_frame); ibuf = BKE_movieclip_get_ibuf(movieClip, &user); if (!ibuf) @@ -115,7 +116,7 @@ KeyingScreenOperation::TriangulationData *KeyingScreenOperation::buildVoronoiTri i = 0; while (track) { VoronoiSite *site = &sites[i]; - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenumber); + MovieTrackingMarker *marker = BKE_tracking_marker_get(track, clip_frame); ImBuf *pattern_ibuf = BKE_tracking_get_pattern_imbuf(ibuf, track, marker, TRUE, FALSE); int j; @@ -182,8 +183,9 @@ void KeyingScreenOperation::determineResolution(unsigned int resolution[], unsig if (this->movieClip) { MovieClipUser user = {0}; int width, height; + int clip_frame = BKE_movieclip_remap_scene_to_clip_frame(this->movieClip, framenumber); - BKE_movieclip_user_set_frame(&user, framenumber); + BKE_movieclip_user_set_frame(&user, clip_frame); BKE_movieclip_get_size(this->movieClip, &user, &width, &height); resolution[0] = width; diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 0493bdee12c..3b7e98433e4 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -75,8 +75,8 @@ void *MaskOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers float *buffer; buffer = (float *)MEM_callocN(sizeof(float) * width * height, "rasterized mask"); - BKE_mask_rasterize(mask, width, height, buffer, TRUE, this->smooth); - if (this->smooth) { + BKE_mask_rasterize(mask, width, height, buffer, TRUE, this->do_smooth, this->do_feather); + if (this->do_smooth) { PLX_antialias_buffer(buffer, width, height); } diff --git a/source/blender/compositor/operations/COM_MaskOperation.h b/source/blender/compositor/operations/COM_MaskOperation.h index 8507cb994c0..6b6d9aa9eeb 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.h +++ b/source/blender/compositor/operations/COM_MaskOperation.h @@ -40,7 +40,8 @@ protected: int maskWidth; int maskHeight; int framenumber; - bool smooth; + bool do_smooth; + bool do_feather; float *rasterizedMask; /** @@ -60,7 +61,8 @@ public: void setMaskWidth(int width) { this->maskWidth = width; } void setMaskHeight(int height) { this->maskHeight = height; } void setFramenumber(int framenumber) { this->framenumber = framenumber; } - void setSmooth(bool smooth) { this->smooth = smooth; } + void setSmooth(bool smooth) { this->do_smooth = smooth; } + void setFeather(bool feather) { this->do_feather = feather; } void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data); }; diff --git a/source/blender/compositor/operations/COM_OpenCLKernels.cl.h b/source/blender/compositor/operations/COM_OpenCLKernels.cl.h index ef8668f6f21..e064b7511cb 100644 --- a/source/blender/compositor/operations/COM_OpenCLKernels.cl.h +++ b/source/blender/compositor/operations/COM_OpenCLKernels.cl.h @@ -16,7 +16,7 @@ const char * clkernelstoh_COM_OpenCLKernels_cl = "/// This file contains all ope " coords += offset;\n" \ " float tempBoundingBox;\n" \ " float4 color = {0.0f,0.0f,0.0f,0.0f};\n" \ -" float4 multiplyer = {0.0f,0.0f,0.0f,0.0f};\n" \ +" float4 multiplier = {0.0f,0.0f,0.0f,0.0f};\n" \ " float4 bokeh;\n" \ " const float radius2 = radius*2.0f;\n" \ " const int2 realCoordinate = coords + offsetOutput;\n" \ @@ -40,10 +40,10 @@ const char * clkernelstoh_COM_OpenCLKernels_cl = "/// This file contains all ope " uv.x = ((realCoordinate.x-nx)/radius2)*bokehImageDim.x+bokehImageCenter.x;\n" \ " bokeh = read_imagef(bokehImage, SAMPLER_NEAREST, uv);\n" \ " color += bokeh * read_imagef(inputImage, SAMPLER_NEAREST, inputXy);\n" \ -" multiplyer += bokeh;\n" \ +" multiplier += bokeh;\n" \ " }\n" \ " }\n" \ -" color /= multiplyer;\n" \ +" color /= multiplier;\n" \ "\n" \ " } else {\n" \ " int2 imageCoordinates = realCoordinate - offsetInput;\n" \ diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index e71178a811d..c0aa139b032 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -92,9 +92,9 @@ static void write_buffer_rect(rcti *rect, MemoryBuffer **memoryBuffers, const bN OutputSingleLayerOperation::OutputSingleLayerOperation( - const Scene *scene, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path) + const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path) { - this->scene = scene; + this->rd = rd; this->tree = tree; this->addInputSocket(datatype); @@ -130,13 +130,13 @@ void OutputSingleLayerOperation::deinitExecution() ibuf->channels = size; ibuf->rect_float = this->outputBuffer; ibuf->mall |= IB_rectfloat; - ibuf->dither = scene->r.dither_intensity; + ibuf->dither = this->rd->dither_intensity; - if (scene->r.color_mgt_flag & R_COLOR_MANAGEMENT) + if (this->rd->color_mgt_flag & R_COLOR_MANAGEMENT) ibuf->profile = IB_PROFILE_LINEAR_RGB; - BKE_makepicstring(filename, this->path, bmain->name, this->scene->r.cfra, this->format->imtype, - (this->scene->r.scemode & R_EXTENSION), true); + BKE_makepicstring(filename, this->path, bmain->name, this->rd->cfra, this->format->imtype, + (this->rd->scemode & R_EXTENSION), true); if (0 == BKE_imbuf_write(ibuf, filename, this->format)) printf("Cannot save Node File Output to %s\n", filename); @@ -160,9 +160,9 @@ OutputOpenExrLayer::OutputOpenExrLayer(const char *name, DataType datatype) } OutputOpenExrMultiLayerOperation::OutputOpenExrMultiLayerOperation( - const Scene *scene, const bNodeTree *tree, const char *path, char exr_codec) + const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec) { - this->scene = scene; + this->rd = rd; this->tree = tree; BLI_strncpy(this->path, path, sizeof(this->path)); @@ -199,8 +199,8 @@ void OutputOpenExrMultiLayerOperation::deinitExecution() char filename[FILE_MAX]; void *exrhandle = IMB_exr_get_handle(); - BKE_makepicstring(filename, this->path, bmain->name, this->scene->r.cfra, R_IMF_IMTYPE_MULTILAYER, - (this->scene->r.scemode & R_EXTENSION), true); + BKE_makepicstring(filename, this->path, bmain->name, this->rd->cfra, R_IMF_IMTYPE_MULTILAYER, + (this->rd->scemode & R_EXTENSION), true); BLI_make_existing_file(filename); for (unsigned int i = 0; i < layers.size(); ++i) { diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h index cfc5f7e41f2..25ee5b31ec0 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.h +++ b/source/blender/compositor/operations/COM_OutputFileOperation.h @@ -32,7 +32,7 @@ /* Writes the image to a single-layer file. */ class OutputSingleLayerOperation : public NodeOperation { private: - const Scene *scene; + const RenderData *rd; const bNodeTree *tree; ImageFormatData *format; @@ -43,7 +43,7 @@ private: SocketReader *imageInput; public: - OutputSingleLayerOperation(const Scene *scene, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path); + OutputSingleLayerOperation(const RenderData *rd, const bNodeTree *tree, DataType datatype, ImageFormatData *format, const char *path); void executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer **memoryBuffers); bool isOutputOperation(bool rendering) const { return true; } @@ -67,7 +67,7 @@ class OutputOpenExrMultiLayerOperation : public NodeOperation { private: typedef std::vector<OutputOpenExrLayer> LayerList; - const Scene *scene; + const RenderData *rd; const bNodeTree *tree; char path[FILE_MAX]; @@ -75,7 +75,7 @@ private: LayerList layers; public: - OutputOpenExrMultiLayerOperation(const Scene *scene, const bNodeTree *tree, const char *path, char exr_codec); + OutputOpenExrMultiLayerOperation(const RenderData *rd, const bNodeTree *tree, const char *path, char exr_codec); void add_layer(const char *name, DataType datatype); diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp index 77f2a06b29b..b337e435df4 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp @@ -27,19 +27,21 @@ ProjectorLensDistortionOperation::ProjectorLensDistortionOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); this->addOutputSocket(COM_DT_COLOR); this->setComplex(true); this->inputProgram = NULL; + this->dispersionAvailable = false; + this->dispersion = 0.0f; } void ProjectorLensDistortionOperation::initExecution() { this->inputProgram = this->getInputSocketReader(0); - kr = 0.25f * MAX2(MIN2(this->dispersion, 1.f), 0.f); - kr2 = kr * 20; } void *ProjectorLensDistortionOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) { + updateDispersion(memoryBuffers); void *buffer = inputProgram->initializeTileData(NULL, memoryBuffers); return buffer; } @@ -69,9 +71,28 @@ void ProjectorLensDistortionOperation::deinitExecution() bool ProjectorLensDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) { rcti newInput; - newInput.ymax = input->ymax; - newInput.ymin = input->ymin; - newInput.xmin = input->xmin - kr2 - 2; - newInput.xmax = input->xmax + kr2 + 2; + if (dispersionAvailable) { + newInput.ymax = input->ymax; + newInput.ymin = input->ymin; + newInput.xmin = input->xmin - kr2 - 2; + newInput.xmax = input->xmax + kr2 + 2; + } else { + newInput.xmin = 0; + newInput.ymin = input->ymin; + newInput.ymax = input->ymax; + newInput.xmax = inputProgram->getWidth(); + } return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } + +void ProjectorLensDistortionOperation::updateDispersion(MemoryBuffer **inputBuffers) +{ + if (!dispersionAvailable) { + float result[4]; + this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST, inputBuffers); + dispersion = result[0]; + kr = 0.25f * MAX2(MIN2(this->dispersion, 1.f), 0.f); + kr2 = kr * 20; + dispersionAvailable = true; + } +} diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h index 2e188617ab5..5023a5df507 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.h @@ -35,6 +35,8 @@ private: NodeLensDist *data; float dispersion; + bool dispersionAvailable; + float kr, kr2; public: ProjectorLensDistortionOperation(); @@ -56,9 +58,10 @@ public: void deinitExecution(); void setData(NodeLensDist *data) { this->data = data; } - void setDispertion(float dispersion) { this->dispersion = dispersion; } bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); + void updateDispersion(MemoryBuffer** inputBuffers); + }; #endif diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index fa1f0280207..857131950dd 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -48,14 +48,21 @@ void ReadBufferOperation::determineResolution(unsigned int resolution[], unsigne } void ReadBufferOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]) { - MemoryBuffer *inputBuffer = inputBuffers[this->offset]; - if (inputBuffer) { - if (sampler == COM_PS_NEAREST) { - inputBuffer->read(color, x, y); - } - else { - inputBuffer->readCubic(color, x, y); + if (inputBuffers) { + MemoryBuffer *inputBuffer = inputBuffers[this->offset]; + if (inputBuffer) { + if (sampler == COM_PS_NEAREST) { + inputBuffer->read(color, x, y); + } + else { + inputBuffer->readCubic(color, x, y); + } } + } else { + color[0] = 0.0f; + color[1] = 0.0f; + color[2] = 0.0f; + color[3] = 0.0f; } } @@ -76,7 +83,8 @@ bool ReadBufferOperation::determineDependingAreaOfInterest(rcti *input, ReadBuff return false; } -void ReadBufferOperation::readResolutionFromWriteBuffer() { +void ReadBufferOperation::readResolutionFromWriteBuffer() +{ if (this->memoryProxy != NULL) { WriteBufferOperation *operation = memoryProxy->getWriteBufferOperation(); this->setWidth(operation->getWidth()); diff --git a/source/blender/compositor/operations/COM_RotateOperation.cpp b/source/blender/compositor/operations/COM_RotateOperation.cpp index ac06048faf3..456dc5d1d0f 100644 --- a/source/blender/compositor/operations/COM_RotateOperation.cpp +++ b/source/blender/compositor/operations/COM_RotateOperation.cpp @@ -48,7 +48,8 @@ void RotateOperation::deinitExecution() this->degreeSocket = NULL; } -inline void RotateOperation::ensureDegree() { +inline void RotateOperation::ensureDegree() +{ if (!isDegreeSet) { float degree[4]; this->degreeSocket->read(degree, 0, 0, COM_PS_NEAREST, NULL); diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 3299434a02e..da3504de971 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -30,34 +30,24 @@ extern "C" { ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); this->addOutputSocket(COM_DT_COLOR); this->setComplex(true); this->inputProgram = NULL; + this->valuesAvailable = false; + this->dispersion = 0.0f; + this->distortion = 0.0f; } void ScreenLensDistortionOperation::initExecution() { this->inputProgram = this->getInputSocketReader(0); - kg = MAX2(MIN2(this->distortion, 1.f), -0.999f); - // smaller dispersion range for somewhat more control - const float d = 0.25f * MAX2(MIN2(this->dispersion, 1.f), 0.f); - kr = MAX2(MIN2((kg + d), 1.f), -0.999f); - kb = MAX2(MIN2((kg - d), 1.f), -0.999f); - maxk = MAX3(kr, kg, kb); - sc = (this->data->fit && (maxk > 0.f)) ? (1.f / (1.f + 2.f * maxk)) : (1.f / (1.f + maxk)); - drg = 4.f * (kg - kr); - dgb = 4.f * (kb - kg); - - kr4 = kr * 4; - kg4 = kg * 4.f; - kb4 *= kb * 4.f; - cx = 0.5f * (float)getWidth(); - cy = 0.5f * (float)getHeight(); - } void *ScreenLensDistortionOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers) { void *buffer = inputProgram->initializeTileData(NULL, memoryBuffers); + updateDispersionAndDistortion(memoryBuffers); return buffer; } @@ -72,19 +62,20 @@ void ScreenLensDistortionOperation::executePixel(float *outputColor, int x, int float tc[4] = {0, 0, 0, 0}; const float v = sc * ((y + 0.5f) - cy) / cy; const float u = sc * ((x + 0.5f) - cx) / cx; + const float uv_dot = u * u + v * v; int sta = 0, mid = 0, end = 0; - if ((t = 1.f - kr4 * (u * u + v * v)) >= 0.f) { + if ((t = 1.f - kr4 * uv_dot) >= 0.f) { d = 1.f / (1.f + sqrtf(t)); ln[0] = (u * d + 0.5f) * width - 0.5f, ln[1] = (v * d + 0.5f) * height - 0.5f; sta = 1; } - if ((t = 1.f - kg4 * (u * u + v * v)) >= 0.f) { + if ((t = 1.f - kg4 * uv_dot) >= 0.f) { d = 1.f / (1.f + sqrtf(t)); ln[2] = (u * d + 0.5f) * width - 0.5f, ln[3] = (v * d + 0.5f) * height - 0.5f; mid = 1; } - if ((t = 1.f - kb4 * (u * u + v * v)) >= 0.f) { + if ((t = 1.f - kb4 * uv_dot) >= 0.f) { d = 1.f / (1.f + sqrtf(t)); ln[4] = (u * d + 0.5f) * width - 0.5f, ln[5] = (v * d + 0.5f) * height - 0.5f; end = 1; @@ -103,10 +94,10 @@ void ScreenLensDistortionOperation::executePixel(float *outputColor, int x, int for (z = 0; z < ds; ++z) { const float tz = ((float)z + (jit ? BLI_frand() : 0.5f)) * sd; - t = 1.f - (kr4 + tz * drg) * (u * u + v * v); + t = 1.f - (kr4 + tz * drg) * uv_dot; d = 1.f / (1.f + sqrtf(t)); - const float nx = (u * d + 0.5f) * getWidth() - 0.5f; - const float ny = (v * d + 0.5f) * getHeight() - 0.5f; + const float nx = (u * d + 0.5f) * width - 0.5f; + const float ny = (v * d + 0.5f) * height - 0.5f; buffer->readCubic(color, nx, ny); tc[0] += (1.f - tz) * color[0], tc[1] += tz * color[1]; dr++, dg++; @@ -121,10 +112,10 @@ void ScreenLensDistortionOperation::executePixel(float *outputColor, int x, int for (z = 0; z < ds; ++z) { const float tz = ((float)z + (jit ? BLI_frand() : 0.5f)) * sd; - t = 1.f - (kg4 + tz * dgb) * (u * u + v * v); + t = 1.f - (kg4 + tz * dgb) * uv_dot; d = 1.f / (1.f + sqrtf(t)); - const float nx = (u * d + 0.5f) * getWidth() - 0.5f; - const float ny = (v * d + 0.5f) * getHeight() - 0.5f; + const float nx = (u * d + 0.5f) * width - 0.5f; + const float ny = (v * d + 0.5f) * height - 0.5f; buffer->readCubic(color, nx, ny); tc[1] += (1.f - tz) * color[1], tc[2] += tz * color[2]; dg++, db++; @@ -170,3 +161,30 @@ bool ScreenLensDistortionOperation::determineDependingAreaOfInterest(rcti *input newInput.xmax = inputProgram->getWidth(); return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } + +void ScreenLensDistortionOperation::updateDispersionAndDistortion(MemoryBuffer **inputBuffers) +{ + if (!valuesAvailable) { + float result[4]; + this->getInputSocketReader(1)->read(result, 0, 0, COM_PS_NEAREST, inputBuffers); + this->distortion = result[0]; + this->getInputSocketReader(2)->read(result, 0, 0, COM_PS_NEAREST, inputBuffers); + this->dispersion = result[0]; + kg = MAX2(MIN2(this->distortion, 1.f), -0.999f); + // smaller dispersion range for somewhat more control + const float d = 0.25f * MAX2(MIN2(this->dispersion, 1.f), 0.f); + kr = MAX2(MIN2((kg + d), 1.f), -0.999f); + kb = MAX2(MIN2((kg - d), 1.f), -0.999f); + maxk = MAX3(kr, kg, kb); + sc = (this->data->fit && (maxk > 0.f)) ? (1.f / (1.f + 2.f * maxk)) : (1.f / (1.f + maxk)); + drg = 4.f * (kg - kr); + dgb = 4.f * (kb - kg); + + kr4 = kr * 4.f; + kg4 = kg * 4.f; + kb4 = kb * 4.f; + cx = 0.5f * (float)getWidth(); + cy = 0.5f * (float)getHeight(); + valuesAvailable = true; + } +} diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h index 34656f38a09..21babd11295 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.h @@ -36,6 +36,7 @@ private: float dispersion; float distortion; + bool valuesAvailable; float kr, kg, kb; float kr4, kg4, kb4; float maxk; @@ -62,13 +63,12 @@ public: void deinitExecution(); void setData(NodeLensDist *data) { this->data = data; } - void setDispertion(float dispersion) { this->dispersion = dispersion; } - void setDistortion(float distortion) { this->distortion = distortion; } bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); private: void determineUV(float *result, float x, float y) const; + void updateDispersionAndDistortion(MemoryBuffer** inputBuffers); }; #endif diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 072528f3fc6..dbdd17adbe4 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -32,7 +32,7 @@ TextureBaseOperation::TextureBaseOperation() : NodeOperation() this->texture = NULL; this->inputSize = NULL; this->inputOffset = NULL; - this->scene = NULL; + this->rd = NULL; } TextureOperation::TextureOperation() : TextureBaseOperation() { @@ -57,8 +57,8 @@ void TextureBaseOperation::deinitExecution() void TextureBaseOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[]) { if (preferredResolution[0] == 0 || preferredResolution[1] == 0) { - int width = this->scene->r.xsch * this->scene->r.size / 100; - int height = this->scene->r.ysch * this->scene->r.size / 100; + int width = this->rd->xsch * this->rd->size / 100; + int height = this->rd->ysch * this->rd->size / 100; resolution[0] = width; resolution[1] = height; } diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index e862a1f1910..14714242511 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -43,7 +43,7 @@ extern "C" { class TextureBaseOperation : public NodeOperation { private: Tex *texture; - const Scene *scene; + const RenderData *rd; SocketReader *inputSize; SocketReader *inputOffset; @@ -65,7 +65,7 @@ public: void setTexture(Tex *texture) { this->texture = texture; } void initExecution(); void deinitExecution(); - void setScene(const Scene *scene) { this->scene = scene; } + void setRenderData(const RenderData *rd) { this->rd = rd; } }; class TextureOperation : public TextureBaseOperation { diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 7c9b0c75518..c17e51e6391 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -31,15 +31,17 @@ VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation() : NodeOperation { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); // do not resize the bokeh image. - this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); // radius + this->addInputSocket(COM_DT_VALUE); // depth this->addOutputSocket(COM_DT_COLOR); this->setComplex(true); this->inputProgram = NULL; this->inputBokehProgram = NULL; this->inputSizeProgram = NULL; + this->inputDepthProgram = NULL; this->maxBlur = 32.0f; - this->threshold = 0.0f; + this->threshold = 1.0f; } @@ -48,61 +50,62 @@ void VariableSizeBokehBlurOperation::initExecution() this->inputProgram = getInputSocketReader(0); this->inputBokehProgram = getInputSocketReader(1); this->inputSizeProgram = getInputSocketReader(2); + this->inputDepthProgram = getInputSocketReader(3); QualityStepHelper::initExecution(COM_QH_INCREASE); } void VariableSizeBokehBlurOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data) { - float tempColor[4]; float readColor[4]; float bokeh[4]; - tempColor[0] = 0; - tempColor[1] = 0; - tempColor[2] = 0; - tempColor[3] = 0; float tempSize[4]; - float overallmultiplyer[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float tempDepth[4]; + float multiplier_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + float color_accum[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int miny = y - maxBlur; int maxy = y + maxBlur; int minx = x - maxBlur; int maxx = x + maxBlur; { + inputSizeProgram->read(tempSize, x, y, COM_PS_NEAREST, inputBuffers); + inputDepthProgram->read(tempDepth, x, y, COM_PS_NEAREST, inputBuffers); inputProgram->read(readColor, x, y, COM_PS_NEAREST, inputBuffers); - tempColor[0] += readColor[0]; - tempColor[1] += readColor[1]; - tempColor[2] += readColor[2]; - tempColor[3] += readColor[3]; - add_v4_v4(tempColor, readColor); - add_v3_fl(overallmultiplyer, 1.0f); + add_v4_v4(color_accum, readColor); + add_v4_fl(multiplier_accum, 1.0f); + float sizeCenter = tempSize[0]; + float centerDepth = tempDepth[0]+threshold; for (int ny = miny; ny < maxy; ny += QualityStepHelper::getStep()) { for (int nx = minx; nx < maxx; nx += QualityStepHelper::getStep()) { if (nx >= 0 && nx < this->getWidth() && ny >= 0 && ny < getHeight()) { + inputDepthProgram->read(tempDepth, nx, ny, COM_PS_NEAREST, inputBuffers); inputSizeProgram->read(tempSize, nx, ny, COM_PS_NEAREST, inputBuffers); float size = tempSize[0]; -// size += this->threshold; - float dx = nx - x; - float dy = ny - y; - if (nx == x && ny == y) { - /* pass */ - } - else if (size >= fabsf(dx) && size >= fabsf(dy)) { - float u = 256 + dx * 256 / size; - float v = 256 + dy * 256 / size; - inputBokehProgram->read(bokeh, u, v, COM_PS_NEAREST, inputBuffers); - inputProgram->read(readColor, nx, ny, COM_PS_NEAREST, inputBuffers); - madd_v4_v4v4(tempColor, bokeh, readColor); - add_v4_v4(overallmultiplyer, bokeh); + if (tempDepth[0] < centerDepth) { + if ((sizeCenter > threshold && size > threshold) || size <= threshold) { + float dx = nx - x; + float dy = ny - y; + if (nx == x && ny == y) { + } + else if (size >= fabsf(dx) && size >= fabsf(dy)) { + float u = 256 + dx * 256 / size; + float v = 256 + dy * 256 / size; + inputBokehProgram->read(bokeh, u, v, COM_PS_NEAREST, inputBuffers); + inputProgram->read(readColor, nx, ny, COM_PS_NEAREST, inputBuffers); + madd_v4_v4v4(color_accum, bokeh, readColor); + add_v4_v4(multiplier_accum, bokeh); + } + } } } } } - color[0] = tempColor[0] * (1.0f / overallmultiplyer[0]); - color[1] = tempColor[1] * (1.0f / overallmultiplyer[1]); - color[2] = tempColor[2] * (1.0f / overallmultiplyer[2]); - color[3] = tempColor[3] * (1.0f / overallmultiplyer[3]); + color[0] = color_accum[0] * (1.0f / multiplier_accum[0]); + color[1] = color_accum[1] * (1.0f / multiplier_accum[1]); + color[2] = color_accum[2] * (1.0f / multiplier_accum[2]); + color[3] = color_accum[3] * (1.0f / multiplier_accum[3]); } } @@ -136,6 +139,10 @@ bool VariableSizeBokehBlurOperation::determineDependingAreaOfInterest(rcti *inpu if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output) ) { return true; } + operation = getInputOperation(3); + if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { + return true; + } operation = getInputOperation(0); if (operation->determineDependingAreaOfInterest(&newInput, readOperation, output) ) { return true; diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h index ede8f0333b4..d04bf08405f 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.h @@ -32,6 +32,7 @@ private: SocketReader *inputProgram; SocketReader *inputBokehProgram; SocketReader *inputSizeProgram; + SocketReader *inputDepthProgram; public: VariableSizeBokehBlurOperation(); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp index e1018e0d037..356ba452185 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.cpp @@ -23,6 +23,7 @@ #include "COM_WriteBufferOperation.h" #include "COM_defines.h" #include <stdio.h> +#include "COM_OpenCLDevice.h" WriteBufferOperation::WriteBufferOperation() : NodeOperation() { @@ -110,7 +111,7 @@ void WriteBufferOperation::executeRegion(rcti *rect, unsigned int tileNumber, Me memoryBuffer->setCreatedState(); } -void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) +void WriteBufferOperation::executeOpenCLRegion(OpenCLDevice* device, rcti *rect, unsigned int chunkNumber, MemoryBuffer **inputMemoryBuffers, MemoryBuffer *outputBuffer) { float *outputFloatBuffer = outputBuffer->getBuffer(); cl_int error; @@ -131,7 +132,7 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr CL_FLOAT }; - cl_mem clOutputBuffer = clCreateImage2D(context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, &imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error); + cl_mem clOutputBuffer = clCreateImage2D(device->getContext(), CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, &imageFormat, outputBufferWidth, outputBufferHeight, 0, outputFloatBuffer, &error); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } // STEP 2 @@ -139,7 +140,7 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr clMemToCleanUp->push_back(clOutputBuffer); list<cl_kernel> *clKernelsToCleanUp = new list<cl_kernel>(); - this->input->executeOpenCL(context, program, queue, outputBuffer, clOutputBuffer, inputMemoryBuffers, clMemToCleanUp, clKernelsToCleanUp); + this->input->executeOpenCL(device, outputBuffer, clOutputBuffer, inputMemoryBuffers, clMemToCleanUp, clKernelsToCleanUp); // STEP 3 @@ -149,9 +150,9 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr // clFlush(queue); // clFinish(queue); - error = clEnqueueBarrier(queue); + error = clEnqueueBarrier(device->getQueue()); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } - error = clEnqueueReadImage(queue, clOutputBuffer, CL_TRUE, origin, region, 0, 0, outputFloatBuffer, 0, NULL, NULL); + error = clEnqueueReadImage(device->getQueue(), clOutputBuffer, CL_TRUE, origin, region, 0, 0, outputFloatBuffer, 0, NULL, NULL); if (error != CL_SUCCESS) { printf("CLERROR[%d]: %s\n", error, clewErrorString(error)); } this->getMemoryProxy()->getBuffer()->copyContentFrom(outputBuffer); @@ -175,7 +176,8 @@ void WriteBufferOperation::executeOpenCLRegion(cl_context context, cl_program pr delete clKernelsToCleanUp; } -void WriteBufferOperation::readResolutionFromInputSocket() { +void WriteBufferOperation::readResolutionFromInputSocket() +{ NodeOperation *inputOperation = this->getInputOperation(0); this->setWidth(inputOperation->getWidth()); this->setHeight(inputOperation->getHeight()); diff --git a/source/blender/compositor/operations/COM_WriteBufferOperation.h b/source/blender/compositor/operations/COM_WriteBufferOperation.h index 321eed7240a..ccc20584186 100644 --- a/source/blender/compositor/operations/COM_WriteBufferOperation.h +++ b/source/blender/compositor/operations/COM_WriteBufferOperation.h @@ -44,7 +44,7 @@ public: void executeRegion(rcti *rect, unsigned int tileNumber, MemoryBuffer **memoryBuffers); void initExecution(); void deinitExecution(); - void executeOpenCLRegion(cl_context context, cl_program program, cl_command_queue queue, rcti *rect, unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer); + void executeOpenCLRegion(OpenCLDevice* device, rcti *rect, unsigned int chunkNumber, MemoryBuffer **memoryBuffers, MemoryBuffer *outputBuffer); void readResolutionFromInputSocket(); }; |