#include <string>
namespace slg { namespace ocl {
std::string KernelSource_texture_funcs = 
"#line 2 \"texture_funcs.cl\"\n"
"\n"
"/***************************************************************************\n"
" *   Copyright (C) 1998-2013 by authors (see AUTHORS.txt)                  *\n"
" *                                                                         *\n"
" *   This file is part of LuxRays.                                         *\n"
" *                                                                         *\n"
" *   LuxRays is free software; you can redistribute it and/or modify       *\n"
" *   it under the terms of the GNU General Public License as published by  *\n"
" *   the Free Software Foundation; either version 3 of the License, or     *\n"
" *   (at your option) any later version.                                   *\n"
" *                                                                         *\n"
" *   LuxRays is distributed in the hope that it will be useful,            *\n"
" *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\n"
" *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\n"
" *   GNU General Public License for more details.                          *\n"
" *                                                                         *\n"
" *   You should have received a copy of the GNU General Public License     *\n"
" *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *\n"
" *                                                                         *\n"
" *   LuxRays website: http://www.luxrender.net                             *\n"
" ***************************************************************************/\n"
"\n"
"#define TEXTURE_STACK_SIZE 16\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Texture utility functions\n"
"//------------------------------------------------------------------------------\n"
"\n"
"// Perlin Noise Data\n"
"#define NOISE_PERM_SIZE 256\n"
"__constant int NoisePerm[2 * NOISE_PERM_SIZE] = {\n"
"	151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96,\n"
"	53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142,\n"
"	// Rest of noise permutation table\n"
"	8, 99, 37, 240, 21, 10, 23,\n"
"	190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,\n"
"	88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,\n"
"	77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,\n"
"	102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,\n"
"	135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,\n"
"	5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,\n"
"	223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,\n"
"	129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,\n"
"	251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,\n"
"	49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,\n"
"	138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,\n"
"	151, 160, 137, 91, 90, 15,\n"
"	131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,\n"
"	190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,\n"
"	88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,\n"
"	77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,\n"
"	102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,\n"
"	135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,\n"
"	5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,\n"
"	223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,\n"
"	129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,\n"
"	251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,\n"
"	49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,\n"
"	138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180\n"
"};\n"
"\n"
"float Grad(int x, int y, int z, float dx, float dy, float dz) {\n"
"	const int h = NoisePerm[NoisePerm[NoisePerm[x] + y] + z] & 15;\n"
"	const float u = h < 8 || h == 12 || h == 13 ? dx : dy;\n"
"	const float v = h < 4 || h == 12 || h == 13 ? dy : dz;\n"
"	return ((h & 1) ? -u : u) + ((h & 2) ? -v : v);\n"
"}\n"
"\n"
"float NoiseWeight(float t) {\n"
"	const float t3 = t * t * t;\n"
"	const float t4 = t3 * t;\n"
"	return 6.f * t4 * t - 15.f * t4 + 10.f * t3;\n"
"}\n"
"\n"
"float Noise(float x, float y, float z) {\n"
"	// Compute noise cell coordinates and offsets\n"
"	int ix = Floor2Int(x);\n"
"	int iy = Floor2Int(y);\n"
"	int iz = Floor2Int(z);\n"
"	const float dx = x - ix, dy = y - iy, dz = z - iz;\n"
"	// Compute gradient weights\n"
"	ix &= (NOISE_PERM_SIZE - 1);\n"
"	iy &= (NOISE_PERM_SIZE - 1);\n"
"	iz &= (NOISE_PERM_SIZE - 1);\n"
"	const float w000 = Grad(ix, iy, iz, dx, dy, dz);\n"
"	const float w100 = Grad(ix + 1, iy, iz, dx - 1, dy, dz);\n"
"	const float w010 = Grad(ix, iy + 1, iz, dx, dy - 1, dz);\n"
"	const float w110 = Grad(ix + 1, iy + 1, iz, dx - 1, dy - 1, dz);\n"
"	const float w001 = Grad(ix, iy, iz + 1, dx, dy, dz - 1);\n"
"	const float w101 = Grad(ix + 1, iy, iz + 1, dx - 1, dy, dz - 1);\n"
"	const float w011 = Grad(ix, iy + 1, iz + 1, dx, dy - 1, dz - 1);\n"
"	const float w111 = Grad(ix + 1, iy + 1, iz + 1, dx - 1, dy - 1, dz - 1);\n"
"	// Compute trilinear interpolation of weights\n"
"	const float wx = NoiseWeight(dx);\n"
"	const float wy = NoiseWeight(dy);\n"
"	const float wz = NoiseWeight(dz);\n"
"	const float x00 = Lerp(wx, w000, w100);\n"
"	const float x10 = Lerp(wx, w010, w110);\n"
"	const float x01 = Lerp(wx, w001, w101);\n"
"	const float x11 = Lerp(wx, w011, w111);\n"
"	const float y0 = Lerp(wy, x00, x10);\n"
"	const float y1 = Lerp(wy, x01, x11);\n"
"	return Lerp(wz, y0, y1);\n"
"}\n"
"\n"
"float Noise3(const float3 P) {\n"
"	return Noise(P.x, P.y, P.z);\n"
"}\n"
"\n"
"float FBm(const float3 P, const float omega, const int maxOctaves) {\n"
"	// Compute number of octaves for anti-aliased FBm\n"
"	const float foctaves = (float)maxOctaves;\n"
"	const int octaves = Floor2Int(foctaves);\n"
"	// Compute sum of octaves of noise for FBm\n"
"	float sum = 0.f, lambda = 1.f, o = 1.f;\n"
"	for (int i = 0; i < octaves; ++i) {\n"
"		sum += o * Noise3(lambda * P);\n"
"		lambda *= 1.99f;\n"
"		o *= omega;\n"
"	}\n"
"	const float partialOctave = foctaves - (float)octaves;\n"
"	sum += o * SmoothStep(.3f, .7f, partialOctave) *\n"
"			Noise3(lambda * P);\n"
"	return sum;\n"
"}\n"
"\n"
"float Turbulence(const float3 P, const float omega, const int maxOctaves) {\n"
"	// Compute number of octaves for anti-aliased FBm\n"
"	const float foctaves = (float)maxOctaves;\n"
"	const int octaves = Floor2Int(foctaves);\n"
"	// Compute sum of octaves of noise for turbulence\n"
"	float sum = 0.f, lambda = 1.f, o = 1.f;\n"
"	for (int i = 0; i < octaves; ++i) {\n"
"		sum += o * fabs(Noise3(lambda * P));\n"
"		lambda *= 1.99f;\n"
"		o *= omega;\n"
"	}\n"
"	const float partialOctave = foctaves - (float)(octaves);\n"
"	sum += o * SmoothStep(.3f, .7f, partialOctave) *\n"
"	       fabs(Noise3(lambda * P));\n"
"\n"
"	// finally, add in value to account for average value of fabsf(Noise())\n"
"	// (~0.2) for the remaining octaves...\n"
"	sum += (maxOctaves - foctaves) * 0.2f;\n"
"\n"
"	return sum;\n"
"}\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// ImageMaps support\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined(PARAM_HAS_IMAGEMAPS)\n"
"\n"
"__global float *ImageMap_GetPixelsAddress(__global float **imageMapBuff,\n"
"		const uint page, const uint offset) {\n"
"	return &imageMapBuff[page][offset];\n"
"}\n"
"\n"
"float ImageMap_GetTexel_Float(__global float *pixels,\n"
"		const uint width, const uint height, const uint channelCount,\n"
"		const int s, const int t) {\n"
"	const uint u = Mod(s, width);\n"
"	const uint v = Mod(t, height);\n"
"\n"
"	const uint index = channelCount * (v * width + u);\n"
"\n"
"	return (channelCount == 1) ? pixels[index] : Spectrum_Y(VLOAD3F(&pixels[index]));\n"
"}\n"
"\n"
"float3 ImageMap_GetTexel_Spectrum(__global float *pixels,\n"
"		const uint width, const uint height, const uint channelCount,\n"
"		const int s, const int t) {\n"
"	const uint u = Mod(s, width);\n"
"	const uint v = Mod(t, height);\n"
"\n"
"	const uint index = channelCount * (v * width + u);\n"
"\n"
"	return (channelCount == 1) ? pixels[index] : VLOAD3F(&pixels[index]);\n"
"}\n"
"\n"
"float ImageMap_GetFloat(__global float *pixels,\n"
"		const uint width, const uint height, const uint channelCount,\n"
"		const float u, const float v) {\n"
"	const float s = u * width - 0.5f;\n"
"	const float t = v * height - 0.5f;\n"
"\n"
"	const int s0 = Floor2Int(s);\n"
"	const int t0 = Floor2Int(t);\n"
"\n"
"	const float ds = s - s0;\n"
"	const float dt = t - t0;\n"
"\n"
"	const float ids = 1.f - ds;\n"
"	const float idt = 1.f - dt;\n"
"\n"
"	const float c0 = ImageMap_GetTexel_Float(pixels, width, height, channelCount, s0, t0);\n"
"	const float c1 = ImageMap_GetTexel_Float(pixels, width, height, channelCount, s0, t0 + 1);\n"
"	const float c2 = ImageMap_GetTexel_Float(pixels, width, height, channelCount, s0 + 1, t0);\n"
"	const float c3 = ImageMap_GetTexel_Float(pixels, width, height, channelCount, s0 + 1, t0 + 1);\n"
"\n"
"	const float k0 = ids * idt;\n"
"	const float k1 = ids * dt;\n"
"	const float k2 = ds * idt;\n"
"	const float k3 = ds * dt;\n"
"\n"
"	return (k0 * c0 + k1 *c1 + k2 * c2 + k3 * c3);\n"
"}\n"
"\n"
"float3 ImageMap_GetSpectrum(__global float *pixels,\n"
"		const uint width, const uint height, const uint channelCount,\n"
"		const float u, const float v) {\n"
"	const float s = u * width - 0.5f;\n"
"	const float t = v * height - 0.5f;\n"
"\n"
"	const int s0 = Floor2Int(s);\n"
"	const int t0 = Floor2Int(t);\n"
"\n"
"	const float ds = s - s0;\n"
"	const float dt = t - t0;\n"
"\n"
"	const float ids = 1.f - ds;\n"
"	const float idt = 1.f - dt;\n"
"\n"
"	const float3 c0 = ImageMap_GetTexel_Spectrum(pixels, width, height, channelCount, s0, t0);\n"
"	const float3 c1 = ImageMap_GetTexel_Spectrum(pixels, width, height, channelCount, s0, t0 + 1);\n"
"	const float3 c2 = ImageMap_GetTexel_Spectrum(pixels, width, height, channelCount, s0 + 1, t0);\n"
"	const float3 c3 = ImageMap_GetTexel_Spectrum(pixels, width, height, channelCount, s0 + 1, t0 + 1);\n"
"\n"
"	const float k0 = ids * idt;\n"
"	const float k1 = ids * dt;\n"
"	const float k2 = ds * idt;\n"
"	const float k3 = ds * dt;\n"
"\n"
"	return (k0 * c0 + k1 *c1 + k2 * c2 + k3 * c3);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// ConstFloat texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_CONST_FLOAT)\n"
"\n"
"void ConstFloatTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = texture->constFloat.value;\n"
"}\n"
"\n"
"void ConstFloatTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = texture->constFloat.value;\n"
"}\n"
"\n"
"void ConstFloatTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = 0.f;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// ConstFloat3 texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_CONST_FLOAT3)\n"
"\n"
"void ConstFloat3Texture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = Spectrum_Y(VLOAD3F(&texture->constFloat3.color.r));\n"
"}\n"
"\n"
"void ConstFloat3Texture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = VLOAD3F(&texture->constFloat3.color.r);\n"
"}\n"
"\n"
"void ConstFloat3Texture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = 0.f;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// ImageMap texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_IMAGEMAP)\n"
"\n"
"void ImageMapTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize\n"
"		IMAGEMAPS_PARAM_DECL) {\n"
"	__global ImageMap *imageMap = &imageMapDescs[texture->imageMapTex.imageMapIndex];\n"
"	__global float *pixels = ImageMap_GetPixelsAddress(\n"
"			imageMapBuff, imageMap->pageIndex, imageMap->pixelsIndex);\n"
"\n"
"	const float2 uv = VLOAD2F(&hitPoint->uv.u);\n"
"	const float2 mapUV = TextureMapping2D_Map(&texture->imageMapTex.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = texture->imageMapTex.gain * ImageMap_GetFloat(\n"
"			pixels,\n"
"			imageMap->width, imageMap->height, imageMap->channelCount,\n"
"			mapUV.s0, mapUV.s1);\n"
"}\n"
"\n"
"void ImageMapTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize\n"
"		IMAGEMAPS_PARAM_DECL) {\n"
"	__global ImageMap *imageMap = &imageMapDescs[texture->imageMapTex.imageMapIndex];\n"
"	__global float *pixels = ImageMap_GetPixelsAddress(\n"
"			imageMapBuff, imageMap->pageIndex, imageMap->pixelsIndex);\n"
"\n"
"	const float2 uv = VLOAD2F(&hitPoint->uv.u);\n"
"	const float2 mapUV = TextureMapping2D_Map(&texture->imageMapTex.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = texture->imageMapTex.gain * ImageMap_GetSpectrum(\n"
"			pixels,\n"
"			imageMap->width, imageMap->height, imageMap->channelCount,\n"
"			mapUV.s0, mapUV.s1);\n"
"}\n"
"\n"
"void ImageMapTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = VLOAD2F(&texture->imageMapTex.Du);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Scale texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_SCALE)\n"
"\n"
"void ScaleTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value = texValues[--(*texValuesSize)] * texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = value;\n"
"}\n"
"\n"
"void ScaleTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value = texValues[--(*texValuesSize)] * texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = value;\n"
"}\n"
"\n"
"void ScaleTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(dudv1, dudv2);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// FresnelApproxN & FresnelApproxK texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_N)\n"
"\n"
"float FresnelApproxN(const float Fr) {\n"
"	const float sqrtReflectance = sqrt(clamp(Fr, 0.f, .999f));\n"
"\n"
"	return (1.f + sqrtReflectance) /\n"
"		(1.f - sqrtReflectance);\n"
"}\n"
"\n"
"float3 FresnelApproxN3(const float3 Fr) {\n"
"	const float3 sqrtReflectance = Spectrum_Sqrt(clamp(Fr, 0.f, .999f));\n"
"\n"
"	return (WHITE + sqrtReflectance) /\n"
"		(WHITE - sqrtReflectance);\n"
"}\n"
"\n"
"void FresnelApproxNTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = FresnelApproxN(value);\n"
"}\n"
"\n"
"void FresnelApproxNTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = FresnelApproxN3(value);\n"
"}\n"
"\n"
"void FresnelApproxNTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = texValues[--(*texValuesSize)];\n"
"}\n"
"\n"
"#endif\n"
"\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_K)\n"
"\n"
"float FresnelApproxK(const float Fr) {\n"
"	const float reflectance = clamp(Fr, 0.f, .999f);\n"
"\n"
"	return 2.f * sqrt(reflectance /\n"
"		(1.f - reflectance));\n"
"}\n"
"\n"
"float3 FresnelApproxK3(const float3 Fr) {\n"
"	const float3 reflectance = clamp(Fr, 0.f, .999f);\n"
"\n"
"	return 2.f * Spectrum_Sqrt(reflectance /\n"
"		(WHITE - reflectance));\n"
"}\n"
"\n"
"void FresnelApproxKTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = FresnelApproxK(value);\n"
"}\n"
"\n"
"void FresnelApproxKTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = FresnelApproxK3(value);\n"
"}\n"
"\n"
"void FresnelApproxKTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = texValues[--(*texValuesSize)];\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// CheckerBoard 2D & 3D texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD2D)\n"
"\n"
"void CheckerBoard2DTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value1 = texValues[--(*texValuesSize)];\n"
"	const float value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float2 uv = VLOAD2F(&hitPoint->uv.u);\n"
"	const float2 mapUV = TextureMapping2D_Map(&texture->checkerBoard2D.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = ((Floor2Int(mapUV.s0) + Floor2Int(mapUV.s1)) % 2 == 0) ? value1 : value2;\n"
"}\n"
"\n"
"void CheckerBoard2DTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value1 = texValues[--(*texValuesSize)];\n"
"	const float3 value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float2 uv = VLOAD2F(&hitPoint->uv.u);\n"
"	const float2 mapUV = TextureMapping2D_Map(&texture->checkerBoard2D.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = ((Floor2Int(mapUV.s0) + Floor2Int(mapUV.s1)) % 2 == 0) ? value1 : value2;\n"
"}\n"
"\n"
"void CheckerBoard2DTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(dudv1, dudv2);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD3D)\n"
"\n"
"void CheckerBoard3DTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value1 = texValues[--(*texValuesSize)];\n"
"	const float value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->checkerBoard3D.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = ((Floor2Int(mapP.x) + Floor2Int(mapP.y) + Floor2Int(mapP.z)) % 2 == 0) ? value1 : value2;\n"
"}\n"
"\n"
"void CheckerBoard3DTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value1 = texValues[--(*texValuesSize)];\n"
"	const float3 value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->checkerBoard3D.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = ((Floor2Int(mapP.x) + Floor2Int(mapP.y) + Floor2Int(mapP.z)) % 2 == 0) ? value1 : value2;\n"
"}\n"
"\n"
"void CheckerBoard3DTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(dudv1, dudv2);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Mix texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_MIX)\n"
"\n"
"void MixTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float amt = clamp(texValues[--(*texValuesSize)], 0.f, 1.f);;\n"
"	const float value1 = texValues[--(*texValuesSize)];\n"
"	const float value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = Lerp(amt, value1, value2);\n"
"}\n"
"\n"
"void MixTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 amt = clamp(texValues[--(*texValuesSize)], 0.f, 1.f);\n"
"	const float3 value1 = texValues[--(*texValuesSize)];\n"
"	const float3 value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = mix(value1, value2, amt);\n"
"}\n"
"\n"
"void MixTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv3 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(fmax(dudv1, dudv2), dudv3);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// FBM texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_FBM_TEX)\n"
"\n"
"void FBMTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->fbm.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = FBm(mapP, texture->fbm.omega, texture->fbm.octaves);\n"
"}\n"
"\n"
"void FBMTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->fbm.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = FBm(mapP, texture->fbm.omega, texture->fbm.octaves);\n"
"}\n"
"\n"
"void FBMTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = (float2)(DUDV_VALUE, DUDV_VALUE);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Marble texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_MARBLE)\n"
"\n"
"// Evaluate marble spline at _t_\n"
"__constant float MarbleTexture_c[9][3] = {\n"
"	{ .58f, .58f, .6f},\n"
"	{ .58f, .58f, .6f},\n"
"	{ .58f, .58f, .6f},\n"
"	{ .5f, .5f, .5f},\n"
"	{ .6f, .59f, .58f},\n"
"	{ .58f, .58f, .6f},\n"
"	{ .58f, .58f, .6f},\n"
"	{.2f, .2f, .33f},\n"
"	{ .58f, .58f, .6f}\n"
"};\n"
"\n"
"float3 MarbleTexture_Evaluate(__global Texture *texture, __global HitPoint *hitPoint) {\n"
"	const float3 P = texture->marble.scale * TextureMapping3D_Map(&texture->marble.mapping, hitPoint);\n"
"\n"
"	float marble = P.y + texture->marble.variation * FBm(P, texture->marble.omega, texture->marble.octaves);\n"
"	float t = .5f + .5f * sin(marble);\n"
"#define NC  sizeof(MarbleTexture_c) / sizeof(MarbleTexture_c[0])\n"
"#define NSEG (NC-3)\n"
"	const int first = Floor2Int(t * NSEG);\n"
"	t = (t * NSEG - first);\n"
"#undef NC\n"
"#undef NSEG\n"
"#define ASSIGN_CF3(a) (float3)(a[0], a[1], a[2])\n"
"	const float3 c0 = ASSIGN_CF3(MarbleTexture_c[first]);\n"
"	const float3 c1 = ASSIGN_CF3(MarbleTexture_c[first + 1]);\n"
"	const float3 c2 = ASSIGN_CF3(MarbleTexture_c[first + 2]);\n"
"	const float3 c3 = ASSIGN_CF3(MarbleTexture_c[first + 3]);\n"
"#undef ASSIGN_CF3\n"
"	// Bezier spline evaluated with de Castilejau's algorithm	\n"
"	float3 s0 = mix(c0, c1, t);\n"
"	float3 s1 = mix(c1, c2, t);\n"
"	float3 s2 = mix(c2, c3, t);\n"
"	s0 = mix(s0, s1, t);\n"
"	s1 = mix(s1, s2, t);\n"
"	// Extra scale of 1.5 to increase variation among colors\n"
"	return 1.5f * mix(s0, s1, t);\n"
"}\n"
"\n"
"void MarbleTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = Spectrum_Y(MarbleTexture_Evaluate(texture, hitPoint));\n"
"}\n"
"\n"
"void MarbleTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = MarbleTexture_Evaluate(texture, hitPoint);\n"
"}\n"
"\n"
"void MarbleTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = (float2)(DUDV_VALUE, DUDV_VALUE);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Dots texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_DOTS)\n"
"\n"
"void DotsTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value1 = texValues[--(*texValuesSize)];\n"
"	const float value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float2 uv = TextureMapping2D_Map(&texture->dots.mapping, hitPoint);\n"
"\n"
"	const int sCell = Floor2Int(uv.s0 + .5f);\n"
"	const int tCell = Floor2Int(uv.s1 + .5f);\n"
"	// Return _insideDot_ result if point is inside dot\n"
"	if (Noise(sCell + .5f, tCell + .5f, .5f) > 0.f) {\n"
"		const float radius = .35f;\n"
"		const float maxShift = 0.5f - radius;\n"
"		const float sCenter = sCell + maxShift *\n"
"			Noise(sCell + 1.5f, tCell + 2.8f, .5f);\n"
"		const float tCenter = tCell + maxShift *\n"
"			Noise(sCell + 4.5f, tCell + 9.8f, .5f);\n"
"		const float ds = uv.s0 - sCenter, dt = uv.s1 - tCenter;\n"
"		if (ds * ds + dt * dt < radius * radius) {\n"
"			texValues[(*texValuesSize)++] = value1;\n"
"			return;\n"
"		}\n"
"	}\n"
"\n"
"	texValues[(*texValuesSize)++] = value2;\n"
"}\n"
"\n"
"void DotsTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value1 = texValues[--(*texValuesSize)];\n"
"	const float3 value2 = texValues[--(*texValuesSize)];\n"
"\n"
"	const float2 uv = TextureMapping2D_Map(&texture->dots.mapping, hitPoint);\n"
"\n"
"	const int sCell = Floor2Int(uv.s0 + .5f);\n"
"	const int tCell = Floor2Int(uv.s1 + .5f);\n"
"	// Return _insideDot_ result if point is inside dot\n"
"	if (Noise(sCell + .5f, tCell + .5f, .5f) > 0.f) {\n"
"		const float radius = .35f;\n"
"		const float maxShift = 0.5f - radius;\n"
"		const float sCenter = sCell + maxShift *\n"
"			Noise(sCell + 1.5f, tCell + 2.8f, .5f);\n"
"		const float tCenter = tCell + maxShift *\n"
"			Noise(sCell + 4.5f, tCell + 9.8f, .5f);\n"
"		const float ds = uv.s0 - sCenter, dt = uv.s1 - tCenter;\n"
"		if (ds * ds + dt * dt < radius * radius) {\n"
"			texValues[(*texValuesSize)++] = value1;\n"
"			return;\n"
"		}\n"
"	}\n"
"\n"
"	texValues[(*texValuesSize)++] = value2;\n"
"}\n"
"\n"
"void DotsTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(dudv1, dudv2);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Brick texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_BRICK)\n"
"\n"
"bool BrickTexture_RunningAlternate(__global Texture *texture, const float3 p, float3 *i, float3 *b,\n"
"		int nWhole) {\n"
"	const float run = texture->brick.run;\n"
"	const float mortarwidth = texture->brick.mortarwidth;\n"
"	const float mortarheight = texture->brick.mortarheight;\n"
"	const float mortardepth = texture->brick.mortardepth;\n"
"\n"
"	const float sub = nWhole + 0.5f;\n"
"	const float rsub = ceil(sub);\n"
"	(*i).z = floor(p.z);\n"
"	(*b).x = (p.x + (*i).z * run) / sub;\n"
"	(*b).y = (p.y + (*i).z * run) / sub;\n"
"	(*i).x = floor((*b).x);\n"
"	(*i).y = floor((*b).y);\n"
"	(*b).x = ((*b).x - (*i).x) * sub;\n"
"	(*b).y = ((*b).y - (*i).y) * sub;\n"
"	(*b).z = (p.z - (*i).z) * sub;\n"
"	(*i).x += floor((*b).x) / rsub;\n"
"	(*i).y += floor((*b).y) / rsub;\n"
"	(*b).x -= floor((*b).x);\n"
"	(*b).y -= floor((*b).y);\n"
"	return (*b).z > mortarheight && (*b).y > mortardepth &&\n"
"		(*b).x > mortarwidth;\n"
"}\n"
"\n"
"bool BrickTexture_Basket(__global Texture *texture, const float3 p, float3 *i) {\n"
"	const float mortarwidth = texture->brick.mortarwidth;\n"
"	const float mortardepth = texture->brick.mortardepth;\n"
"	const float proportion = texture->brick.proportion;\n"
"	const float invproportion = texture->brick.invproportion;\n"
"\n"
"	(*i).x = floor(p.x);\n"
"	(*i).y = floor(p.y);\n"
"	float bx = p.x - (*i).x;\n"
"	float by = p.y - (*i).y;\n"
"	(*i).x += (*i).y - 2.f * floor(0.5f * (*i).y);\n"
"	const bool split = ((*i).x - 2.f * floor(0.5f * (*i).x)) < 1.f;\n"
"	if (split) {\n"
"		bx = fmod(bx, invproportion);\n"
"		(*i).x = floor(proportion * p.x) * invproportion;\n"
"	} else {\n"
"		by = fmod(by, invproportion);\n"
"		(*i).y = floor(proportion * p.y) * invproportion;\n"
"	}\n"
"	return by > mortardepth && bx > mortarwidth;\n"
"}\n"
"\n"
"bool BrickTexture_Herringbone(__global Texture *texture, const float3 p, float3 *i) {\n"
"	const float mortarwidth = texture->brick.mortarwidth;\n"
"	const float mortarheight = texture->brick.mortarheight;\n"
"	const float proportion = texture->brick.proportion;\n"
"	const float invproportion = texture->brick.invproportion;\n"
"\n"
"	(*i).y = floor(proportion * p.y);\n"
"	const float px = p.x + (*i).y * invproportion;\n"
"	(*i).x = floor(px);\n"
"	float bx = 0.5f * px - floor(px * 0.5f);\n"
"	bx *= 2.f;\n"
"	float by = proportion * p.y - floor(proportion * p.y);\n"
"	by *= invproportion;\n"
"	if (bx > 1.f + invproportion) {\n"
"		bx = proportion * (bx - 1.f);\n"
"		(*i).y -= floor(bx - 1.f);\n"
"		bx -= floor(bx);\n"
"		bx *= invproportion;\n"
"		by = 1.f;\n"
"	} else if (bx > 1.f) {\n"
"		bx = proportion * (bx - 1.f);\n"
"		(*i).y -= floor(bx - 1.f);\n"
"		bx -= floor(bx);\n"
"		bx *= invproportion;\n"
"	}\n"
"	return by > mortarheight && bx > mortarwidth;\n"
"}\n"
"\n"
"bool BrickTexture_Running(__global Texture *texture, const float3 p, float3 *i, float3 *b) {\n"
"	const float run = texture->brick.run;\n"
"	const float mortarwidth = texture->brick.mortarwidth;\n"
"	const float mortarheight = texture->brick.mortarheight;\n"
"	const float mortardepth = texture->brick.mortardepth;\n"
"\n"
"	(*i).z = floor(p.z);\n"
"	(*b).x = p.x + (*i).z * run;\n"
"	(*b).y = p.y - (*i).z * run;\n"
"	(*i).x = floor((*b).x);\n"
"	(*i).y = floor((*b).y);\n"
"	(*b).z = p.z - (*i).z;\n"
"	(*b).x -= (*i).x;\n"
"	(*b).y -= (*i).y;\n"
"	return (*b).z > mortarheight && (*b).y > mortardepth &&\n"
"		(*b).x > mortarwidth;\n"
"}\n"
"\n"
"bool BrickTexture_English(__global Texture *texture, const float3 p, float3 *i, float3 *b) {\n"
"	const float run = texture->brick.run;\n"
"	const float mortarwidth = texture->brick.mortarwidth;\n"
"	const float mortarheight = texture->brick.mortarheight;\n"
"	const float mortardepth = texture->brick.mortardepth;\n"
"\n"
"	(*i).z = floor(p.z);\n"
"	(*b).x = p.x + (*i).z * run;\n"
"	(*b).y = p.y - (*i).z * run;\n"
"	(*i).x = floor((*b).x);\n"
"	(*i).y = floor((*b).y);\n"
"	(*b).z = p.z - (*i).z;\n"
"	const float divider = floor(fmod(fabs((*i).z), 2.f)) + 1.f;\n"
"	(*b).x = (divider * (*b).x - floor(divider * (*b).x)) / divider;\n"
"	(*b).y = (divider * (*b).y - floor(divider * (*b).y)) / divider;\n"
"	return (*b).z > mortarheight && (*b).y > mortardepth &&\n"
"		(*b).x > mortarwidth;\n"
"}\n"
"\n"
"bool BrickTexture_Evaluate(__global Texture *texture, __global HitPoint *hitPoint) {\n"
"#define BRICK_EPSILON 1e-3f\n"
"	const float3 P = TextureMapping3D_Map(&texture->brick.mapping, hitPoint);\n"
"\n"
"	const float offs = BRICK_EPSILON + texture->brick.mortarsize;\n"
"	float3 bP = P + (float3)(offs, offs, offs);\n"
"\n"
"	// Normalize coordinates according brick dimensions\n"
"	bP.x /= texture->brick.brickwidth;\n"
"	bP.y /= texture->brick.brickdepth;\n"
"	bP.z /= texture->brick.brickheight;\n"
"\n"
"	bP += VLOAD3F(&texture->brick.offsetx);\n"
"\n"
"	float3 brickIndex;\n"
"	float3 bevel;\n"
"	bool b;\n"
"	switch (texture->brick.bond) {\n"
"		case FLEMISH:\n"
"			b = BrickTexture_RunningAlternate(texture, bP, &brickIndex, &bevel, 1);\n"
"			break;\n"
"		case RUNNING:\n"
"			b = BrickTexture_Running(texture, bP, &brickIndex, &bevel);\n"
"			break;\n"
"		case ENGLISH:\n"
"			b = BrickTexture_English(texture, bP, &brickIndex, &bevel);\n"
"			break;\n"
"		case HERRINGBONE:\n"
"			b = BrickTexture_Herringbone(texture, bP, &brickIndex);\n"
"			break;\n"
"		case BASKET:\n"
"			b = BrickTexture_Basket(texture, bP, &brickIndex);\n"
"			break;\n"
"		case KETTING:\n"
"			b = BrickTexture_RunningAlternate(texture, bP, &brickIndex, &bevel, 2);\n"
"			break; \n"
"		default:\n"
"			b = true;\n"
"			break;\n"
"	}\n"
"\n"
"	return b;\n"
"#undef BRICK_EPSILON\n"
"}\n"
"\n"
"void BrickTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value1 = texValues[--(*texValuesSize)];\n"
"	const float value2 = texValues[--(*texValuesSize)];\n"
"	const float value3 = texValues[--(*texValuesSize)];\n"
"\n"
"	if (BrickTexture_Evaluate(texture, hitPoint))\n"
"		texValues[(*texValuesSize)++] = value1 * value3;\n"
"	else\n"
"		texValues[(*texValuesSize)++] = value2;\n"
"}\n"
"\n"
"void BrickTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value1 = texValues[--(*texValuesSize)];\n"
"	const float3 value2 = texValues[--(*texValuesSize)];\n"
"	const float3 value3 = texValues[--(*texValuesSize)];\n"
"\n"
"	if (BrickTexture_Evaluate(texture, hitPoint))\n"
"		texValues[(*texValuesSize)++] = value1 * value3;\n"
"	else\n"
"		texValues[(*texValuesSize)++] = value2;\n"
"}\n"
"\n"
"void BrickTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv3 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(fmax(dudv1, dudv2), dudv3);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Add texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_ADD)\n"
"\n"
"void AddTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float value = texValues[--(*texValuesSize)] + texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = value;\n"
"}\n"
"\n"
"void AddTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 value = texValues[--(*texValuesSize)] + texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = value;\n"
"}\n"
"\n"
"void AddTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 dudv1 = texValues[--(*texValuesSize)];\n"
"	const float2 dudv2 = texValues[--(*texValuesSize)];\n"
"\n"
"	texValues[(*texValuesSize)++] = fmax(dudv1, dudv2);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Windy texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_WINDY)\n"
"\n"
"void WindyTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->windy.mapping, hitPoint);\n"
"\n"
"	const float windStrength = FBm(.1f * mapP, .5f, 3);\n"
"	const float waveHeight = FBm(mapP, .5f, 6);\n"
"\n"
"	texValues[(*texValuesSize)++] = fabs(windStrength) * waveHeight;\n"
"}\n"
"\n"
"void WindyTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->windy.mapping, hitPoint);\n"
"\n"
"	const float windStrength = FBm(.1f * mapP, .5f, 3);\n"
"	const float waveHeight = FBm(mapP, .5f, 6);\n"
"\n"
"	texValues[(*texValuesSize)++] = fabs(windStrength) * waveHeight;\n"
"}\n"
"\n"
"void WindyTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = (float2)(DUDV_VALUE, DUDV_VALUE);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Wrinkled texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_WRINKLED)\n"
"\n"
"void WrinkledTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->wrinkled.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = Turbulence(mapP, texture->wrinkled.omega, texture->wrinkled.octaves);\n"
"}\n"
"\n"
"void WrinkledTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float3 mapP = TextureMapping3D_Map(&texture->wrinkled.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = Turbulence(mapP, texture->wrinkled.omega, texture->wrinkled.octaves);\n"
"}\n"
"\n"
"void WrinkledTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = (float2)(DUDV_VALUE, DUDV_VALUE);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// UV texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_UV)\n"
"\n"
"void UVTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 uv = TextureMapping2D_Map(&texture->uvTex.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = Spectrum_Y((float3)(uv.s0 - Floor2Int(uv.s0), uv.s1 - Floor2Int(uv.s1), 0.f));\n"
"}\n"
"\n"
"void UVTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float2 uv = TextureMapping2D_Map(&texture->uvTex.mapping, hitPoint);\n"
"\n"
"	texValues[(*texValuesSize)++] = (float3)(uv.s0 - Floor2Int(uv.s0), uv.s1 - Floor2Int(uv.s1), 0.f);\n"
"}\n"
"\n"
"void UVTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = (float2)(DUDV_VALUE, DUDV_VALUE);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Band texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_BAND)\n"
"\n"
"void BandTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float a = clamp(texValues[--(*texValuesSize)], 0.f, 1.f);\n"
"\n"
"	const uint last = texture->band.size - 1;\n"
"	if (a < texture->band.offsets[0])\n"
"		texValues[(*texValuesSize)++] = Spectrum_Y(VLOAD3F(&texture->band.values[0].r));\n"
"	else if (a >= texture->band.offsets[last])\n"
"		texValues[(*texValuesSize)++] = Spectrum_Y(VLOAD3F(&texture->band.values[last].r));\n"
"	else {\n"
"		uint p = 0;\n"
"		for (; p <= last; ++p) {\n"
"			if (a < texture->band.offsets[p])\n"
"				break;\n"
"		}\n"
"\n"
"		const float p1 = Spectrum_Y(VLOAD3F(&texture->band.values[p - 1].r));\n"
"		const float p0 = Spectrum_Y(VLOAD3F(&texture->band.values[p].r));\n"
"		const float o1 = texture->band.offsets[p - 1];\n"
"		const float o0 = texture->band.offsets[p];\n"
"		texValues[(*texValuesSize)++] = Lerp((a - o1) / (o0 - o1), p1, p0);\n"
"	}\n"
"}\n"
"\n"
"void BandTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float a = clamp(Spectrum_Y(texValues[--(*texValuesSize)]), 0.f, 1.f);\n"
"\n"
"	const uint last = texture->band.size - 1;\n"
"	if (a < texture->band.offsets[0])\n"
"		texValues[(*texValuesSize)++] = VLOAD3F(&texture->band.values[0].r);\n"
"	else if (a >= texture->band.offsets[last])\n"
"		texValues[(*texValuesSize)++] = VLOAD3F(&texture->band.values[last].r);\n"
"	else {\n"
"		uint p = 0;\n"
"		for (; p <= last; ++p) {\n"
"			if (a < texture->band.offsets[p])\n"
"				break;\n"
"		}\n"
"\n"
"		const float3 p1 = VLOAD3F(&texture->band.values[p - 1].r);\n"
"		const float3 p0 = VLOAD3F(&texture->band.values[p].r);\n"
"		const float o1 = texture->band.offsets[p - 1];\n"
"		const float o0 = texture->band.offsets[p];\n"
"		texValues[(*texValuesSize)++] = Lerp3((a - o1) / (o0 - o1), p1, p0);\n"
"	}\n"
"}\n"
"\n"
"void BandTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	// Nothing to do:\n"
"	//const float2 dudv = texValues[--(*texValuesSize)];\n"
"	//texValues[(*texValuesSize)++] = dudv;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// HitPointColor texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTCOLOR)\n"
"\n"
"void HitPointColorTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = Spectrum_Y(VLOAD3F(&hitPoint->color.r));\n"
"}\n"
"\n"
"void HitPointColorTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = VLOAD3F(&hitPoint->color.r);\n"
"}\n"
"\n"
"void HitPointColorTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = 0.f;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// HitPointAlpha texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTALPHA)\n"
"\n"
"void HitPointAlphaTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = hitPoint->alpha;\n"
"}\n"
"\n"
"void HitPointAlphaTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const float alpha = hitPoint->alpha;\n"
"	texValues[(*texValuesSize)++] = (float3)(alpha, alpha, alpha);\n"
"}\n"
"\n"
"void HitPointAlphaTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = 0.f;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// HitPointGrey texture\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTGREY)\n"
"\n"
"void HitPointGreyTexture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const uint channel = texture->hitPointGrey.channel;\n"
"	switch (channel) {\n"
"		case 0:\n"
"			texValues[*texValuesSize] = hitPoint->color.r;\n"
"			break;\n"
"		case 1:\n"
"			texValues[*texValuesSize] = hitPoint->color.g;\n"
"			break;\n"
"		case 2:\n"
"			texValues[*texValuesSize] = hitPoint->color.b;\n"
"			break;\n"
"		default:\n"
"			texValues[*texValuesSize] = Spectrum_Y(VLOAD3F(&hitPoint->color.r));\n"
"			break;\n"
"	}\n"
"\n"
"	++(*texValuesSize);\n"
"}\n"
"\n"
"void HitPointGreyTexture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	const uint channel = texture->hitPointGrey.channel;\n"
"	float v;\n"
"	switch (channel) {\n"
"		case 0:\n"
"			v = hitPoint->color.r;\n"
"			break;\n"
"		case 1:\n"
"			v = hitPoint->color.g;\n"
"			break;\n"
"		case 2:\n"
"			v = hitPoint->color.b;\n"
"			break;\n"
"		default:\n"
"			v = Spectrum_Y(VLOAD3F(&hitPoint->color.r));\n"
"			break;\n"
"	}\n"
"\n"
"	texValues[(*texValuesSize)++] = (float3)(v, v, v);\n"
"}\n"
"\n"
"void HitPointGreyTexture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize) {\n"
"	texValues[(*texValuesSize)++] = 0.f;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Generic texture functions with support for recursive textures\n"
"//------------------------------------------------------------------------------\n"
"\n"
"uint Texture_AddSubTexture(__global Texture *texture,\n"
"		__global Texture *todoTex[TEXTURE_STACK_SIZE], uint *todoTexSize\n"
"		TEXTURES_PARAM_DECL) {\n"
"	switch (texture->type) {\n"
"#if defined(PARAM_ENABLE_TEX_SCALE)\n"
"		case SCALE_TEX:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->scaleTex.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->scaleTex.tex2Index];\n"
"			return 2;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_N)\n"
"		case FRESNEL_APPROX_N:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->fresnelApproxN.texIndex];\n"
"			return 1;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_K)\n"
"		case FRESNEL_APPROX_K:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->fresnelApproxK.texIndex];\n"
"			return 1;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_CHECKERBOARD2D)\n"
"		case CHECKERBOARD2D:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->checkerBoard2D.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->checkerBoard2D.tex2Index];\n"
"			return 2;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_CHECKERBOARD3D)\n"
"		case CHECKERBOARD3D:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->checkerBoard3D.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->checkerBoard3D.tex2Index];\n"
"			return 2;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_MIX)\n"
"		case MIX_TEX:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->mixTex.amountTexIndex];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->mixTex.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->mixTex.tex2Index];\n"
"			return 3;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_DOTS)\n"
"		case DOTS:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->dots.insideIndex];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->dots.outsideIndex];\n"
"			return 2;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_BRICK)\n"
"		case BRICK:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->brick.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->brick.tex2Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->brick.tex3Index];\n"
"			return 3;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_ADD)\n"
"		case ADD_TEX:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->addTex.tex1Index];\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->addTex.tex2Index];\n"
"			return 2;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_BAND)\n"
"		case BAND_TEX:\n"
"			todoTex[(*todoTexSize)++] = &texs[texture->band.amountTexIndex];\n"
"			return 1;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTGREY)\n"
"		case HITPOINTGREY:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTALPHA)\n"
"		case HITPOINTALPHA:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_HITPOINTCOLOR)\n"
"		case HITPOINTCOLOR:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_UV)\n"
"		case UV_TEX:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_WRINKLED)\n"
"		case WRINKLED:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_WINDY)\n"
"		case WINDY:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_MARBLE)\n"
"		case MARBLE:\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FBM_TEX)\n"
"		case FBM_TEX:\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT)\n"
"		case CONST_FLOAT:\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT3)\n"
"		case CONST_FLOAT3:\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_IMAGEMAP)\n"
"		case IMAGEMAP:\n"
"#endif\n"
"		default:\n"
"			return 0;\n"
"	}\n"
"}\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Float texture channel\n"
"//------------------------------------------------------------------------------\n"
"\n"
"void Texture_EvaluateFloat(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float texValues[TEXTURE_STACK_SIZE], uint *texValuesSize\n"
"		IMAGEMAPS_PARAM_DECL) {\n"
"	switch (texture->type) {\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT)\n"
"		case CONST_FLOAT:\n"
"			ConstFloatTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT3)\n"
"		case CONST_FLOAT3:\n"
"			ConstFloat3Texture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_IMAGEMAP)\n"
"		case IMAGEMAP:\n"
"			ImageMapTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize\n"
"					IMAGEMAPS_PARAM);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_SCALE)\n"
"		case SCALE_TEX:\n"
"			ScaleTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_N)\n"
"		case FRESNEL_APPROX_N:\n"
"			FresnelApproxNTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_K)\n"
"		case FRESNEL_APPROX_K:\n"
"			FresnelApproxKTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD2D)\n"
"		case CHECKERBOARD2D:\n"
"			CheckerBoard2DTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD3D)\n"
"		case CHECKERBOARD3D:\n"
"			CheckerBoard3DTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_MIX)\n"
"		case MIX_TEX:\n"
"			MixTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FBM_TEX)\n"
"		case FBM_TEX:\n"
"			FBMTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_MARBLE)\n"
"		case MARBLE:\n"
"			MarbleTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_DOTS)\n"
"		case DOTS:\n"
"			DotsTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_BRICK)\n"
"		case BRICK:\n"
"			BrickTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_ADD)\n"
"		case ADD_TEX:\n"
"			AddTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WINDY)\n"
"		case WINDY:\n"
"			WindyTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WRINKLED)\n"
"		case WRINKLED:\n"
"			WrinkledTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_UV)\n"
"		case UV_TEX:\n"
"			UVTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_BAND)\n"
"		case BAND_TEX:\n"
"			BandTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTCOLOR)\n"
"		case HITPOINTCOLOR:\n"
"			HitPointColorTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTALPHA)\n"
"		case HITPOINTALPHA:\n"
"			HitPointAlphaTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTGREY)\n"
"		case HITPOINTGREY:\n"
"			HitPointGreyTexture_EvaluateFloat(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"		default:\n"
"			// Do nothing\n"
"			break;\n"
"	}\n"
"}\n"
"\n"
"float Texture_GetFloatValue(__global Texture *texture, __global HitPoint *hitPoint\n"
"		TEXTURES_PARAM_DECL) {\n"
"	__global Texture *todoTex[TEXTURE_STACK_SIZE];\n"
"	uint todoTexSize = 0;\n"
"\n"
"	__global Texture *pendingTex[TEXTURE_STACK_SIZE];\n"
"	uint targetTexCount[TEXTURE_STACK_SIZE];\n"
"	uint pendingTexSize = 0;\n"
"\n"
"	float texValues[TEXTURE_STACK_SIZE];\n"
"	uint texValuesSize = 0;\n"
"\n"
"	const uint subTexCount = Texture_AddSubTexture(texture, todoTex, &todoTexSize\n"
"			TEXTURES_PARAM);\n"
"	if (subTexCount == 0) {\n"
"		// A fast path for evaluating non recursive textures\n"
"		Texture_EvaluateFloat(texture, hitPoint, texValues, &texValuesSize\n"
"			IMAGEMAPS_PARAM);\n"
"	} else {\n"
"		// Normal complex path for evaluating non recursive textures\n"
"		pendingTex[pendingTexSize] = texture;\n"
"		targetTexCount[pendingTexSize++] = subTexCount;\n"
"		do {\n"
"			if ((pendingTexSize > 0) && (texValuesSize == targetTexCount[pendingTexSize - 1])) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = pendingTex[--pendingTexSize];\n"
"\n"
"				Texture_EvaluateFloat(tex, hitPoint, texValues, &texValuesSize\n"
"						IMAGEMAPS_PARAM);\n"
"				continue;\n"
"			}\n"
"\n"
"			if (todoTexSize > 0) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = todoTex[--todoTexSize];\n"
"\n"
"				// Add this texture to the list of pending one\n"
"				const uint subTexCount = Texture_AddSubTexture(tex, todoTex, &todoTexSize\n"
"						TEXTURES_PARAM);\n"
"				pendingTex[pendingTexSize] = tex;\n"
"				targetTexCount[pendingTexSize++] = subTexCount + texValuesSize;\n"
"			}\n"
"		} while ((todoTexSize > 0) || (pendingTexSize > 0));\n"
"	}\n"
"\n"
"	return texValues[0];\n"
"}\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// Color texture channel\n"
"//------------------------------------------------------------------------------\n"
"\n"
"void Texture_EvaluateSpectrum(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float3 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize\n"
"		IMAGEMAPS_PARAM_DECL) {\n"
"	switch (texture->type) {\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT)\n"
"		case CONST_FLOAT:\n"
"			ConstFloatTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT3)\n"
"		case CONST_FLOAT3:\n"
"			ConstFloat3Texture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_IMAGEMAP)\n"
"		case IMAGEMAP:\n"
"			ImageMapTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize\n"
"					IMAGEMAPS_PARAM);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_SCALE)\n"
"		case SCALE_TEX:\n"
"			ScaleTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_N)\n"
"		case FRESNEL_APPROX_N:\n"
"			FresnelApproxNTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_K)\n"
"		case FRESNEL_APPROX_K:\n"
"			FresnelApproxKTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD2D)\n"
"		case CHECKERBOARD2D:\n"
"			CheckerBoard2DTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD3D)\n"
"		case CHECKERBOARD3D:\n"
"			CheckerBoard3DTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_MIX)\n"
"		case MIX_TEX:\n"
"			MixTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FBM_TEX)\n"
"		case FBM_TEX:\n"
"			FBMTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_MARBLE)\n"
"		case MARBLE:\n"
"			MarbleTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_DOTS)\n"
"		case DOTS:\n"
"			DotsTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_BRICK)\n"
"		case BRICK:\n"
"			BrickTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_ADD)\n"
"		case ADD_TEX:\n"
"			AddTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WINDY)\n"
"		case WINDY:\n"
"			WindyTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WRINKLED)\n"
"		case WRINKLED:\n"
"			WrinkledTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_UV)\n"
"		case UV_TEX:\n"
"			UVTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_BAND)\n"
"		case BAND_TEX:\n"
"			BandTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTCOLOR)\n"
"		case HITPOINTCOLOR:\n"
"			HitPointColorTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTALPHA)\n"
"		case HITPOINTALPHA:\n"
"			HitPointAlphaTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTGREY)\n"
"		case HITPOINTGREY:\n"
"			HitPointGreyTexture_EvaluateSpectrum(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"		default:\n"
"			// Do nothing\n"
"			break;\n"
"	}\n"
"}\n"
"\n"
"float3 Texture_GetSpectrumValue(__global Texture *texture, __global HitPoint *hitPoint\n"
"		TEXTURES_PARAM_DECL) {\n"
"	__global Texture *todoTex[TEXTURE_STACK_SIZE];\n"
"	uint todoTexSize = 0;\n"
"\n"
"	__global Texture *pendingTex[TEXTURE_STACK_SIZE];\n"
"	uint targetTexCount[TEXTURE_STACK_SIZE];\n"
"	uint pendingTexSize = 0;\n"
"\n"
"	float3 texValues[TEXTURE_STACK_SIZE];\n"
"	uint texValuesSize = 0;\n"
"\n"
"	const uint subTexCount = Texture_AddSubTexture(texture, todoTex, &todoTexSize\n"
"			TEXTURES_PARAM);\n"
"	if (subTexCount == 0) {\n"
"		// A fast path for evaluating non recursive textures\n"
"		Texture_EvaluateSpectrum(texture, hitPoint, texValues, &texValuesSize\n"
"			IMAGEMAPS_PARAM);\n"
"	} else {\n"
"		// Normal complex path for evaluating non recursive textures\n"
"		pendingTex[pendingTexSize] = texture;\n"
"		targetTexCount[pendingTexSize++] = subTexCount;\n"
"		do {\n"
"			if ((pendingTexSize > 0) && (texValuesSize == targetTexCount[pendingTexSize - 1])) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = pendingTex[--pendingTexSize];\n"
"\n"
"				Texture_EvaluateSpectrum(tex, hitPoint, texValues, &texValuesSize\n"
"						IMAGEMAPS_PARAM);\n"
"				continue;\n"
"			}\n"
"\n"
"			if (todoTexSize > 0) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = todoTex[--todoTexSize];\n"
"\n"
"				// Add this texture to the list of pending one\n"
"				const uint subTexCount = Texture_AddSubTexture(tex, todoTex, &todoTexSize\n"
"						TEXTURES_PARAM);\n"
"				pendingTex[pendingTexSize] = tex;\n"
"				targetTexCount[pendingTexSize++] = subTexCount + texValuesSize;\n"
"			}\n"
"		} while ((todoTexSize > 0) || (pendingTexSize > 0));\n"
"	}\n"
"\n"
"	return texValues[0];\n"
"}\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// DuDv texture information\n"
"//------------------------------------------------------------------------------\n"
"\n"
"void Texture_EvaluateDuDv(__global Texture *texture, __global HitPoint *hitPoint,\n"
"		float2 texValues[TEXTURE_STACK_SIZE], uint *texValuesSize\n"
"		IMAGEMAPS_PARAM_DECL) {\n"
"	switch (texture->type) {\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT)\n"
"		case CONST_FLOAT:\n"
"			ConstFloatTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_CONST_FLOAT3)\n"
"		case CONST_FLOAT3:\n"
"			ConstFloat3Texture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_IMAGEMAP)\n"
"		case IMAGEMAP:\n"
"			ImageMapTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_SCALE)\n"
"		case SCALE_TEX:\n"
"			ScaleTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_N)\n"
"		case FRESNEL_APPROX_N:\n"
"			FresnelApproxNTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FRESNEL_APPROX_K)\n"
"		case FRESNEL_APPROX_K:\n"
"			FresnelApproxKTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD2D)\n"
"		case CHECKERBOARD2D:\n"
"			CheckerBoard2DTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_CHECKERBOARD3D)\n"
"		case CHECKERBOARD3D:\n"
"			CheckerBoard3DTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_TEX_MIX)\n"
"		case MIX_TEX:\n"
"			MixTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_FBM_TEX)\n"
"		case FBM_TEX:\n"
"			FBMTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_MARBLE)\n"
"		case MARBLE:\n"
"			MarbleTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_DOTS)\n"
"		case DOTS:\n"
"			DotsTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined (PARAM_ENABLE_BRICK)\n"
"		case BRICK:\n"
"			BrickTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_ADD)\n"
"		case ADD_TEX:\n"
"			AddTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WINDY)\n"
"		case WINDY:\n"
"			WindyTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_WRINKLED)\n"
"		case WRINKLED:\n"
"			WrinkledTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_UV)\n"
"		case UV_TEX:\n"
"			UVTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_BAND)\n"
"		case BAND_TEX:\n"
"			BandTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTCOLOR)\n"
"		case HITPOINTCOLOR:\n"
"			HitPointColorTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTALPHA)\n"
"		case HITPOINTALPHA:\n"
"			HitPointAlphaTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"#if defined(PARAM_ENABLE_TEX_HITPOINTGREY)\n"
"		case HITPOINTGREY:\n"
"			HitPointGreyTexture_EvaluateDuDv(texture, hitPoint, texValues, texValuesSize);\n"
"			break;\n"
"#endif\n"
"		default:\n"
"			// Do nothing\n"
"			break;\n"
"	}\n"
"}\n"
"\n"
"float2 Texture_GetDuDv(__global Texture *texture, __global HitPoint *hitPoint\n"
"		TEXTURES_PARAM_DECL) {\n"
"	__global Texture *todoTex[TEXTURE_STACK_SIZE];\n"
"	uint todoTexSize = 0;\n"
"\n"
"	__global Texture *pendingTex[TEXTURE_STACK_SIZE];\n"
"	uint targetTexCount[TEXTURE_STACK_SIZE];\n"
"	uint pendingTexSize = 0;\n"
"\n"
"	float2 texValues[TEXTURE_STACK_SIZE];\n"
"	uint texValuesSize = 0;\n"
"\n"
"	const uint subTexCount = Texture_AddSubTexture(texture, todoTex, &todoTexSize\n"
"			TEXTURES_PARAM);\n"
"	if (subTexCount == 0) {\n"
"		// A fast path for evaluating non recursive textures\n"
"		Texture_EvaluateDuDv(texture, hitPoint, texValues, &texValuesSize\n"
"			IMAGEMAPS_PARAM);\n"
"	} else {\n"
"		// Normal complex path for evaluating non recursive textures\n"
"		pendingTex[pendingTexSize] = texture;\n"
"		targetTexCount[pendingTexSize++] = subTexCount;\n"
"		do {\n"
"			if ((pendingTexSize > 0) && (texValuesSize == targetTexCount[pendingTexSize - 1])) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = pendingTex[--pendingTexSize];\n"
"\n"
"				Texture_EvaluateDuDv(tex, hitPoint, texValues, &texValuesSize\n"
"						IMAGEMAPS_PARAM);\n"
"				continue;\n"
"			}\n"
"\n"
"			if (todoTexSize > 0) {\n"
"				// Pop the a texture to do\n"
"				__global Texture *tex = todoTex[--todoTexSize];\n"
"\n"
"				// Add this texture to the list of pending one\n"
"				const uint subTexCount = Texture_AddSubTexture(tex, todoTex, &todoTexSize\n"
"						TEXTURES_PARAM);\n"
"				pendingTex[pendingTexSize] = tex;\n"
"				targetTexCount[pendingTexSize++] = subTexCount + texValuesSize;\n"
"			}\n"
"		} while ((todoTexSize > 0) || (pendingTexSize > 0));\n"
"	}\n"
"\n"
"	return texValues[0];\n"
"}\n"
; } }
