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; }