Ejemplo n.º 1
0
sRGBAfloat cRenderWorker::EnvMapping(const sShaderInputData &input)
{
	sRGBAfloat envReflect;
	CVector3 reflect;
	double dot = -input.viewVector.Dot(input.normal);
	reflect = input.normal * 2.0 * dot + input.viewVector;

	double alphaTexture = -reflect.GetAlpha() + M_PI;
	double betaTexture = -reflect.GetBeta();
	double texWidth = data->textures.envmapTexture.Width();
	double texHeight = data->textures.envmapTexture.Height();

	if (betaTexture > 0.5 * M_PI) betaTexture = 0.5 * M_PI - betaTexture;

	if (betaTexture < -0.5 * M_PI) betaTexture = -0.5 * M_PI + betaTexture;

	double dtx = (alphaTexture / (2.0 * M_PI)) * texWidth + texWidth * 8.25;
	double dty = (betaTexture / (M_PI) + 0.5) * texHeight + texHeight * 8.0;
	dtx = fmod(dtx, texWidth);
	dty = fmod(dty, texHeight);
	if (dtx < 0) dtx = 0;
	if (dty < 0) dty = 0;

	double reflectance = 1.0;
	if (input.material->fresnelReflectance)
	{
		double n1 = 1.0;
		double n2 = input.material->transparencyIndexOfRefraction;
		reflectance = Reflectance(input.normal, input.viewVector, n1, n2);
		if (reflectance < 0.0) reflectance = 0.0;
		if (reflectance > 1.0) reflectance = 1.0;
	}

	envReflect.R = data->textures.envmapTexture.Pixel(dtx, dty).R * reflectance;
	envReflect.G = data->textures.envmapTexture.Pixel(dtx, dty).G * reflectance;
	envReflect.B = data->textures.envmapTexture.Pixel(dtx, dty).B * reflectance;
	return envReflect;
}
Ejemplo n.º 2
0
cRenderWorker::sRayRecursionOut cRenderWorker::RayRecursion(sRayRecursionIn in,
		sRayRecursionInOut &inOut)
{
	sRayMarchingOut rayMarchingOut;

	*inOut.rayMarchingInOut.buffCount = 0;

	//trace the light in given direction
	CVector3 point = RayMarching(in.rayMarchingIn, &inOut.rayMarchingInOut, &rayMarchingOut);

	sRGBAfloat resultShader = in.resultShader;
	sRGBAfloat objectColour = in.objectColour;

	//here will be called branch for RayRecursion();

	sRGBAfloat objectShader;
	objectShader.A = 0.0;
	sRGBAfloat backgroundShader;
	sRGBAfloat volumetricShader;
	sRGBAfloat specular;

	//prepare data for shaders
	CVector3 lightVector = shadowVector;
	sShaderInputData shaderInputData;
	shaderInputData.distThresh = rayMarchingOut.distThresh;
	shaderInputData.delta = CalcDelta(point);
	shaderInputData.lightVect = lightVector;
	shaderInputData.point = point;
	shaderInputData.viewVector = in.rayMarchingIn.direction;
	shaderInputData.lastDist = rayMarchingOut.lastDist;
	shaderInputData.depth = rayMarchingOut.depth;
	shaderInputData.stepCount = *inOut.rayMarchingInOut.buffCount;
	shaderInputData.stepBuff = inOut.rayMarchingInOut.stepBuff;
	shaderInputData.invertMode = in.calcInside;
	shaderInputData.objectId = rayMarchingOut.objectId;

	cObjectData objectData = data->objectData[shaderInputData.objectId];
	shaderInputData.material = &data->materials[objectData.materialId];

	sRGBAfloat reflectShader = in.resultShader;
	double reflect = shaderInputData.material->reflectance;

	sRGBAfloat transparentShader = in.resultShader;
	double transparent = shaderInputData.material->transparencyOfSurface;
	sRGBfloat transparentColor = sRGBfloat(shaderInputData.material->transparencyInteriorColor.R / 65536.0,
																				 shaderInputData.material->transparencyInteriorColor.G / 65536.0,
																				 shaderInputData.material->transparencyInteriorColor.B / 65536.0);
	resultShader.R = transparentColor.R;
	resultShader.G = transparentColor.G;
	resultShader.B = transparentColor.B;

	CVector3 vn;

	//if found any object
	if (rayMarchingOut.found)
	{
		//calculate normal vector
		vn = CalculateNormals(shaderInputData);
		shaderInputData.normal = vn;

		if(shaderInputData.material->diffusionTexture.IsLoaded())
			shaderInputData.texDiffuse = TextureShader(shaderInputData, cMaterial::texDiffuse, shaderInputData.material);
		else
			shaderInputData.texDiffuse = sRGBfloat(1.0, 1.0, 1.0);

		if(shaderInputData.material->normalMapTexture.IsLoaded())
		{
			vn = NormalMapShader(shaderInputData);
		}

		//prepare refraction values
		double n1, n2;
		if (in.calcInside) //if trance is inside the object
		{
			n1 = shaderInputData.material ->transparencyIndexOfRefraction; //reverse refractive indices
			n2 = 1.0;
		}
		else
		{
			n1 = 1.0;
			n2 = shaderInputData.material ->transparencyIndexOfRefraction;
			;
		}

		if (inOut.rayIndex < reflectionsMax)
		{

			//calculate refraction (transparency)
			if (transparent > 0.0)
			{
				sRayRecursionIn recursionIn;
				sRayMarchingIn rayMarchingIn;
				sRayMarchingInOut rayMarchingInOut;

				//calculate direction of refracted light
				CVector3 newDirection = RefractVector(vn, in.rayMarchingIn.direction, n1, n2);

				//move starting point a little
				CVector3 newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0;

				//if is total internal reflection the use reflection instead of refraction
				bool internalReflection = false;
				if (newDirection.Length() == 0.0)
				{
					newDirection = ReflectionVector(vn, in.rayMarchingIn.direction);
					newPoint = point + in.rayMarchingIn.direction * shaderInputData.distThresh * 1.0;
					internalReflection = true;
				}

				//preparation for new recursion
				rayMarchingIn.binaryEnable = true;
				rayMarchingIn.direction = newDirection;
				rayMarchingIn.maxScan = params->viewDistanceMax;
				rayMarchingIn.minScan = 0.0;
				rayMarchingIn.start = newPoint;
				rayMarchingIn.invertMode = !in.calcInside || internalReflection;
				recursionIn.rayMarchingIn = rayMarchingIn;
				recursionIn.calcInside = !in.calcInside || internalReflection;
				recursionIn.resultShader = resultShader;
				recursionIn.objectColour = objectColour;

				//setup buffers for ray data
				inOut.rayIndex++; //increase recursion index
				rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount;
				rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff;
				inOut.rayMarchingInOut = rayMarchingInOut;

				//recursion for refraction
				sRayRecursionOut recursionOutTransparent = RayRecursion(recursionIn, inOut);
				transparentShader = recursionOutTransparent.resultShader;
			}

			//calculate reflection
			if (reflect > 0.0)
			{
				sRayRecursionIn recursionIn;
				sRayMarchingIn rayMarchingIn;
				sRayMarchingInOut rayMarchingInOut;

				//calculate new direction of reflection
				CVector3 newDirection = ReflectionVector(vn, in.rayMarchingIn.direction);
				CVector3 newPoint = point + newDirection * shaderInputData.distThresh;

				//prepare for new recursion
				rayMarchingIn.binaryEnable = true;
				rayMarchingIn.direction = newDirection;
				rayMarchingIn.maxScan = params->viewDistanceMax;
				rayMarchingIn.minScan = 0.0;
				rayMarchingIn.start = newPoint;
				rayMarchingIn.invertMode = false;
				recursionIn.rayMarchingIn = rayMarchingIn;
				recursionIn.calcInside = false;
				recursionIn.resultShader = resultShader;
				recursionIn.objectColour = objectColour;

				//setup buffers for ray data
				inOut.rayIndex++; //increase recursion index
				rayMarchingInOut.buffCount = &rayBuffer[inOut.rayIndex].buffCount;
				rayMarchingInOut.stepBuff = rayBuffer[inOut.rayIndex].stepBuff;
				inOut.rayMarchingInOut = rayMarchingInOut;

				//recursion for reflection
				sRayRecursionOut recursionOutReflect = RayRecursion(recursionIn, inOut);
				reflectShader = recursionOutReflect.resultShader;

			}
			if (transparent > 0.0) inOut.rayIndex--; //decrease recursion index
			if (reflect > 0.0) inOut.rayIndex--; //decrease recursion index
		}

		shaderInputData.normal = vn;

		//calculate effects for object surface
		objectShader = ObjectShader(shaderInputData, &objectColour, &specular);

		//calculate reflectance according to Fresnel equations
		double reflectance = 1.0;
		double reflectanceN = 1.0;

		if (shaderInputData.material->fresnelReflectance)
		{
			reflectance = Reflectance(vn, in.rayMarchingIn.direction, n1, n2);
			if (reflectance < 0.0) reflectance = 0.0;
			if (reflectance > 1.0) reflectance = 1.0;
			reflectanceN = 1.0 - reflectance;
		}

		//combine all results
		resultShader.R = (objectShader.R + specular.R);
		resultShader.G = (objectShader.G + specular.G);
		resultShader.B = (objectShader.B + specular.B);

		if (reflectionsMax > 0)
		{
			sRGBfloat reflectDiffused;
			double diffIntes = shaderInputData.material->diffussionTextureIntensity;
			double diffIntesN = 1.0 - diffIntes;
			reflectDiffused.R = reflect * shaderInputData.texDiffuse.R * diffIntes + reflect * diffIntesN;
			reflectDiffused.G = reflect * shaderInputData.texDiffuse.G * diffIntes + reflect * diffIntesN;
			reflectDiffused.B = reflect * shaderInputData.texDiffuse.B * diffIntes + reflect * diffIntesN;

			resultShader.R = transparentShader.R * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.R;
			resultShader.G = transparentShader.G * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.G;
			resultShader.B = transparentShader.B * transparent * reflectanceN
					+ (1.0 - transparent * reflectanceN) * resultShader.B;

			resultShader.R = reflectShader.R * reflectDiffused.R * reflectance
					+ (1.0 - reflectDiffused.R * reflectance) * resultShader.R;
			resultShader.G = reflectShader.G * reflectDiffused.G * reflectance
					+ (1.0 - reflectDiffused.G * reflectance) * resultShader.G;
			resultShader.B = reflectShader.B * reflectDiffused.B * reflectance
					+ (1.0 - reflectDiffused.B * reflectance) * resultShader.B;
		}
		if(resultShader.R < 0.0) resultShader.R = 0.0;
		if(resultShader.G < 0.0) resultShader.G = 0.0;
		if(resultShader.B < 0.0) resultShader.B = 0.0;
	}
	else //if object not found then calculate background
	{
		backgroundShader = BackgroundShader(shaderInputData);
		resultShader = backgroundShader;
		shaderInputData.depth = 1e20;
		vn =  mRot.RotateVector(CVector3(0.0, -1.0, 0.0));
	}

	sRGBAfloat opacityOut;

	if (in.calcInside) //if the object interior is traced, then the absorption of light has to be calculated
	{
		for (int index = shaderInputData.stepCount - 1; index > 0; index--)
		{
			double step = shaderInputData.stepBuff[index].step;

			//CVector3 point = shaderInputData.stepBuff[index].point;
			//shaderInputData.point = point;
			//sRGBAfloat color = SurfaceColour(shaderInputData);
			//transparentColor.R = color.R;
			//transparentColor.G = color.G;
			//transparentColor.B = color.B;

			double opacity = -log(shaderInputData.material ->transparencyOfInterior) * step;
			if (opacity > 1.0) opacity = 1.0;

			resultShader.R = opacity * transparentColor.R + (1.0 - opacity) * resultShader.R;
			resultShader.G = opacity * transparentColor.G + (1.0 - opacity) * resultShader.G;
			resultShader.B = opacity * transparentColor.B + (1.0 - opacity) * resultShader.B;
		}
	}
	else //if now is outside the object, then calculate all volumetric effects like fog, glow...
	{
		volumetricShader = VolumetricShader(shaderInputData, resultShader, &opacityOut);
		resultShader = volumetricShader;
	}

	//prepare final result
	sRayRecursionOut out;
	out.point = point;
	out.rayMarchingOut = rayMarchingOut;
	out.objectColour = objectColour;
	out.resultShader = resultShader;
	out.found = (shaderInputData.depth == 1e20) ? false : true;
	out.fogOpacity = opacityOut.R;
	out.normal = vn;

	return out;
}