
// Sh: A GPU metaprogramming language.
//
// Copyright (c) 2003 University of Waterloo Computer Graphics Laboratory
// Project administrator: Michael D. McCool
// Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
// Michael D. McCool
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product documentation
// would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//////////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include "Shader.hpp"
#include "Globals.hpp"
using namespace SH;
using namespace ShUtil;
#include "util.hpp"
class GlassShader : public Shader {
public:
ShProgram vsh, fsh;
GlassShader();
~GlassShader();
bool init();
ShProgram vertex() { return vsh;}
ShProgram fragment() { return fsh;}
};
GlassShader::GlassShader()
: Shader("Refraction: Glass")
{
}
GlassShader::~GlassShader()
{
}
bool GlassShader::init()
{
std::cerr << "Initializing " << name() << std::endl;
std::string imageNames[6] = {"left", "right", "top", "bottom", "back", "front"};
ShImage test_image;
test_image.loadPng(std::string(SHMEDIA_DIR "/envmaps/aniroom/") + imageNames[0] + ".png");
ShTextureCube cubemap(test_image.width(), test_image.height());
{
for (int i = 0; i < 6; i++) {
ShImage image;
image.loadPng(std::string(SHMEDIA_DIR "/envmaps/aniroom/") + imageNames[i] + ".png");
cubemap.memory(image.memory(), static_cast(i));
}
}
ShAttrib1f theta = ShAttrib1f(1.3f);
theta.name("relative indices of refraction");
theta.range(0.0f,2.0f);
vsh = SH_BEGIN_PROGRAM("gpu:vertex") {
ShInputPosition4f ipos;
ShInputNormal3f inorm;
ShOutputPosition4f opos; // Position in NDC
ShOutputNormal3f onorm; // view-space normal
ShOutputVector3f reflv; // Compute reflection vector
ShOutputVector3f refrv; // Compute refraction vector
ShOutputAttrib1f fres; // Compute fresnel term
opos = Globals::mvp | ipos; // Compute NDC position
onorm = Globals::mv | inorm; // Compute view-space normal
onorm = normalize(onorm);
ShPoint3f posv = (Globals::mv | ipos)(0,1,2); // Compute view-space position
ShVector3f viewv = -normalize(posv); // Compute view vector
reflv = reflect(viewv,onorm); // Compute reflection vector
refrv = refract(viewv,onorm,theta); // Compute refraction vector
fres = fresnel(viewv,onorm,theta); // Compute fresnel term
// actually do reflection and refraction lookup in model space
reflv = Globals::mv_inverse | reflv;
refrv = Globals::mv_inverse | refrv;
} SH_END;
fsh = SH_BEGIN_PROGRAM("gpu:fragment") {
ShInputPosition4f posh;
ShInputNormal3f n; // normal
ShInputVector3f reflv; // Compute reflection vector
ShInputVector3f refrv; // Compute refraction vector
ShInputAttrib1f fres; // Compute fresnel term
ShOutputColor3f result;
result = fres*cubemap(reflv)(0,1,2) + (1.0f-fres)*cubemap(refrv)(0,1,2);
} SH_END;
return true;
}
GlassShader the_glass_shader; This page contains the source for the GlassShader class, a Sh shader that renders a refractive glass material. It loads a six-face cube map environment (the aniroom environment map) and uses it for both reflection and refraction lookups, blending the two results with a Fresnel term.
The vertex program transforms the input position and normal into view space, computes the view vector, and derives the reflection vector, refraction vector, and Fresnel term. The reflection and refraction vectors are then transformed back into model space so they can be used to sample the cube map.
The fragment program samples the cube map along the interpolated reflection and refraction vectors and combines the two colors using the interpolated Fresnel term, producing the final glass color.
The shader exposes a single named attribute, theta, described as the relative indices of refraction, with a range of 0.0 to 2.0.
It renders a refractive glass material by combining a reflection lookup and a refraction lookup into a cube map environment, weighted by a Fresnel term.
It loads six PNG images named left, right, top, bottom, back, and front from the envmaps/aniroom/ directory under SHMEDIA_DIR and assembles them into a cube map.
theta attribute for?theta is a named attribute representing the relative indices of refraction. It is used when computing the refraction vector and the Fresnel term, and its range is set from 0.0 to 2.0.
The fragment program computes fres * cubemap(reflv) plus (1.0 - fres) * cubemap(refrv), so the Fresnel term controls how much of the reflection versus the refraction contributes to the final color.
The vectors are computed in view space, then transformed back into model space so the cube map lookups are performed in model space, as noted in the source comments.