// 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"
#include "LCD.hpp"
using namespace SH;
LCD::LCD()
: Shader("LCD")
{
}
LCD::~LCD()
{
}
template
ShAttrib construct(double a, ...)
{
va_list ap;
va_start(ap, a);
float args[N];
args[0] = a;
for (int i = 1; i < N; i++) {
args[i] = va_arg(ap, double);
}
va_end(ap);
return ShAttrib(args);
}
ShAttrib1f lcd(const ShTexCoord2f& tc, ShAttrib1f number,
int intDigits, int fracDigits, bool showgrid, bool handleneg)
{
float w = 0.2;
float h = 0.5;
float t = 0.02;
float eps = 0.01;
ShAttrib<7, SH_CONST> segments[10] = {
// TT LT RT CE LB RB BB
construct<7>(1.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0), // 0
construct<7>(0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0), // 1
construct<7>(1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0), // 2
construct<7>(1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0), // 3
construct<7>(0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0), // 4
construct<7>(1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0), // 5
construct<7>(1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0), // 6
construct<7>(1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0), // 7
construct<7>(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0), // 8
construct<7>(1.0, 1.0, 1.0, 1.0, 0.0, 1.0, 1.0)};// 9
ShAttrib<7, SH_CONST> posns[4] = {
construct<7>(0.0 , 0.0 , w - t, t , 0.0 , w - t , 0.0), // left
construct<7>(w , t , w , w - t , t , w , w ), // right
construct<7>(h - t, h/2.0, h/2.0, (h - t)/2.0, 0.0 , 0.0 , 0.0), // bottom
construct<7>(h , h , h , (h + t)/2.0, h/2.0, h/2.0 , t )}; // top
ShAttrib1f result(0.0f);
ShTexCoord2f loc = tc;
ShAttrib1f f = floor(loc(0) / (w + t));
ShAttrib1f index = f - intDigits + 1;
number = number * pow(10.0, index);
loc(0) = loc(0) - f * (w+t);
ShAttrib1f digit = floor(number) - floor(number / 10.0f)*10.0f;
if (handleneg) {
digit = cond(number < 0.0, 9.0 - digit, digit);
}
// digit = abs(index); // Useful for debugging
ShAttrib<7, SH_TEMP> in[4];
in[0] = posns[0] < loc(0);
in[1] = posns[1] > loc(0);
in[2] = posns[2] < loc(1);
in[3] = posns[3] > loc(1);
in[0] = in[0] * in[1] * in[2] * in[3];
for (int d = 0; d < 10; d++) {
result += (abs(digit - (float)d) < eps) * dot(segments[d], in[0]);
}
result *= (index < fracDigits + 1 + eps);
if (handleneg) {
result = cond(index < -0.9 && abs(number/10.0) < 0.1,
ShConstAttrib1f(0.0f), result);
result = cond(number < 0.0 && index < -0.9 && abs(number/10.0) < 0.1 && abs(number) > 0.1,
in[0][3], result);
result = cond(number < 0.0 && index > -1.1 && index < -0.9 && abs(number) < 0.1,
in[0][3], result);
}
if (showgrid) {
result = result || (dot(fillcast<7>(ShConstAttrib1f(0.1)), in[0]) > 0.0) * 0.2;
}
return result;
}
bool LCD::init()
{
vsh = SH_BEGIN_PROGRAM("gpu:vertex") {
ShInputPosition4f ipos;
ShInputNormal3f inorm;
ShOutputPosition4f opos; // Position in NDC
ShOutputNormal3f onorm;
ShInOutTexCoord2f tc; // pass through tex coords
ShOutputVector3f lightv; // direction to light
opos = Globals::mvp | ipos; // Compute NDC position
onorm = Globals::mv | inorm; // Compute view-space normal
ShPoint3f posv = (Globals::mv | ipos)(0,1,2); // Compute view-space position
lightv = normalize(Globals::lightPos - posv); // Compute light direction
} SH_END;
ShAttrib1f SH_DECL(value);
value.range(-500.1, 50.1);
ShColor3f SH_DECL(background) = ShColor3f(0.69, 0.75, 0.68);
ShColor3f SH_DECL(foreground) = ShColor3f(0.18, 0.20, 0.18);
ShVector2f SH_DECL(offset) = ShVector2f(0.0, 0.25);
ShVector2f SH_DECL(scale) = ShVector2f(1.0, 1.0);
scale.range(0.01, 3.0);
fsh = SH_BEGIN_PROGRAM("gpu:fragment") {
ShInputNormal3f normal;
ShInputTexCoord2f tc; // ignore texcoords
ShInputVector3f light;
ShInputPosition4f posh;
ShOutputColor3f result;
normal = normalize(normal);
light = normalize(light);
tc *= scale;
tc(1) = 1.0 - tc(1);
result = cond(lcd(tc - offset, value), foreground, background);
} SH_END;
return true;
}
LCD LCD::instance = LCD();