Beispiel #1
0
sRGBAfloat cRenderWorker::FastAmbientOcclusion(const sShaderInputData &input)
{
	//reference: http://www.iquilezles.org/www/material/nvscene2008/rwwtt.pdf (Iñigo Quilez – iq/rgba)

	double delta = input.distThresh;
	double aoTemp = 0;
	double quality = params->ambientOcclusionQuality;
	for (int i = 1; i < quality * quality; i++)
	{
		double scan = i * i * delta;
		CVector3 pointTemp = input.point + input.normal * scan;

		sDistanceOut distanceOut;
		sDistanceIn distanceIn(pointTemp, input.distThresh, false);
		double dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;
		aoTemp += 1.0 / pow(2.0, i) * (scan - params->ambientOcclusionFastTune * dist)
				/ input.distThresh;
	}
	double ao = 1.0 - 0.2 * aoTemp;
	if (ao < 0) ao = 0;
	sRGBAfloat output(ao, ao, ao, 1.0);
	return output;
}
CVector3 cRenderWorker::CalculateNormals(const sShaderInputData &input)
{
	CVector3 normal(0.0, 0.0, 0.0);
	// calculating normal vector based on distance estimation (gradient of distance function)
	if (!params->slowShading)
	{
		double delta = input.delta * params->smoothness;
		if (params->interiorMode) delta = input.distThresh * 0.2 * params->smoothness;

		double sx1, sx2, sy1, sy2, sz1, sz2;
		sDistanceOut distanceOut;

		CVector3 deltax(delta, 0.0, 0.0);
		sDistanceIn distanceIn1(input.point + deltax, input.distThresh, true);
		sx1 = CalculateDistance(*params, *fractal, distanceIn1, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;
		sDistanceIn distanceIn2(input.point - deltax, input.distThresh, true);
		sx2 = CalculateDistance(*params, *fractal, distanceIn2, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;

		CVector3 deltay(0.0, delta, 0.0);
		sDistanceIn distanceIn3(input.point + deltay, input.distThresh, true);
		sy1 = CalculateDistance(*params, *fractal, distanceIn3, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;
		sDistanceIn distanceIn4(input.point - deltay, input.distThresh, true);
		sy2 = CalculateDistance(*params, *fractal, distanceIn4, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;

		CVector3 deltaz(0.0, 0.0, delta);
		sDistanceIn distanceIn5(input.point + deltaz, input.distThresh, true);
		sz1 = CalculateDistance(*params, *fractal, distanceIn5, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;
		sDistanceIn distanceIn6(input.point - deltaz, input.distThresh, true);
		sz2 = CalculateDistance(*params, *fractal, distanceIn6, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;

		normal.x = sx1 - sx2;
		normal.y = sy1 - sy2;
		normal.z = sz1 - sz2;
	}

	// calculating normal vector based on average value of binary central difference
	else
	{
		CVector3 point2;
		CVector3 point3;
		double delta = input.delta * params->smoothness * 0.5;
		if (params->interiorMode) delta = input.distThresh * 0.2 * params->smoothness;

		sDistanceOut distanceOut;
		for (point2.x = -1.0; point2.x <= 1.0; point2.x += 0.2) //+0.2
		{
			for (point2.y = -1.0; point2.y <= 1.0; point2.y += 0.2)
			{
				for (point2.z = -1.0; point2.z <= 1.0; point2.z += 0.2)
				{
					point3 = input.point + point2 * delta;

					sDistanceIn distanceIn(point3, input.distThresh, true);
					double dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut, data);
					data->statistics.totalNumberOfIterations += distanceOut.totalIters;
					normal += (point2 * dist);
				}
			}
		}
	}

	if ((normal.x == 0 && normal.y == 0 && normal.z == 0))
	{
		normal = CVector3(1.0, 0.0, 0.0);
	}
	else
	{
		normal.Normalize();
	}

	if (normal.IsNotANumber())
	{
		normal = CVector3(1.0, 0.0, 0.0);
	}

	if (input.invertMode) normal *= (-1.0);

	// qDebug() << input.point.Debug() << normal.Debug();

	return normal;
}
sRGBAfloat cRenderWorker::AmbientOcclusion(const sShaderInputData &input)
{
	sRGBAfloat AO(0, 0, 0, 1.0);

	double start_dist = input.delta;
	double end_dist = input.delta / params->resolution;
	double intense = 0;

	for (int i = 0; i < AOvectorsCount; i++)
	{
		sVectorsAround v = AOvectorsAround[i];

		double dist = input.lastDist;

		double opacity = 0.0;
		double shadowTemp = 1.0;

		for (double r = start_dist; r < end_dist; r += dist * 2.0)
		{
			CVector3 point2 = input.point + v.v * r;

			sDistanceOut distanceOut;
			sDistanceIn distanceIn(point2, input.distThresh, false);
			dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut, data);
			data->statistics.totalNumberOfIterations += distanceOut.totalIters;

			if (params->iterFogEnabled)
			{
				opacity = IterOpacity(dist * 2.0, distanceOut.iters, params->N, params->iterFogOpacityTrim,
					params->iterFogOpacity);
			}
			else
			{
				opacity = 0.0;
			}
			shadowTemp -= opacity * (end_dist - r) / end_dist;

			float dist_thresh;
			if (params->iterFogEnabled || params->volumetricLightEnabled[0])
			{
				dist_thresh = CalcDistThresh(point2);
			}
			else
				dist_thresh = input.distThresh;

			if (dist < dist_thresh || distanceOut.maxiter || shadowTemp < 0.0)
			{
				shadowTemp -= (end_dist - r) / end_dist;
				if (shadowTemp < 0.0) shadowTemp = 0.0;
				break;
			}
		}

		intense = shadowTemp;

		AO.R += intense * v.R;
		AO.G += intense * v.G;
		AO.B += intense * v.B;
	}
	AO.R /= (AOvectorsCount * 256.0);
	AO.G /= (AOvectorsCount * 256.0);
	AO.B /= (AOvectorsCount * 256.0);

	return AO;
}
sRGBAfloat cRenderWorker::MainShadow(const sShaderInputData &input)
{
	sRGBAfloat shadow(1.0, 1.0, 1.0, 1.0);

	// starting point
	CVector3 point2;

	double factor = input.delta / params->resolution;
	if (!params->penetratingLights) factor = params->viewDistanceMax;
	double dist = input.distThresh;

	double DEFactor = params->DEFactor;
	if (params->iterFogEnabled || params->volumetricLightEnabled[0]) DEFactor = 1.0;

	// double start = input.delta;
	double start = input.distThresh;
	if (params->interiorMode) start = input.distThresh * DEFactor;

	double opacity = 0.0;
	double shadowTemp = 1.0;

	double softRange = tan(params->shadowConeAngle / 180.0 * M_PI);
	double maxSoft = 0.0;

	const bool bSoft = (!params->iterFogEnabled && !params->limitsEnabled && !params->iterThreshMode)
										 && softRange > 0.0;

	for (double i = start; i < factor; i += dist * DEFactor)
	{
		point2 = input.point + input.lightVect * i;

		float dist_thresh;
		if (params->iterFogEnabled || params->volumetricLightEnabled[0])
		{
			dist_thresh = CalcDistThresh(point2);
		}
		else
			dist_thresh = input.distThresh;

		sDistanceOut distanceOut;
		sDistanceIn distanceIn(point2, dist_thresh, false);
		dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut, data);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;

		if (bSoft)
		{
			double angle = (dist - dist_thresh) / i;
			if (angle < 0) angle = 0;
			if (dist < dist_thresh) angle = 0;
			double softShadow = (1.0 - angle / softRange);
			if (params->penetratingLights) softShadow *= (factor - i) / factor;
			if (softShadow < 0) softShadow = 0;
			if (softShadow > maxSoft) maxSoft = softShadow;
		}

		if (params->iterFogEnabled)
		{
			opacity = IterOpacity(dist * DEFactor, distanceOut.iters, params->N,
				params->iterFogOpacityTrim, params->iterFogOpacity);
		}
		else
		{
			opacity = 0.0;
		}
		shadowTemp -= opacity * (factor - i) / factor;

		if (dist < dist_thresh || shadowTemp < 0.0)
		{
			shadowTemp -= (factor - i) / factor;
			if (!params->penetratingLights) shadowTemp = 0.0;
			if (shadowTemp < 0.0) shadowTemp = 0.0;
			break;
		}
	}
	if (!bSoft)
	{
		shadow.R = shadowTemp;
		shadow.G = shadowTemp;
		shadow.B = shadowTemp;
	}
	else
	{
		shadow.R = (1.0 - maxSoft);
		shadow.G = (1.0 - maxSoft);
		shadow.B = (1.0 - maxSoft);
	}
	return shadow;
}
//Ray-Marching
CVector3 cRenderWorker::RayMarching(sRayMarchingIn &in, sRayMarchingInOut *inOut,
		sRayMarchingOut *out)
{
	CVector3 point;
	bool found = false;
	double scan = in.minScan;
	double dist = 0;
	double search_accuracy = 0.01 * params->detailLevel;
	double search_limit = 1.0 - search_accuracy;
	int counter = 0;
	double step = 0.0;
	(*inOut->buffCount) = 0;
	double distThresh;
	out->objectId = 0;

	//qDebug() << "Start ************************";

	CVector3 lastPoint, lastGoodPoint;
	bool deadComputationFound = false;

	for (int i = 0; i < 10000; i++)
	{
		lastGoodPoint = lastPoint;
		lastPoint = point;

		counter++;

		point = in.start + in.direction * scan;

		if (point == lastPoint || point == point/0.0) //detection of dead calculation
		{
			//qWarning() << "Dead computation\n"
			//		<< "Point:" << point.Debug()
			//		<< "\nPrevious point:" << lastPoint.Debug();
			point = lastPoint;
			found = true;
			deadComputationFound = true;
			break;
		}

		distThresh = CalcDistThresh(point);

		sDistanceIn distanceIn(point, distThresh, false);
		sDistanceOut distanceOut;
		dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut, data);
		//qDebug() <<"thresh" <<  distThresh << "dist" << dist << "scan" << scan;
		if (in.invertMode)
		{
			dist = distThresh * 1.99 - dist;
			if (dist < 0.0) dist = 0.0;
		}
		out->objectId = distanceOut.objectId;

		//-------------------- 4.18us for Calculate distance --------------

		//printf("Distance = %g\n", dist/distThresh);
		inOut->stepBuff[i].distance = dist;
		inOut->stepBuff[i].iters = distanceOut.iters;
		inOut->stepBuff[i].distThresh = distThresh;

		data->statistics.histogramIterations.Add(distanceOut.iters);
		data->statistics.totalNumberOfIterations += distanceOut.totalIters;

		if (dist > 3.0) dist = 3.0;
		if (dist < distThresh)
		{
			if (dist < 0.1 * distThresh) data->statistics.missedDE++;
			found = true;
			break;
		}

		inOut->stepBuff[i].step = step;
		if (params->interiorMode)
		{
			step = (dist - 0.8 * distThresh) * params->DEFactor * (1.0 - Random(1000) / 10000.0);
			;
		}
		else
		{
			step = (dist - 0.5 * distThresh) * params->DEFactor * (1.0 - Random(1000) / 10000.0);
			;
		}
		inOut->stepBuff[i].point = point;
		//qDebug() << "i" << i << "dist" << inOut->stepBuff[i].distance << "iters" << inOut->stepBuff[i].iters << "distThresh" << inOut->stepBuff[i].distThresh << "step" << inOut->stepBuff[i].step << "point" << inOut->stepBuff[i].point.Debug();
		(*inOut->buffCount) = i + 1;
		scan += step / in.direction.Length(); //divided by length of view Vector to eliminate overstepping when fov is big
		if (scan > in.maxScan)
		{
			break;
		}

	}
	//------------- 83.2473 us for RayMarching loop -------------------------

	//qDebug() << "------------ binary search";
	if (found && in.binaryEnable && !deadComputationFound)
	{
		step *= 0.5;
		for (int i = 0; i < 30; i++)
		{
			counter++;
			if (dist < distThresh && dist > distThresh * search_limit)
			{
				break;
			}
			else
			{
				if (dist > distThresh)
				{
					scan += step;
					point = in.start + in.direction * scan;
				}
				else if (dist < distThresh * search_limit)
				{
					scan -= step;
					point = in.start + in.direction * scan;
				}
			}

			distThresh = CalcDistThresh(point);

			sDistanceIn distanceIn(point, distThresh, false);
			sDistanceOut distanceOut;
			dist = CalculateDistance(*params, *fractal, distanceIn, &distanceOut, data);

			//qDebug() << "i" << i <<"thresh" <<  distThresh << "dist" << dist << "scan" << scan << "step" << step;

			if (in.invertMode)
			{
				dist = distThresh * 1.99 - dist;
				if (dist < 0.0) dist = 0.0;
			}

			out->objectId = distanceOut.objectId;

			data->statistics.histogramIterations.Add(distanceOut.iters);
			data->statistics.totalNumberOfIterations += distanceOut.totalIters;

			step *= 0.5;
		}
	}
	if (params->iterThreshMode)
	{
		//this fixes problem with noise when there is used "stop at maxIter" mode
		scan -= distThresh;
		point = in.start + in.direction * scan;
	}

	//---------- 7.19605us for binary searching ---------------

	data->statistics.histogramStepCount.Add(counter);

	out->found = found;
	out->lastDist = dist;
	out->depth = scan;
	out->distThresh = distThresh;
	data->statistics.numberOfRaymarchings++;
	return point;
}