#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 ); } }