⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 brickhorizon.cpp

📁 shrike is a utility application that acts as a testbed for shaders written in Sh
💻 CPP
字号:
// Sh: A GPU metaprogramming language.//// Copyright 2003-2005 Serious Hack Inc.// // This library is free software; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public// License as published by the Free Software Foundation; either// version 2.1 of the License, or (at your option) any later version.//// This library 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// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this library; if not, write to the Free Software// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, // MA  02110-1301, USA//////////////////////////////////////////////////////////////////////////////#include <sh/sh.hpp>#include <sh/shutil.hpp>#include <iostream>#include <math.h>#include "Shader.hpp"#include "Globals.hpp"using namespace SH;using namespace ShUtil;class BrickHorizon : public Shader {public:  BrickHorizon();  ~BrickHorizon();  bool init();  ShProgram vertex() { return vsh;}  ShProgram fragment() { return fsh;}  ShProgram vsh, fsh;  static BrickHorizon instance;};BrickHorizon::BrickHorizon()  : Shader("Brick Wall: Horizon Maps"){}BrickHorizon::~BrickHorizon(){}bool BrickHorizon::init(){  vsh = SH_BEGIN_PROGRAM("gpu:vertex") {    ShInputPosition4f ipos;    ShInputNormal3f inorm;    ShInputVector3f itan;        ShOutputPosition4f opos; // Position in NDC    ShInOutTexCoord2f tc; // pass through tex coords    ShOutputNormal3f onorm;    ShOutputVector3f otan;    ShOutputVector3f osurf;    ShOutputVector3f lightv; // direction to light    opos = Globals::mvp | ipos; // Compute NDC position    onorm = normalize(Globals::mv | inorm); // Compute view-space normal    otan = normalize(Globals::mv | itan); // Compute the view-space tangent    osurf = cross(onorm, otan);    ShPoint3f posv = (Globals::mv | ipos)(0,1,2); // Compute view-space position    lightv = normalize(Globals::lightPos - posv); // Compute light direction  } SH_END;  ShColor3f brick = ShColor3f(0.7, 0.1, 0.1);  ShColor3f mortar = ShColor3f(0.3, 0.3, 0.3);  ShAttrib2f SH_DECL(scale) = ShAttrib2f(3.0, 5.0);  scale.name("brick size");  scale.range(1.0, 100.0);  ShAttrib2f SH_DECL(mortarsize) = ShAttrib2f(0.03, 0.03);  mortarsize.name("mortar size");  mortarsize.range(0.0, 0.1);  ShAttrib1f SH_DECL(offset) = ShAttrib1f(0.5);   ShAttrib3f SH_DECL(colorVariations) = ShAttrib3f(0.2, 0.1, 0.1);  colorVariations.range(0.0, 1.0);	  ShAttrib1f SH_DECL(brickHeight) = ShAttrib1f(0.1);  brickHeight.name("brick height");  brickHeight.range(0.01,0.1); 	  ShAttrib1f SH_DECL(intensity) = ShAttrib1f(1.0);  intensity.name("shadow intensity");  intensity.range(0.1,10.0);  ShAttrib1f SH_DECL(noiseScale) = ShConstAttrib1f(0.15f);  noiseScale.range(0.0f, 1.0f);  ShAttrib1f SH_DECL(noiseFreq) = ShConstAttrib1f(20.0f);  noiseFreq.range(0.0f, 100.0f);  ShAttrib1f SH_DECL(noiseAmps) = ShConstAttrib1f(1.0f);	  noiseAmps.range(0.0f, 1.0f);  // Create the bricks and the mortar between them  ShProgram brickID = SH_BEGIN_PROGRAM("gpu:fragment") {    ShInputPosition4f pos;    ShInOutTexCoord2f tc;    ShOutputAttrib1f changeColor; // change the color between 2 consecutive bricks    ShInOutNormal3f normal;    ShOutputAttrib1f id; // define if the current point belongs to a brick or to the mortar    tc *= scale;    tc += 2*mortarsize;    tc(0) -= floor(tc(1))*offset; // change the horizontal position of a line    changeColor = abs(floor(tc(1))) * abs(floor(tc(0)));    tc(1) -= floor(tc(1));    tc(0) -= floor(tc(0));		    id = SH::min(abs(tc(0)) > 2*mortarsize(0), abs(tc(1)) > 2*mortarsize(1)); // limits of a brick		  } SH_END;  /* Add bump-mapping to the wall   * bricks and mortar are bumpmapped with some noise   */  ShProgram bumpmap = SH_BEGIN_PROGRAM("gpu:fragment") {    ShInOutTexCoord2f tc;    ShInOutAttrib1f changeColor;    ShInOutNormal3f normal;        ShVector3f TilePerturb = noiseScale * sperlin<3>(tc * noiseFreq, noiseAmps, true);    normal = mad(0.35, TilePerturb, normal);        normal = normalize(normal);		  } SH_END;  /* Change the color of a brick   * a noise function is used to add variations to the initial color   */  ShProgram brickModifier = SH_BEGIN_PROGRAM("gpu:fragment") {    ShInOutTexCoord2f tc;    ShInputAttrib1f changeColor;    ShOutputColor3f brickVariations;     brickVariations = noiseScale * perlin<3>(tc * noiseFreq, noiseAmps, true);    brickVariations = mad(cellnoise<1>(changeColor, false), colorVariations, brickVariations);    brickVariations = mad(0.35, brickVariations, brick);  } SH_END;  /* Select the color to render in function of the id   * id = 1.0 is a brick   * id = 0.0 is the mortar   */  ShProgram select = SH_BEGIN_PROGRAM("gpu:fragment") {    ShInOutTexCoord2f tc;    ShInputColor3f brickVariations;    ShInOutNormal3f normal;    ShInputAttrib1f id;    ShInOutVector3f tangent;    ShInOutVector3f surface;    ShInOutVector3f light;     ShOutputColor3f result;      result= cond(id, brickVariations, mortar);    normal = normalize(normal);    light = normalize(light);    result = result * pos(normal | light);           } SH_END;	  /* Add horizon mapping to the bricks   */  ShProgram horizonmapping = SH_BEGIN_PROGRAM("gpu:fragment") {    ShInputTexCoord2f tc;    ShInputNormal3f normal;    ShInputVector3f tangent;    ShInputVector3f surface;    ShInputVector3f light;    ShInOutColor3f result;		    ShColor3f shadow = ShColor3f(0.5,0.5,0.5);		    ShAttrib1f lt = light | tangent;    ShAttrib1f ls = light | surface;    ShAttrib1f ln = light | normal;    ShAttrib1f normS = lt*lt+ls*ls;    ShAttrib1f cosAngle = sqrt(normS) / sqrt(normS+ln*ln);		    ShVector2f lightS = ShVector2f(lt,ls);    lightS = normalize(lightS);    lt = lightS(0);    ls = lightS(1);		    ShAttrib1f b = 2.0*lt*lt-1;    ShAttrib1f bb = b*b;    ShAttrib1f bb2 = 1.0-bb;		    ShAttrib1f brickHeight2 = brickHeight*brickHeight;    ShAttrib1f horizonLoc; // position of the horizon	    // create a horizon value for a brick, to make some "holes" in the surface    ShAttrib1f hole = 1.0 - noiseScale * sperlin<1>(tc *2.0 * noiseFreq, noiseAmps, true);		    ShAttrib1f horizon1 = hole, horizon2 = hole, horizon3 = hole, horizon4 = hole,    horizon5 = hole, horizon6 = hole, horizon7 = hole, horizon8 = hole;		    horizonLoc = SH::min(tc(0)<2*mortarsize(0),tc(1)>2*mortarsize(1));    horizon1 = cond(horizonLoc, tc(0)/sqrt(tc(0)*tc(0)+brickHeight*brickHeight), horizon1);		    ShAttrib2f tc2 = ShAttrib2f(2*mortarsize(0)-tc(0),1.0+2*mortarsize(1)-tc(1));    horizon3 = cond(horizonLoc, tc2(0)/sqrt(tc2(0)*tc2(0)+brickHeight2), horizon3);    horizonLoc = SH::max(tc(0)<2*mortarsize(0), SH::min(tc(0)>2*mortarsize(0), tc(1)<2*mortarsize(1)));    horizon2 = cond(horizonLoc, tc(1)/sqrt(tc(1)*tc(1)+brickHeight2), horizon2);    horizonLoc = SH::min(tc(1)<2*mortarsize(1), SH::min(tc(0)>offset, tc(0)<offset+2*mortarsize(0)));    horizon2 = cond(horizonLoc, tc2(1)/sqrt(tc2(1)*tc2(1)+brickHeight2), horizon2);		    horizon4 = cond(tc(0)<2*mortarsize(0), tc2(1)/sqrt(tc2(1)*tc2(1)+brickHeight2), horizon4);    tc2[1] = 2*mortarsize(1)-tc(1);    horizonLoc = SH::min(tc(1)<2*mortarsize(1),tc(0)>2*mortarsize(0));    horizon4 = cond(horizonLoc, tc2(1)/sqrt(tc2(1)*tc2(1)+brickHeight2), horizon4);			    // the diagonals    // part5    ShAttrib1f diag;    diag = 2*tc(0)*tc(0);    horizonLoc = SH::min(tc(0)<2*mortarsize(0), tc(1)>2*mortarsize(1));    horizon5 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon5);    horizon8 = horizon5; // same orientation for the 8th part    diag = 2*tc(1)*tc(1);    horizonLoc = tc(1)<2*mortarsize(1);    horizon5 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon5);    horizon6 = horizon5; // same orientation for the 6th part    horizonLoc = SH::min(tc(0)<2*mortarsize(0), SH::min(tc(1)>=2*mortarsize(1), tc(1)<=tc(0)+2*mortarsize(1)));    horizon5 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon5);    diag = tc(0)-1.0+offset;	    diag *= 2*diag;    horizonLoc = SH::min(tc(1)<2*mortarsize(1), SH::min(tc(0)>=1.0-offset+tc(1), tc(0)<=1.0-offset+tc(1)+2*mortarsize(0)));    horizon5 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon5);    // part 6    diag = 2*mortarsize(0)-tc(0);    diag *= 2*diag;    horizonLoc = SH::min(tc(0)<2*mortarsize(0), tc(1)>2*mortarsize(1));    horizon6 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon6);    horizon7 = horizon6; // same orientation for the 7th part    diag = 2*tc(1)*tc(1);    horizonLoc = SH::min(tc(0)<2*mortarsize(0), SH::min(tc(1)>=2*mortarsize(1), tc(1)<=-tc(0)+2*mortarsize(0)+2*mortarsize(1)));    horizon6 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon6);    diag = 1.0+2*mortarsize(0)-tc(0)-offset;    diag *= 2*diag;    horizonLoc = SH::min(tc(1)<2*mortarsize(1), SH::min(tc(0)>=1.0-offset-tc(1), tc(0)<=1.0-offset-tc(1)+2*mortarsize(0)));    horizon6 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon6);		    // part 7    diag = 2*mortarsize(1)-tc(1);    diag *= 2*diag;    horizonLoc = tc(1)<2*mortarsize(1);    horizon7 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon7);    diag = 1.0+2*mortarsize(0)-tc(0);    diag *= 2*diag;    horizonLoc = SH::min(tc(1)<2*mortarsize(1), SH::min(tc(0)>1.0-2*mortarsize(1)+tc(1),tc(0)<1.0+2*mortarsize(0)-2*mortarsize(1)+tc(1)));    horizon7 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon7);    diag = 2*mortarsize(0)-tc(0);    diag *= 2*diag;    horizonLoc = SH::min(tc(1)<2*mortarsize(1), tc(0)<tc(1)+2*mortarsize(0)-2*mortarsize(1));    horizon7 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon7);    diag = 1.0-tc(1)+2*mortarsize(1);    diag *= 2*diag;    horizonLoc = SH::min(tc(0)<2*mortarsize(0), tc(1)>=1.0+tc(0)-2*mortarsize(0));    horizon7 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon7);		    // part 8    diag = 2*mortarsize(1)-tc(1);    diag *= 2*diag;    horizonLoc = tc(1)<2*mortarsize(1);    horizon8 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon8);    diag = 2*tc(0)*tc(0);    horizonLoc = SH::min(tc(1)<2*mortarsize(1), SH::min(tc(0)>=2*mortarsize(1)-tc(1), tc(0)<=2*mortarsize(0)+2*mortarsize(1)-tc(1)));    horizon8 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon8);    diag = 1.0-tc(1)+2*mortarsize(1);    diag *= 2*diag;    horizonLoc = SH::min(tc(0)<2*mortarsize(0), tc(1)>=1.0-tc(0));    horizon8 = cond(horizonLoc, sqrt(diag)/sqrt(diag+brickHeight2), horizon8);		    // define the basis functions    ShAttrib1f null = 0.0;    ShAttrib1f b1 = cond(SH::min(-lt, b), bb, null);    ShAttrib1f b2 = cond(SH::min(ls, -b), bb, null);    ShAttrib1f b3 = cond(SH::min(lt, b), bb, null);    ShAttrib1f b4 = cond(SH::min(-ls, -b), bb, null);    ShAttrib1f b5 = cond(SH::min(-lt, ls), bb2, null);    ShAttrib1f b6 = cond(SH::min(lt, ls), bb2, null);    ShAttrib1f b7 = cond(SH::min(lt, -ls), bb2, null);    ShAttrib1f b8 = cond(SH::min(-lt, -ls), bb2, null);    // the interpolated horizon value    ShAttrib1f cosHorizon = b1*horizon1 + b2*horizon2 + b3*horizon3 + b4*horizon4 +    b5*horizon5 + b6*horizon6 +	b7*horizon7 + b8*horizon8;	    ShAttrib1f x = abs(cosAngle-cosHorizon)*intensity;    shadow = ((pow(M_E, 2*x) - 1) / (pow(M_E, 2*x) + 1))*shadow; // use tanh to create soft shadows    result = cond( cosAngle>cosHorizon, result-shadow, result); // draw shadows in function of the angle  } SH_END;   fsh = horizonmapping << (select << (((brickModifier & keep<ShNormal3f>() & keep<ShAttrib1f>()) << (bumpmap & keep<ShAttrib1f>()) << brickID) & keep<ShVector3f>() & keep<ShVector3f>() & keep<ShVector3f>()));  return true;}BrickHorizon BrickHorizon::instance = BrickHorizon();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -