// // texture.h // // Various texture functions derived from "Texturing and Modelling..." // // Copyright (C) J. Belson 2000.02.08 // // $Author: jon $ : $Date: 2003/10/11 18:11:00 $ // #ifndef _TEXTURE_H_ #define _TEXTURE_H_ #include #include #include "fcolour.h" #include "perlin.h" #include "perlin2.h" #include "settings.h" #include "skylight.h" /** * Generic class to hold texture settings */ struct textset { // Most textures have a foreground and background fcolour fg, bg; float scale; textset() { fg = fcolour(1.0, 1.0, 1.0); bg = fcolour(0.0, 0.0, 0.0); scale = 1.0; } }; /** * Settings class for textures which use noise */ struct textset_noise : public textset { int seed; float persistence; float presence; }; /** * Procedural texture base class */ class texture { private: protected: // Virtually all textures have a foreground and background fcolour fg; fcolour bg; public: texture(const textset& ts); // Mix of n1 and n2 with proportion f static float mix(float n1, float n2, float f); static fcolour mix(fcolour c1, fcolour c2, float f); // Return 0 when x static T spline(float x, int nknots, T* knot); // Gamma correction static float gamma_correct(float gamma, float n); static float bias(float b, float n); static float gain(float g, float n); // Return colour at specified texture coordinate virtual fcolour colour(float s, float t, float u = 0, vector3d* normal = 0) = 0; }; class texture_chessboard : public texture { public: texture_chessboard(const textset& ts) : texture(ts) {}; virtual fcolour colour(float s, float t, float u = 0, vector3d* normal = 0); }; class texture_brickwall : public texture { public: texture_brickwall(const textset& ts) : texture(ts) {}; virtual fcolour colour(float s, float t, float u = 0, vector3d* normal = 0); }; class texture_spheres: public texture { public: texture_spheres(const textset& ts) : texture(ts) {}; virtual fcolour colour(float s, float t, float u = 0, vector3d* normal = 0); }; class texture_strata : public texture { private: perlin2* noise; public: texture_strata(const textset& ts); virtual ~texture_strata(); virtual fcolour colour(float s, float t, float u = 0, vector3d* normal = 0); }; /** * Spline function using templates */ template T texture::spline(float x, int nknots, T* knot) { const float CR00 = -0.5; const float CR01 = 1.5; const float CR02 = -1.5; const float CR03 = 0.5; const float CR10 = 1.0; const float CR11 = -2.5; const float CR12 = 2.0; const float CR13 = -0.5; const float CR20 = -0.5; const float CR21 = 0.0; const float CR22 = 0.5; const float CR23 = 0.0; const float CR30 = 0.0; const float CR31 = 1.0; const float CR32 = 0.0; const float CR33 = 0.0; int span; int nspans = nknots - 3; T c0, c1, c2, c3; if (nspans < 1) { // Must be at least one span fprintf(stderr, "Insufficient knots.\n"); return T(); } // Find appropriate 4-point span of the spline x = texture::clamp(x, 0, 1) * nspans; span = int (x); if (span >= nknots - 3) { span = nknots - 3; } x -= span; knot += span; // Evaluate the span cubic at x using Horner's rule c3 = knot[0]*CR00 + knot[1]*CR01 + knot[2]*CR02 + knot[3]*CR03; c2 = knot[0]*CR10 + knot[1]*CR11 + knot[2]*CR12 + knot[3]*CR13; c1 = knot[0]*CR20 + knot[1]*CR21 + knot[2]*CR22 + knot[3]*CR23; c0 = knot[0]*CR30 + knot[1]*CR31 + knot[2]*CR32 + knot[3]*CR33; return ((c3*x + c2)*x + c1)*x + c0; } #endif // _TEXTURE_H_