#include "WorleyShader.hpp"
#include
#include "Globals.hpp"
using namespace SH;
using namespace ShUtil;
#define WORLEY_FREQ 8
WorleyShader::WorleyShader(bool useTexture, int whichW, ShWorleyMetric metric):
worleyizer( WORLEY_FREQ, useTexture ), useTexture( useTexture ), metric( metric ), whichW(whichW)
{
}
WorleyShader::~WorleyShader()
{
}
char* WorleyShader::name(void) {
char name[100];
if( useTexture ) {
sprintf (name, "Worley (Texture hash) %d", whichW);
} else {
sprintf (name, "Worley (Procedural hash) %d", whichW);
}
return strdup(name);
}
ShAttrib4f WorleyShader::getWorley (int i, ShTexCoord2f t)
{
ShAttrib4f w, z;
ShAttrib4f wC;
ShAttrib1f p;
p = Globals::param * ShAttrib1f(0.1);
switch (i)
{
case 1:
wC = ShAttrib4f(1,0,0,0);
w(2) = worleyizer.worleyNoGradient(t, wC, L2_SQ);
w(2) = (ShAttrib1f(1)-w(2) - p)*ShAttrib1f(30);
w(2) = clamp(0, 1, w(2));
w(0,1) = w(2,2);
break;
case 2:
wC = ShAttrib4f (-1,1.2,0,0);
w(0,1,2) = worleyizer.worleyNoGradient(t, wC, L1)(0,0,0);
wC = ShAttrib4f (0,1,1,0);
z(0,1,2) = worleyizer.worleyNoGradient(t*ShAttrib1f(2), wC, L2_SQ)(0,0,0);
w = w-z;
break;
case 3:
wC = ShAttrib4f (-1,1,0,0);
w(2) = worleyizer.worleyNoGradient(t, wC, L1);
w(2) = (ShAttrib1f(1)-w(2) - p)*ShAttrib1f(30);
//w(2) = clamp(0, 1, w(2));
wC = ShAttrib4f (0,-1,1,0);
w(1) = worleyizer.worleyNoGradient(t, wC, L1);
w(1) = (ShAttrib1f(1)-w(1) - p)*ShAttrib1f(10);
//w(1) = clamp(0, 1, w(1));
w(2) = clamp(0, 1, w(1)+w(2));
w(0,1) = w(2,2);
break;
case 4:
wC = ShAttrib4f (0,0,0,1);
w(2) = worleyizer.worleyNoGradient(t, wC, L1) * ShAttrib1f(0.5);
w(2) = (ShAttrib1f(1)-w(2) - p)*ShAttrib1f(30);
w(2) = clamp(0, 1, w(2));
w(0) = worleyizer.worleyNoGradient(t*ShAttrib1f(2), wC, L1) * ShAttrib1f(0.5);
w(0) = (ShAttrib1f(1)-w(0) - p)*ShAttrib1f(30);
w(0) = clamp(0, 1, w(0));
w(1) = ShAttrib1f(1) - w(0);
break;
case 0:
default:
wC = ShAttrib4f(1,0,0,0);
w(0,1,2) = worleyizer.worley(t*ShAttrib1f(2), wC, L2_SQ);
break;
}
w(3) = ShAttrib1f(1) - w(2);
return w;
}
void WorleyShader::init()
{
ShVector3f lightDir = normalize(Globals::lightPos - ShVector3f(0,0,0));
vsh = SH_BEGIN_VERTEX_PROGRAM {
ShInputNormal3f normal;
ShInputTexCoord2f texture;
ShInputPosition4f p;
ShOutputVector3f ohv;
ShOutputNormal3f on;
ShOutputTexCoord2f ot;
ShOutputAttrib1f ec; //irradiance
ShOutputPosition4f opd;
//Used for lighting
ShNormal3f nvt = normalize(Globals::mv | normal);
ShPoint3f pvt = (Globals::mv | p)(0,1,2);
ShVector3f vvv = -normalize(pvt);
ShVector3f lvv = normalize(Globals::lightPos - pvt);
ShAttrib1f ect = (nvt | lvv);
opd = Globals::mvp | p;
on = nvt;
ohv = normalize(lvv + vvv);
ot = texture;
ec = ect * (ect>0.0);
} SH_END_PROGRAM;
fsh = SH_BEGIN_FRAGMENT_PROGRAM {
ShInputVector3f hv;
ShInputNormal3f n;
ShInputTexCoord2f t;
ShInputAttrib1f ec;
ShInputPosition4f p;
ShOutputColor3f out;
ShAttrib4f w = getWorley (whichW, t);
ShAttrib1f spec;
spec = dot(normalize(hv), normalize(n)) ^ Globals::exponent;
ShColor3f col1;
ShColor3f col2;
switch (whichW)
{
case 0:
col1 = ShColor3f(0.7,0.2,0.3)*w(3) + ShColor3f(0.4,0,0)*w(2);
//col1 = w(2,3,2);
spec*= w(3);
break;
case 1:
col1 = ShColor3f(0.27,0.35,0.45)*w(3) + ShColor3f(1,0.7,0)*w(2);
break;
case 2:
col1 = ShColor3f(0.5,0,0)*w(3) + ShColor3f(0,0,1)*w(2);
break;
case 3:
col1 = ShColor3f(0.45,0.3,0)*w(3) + ShColor3f(1,0.95,0.8)*w(2);
spec*= 0.2;
break;
case 4:
//col1 = ShColor3f(0,0.45,0)*w(0) + ShColor3f(0,0.3,0.8)*w(2);
col1 = ShColor3f(0,0.2,0.8)*w(0) + ShColor3f(0.6,0.6,0.7)*w(2);
spec*= col1(1);
break;
case 5:
col2(0) = (w(0)>ShAttrib1f(0));
col1 = (ShColor3f(0,0.6,0)*w(3) + ShColor3f(0.5,0.5,0.5)*w(2))*(ShAttrib1f(1)-col2(0)) + col2(0)*(ShColor3f(0.2,0.2,0.9)*w(0));
break;
}
col1 = (col1 + ShColor3f(1,1,1)*spec) * ec;
col2 = w(1,0,1);
out = Globals::toggle*col2 + (1.0-Globals::toggle)*col1;
} SH_END_PROGRAM;
}
void WorleyShader::apply()
{
shBindShader(vsh);
shBindShader(fsh);
}
void WorleyShader::vertex(const SH::ShPoint4f& n, // normal
const SH::ShPoint4f& t, // tangent
const SH::ShPoint4f& tex, // texture
// coordinates
const SH::ShPoint4f& t2, // secondary
// tangent
const SH::ShPoint4f& v // vertex
)
{
pushSmAttrib(n);
pushSmAttrib(tex);
pushSmVertex(v);
}
// Instantiate the shader
WorleyShader worleyShader0( false, 0 );
WorleyShader worleyShader1( false, 1 );
WorleyShader worleyShader2( false, 2 );
WorleyShader worleyShader3( false, 3 );
WorleyShader worleyShader0( false, 4 );