#include <string>
namespace slg { namespace ocl {
std::string KernelSource_camera_funcs = 
"#line 2 \"camera_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"
"#if defined(PARAM_CAMERA_ENABLE_OCULUSRIFT_BARREL)\n"
"void Camera_OculusRiftBarrelPostprocess(const float x, const float y, float *barrelX, float *barrelY) {\n"
"	// Express the sample in coordinates relative to the eye center\n"
"	float ex, ey;\n"
"	if (x < .5f) {\n"
"		// A left eye sample\n"
"		ex = x * 4.f - 1.f;\n"
"		ey = y * 2.f - 1.f;\n"
"	} else {\n"
"		// A right eye sample\n"
"		ex = (x - .5f) * 4.f - 1.f;\n"
"		ey = y * 2.f - 1.f;\n"
"	}\n"
"\n"
"	if ((ex == 0.f) && (ey == 0.f)) {\n"
"		*barrelX = 0.f;\n"
"		*barrelY = 0.f;\n"
"		return;\n"
"	}\n"
"\n"
"	// Distance from the eye center\n"
"	const float distance = sqrt(ex * ex + ey * ey);\n"
"\n"
"	// \"Push\" the sample away base on the distance from the center\n"
"	const float scale = 1.f / 1.4f;\n"
"	const float k0 = 1.f;\n"
"	const float k1 = .22f;\n"
"	const float k2 = .23f;\n"
"	const float k3 = 0.f;\n"
"	const float distance2 = distance * distance;\n"
"	const float distance4 = distance2 * distance2;\n"
"	const float distance6 = distance2 * distance4;\n"
"	const float fr = scale * (k0 + k1 * distance2 + k2 * distance4 + k3 * distance6);\n"
"\n"
"	ex *= fr;\n"
"	ey *= fr;\n"
"\n"
"	// Clamp the coordinates\n"
"	ex = clamp(ex, -1.f, 1.f);\n"
"	ey = clamp(ey, -1.f, 1.f);\n"
"\n"
"	if (x < .5f) {\n"
"		*barrelX = (ex + 1.f) * .25f;\n"
"		*barrelY = (ey + 1.f) * .5f;\n"
"	} else {\n"
"		*barrelX = (ex + 1.f) * .25f + .5f;\n"
"		*barrelY = (ey + 1.f) * .5f;\n"
"	}\n"
"}\n"
"#endif\n"
"\n"
"void Camera_GenerateRay(\n"
"		__global Camera *camera,\n"
"		__global Ray *ray,\n"
"		const float scrSampleX, const float scrSampleY\n"
"#if defined(PARAM_CAMERA_HAS_DOF)\n"
"		, const float dofSampleX, const float dofSampleY\n"
"#endif\n"
"		) {\n"
"#if defined(PARAM_CAMERA_ENABLE_HORIZ_STEREO)\n"
"	// Left eye or right eye\n"
"	const uint transIndex = (scrSampleX < .5f) ? 0 : 1;\n"
"#else\n"
"	const uint transIndex = 0;\n"
"#endif\n"
"\n"
"	float ssx, ssy;\n"
"#if defined(PARAM_CAMERA_ENABLE_HORIZ_STEREO) && defined(PARAM_CAMERA_ENABLE_OCULUSRIFT_BARREL)\n"
"	Camera_OculusRiftBarrelPostprocess(scrSampleX, scrSampleY, &ssx, &ssy);\n"
"#else\n"
"	ssx = scrSampleX;\n"
"	ssy = scrSampleY;\n"
"#endif\n"
"\n"
"	const float screenX = min(ssx * PARAM_IMAGE_WIDTH, (float)(PARAM_IMAGE_WIDTH - 1));\n"
"	const float screenY = min((1.f - ssy) * PARAM_IMAGE_HEIGHT, (float)(PARAM_IMAGE_HEIGHT - 1));\n"
"	float3 Pras = (float3)(screenX, screenY, 0.f);\n"
"\n"
"	float3 rayOrig = Transform_ApplyPoint(&camera->rasterToCamera[transIndex], Pras);\n"
"	float3 rayDir = rayOrig;\n"
"\n"
"	const float hither = camera->hither;\n"
"\n"
"#if defined(PARAM_CAMERA_HAS_DOF)\n"
"	// Sample point on lens\n"
"	float lensU, lensV;\n"
"	ConcentricSampleDisk(dofSampleX, dofSampleY, &lensU, &lensV);\n"
"	const float lensRadius = camera->lensRadius;\n"
"	lensU *= lensRadius;\n"
"	lensV *= lensRadius;\n"
"\n"
"	// Compute point on plane of focus\n"
"	const float focalDistance = camera->focalDistance;\n"
"	const float dist = focalDistance - hither;\n"
"	const float ft = dist / rayDir.z;\n"
"	float3 Pfocus;\n"
"	Pfocus = rayOrig + rayDir * ft;\n"
"\n"
"	// Update ray for effect of lens\n"
"	const float k = dist / focalDistance;\n"
"	rayOrig.x += lensU * k;\n"
"	rayOrig.y += lensV * k;\n"
"\n"
"	rayDir = Pfocus - rayOrig;\n"
"#endif\n"
"\n"
"	rayDir = normalize(rayDir);\n"
"	const float maxt = (camera->yon - hither) / rayDir.z;\n"
"\n"
"	// Transform ray in world coordinates\n"
"	rayOrig = Transform_ApplyPoint(&camera->cameraToWorld[transIndex], rayOrig);\n"
"	rayDir = Transform_ApplyVector(&camera->cameraToWorld[transIndex], rayDir);\n"
"\n"
"	Ray_Init3(ray, rayOrig, rayDir, maxt);\n"
"\n"
"	/*printf(\"(%f, %f, %f) (%f, %f, %f) [%f, %f]\\n\",\n"
"		ray->o.x, ray->o.y, ray->o.z, ray->d.x, ray->d.y, ray->d.z,\n"
"		ray->mint, ray->maxt);*/\n"
"}\n"
; } }
