Fix for [#31602] Node Glare: Ghosts effect
This commit is contained in:
@@ -187,10 +187,6 @@ set(SRC
|
||||
operations/COM_CropOperation.cpp
|
||||
operations/COM_CropOperation.h
|
||||
|
||||
operations/COM_LensGlowOperation.cpp
|
||||
operations/COM_LensGlowOperation.h
|
||||
operations/COM_LensGhostOperation.cpp
|
||||
operations/COM_LensGhostOperation.h
|
||||
nodes/COM_TransformNode.cpp
|
||||
nodes/COM_TransformNode.h
|
||||
nodes/COM_Stabilize2dNode.cpp
|
||||
@@ -374,16 +370,14 @@ operations/COM_ColorSpillOperation.h
|
||||
operations/COM_RenderLayersCyclesOperation.cpp
|
||||
operations/COM_RenderLayersCyclesOperation.h
|
||||
|
||||
operations/COM_ImageOperation.cpp
|
||||
operations/COM_ImageOperation.h
|
||||
operations/COM_MultilayerImageOperation.cpp
|
||||
operations/COM_MultilayerImageOperation.h
|
||||
operations/COM_TextureOperation.cpp
|
||||
operations/COM_TextureOperation.h
|
||||
operations/COM_BokehImageOperation.cpp
|
||||
operations/COM_BokehImageOperation.h
|
||||
operations/COM_LensGlowImageOperation.cpp
|
||||
operations/COM_LensGlowImageOperation.h
|
||||
operations/COM_ImageOperation.cpp
|
||||
operations/COM_ImageOperation.h
|
||||
operations/COM_MultilayerImageOperation.cpp
|
||||
operations/COM_MultilayerImageOperation.h
|
||||
operations/COM_TextureOperation.cpp
|
||||
operations/COM_TextureOperation.h
|
||||
operations/COM_BokehImageOperation.cpp
|
||||
operations/COM_BokehImageOperation.h
|
||||
|
||||
|
||||
operations/COM_SocketProxyOperation.h
|
||||
@@ -575,6 +569,8 @@ operations/COM_ConvertDepthToRadiusOperation.cpp
|
||||
operations/COM_GlareSimpleStarOperation.h
|
||||
operations/COM_GlareStreaksOperation.cpp
|
||||
operations/COM_GlareStreaksOperation.h
|
||||
operations/COM_GlareGhostOperation.cpp
|
||||
operations/COM_GlareGhostOperation.h
|
||||
operations/COM_SetSamplerOperation.cpp
|
||||
operations/COM_SetSamplerOperation.h
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "COM_SetValueOperation.h"
|
||||
#include "COM_MixBlendOperation.h"
|
||||
#include "COM_FastGaussianBlurOperation.h"
|
||||
#include "COM_GlareGhostOperation.h"
|
||||
|
||||
GlareNode::GlareNode(bNode *editorNode): Node(editorNode)
|
||||
{
|
||||
@@ -42,6 +43,30 @@ void GlareNode::convertToOperations(ExecutionSystem *system, CompositorContext *
|
||||
switch (glare->type) {
|
||||
|
||||
default:
|
||||
case 3:
|
||||
{
|
||||
GlareThresholdOperation *thresholdOperation = new GlareThresholdOperation();
|
||||
GlareGhostOperation * glareoperation = new GlareGhostOperation();
|
||||
SetValueOperation * mixvalueoperation = new SetValueOperation();
|
||||
MixBlendOperation * mixoperation = new MixBlendOperation();
|
||||
|
||||
this->getInputSocket(0)->relinkConnections(thresholdOperation->getInputSocket(0), 0, system);
|
||||
addLink(system, thresholdOperation->getOutputSocket(), glareoperation->getInputSocket(0));
|
||||
addLink(system, mixvalueoperation->getOutputSocket(), mixoperation->getInputSocket(0));
|
||||
addLink(system, glareoperation->getOutputSocket(), mixoperation->getInputSocket(2));
|
||||
addLink(system, thresholdOperation->getInputSocket(0)->getConnection()->getFromSocket(), mixoperation->getInputSocket(1));
|
||||
this->getOutputSocket()->relinkConnections(mixoperation->getOutputSocket());
|
||||
|
||||
thresholdOperation->setThreshold(glare->threshold);
|
||||
glareoperation->setGlareSettings(glare);
|
||||
mixvalueoperation->setValue(0.5f+glare->mix*0.5f);
|
||||
mixoperation->setResolutionInputSocketIndex(1);
|
||||
|
||||
system->addOperation(glareoperation);
|
||||
system->addOperation(thresholdOperation);
|
||||
system->addOperation(mixvalueoperation);
|
||||
system->addOperation(mixoperation);
|
||||
}
|
||||
case 2: // streaks
|
||||
{
|
||||
GlareThresholdOperation *thresholdOperation = new GlareThresholdOperation();
|
||||
|
||||
@@ -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);
|
||||
|
||||
void IIR_gauss(MemoryBuffer *src, float sigma, int channel, int xy);
|
||||
static void IIR_gauss(MemoryBuffer *src, float sigma, int channel, int xy);
|
||||
void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers);
|
||||
void deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data);
|
||||
|
||||
|
||||
@@ -25,6 +25,36 @@
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
|
||||
/* utility functions used by glare, tonemap and lens distortion */
|
||||
/* soms macros for color handling */
|
||||
typedef float fRGB[4];
|
||||
/* clear color */
|
||||
#define fRGB_clear(c) { c[0]=c[1]=c[2]=0.f; } (void)0
|
||||
/* copy c2 to c1 */
|
||||
#define fRGB_copy(c1, c2) { c1[0]=c2[0]; c1[1]=c2[1]; c1[2]=c2[2]; c1[3]=c2[3]; } (void)0
|
||||
/* add c2 to c1 */
|
||||
#define fRGB_add(c1, c2) { c1[0]+=c2[0]; c1[1]+=c2[1]; c1[2]+=c2[2]; } (void)0
|
||||
/* subtract c2 from c1 */
|
||||
#define fRGB_sub(c1, c2) { c1[0]-=c2[0]; c1[1]-=c2[1]; c1[2]-=c2[2]; } (void)0
|
||||
/* multiply c by float value s */
|
||||
#define fRGB_mult(c, s) { c[0]*=s; c[1]*=s; c[2]*=s; } (void)0
|
||||
/* multiply c2 by s and add to c1 */
|
||||
#define fRGB_madd(c1, c2, s) { c1[0]+=c2[0]*s; c1[1]+=c2[1]*s; c1[2]+=c2[2]*s; } (void)0
|
||||
/* multiply c2 by color c1 */
|
||||
#define fRGB_colormult(c, cs) { c[0]*=cs[0]; c[1]*=cs[1]; c[2]*=cs[2]; } (void)0
|
||||
/* multiply c2 by color c3 and add to c1 */
|
||||
#define fRGB_colormadd(c1, c2, c3) { c1[0]+=c2[0]*c3[0]; c1[1]+=c2[1]*c3[1]; c1[2]+=c2[2]*c3[2]; } (void)0
|
||||
/* multiply c2 by color rgb, rgb as separate arguments */
|
||||
#define fRGB_rgbmult(c, r, g, b) { c[0]*=(r); c[1]*=(g); c[2]*=(b); } (void)0
|
||||
/* swap colors c1 & c2 */
|
||||
#define fRGB_swap(c1, c2) { float _t=c1[0]; c1[0]=c2[0]; c2[0]=_t;\
|
||||
_t=c1[1]; c1[1]=c2[1]; c2[1]=_t;\
|
||||
_t=c1[2]; c1[2]=c2[2]; c2[2]=_t;\
|
||||
_t=c1[3]; c1[3]=c2[3]; c3[3]=_t;\
|
||||
} (void)0
|
||||
|
||||
|
||||
class GlareBaseOperation : public NodeOperation {
|
||||
private:
|
||||
/**
|
||||
|
||||
114
source/blender/compositor/operations/COM_GlareGhostOperation.cpp
Normal file
114
source/blender/compositor/operations/COM_GlareGhostOperation.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "COM_GlareGhostOperation.h"
|
||||
#include "BLI_math.h"
|
||||
#include "COM_FastGaussianBlurOperation.h"
|
||||
|
||||
static float smoothMask(float x, float y)
|
||||
{
|
||||
float t;
|
||||
x = 2.f*x - 1.f, y = 2.f*y - 1.f;
|
||||
if ((t = 1.f - sqrtf(x*x + y*y)) <= 0.f) return 0.f;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings)
|
||||
{
|
||||
const int qt = 1 << settings->quality;
|
||||
const float s1 = 4.f/(float)qt, s2 = 2.f*s1;
|
||||
int x, y, n, p, np;
|
||||
fRGB c, tc, cm[64];
|
||||
float sc, isc, u, v, sm, s, t, ofs, scalef[64];
|
||||
const float cmo = 1.f - settings->colmod;
|
||||
|
||||
MemoryBuffer *gbuf = inputTile->duplicate();
|
||||
MemoryBuffer *tbuf1 = inputTile->duplicate();
|
||||
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 0, 3);
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 1, 3);
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf1, s1, 2, 3);
|
||||
|
||||
MemoryBuffer *tbuf2 = tbuf1->duplicate();
|
||||
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 0, 3);
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 1, 3);
|
||||
FastGaussianBlurOperation::IIR_gauss(tbuf2, s2, 2, 3);
|
||||
|
||||
if (settings->iter & 1) ofs = 0.5f; else ofs = 0.f;
|
||||
for (x=0; x<(settings->iter*4); x++) {
|
||||
y = x & 3;
|
||||
cm[x][0] = cm[x][1] = cm[x][2] = 1;
|
||||
if (y==1) fRGB_rgbmult(cm[x], 1.f, cmo, cmo);
|
||||
if (y==2) fRGB_rgbmult(cm[x], cmo, cmo, 1.f);
|
||||
if (y==3) fRGB_rgbmult(cm[x], cmo, 1.f, cmo);
|
||||
scalef[x] = 2.1f*(1.f-(x+ofs)/(float)(settings->iter*4));
|
||||
if (x & 1) scalef[x] = -0.99f/scalef[x];
|
||||
}
|
||||
|
||||
sc = 2.13;
|
||||
isc = -0.97;
|
||||
for (y=0; y<gbuf->getHeight(); y++) {
|
||||
v = (float)(y+0.5f) / (float)gbuf->getHeight();
|
||||
for (x=0; x<gbuf->getWidth(); x++) {
|
||||
u = (float)(x+0.5f) / (float)gbuf->getWidth();
|
||||
s = (u-0.5f)*sc + 0.5f, t = (v-0.5f)*sc + 0.5f;
|
||||
tbuf1->read(c, s*gbuf->getWidth(), t*gbuf->getHeight());
|
||||
sm = smoothMask(s, t);
|
||||
fRGB_mult(c, sm);
|
||||
s = (u-0.5f)*isc + 0.5f, t = (v-0.5f)*isc + 0.5f;
|
||||
tbuf2->read(tc, s*gbuf->getWidth()-0.5f, t*gbuf->getHeight()-0.5f);
|
||||
sm = smoothMask(s, t);
|
||||
fRGB_madd(c, tc, sm);
|
||||
|
||||
gbuf->writePixel(x, y, c);
|
||||
}
|
||||
}
|
||||
|
||||
memset(tbuf1->getBuffer(), 0, tbuf1->getWidth()*tbuf1->getHeight()*COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
for (n=1; n<settings->iter; n++) {
|
||||
for (y=0; y<gbuf->getHeight(); y++) {
|
||||
v = (float)(y+0.5f) / (float)gbuf->getHeight();
|
||||
for (x=0; x<gbuf->getWidth(); x++) {
|
||||
u = (float)(x+0.5f) / (float)gbuf->getWidth();
|
||||
tc[0] = tc[1] = tc[2] = 0.f;
|
||||
for (p=0;p<4;p++) {
|
||||
np = (n<<2) + p;
|
||||
s = (u-0.5f)*scalef[np] + 0.5f;
|
||||
t = (v-0.5f)*scalef[np] + 0.5f;
|
||||
gbuf->read(c, s*gbuf->getWidth() - 0.5f, t*gbuf->getHeight() - 0.5f);
|
||||
fRGB_colormult(c, cm[np]);
|
||||
sm = smoothMask(s, t)*0.25f;
|
||||
fRGB_madd(tc, c, sm);
|
||||
}
|
||||
tbuf1->writePixel(x, y, tc);
|
||||
}
|
||||
}
|
||||
memcpy(gbuf->getBuffer(), tbuf1->getBuffer(), tbuf1->getWidth()*tbuf1->getHeight()*COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
}
|
||||
memcpy(data, gbuf->getBuffer(), gbuf->getWidth()*gbuf->getHeight()*COM_NUMBER_OF_CHANNELS*sizeof(float));
|
||||
|
||||
delete gbuf;
|
||||
delete tbuf1;
|
||||
delete tbuf2;
|
||||
}
|
||||
@@ -20,33 +20,16 @@
|
||||
* Monique Dewanchand
|
||||
*/
|
||||
|
||||
#ifndef _COM_LensGlowImageOperation_h
|
||||
#define _COM_LensGlowImageOperation_h
|
||||
#ifndef _COM_GlareGhostOperation_h
|
||||
#define _COM_GlareGhostOperation_h
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "DNA_node_types.h"
|
||||
#include "COM_GlareBaseOperation.h"
|
||||
|
||||
|
||||
class LensGlowImageOperation : public NodeOperation {
|
||||
private:
|
||||
float scale;
|
||||
|
||||
class GlareGhostOperation : public GlareBaseOperation {
|
||||
public:
|
||||
LensGlowImageOperation();
|
||||
|
||||
/**
|
||||
* the inner loop of this program
|
||||
*/
|
||||
void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]);
|
||||
|
||||
/**
|
||||
* Initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
|
||||
/**
|
||||
* Deinitialize the execution
|
||||
*/
|
||||
void deinitExecution();
|
||||
|
||||
void determineResolution(unsigned int resolution[], unsigned int preferredResolution[]);
|
||||
GlareGhostOperation() : GlareBaseOperation() {}
|
||||
protected:
|
||||
void generateGlare(float *data, MemoryBuffer *inputTile, NodeGlare *settings);
|
||||
};
|
||||
#endif
|
||||
@@ -1,815 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "COM_LensGhostOperation.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#define MAX_STEP 256
|
||||
class Ray {
|
||||
public:
|
||||
float position[3];
|
||||
float direction[3];
|
||||
float uv[2];
|
||||
double wavelength;
|
||||
float intensity;
|
||||
bool valid;
|
||||
void copyFrom(Ray *other) {
|
||||
copy_v3_v3(position, other->position);
|
||||
copy_v3_v3(direction, other->direction);
|
||||
copy_v2_v2(uv, other->uv);
|
||||
wavelength = other->wavelength;
|
||||
intensity = other->intensity;
|
||||
this->valid = other->valid;
|
||||
}
|
||||
};
|
||||
|
||||
class Intersection {
|
||||
public:
|
||||
float position[3];
|
||||
float normal[3];
|
||||
double theta;
|
||||
bool hit;
|
||||
bool inverted;
|
||||
};
|
||||
|
||||
class LensInterface {
|
||||
public:
|
||||
float position[3];
|
||||
float radius;
|
||||
float nominalRadius;
|
||||
double refraction1;
|
||||
double refraction2;
|
||||
double refraction3;
|
||||
float thicknessCoathing;
|
||||
virtual bool isFlat() = 0;
|
||||
virtual void intersect(Intersection *result, Ray *ray) = 0;
|
||||
};
|
||||
|
||||
class FlatInterface: public LensInterface {
|
||||
public:
|
||||
bool isFlat() {return true;}
|
||||
FlatInterface(float positionX, float positionY, float positionZ, float radius) {
|
||||
this->position[0] = positionX;
|
||||
this->position[1] = positionY;
|
||||
this->position[2] = positionZ;
|
||||
this->radius = radius;
|
||||
this->nominalRadius = radius;
|
||||
this->refraction1 = 1.0f;
|
||||
this->refraction2 = 1.0f;
|
||||
this->refraction3 = 1.0f;
|
||||
this->thicknessCoathing = 0.0f;
|
||||
|
||||
}
|
||||
void intersect(Intersection *result, Ray *ray) {
|
||||
const float dz = this->position[2]-ray->position[2];
|
||||
result->position[0] = ray->position[0] + ray->direction[0]*(dz)/ray->direction[2];
|
||||
result->position[1] = ray->position[1] + ray->direction[1]*(dz)/ray->direction[2];
|
||||
result->position[2] = ray->position[2] + ray->direction[2]*(dz)/ray->direction[2];
|
||||
result->normal[0] = 0.0f;
|
||||
result->normal[1] = 0.0f;
|
||||
result->normal[2] = ray->direction[2]>0?-1.0f:1.0f;
|
||||
result->theta = 0.0f;
|
||||
// result->hit = this->nominalRadius>maxf(fabs(result->position[0]), fabs(result->position[1]));
|
||||
result->hit = true;
|
||||
result->inverted = false;
|
||||
}
|
||||
};
|
||||
|
||||
class SphereInterface: public LensInterface {
|
||||
public:
|
||||
SphereInterface(float positionX, float positionY, float positionZ, float radius, float nominalRadius, float n0, float n2, float coatingPhase) {
|
||||
this->position[0] = positionX;
|
||||
this->position[1] = positionY;
|
||||
this->position[2] = positionZ;
|
||||
this->radius = radius;
|
||||
this->nominalRadius = nominalRadius;
|
||||
this->refraction1 = n0;
|
||||
this->refraction3 = n2;
|
||||
this->refraction2 = maxf(sqrtf(n0*n2), 1.38);
|
||||
|
||||
this->thicknessCoathing = coatingPhase/4/this->refraction2;
|
||||
}
|
||||
bool isFlat() {return false;}
|
||||
void intersect(Intersection *result, Ray *ray) {
|
||||
float delta[3] ={ray->position[0] - this->position[0],
|
||||
ray->position[1] - this->position[1],
|
||||
ray->position[2] - this->position[2]};
|
||||
float b = dot_v3v3(delta, ray->direction);
|
||||
float c = dot_v3v3(delta, delta) - this->radius*this->radius;
|
||||
float b2c = b*b-c;
|
||||
if (b2c < 0) {
|
||||
result->hit = false;
|
||||
}
|
||||
else {
|
||||
float sgn = (this->radius*ray->direction[2])>0?1.0f:-1.0f;
|
||||
float t = sqrtf(b2c)*sgn-b;
|
||||
result->position[0] = ray->direction[0]*t+ray->position[0];
|
||||
result->position[1] = ray->direction[1]*t+ray->position[1];
|
||||
result->position[2] = ray->direction[2]*t+ray->position[2];
|
||||
|
||||
float p[3] = {
|
||||
result->position[0] - this->position[0],
|
||||
result->position[1] - this->position[1],
|
||||
result->position[2] - this->position[2]
|
||||
};
|
||||
normalize_v3(p);
|
||||
|
||||
if (dot_v3v3(p, ray->direction)> 0) {
|
||||
result->normal[0] = -p[0];
|
||||
result->normal[1] = -p[1];
|
||||
result->normal[2] = -p[2];
|
||||
}
|
||||
else {
|
||||
result->normal[0] = p[0];
|
||||
result->normal[1] = p[1];
|
||||
result->normal[2] = p[2];
|
||||
}
|
||||
|
||||
float inverse[3] ={
|
||||
-ray->direction[0],
|
||||
-ray->direction[1],
|
||||
-ray->direction[2]};
|
||||
|
||||
result->theta = acosf(dot_v3v3(inverse, result->normal));
|
||||
result->hit = this->nominalRadius>sqrt(result->position[0]*result->position[0]+result->position[1]*result->position[1]);
|
||||
// result->hit = this->nominalRadius>maxf(fabs(result->position[0]), fabs(result->position[1]));
|
||||
// result->hit = true;
|
||||
result->inverted = t < 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
class RayResult {
|
||||
public:
|
||||
float x;
|
||||
float y;
|
||||
float intensity[3];
|
||||
float u;
|
||||
float v;
|
||||
float screenX;
|
||||
float screenY;
|
||||
bool valid;
|
||||
bool hasIntensity;
|
||||
};
|
||||
class Bounce {
|
||||
public:
|
||||
LensInterface *interface1;
|
||||
LensInterface *interface2;
|
||||
RayResult *raster;
|
||||
int length; // number of interfaces to travel
|
||||
int rasterLength;
|
||||
Bounce(LensInterface *interface1, LensInterface *interface2, int length, int rasterStep) {
|
||||
this->interface1 = interface1;
|
||||
this->interface2 = interface2;
|
||||
this->length = length;
|
||||
this->rasterLength = rasterStep;
|
||||
this->raster = new RayResult[rasterLength*rasterLength];
|
||||
for (int i = 0 ; i < rasterLength*rasterLength ; i++) {
|
||||
RayResult * res = &this->raster[i];
|
||||
res->intensity[0] = 0.0f;
|
||||
res->intensity[1] = 0.0f;
|
||||
res->intensity[2] = 0.0f;
|
||||
res->x = 0.0f;
|
||||
res->y = 0.0f;
|
||||
res->u = 0.0f;
|
||||
res->v = 0.0f;
|
||||
res->valid = false;
|
||||
}
|
||||
}
|
||||
~Bounce() {
|
||||
delete raster;
|
||||
|
||||
}
|
||||
|
||||
RayResult *getRayResult(int x, int y) {
|
||||
return &(raster[x+y*rasterLength]);
|
||||
}
|
||||
};
|
||||
class LensSystem {
|
||||
public:
|
||||
vector<LensInterface*> interfaces;
|
||||
vector<Bounce*> bounces;
|
||||
int bokehIndex;
|
||||
int lensIndex;
|
||||
|
||||
~LensSystem() {
|
||||
for (int index = 0 ; index <bounces.size();index++) {delete bounces[index];}
|
||||
for (int index = 0 ; index <interfaces.size();index++) {delete interfaces[index];}
|
||||
}
|
||||
|
||||
void updateBounces(int step) {
|
||||
for (int i = 0; i < interfaces.size()-1 ; i ++) {
|
||||
if (!interfaces[i]->isFlat()) {
|
||||
for (int j = i+1; j < interfaces.size()-1 ; j ++) {
|
||||
if (!interfaces[j]->isFlat()) {
|
||||
int length = interfaces.size()+2*(j-i);
|
||||
Bounce *bounce = new Bounce(interfaces[j], interfaces[i], length, step);
|
||||
bounces.push_back(bounce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void addInterface(LensInterface *pinterface) {
|
||||
this->interfaces.push_back(pinterface);
|
||||
this->lensIndex = this->interfaces.size()-1;
|
||||
}
|
||||
|
||||
static int refraction(float *refract, float *n, float *view, double index)
|
||||
{
|
||||
|
||||
return 1;
|
||||
|
||||
// float dot, fac;
|
||||
|
||||
// VECCOPY(refract, view);
|
||||
|
||||
// dot = view[0]*n[0] + view[1]*n[1] + view[2]*n[2];
|
||||
|
||||
// if (dot>0.0f) {
|
||||
// index = 1.0f/index;
|
||||
// fac = 1.0f - (1.0f - dot*dot)*index*index;
|
||||
// if (fac<= 0.0f) return 0;
|
||||
// fac= -dot*index + sqrt(fac);
|
||||
// }
|
||||
// else {
|
||||
// fac = 1.0f - (1.0f - dot*dot)*index*index;
|
||||
// if (fac<= 0.0f) return 0;
|
||||
// fac= -dot*index - sqrt(fac);
|
||||
// }
|
||||
|
||||
// refract[0] = index*view[0] + fac*n[0];
|
||||
// refract[1] = index*view[1] + fac*n[1];
|
||||
// refract[2] = index*view[2] + fac*n[2];
|
||||
|
||||
// normalize_v3(refract);
|
||||
// return 1;
|
||||
//---
|
||||
// const double cosI = dot_v3v3(n, view);
|
||||
// const double sinT2 = index * index * (1.0 - cosI * cosI);
|
||||
// if (sinT2 >= 1.0f)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// refract[0] = index*view[0] - (index + sqrt(1.0-sinT2))*n[0];
|
||||
// refract[1] = index*view[1] - (index + sqrt(1.0-sinT2))*n[1];
|
||||
// refract[2] = index*view[2] - (index + sqrt(1.0-sinT2))*n[2];
|
||||
// normalize_v3(refract);
|
||||
// return 1;
|
||||
//---
|
||||
|
||||
// double ni = -dot_v3v3(view, n);
|
||||
// double test = 1.0f - index*index*(1.0f-ni*ni);
|
||||
// if (test < 0) {
|
||||
// return 0;
|
||||
// }
|
||||
// else {
|
||||
// double mul = index*ni + sqrt(test);
|
||||
// refract[0] = index * view[0] - mul*n[0];
|
||||
// refract[1] = index * view[1] - mul*n[1];
|
||||
// refract[2] = index * view[2] - mul*n[2];
|
||||
// normalize_v3(refract);
|
||||
// return 1;
|
||||
// }
|
||||
}
|
||||
|
||||
/* orn = original face normal */
|
||||
static void reflection(float *ref, float *n, float *view)
|
||||
{
|
||||
float f1;
|
||||
|
||||
f1= -2.0f*dot_v3v3(n, view);
|
||||
|
||||
ref[0] = (view[0]+f1*n[0]);
|
||||
ref[1] = (view[1]+f1*n[1]);
|
||||
ref[2] = (view[2]+f1*n[2]);
|
||||
normalize_v3(ref);
|
||||
}
|
||||
|
||||
static float fresnelAR(float theta0, float lambda, float d1, float n0, float n1, float n2) {
|
||||
// refractionangles in coating and the 2nd medium
|
||||
float theta1 = asin(sin(theta0)*n0/n1);
|
||||
float theta2 = asin(sin(theta0)*n0/n2);
|
||||
|
||||
float rs01 = -sin(theta0-theta1)/sin(theta0+theta1);
|
||||
float rp01 = tan( theta0-theta1)/tan(theta0+theta1);
|
||||
float ts01 = 2 * sin( theta1 ) * cos( theta0 ) / sin( theta0+theta1 ) ;
|
||||
float tp01 = ts01*cos(theta0-theta1);
|
||||
// amplitude for inner reflection
|
||||
float rs12 = -sin( theta1-theta2 ) / sin( theta1+theta2 ) ;
|
||||
float rp12 = +tan( theta1-theta2 ) / tan( theta1+theta2 ) ;
|
||||
// after passing through first surface twice :
|
||||
// 2 transmissions and 1 reflection
|
||||
float ris = ts01 * ts01 * rs12 ;
|
||||
float rip = tp01 * tp01 * rp12 ;
|
||||
// phase difference between outer and inner reflections
|
||||
float dy = d1 * n1 ;
|
||||
float dx = tan( theta1 ) * dy ;
|
||||
float delay = sqrt( dx * dx+dy * dy ) ;
|
||||
float relPhase = 4 * M_PI / lambda * ( delay-dx * sin( theta0 ) ) ;
|
||||
// Add up sines of different phase and amplitude
|
||||
float out_s2 = rs01 * rs01 + ris * ris + 2 * rs01 * ris * cos( relPhase ) ;
|
||||
float out_p2 = rp01 * rp01 + rip * rip + 2 * rp01 * rip * cos( relPhase ) ;
|
||||
return (out_s2 + out_p2) / 2 ;
|
||||
}
|
||||
|
||||
void detectHit(Ray *result, Ray *inputRay, Bounce *bounce) {
|
||||
int phase = 0;
|
||||
int delta = 1;
|
||||
int t = 1;
|
||||
int k;
|
||||
result->copyFrom(inputRay);
|
||||
result->valid = false;
|
||||
LensInterface *next = bounce->interface1;
|
||||
LensInterface *f = NULL;
|
||||
Intersection intersection;
|
||||
for (k = 0 ; k < bounce->length-1;k++, t+=delta) {
|
||||
f = this->interfaces[t];
|
||||
bool breflect = next == f;
|
||||
if (breflect) {
|
||||
delta = -delta;
|
||||
if (phase == 0) {
|
||||
next = bounce->interface2;
|
||||
}
|
||||
else {
|
||||
next = NULL;
|
||||
}
|
||||
phase ++;
|
||||
}
|
||||
|
||||
f->intersect(&intersection, result);
|
||||
if (!intersection.hit) {
|
||||
break;
|
||||
}
|
||||
if (f->isFlat()) {
|
||||
if (t == this->bokehIndex) {
|
||||
result->uv[0] = intersection.position[0]/f->nominalRadius;
|
||||
result->uv[1] = intersection.position[1]/f->nominalRadius;
|
||||
}
|
||||
}
|
||||
|
||||
float p[3] = {
|
||||
intersection.position[0]-result->position[0],
|
||||
intersection.position[1]-result->position[1],
|
||||
intersection.position[2]-result->position[2]
|
||||
};
|
||||
|
||||
float nfac = sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
|
||||
|
||||
if (intersection.inverted) {
|
||||
nfac *= -1;
|
||||
}
|
||||
|
||||
result->direction[0] = p[0]/nfac;
|
||||
result->direction[1] = p[1]/nfac;
|
||||
result->direction[2] = p[2]/nfac;
|
||||
result->position[0] = intersection.position[0];
|
||||
result->position[1] = intersection.position[1];
|
||||
result->position[2] = intersection.position[2];
|
||||
|
||||
if (!f->isFlat()) {
|
||||
// do refraction and reflection
|
||||
double n0 = result->direction[2]<0?f->refraction1:f->refraction3;
|
||||
double n1 = f->refraction2;
|
||||
double n2 = result->direction[2]<0?f->refraction3:f->refraction1;
|
||||
if (!breflect) {
|
||||
float view[3] ={
|
||||
result->direction[0],
|
||||
result->direction[1],
|
||||
result->direction[2]
|
||||
};
|
||||
int ref = this->refraction(result->direction, intersection.normal, view, n0/n1);
|
||||
if (ref == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this->reflection(result->direction, intersection.normal, result->direction);
|
||||
float fresnelMultiplyer = fresnelAR(intersection.theta, result->wavelength, f->thicknessCoathing, n0, n1, n2);
|
||||
if (isnan(fresnelMultiplyer)) {
|
||||
fresnelMultiplyer = 0.0f;
|
||||
}
|
||||
result->intensity *= fresnelMultiplyer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (k < bounce->length-1) {
|
||||
result->intensity = 0;
|
||||
}
|
||||
else {
|
||||
result->valid = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct LensFace {
|
||||
RayResult *v1;
|
||||
RayResult *v2;
|
||||
RayResult *v3;
|
||||
} LensFace;
|
||||
|
||||
LensGhostProjectionOperation::LensGhostProjectionOperation(): NodeOperation()
|
||||
{
|
||||
this->addInputSocket(COM_DT_COLOR);
|
||||
this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
this->lampObject = NULL;
|
||||
this->cameraObject = NULL;
|
||||
this->system = NULL;
|
||||
this->quality = COM_QUALITY_HIGH;
|
||||
this->setComplex(false);
|
||||
}
|
||||
|
||||
LensGhostOperation::LensGhostOperation(): LensGhostProjectionOperation()
|
||||
{
|
||||
this->setComplex(true);
|
||||
|
||||
}
|
||||
|
||||
void LensGhostProjectionOperation::initExecution()
|
||||
{
|
||||
if (this->cameraObject != NULL && this->lampObject != NULL) {
|
||||
if (lampObject == NULL || cameraObject == NULL) {
|
||||
visualLampPosition[0] = 0;
|
||||
visualLampPosition[1] = 0;
|
||||
visualLampPosition[2] = 0;
|
||||
}
|
||||
else {
|
||||
/* too simple, better to return the distance on the view axis only
|
||||
* return len_v3v3(ob->obmat[3], cam->dof_ob->obmat[3]); */
|
||||
float matt[4][4], imat[4][4], obmat[4][4];
|
||||
|
||||
copy_m4_m4(obmat, cameraObject->obmat);
|
||||
normalize_m4(obmat);
|
||||
invert_m4_m4(imat, obmat);
|
||||
mult_m4_m4m4(matt, imat, lampObject->obmat);
|
||||
|
||||
visualLampPosition[0] = (float)(matt[3][0]);
|
||||
visualLampPosition[1] = (float)(matt[3][1]);
|
||||
visualLampPosition[2] = (float)fabs(matt[3][2]);
|
||||
}
|
||||
}
|
||||
this->lamp = (Lamp*)lampObject->data;
|
||||
|
||||
this->step = this->quality==COM_QUALITY_LOW?64:this->quality==COM_QUALITY_MEDIUM?128:256;
|
||||
this->bokehReader = this->getInputSocketReader(1);
|
||||
|
||||
#define MM *0.001f
|
||||
#define CM *0.01f
|
||||
#define NM *0.000000001
|
||||
#define RED 650 NM
|
||||
#define GREEN 510 NM
|
||||
#define BLUE 475 NM
|
||||
#define AIR 1.000293f
|
||||
#define GLASS 1.5200f
|
||||
#define TEST 0.000002f
|
||||
// determine interfaces
|
||||
LensSystem *system = new LensSystem();
|
||||
system->addInterface(new FlatInterface(0.0f,0.0f, 6.5 CM, 30 MM)); //ENTRANCE
|
||||
system->addInterface(new SphereInterface(0.0f,0.0f, -3 CM, 8 CM, 3 CM, AIR, GLASS , 0.f));
|
||||
system->addInterface(new SphereInterface(0.0f,0.0f, -4 CM, 8 CM, 3 CM, GLASS, AIR, GREEN));
|
||||
system->addInterface(new FlatInterface(0.0f,0.0f, 3.0 CM, 15 MM)); // BOKEH
|
||||
system->addInterface(new SphereInterface(0.0f,0.0f, 6 CM, 3 CM, 2 CM, AIR, GLASS, 0.0f));
|
||||
system->addInterface(new SphereInterface(0.0f,0.0f, 5.5 CM, 3 CM, 2 CM, GLASS, AIR, 0.f));
|
||||
system->addInterface(new FlatInterface(0.0f,0.0f,0 CM, 30 MM)); // SENSOR
|
||||
system->bokehIndex = 3;
|
||||
|
||||
// determine interfaces
|
||||
// LensSystem *system = new LensSystem();
|
||||
// system->addInterface(new FlatInterface(0.0f,0.0f, 6.5 CM, 30 MM)); //ENTRANCE
|
||||
// system->addInterface(new SphereInterface(0.0f,0.0f, 14 CM, 8 CM, 6 CM, AIR, GLASS , 0.0f));
|
||||
// system->addInterface(new SphereInterface(0.0f,0.0f, 12 CM, 8 CM, 6 CM, GLASS, AIR, GREEN));
|
||||
// system->addInterface(new FlatInterface(0.0f,0.0f, 3.0 CM, 30 MM)); // BOKEH
|
||||
// system->addInterface(new SphereInterface(0.0f,0.0f, 1 CM, 3 CM, 2 CM, AIR, GLASS, GREEN));
|
||||
// system->addInterface(new SphereInterface(0.0f,0.0f, -2 CM, 3 CM, 2 CM, GLASS, AIR, RED));
|
||||
// system->addInterface(new FlatInterface(0.0f,0.0f,0 CM, 20 MM)); // SENSOR
|
||||
// system->bokehIndex = 3;
|
||||
#undef CM
|
||||
#undef MM
|
||||
// determine bounces
|
||||
system->updateBounces(step);
|
||||
this->system = system;
|
||||
}
|
||||
|
||||
void LensGhostOperation::initExecution()
|
||||
{
|
||||
LensGhostProjectionOperation::initExecution();
|
||||
LensSystem *system = (LensSystem*)this->system;
|
||||
LensInterface *interface1 = system->interfaces[0];
|
||||
|
||||
// for every herz
|
||||
float HERZ[3]={650 NM,510 NM,475 NM}; /// @todo use 7 for high quality?
|
||||
for (int iw = 0 ; iw < 3 ; iw ++) {
|
||||
float wavelength = HERZ[iw];
|
||||
// for every bounce
|
||||
for (int ib = 0 ; ib < system->bounces.size() ; ib++) {
|
||||
Bounce *bounce = system->bounces[ib];
|
||||
// based on quality setting the number of iteration will be different (128^2, 64^2, 32^2)
|
||||
for (int xi = 0 ; xi < step ; xi ++) {
|
||||
float x = -interface1->radius+xi*(interface1->radius*2/step);
|
||||
for (int yi = 0 ; yi < step ; yi ++) {
|
||||
float y = -interface1->radius+yi*(interface1->radius*2/step);
|
||||
Ray r;
|
||||
Ray result;
|
||||
r.wavelength = wavelength;
|
||||
r.intensity = this->lamp->energy;
|
||||
r.uv[0] = 0.0f;
|
||||
r.uv[1] = 0.0f;
|
||||
r.position[0] = visualLampPosition[0];
|
||||
r.position[1] = visualLampPosition[1];
|
||||
r.position[2] = visualLampPosition[2];
|
||||
r.direction[0] = interface1->position[0]+x - r.position[0];
|
||||
r.direction[1] = interface1->position[1]+y - r.position[1];
|
||||
r.direction[2] = interface1->position[2] - r.position[2];
|
||||
normalize_v3(r.direction);
|
||||
system->detectHit(&result, &r, bounce);
|
||||
RayResult *res = bounce->getRayResult(xi, yi);
|
||||
if (iw == 0) {
|
||||
res->x = result.position[0];
|
||||
res->y = result.position[1];
|
||||
res->u = result.uv[0];
|
||||
res->v = result.uv[1];
|
||||
}
|
||||
res->intensity[iw] = result.intensity;
|
||||
if (result.valid) {
|
||||
res->valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef NM
|
||||
const int width = this->getWidth();
|
||||
const int height = this->getHeight();
|
||||
const float width2 = width/2.0f;
|
||||
const float height2 = height/2.0f;
|
||||
float *data = new float[width*height*4];
|
||||
for (int i = 0 ; i < width*height ; i ++) {
|
||||
data[i*4+0] = 0.0f;
|
||||
data[i*4+1] = 0.0f;
|
||||
data[i*4+2] = 0.0f;
|
||||
data[i*4+3] = 1.0f;
|
||||
}
|
||||
/// @todo every bounce creates own image. these images are added together at the end
|
||||
// LensSystem *system = (LensSystem*)this->system;
|
||||
LensInterface * lens = system->interfaces[system->lensIndex];
|
||||
for (int i = 0 ; i < system->bounces.size() ; i ++) {
|
||||
Bounce *bounce = system->bounces[i];
|
||||
for (int r = 0 ; r < bounce->rasterLength*bounce->rasterLength ; r ++) {
|
||||
RayResult *result = &bounce->raster[r];
|
||||
// if (result->valid) {
|
||||
float ru = result->x/lens->nominalRadius*width2+width2;
|
||||
float rv = result->y/lens->nominalRadius*height2+height2;
|
||||
result->screenX = ru;
|
||||
result->screenY = rv;
|
||||
result->hasIntensity = result->intensity[0]>0.0f &&result->intensity[1]>0.0f&& result->intensity[2]>0.0f;
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *LensGhostOperation::initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers)
|
||||
{
|
||||
vector<LensFace*>* result = new vector<LensFace*>();
|
||||
LensSystem *system = (LensSystem*)this->system;
|
||||
const float minx = rect->xmin;
|
||||
const float miny = rect->ymin;
|
||||
const float maxx = rect->xmax;
|
||||
const float maxy = rect->ymax;
|
||||
for (int i = 0 ; i < system->bounces.size() ; i ++) {
|
||||
Bounce *bounce = system->bounces[i];
|
||||
int faceX, faceY;
|
||||
for (faceX = 0 ; faceX < bounce->rasterLength-1 ; faceX++) {
|
||||
for (faceY = 0 ; faceY < bounce->rasterLength-1 ; faceY++) {
|
||||
RayResult *vertex1 = bounce->getRayResult(faceX, faceY);
|
||||
RayResult *vertex2 = bounce->getRayResult(faceX+1, faceY);
|
||||
RayResult *vertex3 = bounce->getRayResult(faceX+1, faceY+1);
|
||||
RayResult *vertex4 = bounce->getRayResult(faceX, faceY+1);
|
||||
// early hit test
|
||||
if (!((vertex1->screenX < minx && vertex2->screenX < minx && vertex3->screenX < minx && vertex4->screenX < minx) ||
|
||||
(vertex1->screenX > maxx && vertex2->screenX > maxx && vertex3->screenX > maxx && vertex4->screenX > maxx) ||
|
||||
(vertex1->screenY < miny && vertex2->screenY < miny && vertex3->screenY < miny && vertex4->screenY < miny) ||
|
||||
(vertex1->screenY > maxy && vertex2->screenY > maxy && vertex3->screenY > maxy && vertex4->screenY > maxy))) {
|
||||
int number = vertex1->hasIntensity + vertex2->hasIntensity + vertex3->hasIntensity + vertex4->hasIntensity;
|
||||
if (number == 4) {
|
||||
LensFace *face = new LensFace();
|
||||
face->v1 = vertex1;
|
||||
face->v2 = vertex2;
|
||||
face->v3 = vertex3;
|
||||
result->push_back(face);
|
||||
face = new LensFace();
|
||||
face->v1 = vertex3;
|
||||
face->v2 = vertex4;
|
||||
face->v3 = vertex1;
|
||||
result->push_back(face);
|
||||
}
|
||||
else if (number == 3) {
|
||||
LensFace *face = new LensFace();
|
||||
if (!vertex1->hasIntensity) {
|
||||
face->v1 = vertex2;
|
||||
face->v2 = vertex3;
|
||||
face->v3 = vertex4;
|
||||
}
|
||||
else if (!vertex2->hasIntensity) {
|
||||
face->v1 = vertex1;
|
||||
face->v2 = vertex3;
|
||||
face->v3 = vertex4;
|
||||
}
|
||||
else if (!vertex3->hasIntensity) {
|
||||
face->v1 = vertex1;
|
||||
face->v2 = vertex2;
|
||||
face->v3 = vertex4;
|
||||
}
|
||||
else {
|
||||
face->v1 = vertex1;
|
||||
face->v2 = vertex2;
|
||||
face->v3 = vertex3;
|
||||
}
|
||||
result->push_back(face);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void LensGhostOperation::deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data)
|
||||
{
|
||||
if (data) {
|
||||
vector<LensFace*>* faces = (vector<LensFace*>*)data;
|
||||
while (faces->size() != 0) {
|
||||
LensFace *face = faces->back();
|
||||
faces->pop_back();
|
||||
delete face;
|
||||
}
|
||||
delete faces;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LensGhostProjectionOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[])
|
||||
{
|
||||
float bokeh[4];
|
||||
LensSystem *system = (LensSystem*)this->system;
|
||||
LensInterface *interface1 = system->interfaces[0];
|
||||
color[0] = 0.0f;
|
||||
color[1] = 0.0f;
|
||||
color[2] = 0.0f;
|
||||
color[3] = 0.0f;
|
||||
const float width = this->getWidth();
|
||||
const float height = this->getHeight();
|
||||
const float size = min(height, width);
|
||||
const float width2 = width/2;
|
||||
const float height2 = height/2;
|
||||
const float size2 = size/2;
|
||||
|
||||
#define NM *0.000000001
|
||||
float HERZ[3]={650 NM,510 NM,475 NM}; /// @todo use 7 for high quality?
|
||||
float rx = ((x-width2)/size2) * interface1->radius;
|
||||
float ry = ((y-height2)/size2) * interface1->radius;
|
||||
|
||||
for (int iw = 0 ; iw < 3 ; iw ++) {
|
||||
float intensity = 0.0f;
|
||||
float wavelength = HERZ[iw];
|
||||
float colorcomponent = 0.0f;
|
||||
if (iw ==0 ) colorcomponent = lamp->r;
|
||||
if (iw ==1 ) colorcomponent = lamp->g;
|
||||
if (iw ==2 ) colorcomponent = lamp->b;
|
||||
|
||||
|
||||
// for every bounce
|
||||
for (int ib = 0 ; ib < system->bounces.size() ; ib++) {
|
||||
Bounce *bounce = system->bounces[ib];
|
||||
// based on quality setting the number of iteration will be different (128^2, 64^2, 32^2)
|
||||
|
||||
Ray r;
|
||||
Ray result;
|
||||
r.wavelength = wavelength;
|
||||
r.intensity = this->lamp->energy;
|
||||
r.uv[0] = 0.0f;
|
||||
r.uv[1] = 0.0f;
|
||||
r.position[0] = visualLampPosition[0];
|
||||
r.position[1] = visualLampPosition[1];
|
||||
r.position[2] = visualLampPosition[2];
|
||||
r.direction[0] = interface1->position[0]+rx - r.position[0];
|
||||
r.direction[1] = interface1->position[1]+ry - r.position[1];
|
||||
r.direction[2] = interface1->position[2] - r.position[2];
|
||||
normalize_v3(r.direction);
|
||||
system->detectHit(&result, &r, bounce);
|
||||
if (result.valid) {
|
||||
float u = ((result.uv[0]+1.0f)/2)*bokehReader->getWidth();
|
||||
float v = ((result.uv[1]+1.0f)/2)*bokehReader->getHeight();
|
||||
|
||||
bokehReader->read(bokeh, u, v, sampler, inputBuffers);
|
||||
|
||||
intensity += result.intensity *bokeh[iw];
|
||||
}
|
||||
}
|
||||
intensity = maxf(0.0f, intensity);
|
||||
color[iw] = intensity*colorcomponent;
|
||||
}
|
||||
color[3] = 1.0f;
|
||||
#undef NM
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LensGhostOperation::executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void *data)
|
||||
{
|
||||
vector<LensFace*>* faces = (vector<LensFace*>*)data;
|
||||
#if 0 /* UNUSED */
|
||||
const float bokehWidth = bokehReader->getWidth();
|
||||
const float bokehHeight = bokehReader->getHeight();
|
||||
float bokeh[4];
|
||||
#endif
|
||||
color[0] = 0.0f;
|
||||
color[1] = 0.0f;
|
||||
color[2] = 0.0f;
|
||||
color[3] = 1.0f;
|
||||
|
||||
unsigned int index;
|
||||
for (index = 0 ; index < faces->size() ; index ++) {
|
||||
LensFace * face = faces->operator [](index);
|
||||
RayResult *vertex1 = face->v1;
|
||||
RayResult *vertex2 = face->v2;
|
||||
RayResult *vertex3 = face->v3;
|
||||
if (!((vertex1->screenX < x && vertex2->screenX < x && vertex3->screenX < x) ||
|
||||
(vertex1->screenX > x && vertex2->screenX > x && vertex3->screenX > x) ||
|
||||
(vertex1->screenY < y && vertex2->screenY < y && vertex3->screenY < y) ||
|
||||
(vertex1->screenY > y && vertex2->screenY > y && vertex3->screenY > y))) {
|
||||
|
||||
const float v1[2] = {vertex1->screenX, vertex1->screenY};
|
||||
const float v2[2] = {vertex2->screenX, vertex2->screenY};
|
||||
const float v3[2] = {vertex3->screenX, vertex3->screenY};
|
||||
const float co[2] = {x, y};
|
||||
float weights[3];
|
||||
|
||||
barycentric_weights_v2(v1, v2, v3, co, weights);
|
||||
if (weights[0]>=0.0f && weights[0]<=1.0f &&
|
||||
weights[1]>=0.0f && weights[1]<=1.0f &&
|
||||
weights[2]>=0.0f && weights[2]<=1.0f) {
|
||||
// const float u = (vertex1->u*weights[0]+vertex2->u*weights[1]+vertex3->u*weights[2]);
|
||||
// const float v = (vertex1->v*weights[0]+vertex2->v*weights[1]+vertex3->v*weights[2]);
|
||||
// const float tu = ((u+1.0f)/2.0f)*bokehWidth;
|
||||
// const float tv = ((v+1.0f)/2.0f)*bokehHeight;
|
||||
// bokehReader->read(bokeh, tu, tv, inputBuffers);
|
||||
|
||||
// color[0] = max(color[0], bokeh[0]*(vertex1->intensity[0]*weights[0]+vertex2->intensity[0]*weights[1]+vertex3->intensity[0]*weights[2]));
|
||||
// color[1] = max(color[1], bokeh[1]*(vertex1->intensity[1]*weights[0]+vertex2->intensity[1]*weights[1]+vertex3->intensity[1]*weights[2]));
|
||||
// color[2] = max(color[2], bokeh[2]*(vertex1->intensity[2]*weights[0]+vertex2->intensity[2]*weights[1]+vertex3->intensity[2]*weights[2]));
|
||||
color[0] = max(color[0], (vertex1->intensity[0]*weights[0]+vertex2->intensity[0]*weights[1]+vertex3->intensity[0]*weights[2]));
|
||||
color[1] = max(color[1], (vertex1->intensity[1]*weights[0]+vertex2->intensity[1]*weights[1]+vertex3->intensity[1]*weights[2]));
|
||||
color[2] = max(color[2], (vertex1->intensity[2]*weights[0]+vertex2->intensity[2]*weights[1]+vertex3->intensity[2]*weights[2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LensGhostProjectionOperation::deinitExecution()
|
||||
{
|
||||
if (this->system) delete (LensSystem*)this->system;
|
||||
this->system = NULL;
|
||||
this->bokehReader = NULL;
|
||||
}
|
||||
|
||||
bool LensGhostProjectionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output)
|
||||
{
|
||||
rcti bokehInput;
|
||||
|
||||
NodeOperation *operation = this->getInputOperation(1);
|
||||
bokehInput.xmax = operation->getWidth();
|
||||
bokehInput.xmin = 0;
|
||||
bokehInput.ymax = operation->getHeight();
|
||||
bokehInput.ymin = 0;
|
||||
if (operation->determineDependingAreaOfInterest(&bokehInput, readOperation, output) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return NodeOperation::determineDependingAreaOfInterest(input, readOperation, output);
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _COM_LensGhostOperation_h
|
||||
#define _COM_LensGhostOperation_h
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
|
||||
class LensGhostProjectionOperation : public NodeOperation {
|
||||
protected:
|
||||
Object *lampObject;
|
||||
Lamp *lamp;
|
||||
Object *cameraObject;
|
||||
|
||||
void *system;
|
||||
float visualLampPosition[3];
|
||||
CompositorQuality quality;
|
||||
int step;
|
||||
SocketReader * bokehReader;
|
||||
|
||||
public:
|
||||
LensGhostProjectionOperation();
|
||||
|
||||
/**
|
||||
* the inner loop of this program
|
||||
*/
|
||||
void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]);
|
||||
|
||||
/**
|
||||
* Initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
|
||||
/**
|
||||
* Deinitialize the execution
|
||||
*/
|
||||
void deinitExecution();
|
||||
bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output);
|
||||
|
||||
void setLampObject(Object *lampObject) {this->lampObject = lampObject;}
|
||||
void setCameraObject(Object *cameraObject) {this->cameraObject = cameraObject;}
|
||||
|
||||
void setQuality(CompositorQuality quality) {this->quality = quality;}
|
||||
};
|
||||
|
||||
class LensGhostOperation : public LensGhostProjectionOperation {
|
||||
public:
|
||||
LensGhostOperation();
|
||||
|
||||
void *initializeTileData(rcti *rect, MemoryBuffer **memoryBuffers);
|
||||
void deinitializeTileData(rcti *rect, MemoryBuffer **memoryBuffers, void *data);
|
||||
/**
|
||||
* the inner loop of this program
|
||||
*/
|
||||
void executePixel(float *color, int x, int y, MemoryBuffer *inputBuffers[], void * data);
|
||||
/**
|
||||
* Initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
};
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "COM_LensGlowImageOperation.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
LensGlowImageOperation::LensGlowImageOperation(): NodeOperation()
|
||||
{
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
}
|
||||
void LensGlowImageOperation::initExecution()
|
||||
{
|
||||
this->scale = 1/20000.0f;
|
||||
}
|
||||
void LensGlowImageOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[])
|
||||
{
|
||||
const float cs_r = 1.f, cs_g = 1.f, cs_b = 1.f;
|
||||
const float v = 2.f*(y / (float)512.0f) - 1.f;
|
||||
const float u = 2.f*(x / (float)512.0f) - 1.f;
|
||||
const float r = (u*u + v*v)*scale;
|
||||
const float d = -sqrtf(sqrtf(sqrtf(r)))*9.f;
|
||||
const float w = (0.5f + 0.5f*cos((double)u*M_PI))*(0.5f + 0.5f*cos((double)v*M_PI));
|
||||
color[0] = expf(d*cs_r) * w;
|
||||
color[1] = expf(d*cs_g) * w;
|
||||
color[2] = expf(d*cs_b) * w;
|
||||
color[3] = 1.0f;
|
||||
}
|
||||
|
||||
void LensGlowImageOperation::deinitExecution()
|
||||
{
|
||||
}
|
||||
|
||||
void LensGlowImageOperation::determineResolution(unsigned int resolution[], unsigned int preferredResolution[])
|
||||
{
|
||||
resolution[0] = 512;
|
||||
resolution[1] = 512;
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "COM_LensGlowOperation.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
LensGlowOperation::LensGlowOperation(): NodeOperation()
|
||||
{
|
||||
this->addInputSocket(COM_DT_COLOR);
|
||||
this->addOutputSocket(COM_DT_COLOR);
|
||||
this->inputProgram = NULL;
|
||||
this->lamp = NULL;
|
||||
}
|
||||
void LensGlowOperation::initExecution()
|
||||
{
|
||||
this->inputProgram = this->getInputSocketReader(0);
|
||||
}
|
||||
|
||||
void LensGlowOperation::executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[])
|
||||
{
|
||||
// const float emit100 = this->lamp->energy*100;
|
||||
// const float emit200 = emit100*2;
|
||||
// const float deltaX = 160-x;
|
||||
// const float deltaY = 100-y;
|
||||
// const float distance = deltaX * deltaX + deltaY*deltaY;
|
||||
|
||||
// float glow = (emit100-(distance))/(emit200);
|
||||
// if (glow<0) glow=0;
|
||||
|
||||
// color[0] = glow*lamp->r;
|
||||
// color[1] = glow*lamp->g;
|
||||
// color[2] = glow*lamp->b;
|
||||
// color[3] = 1.0f;
|
||||
}
|
||||
|
||||
void LensGlowOperation::deinitExecution()
|
||||
{
|
||||
this->inputProgram = NULL;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef _COM_LensGlowOperation_h
|
||||
#define _COM_LensGlowOperation_h
|
||||
#include "COM_NodeOperation.h"
|
||||
#include "DNA_lamp_types.h"
|
||||
|
||||
class LensGlowOperation : public NodeOperation {
|
||||
private:
|
||||
/**
|
||||
* Cached reference to the inputProgram
|
||||
*/
|
||||
SocketReader * inputProgram;
|
||||
Lamp *lamp;
|
||||
|
||||
public:
|
||||
LensGlowOperation();
|
||||
|
||||
/**
|
||||
* the inner loop of this program
|
||||
*/
|
||||
void executePixel(float *color, float x, float y, PixelSampler sampler, MemoryBuffer *inputBuffers[]);
|
||||
|
||||
/**
|
||||
* Initialize the execution
|
||||
*/
|
||||
void initExecution();
|
||||
|
||||
/**
|
||||
* Deinitialize the execution
|
||||
*/
|
||||
void deinitExecution();
|
||||
|
||||
void setLamp(Lamp *lamp) {this->lamp = lamp;}
|
||||
};
|
||||
#endif
|
||||
Reference in New Issue
Block a user