#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include
#include
#include
#include
#include
#include
#include
#include
#include "Noise.hpp"
using namespace SH;
using namespace ShUtil;
NoiseShader::NoiseShader() {
}
void NoiseShader::makePhong() {
phong = ShKernelLib::shPhong();
phong = phong << coeffs << (bander & noise) << shDup();
}
SimpleWoodShader::SimpleWoodShader()
: diffuseIn(0.35f, 0.177f, 0.07f), diffuseOut(0.8f, 0.3f, 0.1f),
specularIn(0.3f, 0.3f, 0.3f), specularOut(1.0f, 1.0f, 1.0f) {
bandFreq = ShConstant3f(10.0f, 10.0f, 10.0f);
noiseFreq = ShConstant3f(15.0f, 15.0f, 1.0f);
noiseScale = ShConstant1f(0.3f);
exp = ShConstant1f(40.0f);
name = "Simple Wood";
bander = SH_BEGIN_PROGRAM() {
ShInputPoint3f SH_DECL(pm);
pm *= bandFreq;
ShOutputAttrib1f SH_DECL(inband) = sqrt(pm(0,1) | pm(0,1));
} SH_END;
noise = SH_BEGIN_PROGRAM() {
ShInputPoint3f SH_DECL(pm);
ShOutputAttrib1f SH_DECL(noise) = noiseScale * snoise<1>(pm * noiseFreq);
} SH_END;
coeffs = SH_BEGIN_PROGRAM() {
ShInputAttrib1f SH_DECL(inband);
ShInputAttrib1f SH_DECL(noise);
ShOutputColor3f SH_DECL(kd);
ShOutputColor3f SH_DECL(ks);
ShOutputAttrib1f SH_DECL(specExp);
inband = frac(inband + noise);
kd = lerp(inband, diffuseIn, diffuseOut);
ks = lerp(inband, specularIn, specularOut);
specExp = exp;
} SH_END;
makePhong();
}
ComplexWoodShader::ComplexWoodShader()
: SimpleWoodShader() {
octaveAmps = ShConstant3f(0.5f, 0.25f, 0.125f);
name = "Complex Wood";
noise = SH_BEGIN_PROGRAM() {
ShInputPoint3f SH_DECL(pm);
ShOutputAttrib1f SH_DECL(noise) = noiseScale * (sturbulence<1>(octaveAmps, pm * noiseFreq)
+ snoise<1>(10.0*sqrt(pm(0,1)|pm(0,1))) );
} SH_END;
makePhong();
}
MarbleShader::MarbleShader()
: octaveAmps(0.4f, 0.3f, 0.3f) {
bandFreq = ShConstant3f(5.0f, 5.0f, 5.0f);
noiseFreq = bandFreq * 2.0f;
noiseScale = ShConstant1f(0.8f);
exp = ShConstant1f(40.0f);
name = "Marble";
bander = SH_BEGIN_PROGRAM() {
ShInputPoint3f SH_DECL(pm);
pm *= bandFreq;
ShOutputAttrib1f SH_DECL(inband) = pm(0);
} SH_END;
noise = SH_BEGIN_PROGRAM() {
ShInputPoint3f SH_DECL(pm);
ShOutputAttrib1f SH_DECL(noise) = noiseScale * (sturbulence<1>(octaveAmps, pm * noiseFreq)
+ snoise<1>(10.0*pm(0)));
} SH_END;
coeffs = SH_BEGIN_PROGRAM() {
ShInputAttrib1f SH_DECL(inband);
ShInputAttrib1f SH_DECL(noise);
ShOutputColor3f SH_DECL(kd);
ShOutputColor3f SH_DECL(ks);
ShOutputAttrib1f SH_DECL(specExp);
inband = frac(inband + noise);
ShColor3f bandColor = lerp(smoothstep(ShConstant1f(0.3f), ShConstant1f(0.4f), inband),
ShConstant3f(0.0f, 0.2f, 0.0f), ShConstant3f(0.4f,0.4f,0.75f));
inband = smoothstep(ShConstant1f(0.1f), ShConstant1f(0.3f), inband)
- smoothstep(ShConstant1f(0.5f), ShConstant1f(0.6f), inband); // black band
kd = lerp(inband, bandColor, ShConstant3f(1.0f, 0.95f, 1.0f));
ks = ShConstant3f( 0.5f, 0.5f, 0.5f );
specExp = exp;
} SH_END;
makePhong();
}
Noise::Noise(void) {
obj = 0;
lightColour = ShColor3f(1.0, 1.0, 1.0);
light = ShPoint3f(5.0, 5.0, 5.0);
shader = new SimpleWoodShader();
displayList = -1;
bandTransform = false;
camera.move(0,0,-4);
}
Noise::~Noise(void) {
if(obj) delete obj;
}
void Noise::init(int argc, char *argv[]) {
Demo::init(argc, argv);
// Load the molecule definition from a file.
std::string filename = "";
if (argc >= 2) {
filename = argv[1];
std::ifstream file(filename.c_str());
if (!file) {
std::cerr << "Error loading obj file from " << filename << std::endl;
} else {
obj = new ShObjFile;
file >> (*obj);
}
}
compileNoise();
}
void Noise::keyboard(unsigned char k, int x, int y) {
bool recompile = false;
switch(k) {
case '?':
std::cout << "Usage:" << std::endl;
std::cout << "m Marble shader" << std::endl;
std::cout << "w Oak shader (smoothstepped rings, 3 octave turbulence)" << std::endl;
std::cout << "o Simple oak shader (lerped rings, perlin noise)" << std::endl;
std::cout << "z toggle transforming the bands rather than the model" << std::endl;
std::cout << "B/b inc/dec band frequency" << std::endl;
std::cout << "F/f inc/dec noise frequency" << std::endl;
std::cout << "N/n inc/dec noise scaling" << std::endl;
return;
case 'm': ShEnvironment::boundShaders().clear();
shader = new MarbleShader();
recompile = true;
break;
case 'w': ShEnvironment::boundShaders().clear();
shader = new ComplexWoodShader();
recompile = true;
break;
case 'o': ShEnvironment::boundShaders().clear();
shader = new SimpleWoodShader();
recompile = true;
break;
case 'z': bandTransform = !bandTransform; break;
case 'B': if( shader ) shader->bandFreq *= 1.2f; break;
case 'b': if( shader ) shader->bandFreq *= 1.0f / 1.2f; break;
case 'F': if( shader ) shader->noiseFreq *= 1.2f; break;
case 'f': if( shader ) shader->noiseFreq *= 1.0f / 1.2f; break;
case 'N': if( shader ) shader->noiseScale += 0.2f; break;
case 'n': if( shader ) shader->noiseScale -= 0.2f; break;
case 'q':
exit(0);
default:
return;
}
if(recompile) {
compileNoise();
}
printStatus();
glutPostRedisplay();
}
void Noise::printStatus() {
std::cout << "Current Noise Shader: " << shader->name << std::endl;
std::cout << "Mouse Mode: " << ( bandTransform ? "Move Texture Bands" : "Move Camera") << std::endl;
std::cout << "Band Frequency: (" << shader->bandFreq.node()->getValue(0)
<< ", " << shader->bandFreq.node()->getValue(1)
<< ", " << shader->bandFreq.node()->getValue(2) << ")" << std::endl;
std::cout << "Noise Frequency: (" << shader->noiseFreq.node()->getValue(0)
<< ", " << shader->noiseFreq.node()->getValue(1)
<< ", " << shader->noiseFreq.node()->getValue(2) << ")" << std::endl;
std::cout << "Noise Scaling: " << shader->noiseScale.node()->getValue(0) << std::endl;
std::cout << std::endl;
}
void Noise::motion(int x, int y) {
Camera &modcam = bandTransform ? bandCamera : camera;
if (buttons[GLUT_LEFT_BUTTON] == GLUT_DOWN) {
modcam.orbit(cur_x, cur_y, x, y, m_width, m_height);
}
if (buttons[GLUT_MIDDLE_BUTTON] == GLUT_DOWN) {
modcam.move(0, 0, (y - cur_y)/20.0);
}
if (buttons[GLUT_RIGHT_BUTTON] == GLUT_DOWN) {
modcam.move((x - cur_x)/20.0, (cur_y - y)/20.0, 0);
}
cur_x = x;
cur_y = y;
glutPostRedisplay();
}
void Noise::compileNoise()
{
printf("Compiling Noise");
ShEnvironment::boundShaders().clear();
ShProgram specialVsh = ShKernelLib::shVsh(mv, mvp) >> shRange("normal","lightVec")("posh");
ShProgram vsh = shExtract("pm")
<< (specialVsh & ( transform(bandTrans,"pm") << cast("pm")))
<< (shKeep(3) & shDup());
vsh = vsh << shExtract("lightPos") << light;
//ShProgram fsh;
ShProgram fsh = shader->phong;
shBindShader(vsh);
shBindShader(fsh);
}
void Noise::idle() {
glutPostRedisplay();
}
void Noise::display()
{
// Render the object
ArbRenderer* arbrend = dynamic_cast(renderer);
bool usingArb = ( arbrend != 0 );
bool arbInit = (usingArb && displayList == -1);
mv = camera.shModelView();
mvp = camera.shModelViewProjection(ShMatrix4x4f());
bandTrans = bandCamera.shModelView();
if( arbInit || !usingArb ) { // draw it out
if( arbInit ) {
displayList = arbrend->startDisplayList();
}
if( !obj ) {
glDisable(GL_CULL_FACE);
glFrontFace(GL_CW);
glutSolidTeapot(2.0);
glFrontFace(GL_CCW);
} else {
renderer->begin( SH_TRIANGLES );
for( int i = 0; i < obj->faces.size(); i++ ) {
for ( int j = 0; j < 3; j++ ) {
ShTexCoord2f texc = obj->texcoords[obj->faces[i].texcoords[j]];
ShNormal3f nrm = obj->normals[obj->faces[i].normals[j]];
ShVector3f tngt1 = obj->tangents[obj->faces[i].tangents[j]];
ShVector3f tngt2 = cross( nrm, tngt1 );
ShPoint3f vtx = obj->vertices[obj->faces[i].points[j]];
renderer->normal( nrm );
renderer->texcoord( 0, texc );
renderer->texcoord( 1, tngt1 );
renderer->texcoord( 2, -tngt2 );
renderer->vertex( vtx );
}
}
renderer->end();
}
if( arbInit ) {
arbrend->endDisplayList();
}
}
if( usingArb ) {
arbrend->callDisplayList( displayList );
}
}