#include <string>
namespace slg { namespace ocl {
std::string KernelSource_light_funcs = 
"#line 2 \"light_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"
"//------------------------------------------------------------------------------\n"
"// InfiniteLight\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined(PARAM_HAS_INFINITELIGHT)\n"
"\n"
"float3 InfiniteLight_GetRadiance(\n"
"	__global InfiniteLight *infiniteLight, const float3 dir\n"
"	IMAGEMAPS_PARAM_DECL) {\n"
"	__global ImageMap *imageMap = &imageMapDescs[infiniteLight->imageMapIndex];\n"
"	__global float *pixels = ImageMap_GetPixelsAddress(\n"
"			imageMapBuff, imageMap->pageIndex, imageMap->pixelsIndex);\n"
"\n"
"	const float3 localDir = normalize(Transform_InvApplyVector(&infiniteLight->light2World, -dir));\n"
"	const float2 uv = (float2)(\n"
"		SphericalPhi(localDir) * (1.f / (2.f * M_PI_F)),\n"
"		SphericalTheta(localDir) * M_1_PI_F);\n"
"\n"
"	// TextureMapping2D_Map() is expendaded here\n"
"	const float2 scale = VLOAD2F(&infiniteLight->mapping.uvMapping2D.uScale);\n"
"	const float2 delta = VLOAD2F(&infiniteLight->mapping.uvMapping2D.uDelta);\n"
"	const float2 mapUV = uv * scale + delta;\n"
"	\n"
"	return VLOAD3F(&infiniteLight->gain.r) * ImageMap_GetSpectrum(\n"
"			pixels,\n"
"			imageMap->width, imageMap->height, imageMap->channelCount,\n"
"			mapUV.s0, mapUV.s1);\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// SktLight\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined(PARAM_HAS_SKYLIGHT)\n"
"\n"
"float SkyLight_PerezBase(__global float *lam, const float theta, const float gamma) {\n"
"	return (1.f + lam[1] * exp(lam[2] / cos(theta))) *\n"
"		(1.f + lam[3] * exp(lam[4] * gamma)  + lam[5] * cos(gamma) * cos(gamma));\n"
"}\n"
"\n"
"float SkyLight_RiAngleBetween(const float thetav, const float phiv, const float theta, const float phi) {\n"
"	const float cospsi = sin(thetav) * sin(theta) * cos(phi - phiv) + cos(thetav) * cos(theta);\n"
"	if (cospsi >= 1.f)\n"
"		return 0.f;\n"
"	if (cospsi <= -1.f)\n"
"		return M_PI_F;\n"
"	return acos(cospsi);\n"
"}\n"
"\n"
"float3 SkyLight_ChromaticityToSpectrum(float Y, float x, float y) {\n"
"	float X, Z;\n"
"	\n"
"	if (y != 0.f)\n"
"		X = (x / y) * Y;\n"
"	else\n"
"		X = 0.f;\n"
"	\n"
"	if (y != 0.f && Y != 0.f)\n"
"		Z = (1.f - x - y) / y * Y;\n"
"	else\n"
"		Z = 0.f;\n"
"\n"
"	// Assuming sRGB (D65 illuminant)\n"
"	return (float3)(3.2410f * X - 1.5374f * Y - 0.4986f * Z,\n"
"			-0.9692f * X + 1.8760f * Y + 0.0416f * Z,\n"
"			0.0556f * X - 0.2040f * Y + 1.0570f * Z);\n"
"}\n"
"\n"
"float3 SkyLight_GetSkySpectralRadiance(__global SkyLight *skyLight,\n"
"		const float theta, const float phi) {\n"
"	// Add bottom half of hemisphere with horizon colour\n"
"	const float theta_fin = fmin(theta, (M_PI_F * .5f) - .001f);\n"
"	const float gamma = SkyLight_RiAngleBetween(theta, phi, skyLight->thetaS, skyLight->phiS);\n"
"\n"
"	// Compute xyY values\n"
"	const float x = skyLight->zenith_x * SkyLight_PerezBase(skyLight->perez_x, theta_fin, gamma);\n"
"	const float y = skyLight->zenith_y * SkyLight_PerezBase(skyLight->perez_y, theta_fin, gamma);\n"
"	const float Y = skyLight->zenith_Y * SkyLight_PerezBase(skyLight->perez_Y, theta_fin, gamma);\n"
"\n"
"	return SkyLight_ChromaticityToSpectrum(Y, x, y);\n"
"}\n"
"\n"
"float3 SkyLight_GetRadiance(__global SkyLight *skyLight, const float3 dir) {\n"
"	const float3 localDir = normalize(Transform_InvApplyVector(&skyLight->light2World, -dir));\n"
"	const float theta = SphericalTheta(localDir);\n"
"	const float phi = SphericalPhi(localDir);\n"
"	const float3 s = SkyLight_GetSkySpectralRadiance(skyLight, theta, phi);\n"
"\n"
"	return VLOAD3F(&skyLight->gain.r) * s;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// SunLight\n"
"//------------------------------------------------------------------------------\n"
"\n"
"#if defined(PARAM_HAS_SUNLIGHT)\n"
"\n"
"float3 SunLight_Illuminate(__global SunLight *sunLight,\n"
"		const float u0, const float u1,\n"
"		float3 *dir, float *distance, float *directPdfW) {\n"
"	const float cosThetaMax = sunLight->cosThetaMax;\n"
"	const float3 sunDir = VLOAD3F(&sunLight->sunDir.x);\n"
"	*dir = UniformSampleCone(u0, u1, cosThetaMax, VLOAD3F(&sunLight->x.x), VLOAD3F(&sunLight->y.x), sunDir);\n"
"\n"
"	// Check if the point can be inside the sun cone of light\n"
"	const float cosAtLight = dot(sunDir, *dir);\n"
"	if (cosAtLight <= cosThetaMax)\n"
"		return BLACK;\n"
"\n"
"	*distance = INFINITY;\n"
"	*directPdfW = UniformConePdf(cosThetaMax);\n"
"\n"
"	return VLOAD3F(&sunLight->sunColor.r);\n"
"}\n"
"\n"
"float3 SunLight_GetRadiance(__global SunLight *sunLight, const float3 dir, float *directPdfA) {\n"
"	// Make the sun visible only if relsize has been changed (in order\n"
"	// to avoid fireflies).\n"
"	if (sunLight->relSize > 5.f) {\n"
"		const float cosThetaMax = sunLight->cosThetaMax;\n"
"		const float3 sunDir = VLOAD3F(&sunLight->sunDir.x);\n"
"\n"
"		if ((cosThetaMax < 1.f) && (dot(-dir, sunDir) > cosThetaMax)) {\n"
"			if (directPdfA)\n"
"				*directPdfA = UniformConePdf(cosThetaMax);\n"
"\n"
"			return VLOAD3F(&sunLight->sunColor.r);\n"
"		}\n"
"	}\n"
"\n"
"	return BLACK;\n"
"}\n"
"\n"
"#endif\n"
"\n"
"//------------------------------------------------------------------------------\n"
"// TriangleLight\n"
"//------------------------------------------------------------------------------\n"
"\n"
"float3 TriangleLight_Illuminate(__global TriangleLight *triLight, __global HitPoint *tmpHitPoint,\n"
"		const float3 p, const float u0, const float u1, const float passThroughEvent,\n"
"		float3 *dir, float *distance, float *directPdfW\n"
"		MATERIALS_PARAM_DECL) {\n"
"	const float3 p0 = VLOAD3F(&triLight->v0.x);\n"
"	const float3 p1 = VLOAD3F(&triLight->v1.x);\n"
"	const float3 p2 = VLOAD3F(&triLight->v2.x);\n"
"	float b0, b1, b2;\n"
"	float3 samplePoint = Triangle_Sample(\n"
"			p0, p1, p2,\n"
"			u0, u1,\n"
"			&b0, &b1, &b2);\n"
"\n"
"	const float3 sampleN = Triangle_GetGeometryNormal(p0, p1, p2); // Light sources are supposed to be flat\n"
"\n"
"	*dir = samplePoint - p;\n"
"	const float distanceSquared = dot(*dir, *dir);;\n"
"	*distance = sqrt(distanceSquared);\n"
"	*dir /= (*distance);\n"
"\n"
"	const float cosAtLight = dot(sampleN, -(*dir));\n"
"	if (cosAtLight < DEFAULT_COS_EPSILON_STATIC)\n"
"		return BLACK;\n"
"\n"
"	*directPdfW = triLight->invArea * distanceSquared / cosAtLight;\n"
"\n"
"	const float2 uv0 = VLOAD2F(&triLight->uv0.u);\n"
"	const float2 uv1 = VLOAD2F(&triLight->uv1.u);\n"
"	const float2 uv2 = VLOAD2F(&triLight->uv2.u);\n"
"	const float2 triUV = Triangle_InterpolateUV(uv0, uv1, uv2, b0, b1, b2);\n"
"\n"
"	VSTORE3F(-sampleN, &tmpHitPoint->fixedDir.x);\n"
"	VSTORE3F(samplePoint, &tmpHitPoint->p.x);\n"
"	VSTORE2F(triUV, &tmpHitPoint->uv.u);\n"
"	VSTORE3F(sampleN, &tmpHitPoint->geometryN.x);\n"
"	VSTORE3F(sampleN, &tmpHitPoint->shadeN.x);\n"
"#if defined(PARAM_HAS_PASSTHROUGH)\n"
"	tmpHitPoint->passThroughEvent = passThroughEvent;\n"
"#endif\n"
"\n"
"	return Material_GetEmittedRadiance(&mats[triLight->materialIndex], tmpHitPoint\n"
"			MATERIALS_PARAM);\n"
"}\n"
"\n"
"float3 TriangleLight_GetRadiance(__global TriangleLight *triLight,\n"
"		 __global HitPoint *hitPoint, float *directPdfA\n"
"		MATERIALS_PARAM_DECL) {\n"
"	const float3 dir = VLOAD3F(&hitPoint->fixedDir.x);\n"
"	const float3 hitPointNormal = VLOAD3F(&hitPoint->geometryN.x);\n"
"	const float cosOutLight = dot(hitPointNormal, dir);\n"
"	if (cosOutLight <= 0.f)\n"
"		return BLACK;\n"
"\n"
"	if (directPdfA)\n"
"		*directPdfA = triLight->invArea;\n"
"\n"
"	return Material_GetEmittedRadiance(&mats[triLight->materialIndex], hitPoint\n"
"			MATERIALS_PARAM);\n"
"}\n"
; } }
