text: #include <string>
  namespace slg { namespace ocl {
  std::string KernelSource_texture_bump_funcs = 
  "#line 2 \"texture_bump_funcs.cl\"\n"
  "\n"
  "/***************************************************************************\n"
  " * Copyright 1998-2015 by authors (see AUTHORS.txt)                        *\n"
  " *                                                                         *\n"
  " *   This file is part of LuxRender.                                       *\n"
  " *                                                                         *\n"
  " * Licensed under the Apache License, Version 2.0 (the \"License\");         *\n"
  " * you may not use this file except in compliance with the License.        *\n"
  " * You may obtain a copy of the License at                                 *\n"
  " *                                                                         *\n"
  " *     http://www.apache.org/licenses/LICENSE-2.0                          *\n"
  " *                                                                         *\n"
  " * Unless required by applicable law or agreed to in writing, software     *\n"
  " * distributed under the License is distributed on an \"AS IS\" BASIS,       *\n"
  " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.*\n"
  " * See the License for the specific language governing permissions and     *\n"
  " * limitations under the License.                                          *\n"
  " ***************************************************************************/\n"
  "\n"
  "//------------------------------------------------------------------------------\n"
  "// Duv texture information\n"
  "//------------------------------------------------------------------------------\n"
  "\n"
  "#if defined(PARAM_HAS_BUMPMAPS)\n"
  "\n"
  "float2 Texture_GetDuv(\n"
  "		const uint texIndex,\n"
  "		__global HitPoint *hitPoint,\n"
  "		const float sampleDistance\n"
  "		TEXTURES_PARAM_DECL) {\n"
  "	const float3 dpdu = VLOAD3F(&hitPoint->dpdu.x);\n"
  "	const float3 dpdv = VLOAD3F(&hitPoint->dpdv.x);\n"
  "	const float3 dndu = VLOAD3F(&hitPoint->dndu.x);\n"
  "	const float3 dndv = VLOAD3F(&hitPoint->dndv.x);\n"
  "\n"
  "	// Calculate bump map value at intersection point\n"
  "	const float base = Texture_GetFloatValue(texIndex, hitPoint\n"
  "			TEXTURES_PARAM);\n"
  "\n"
  "	// Compute offset positions and evaluate displacement texIndex\n"
  "	const float3 origP = VLOAD3F(&hitPoint->p.x);\n"
  "	const float3 origShadeN = VLOAD3F(&hitPoint->shadeN.x);\n"
  "	const float2 origUV = VLOAD2F(&hitPoint->uv.u);\n"
  "\n"
  "	float2 duv;\n"
  "\n"
  "	// Shift hitPointTmp.du in the u direction and calculate value\n"
  "	const float uu = sampleDistance / length(dpdu);\n"
  "	VSTORE3F(origP + uu * dpdu, &hitPoint->p.x);\n"
  "	hitPoint->uv.u += uu;\n"
  "	VSTORE3F(normalize(origShadeN + uu * dndu), &hitPoint->shadeN.x);\n"
  "	const float duValue = Texture_GetFloatValue(texIndex, hitPoint\n"
  "			TEXTURES_PARAM);\n"
  "	duv.s0 = (duValue - base) / uu;\n"
  "\n"
  "	// Shift hitPointTmp.dv in the v direction and calculate value\n"
  "	const float vv = sampleDistance / length(dpdv);\n"
  "	VSTORE3F(origP + vv * dpdv, &hitPoint->p.x);\n"
  "	hitPoint->uv.u = origUV.s0;\n"
  "	hitPoint->uv.v += vv;\n"
  "	VSTORE3F(normalize(origShadeN + vv * dndv), &hitPoint->shadeN.x);\n"
  "	const float dvValue = Texture_GetFloatValue(texIndex, hitPoint\n"
  "			TEXTURES_PARAM);\n"
  "	duv.s1 = (dvValue - base) / vv;\n"
  "\n"
  "	// Restore HitPoint\n"
  "	VSTORE3F(origP, &hitPoint->p.x);\n"
  "	VSTORE2F(origUV, &hitPoint->uv.u);\n"
  "	VSTORE3F(origShadeN, &hitPoint->shadeN.x);\n"
  "\n"
  "	return duv;\n"
  "}\n"
  "\n"
  "#if defined(PARAM_ENABLE_TEX_NORMALMAP)\n"
  "float2 NormalMapTexture_GetDuv(\n"
  "		const uint texIndex,\n"
  "		__global HitPoint *hitPoint,\n"
  "		const float sampleDistance\n"
  "		TEXTURES_PARAM_DECL) {\n"
  "	const float3 dpdu = VLOAD3F(&hitPoint->dpdu.x);\n"
  "	const float3 dpdv = VLOAD3F(&hitPoint->dpdv.x);\n"
  "	__global Texture *texture = &texs[texIndex];\n"
  "	float3 rgb = Texture_GetSpectrumValue(texture->normalMap.texIndex, hitPoint\n"
  "			TEXTURES_PARAM);\n"
  "	rgb = clamp(rgb, -1.f, 1.f);\n"
  "\n"
  "	// Normal from normal map\n"
  "	float3 n = 2.f * rgb - (float3)(1.f, 1.f, 1.f);\n"
  "\n"
  "	const float3 k = VLOAD3F(&hitPoint->shadeN.x);\n"
  "\n"
  "	// Transform n from tangent to object space\n"
  "	const float btsign = (dot(dpdv, k) > 0.f) ? 1.f : -1.f;\n"
  "\n"
  "	// Magnitude of btsign is the magnitude of the interpolated normal\n"
  "	const float3 kk = k * fabs(btsign);\n"
  "\n"
  "	// tangent -> object\n"
  "	n = normalize(n.x * dpdu + n.y * btsign * dpdv + n.z * kk);\n"
  "\n"
  "	// Since n is stored normalized in the normal map\n"
  "	// we need to recover the original length (lambda).\n"
  "	// We do this by solving \n"
  "	//   lambda*n = dp/du x dp/dv\n"
  "	// where \n"
  "	//   p(u,v) = base(u,v) + h(u,v) * k\n"
  "	// and\n"
  "	//   k = dbase/du x dbase/dv\n"
  "	//\n"
  "	// We recover lambda by dotting the above with k\n"
  "	//   k . lambda*n = k . (dp/du x dp/dv)\n"
  "	//   lambda = (k . k) / (k . n)\n"
  "	// \n"
  "	// We then recover dh/du by dotting the first eq by dp/du\n"
  "	//   dp/du . lambda*n = dp/du . (dp/du x dp/dv)\n"
  "	//   dp/du . lambda*n = dh/du * [dbase/du . (k x dbase/dv)]\n"
  "	//\n"
  "	// The term \"dbase/du . (k x dbase/dv)\" reduces to \"-(k . k)\", so we get\n"
  "	//   dp/du . lambda*n = dh/du * -(k . k)\n"
  "	//   dp/du . [(k . k) / (k . n)*n] = dh/du * -(k . k)\n"
  "	//   dp/du . [-n / (k . n)] = dh/du\n"
  "	// and similar for dh/dv\n"
  "	// \n"
  "	// Since the recovered dh/du will be in units of ||k||, we must divide\n"
  "	// by ||k|| to get normalized results. Using dg.nn as k in the last eq\n"
  "	// yields the same result.\n"
  "	const float3 nn = (-1.f / dot(k, n)) * n;\n"
  "\n"
  "	return (float2)(dot(dpdu, nn), dot(dpdv, nn));\n"
  "}\n"
  "#endif\n"
  "\n"
  "#endif\n"
  ; } }
  