Di recente sto costruendo da zero un tracciante di base in C # come progetto di apprendimento / insegnamento. Una versione precedente del progetto (chiamiamola A) fa riflessioni e sfumature diffuse. Il programma esegue il rendering della scena a circa 900 ms. Ora ho appena realizzato un rilascio B che aggiunge riflessi speculari. Naturalmente, ho pensato che il tempo di rendering sarebbe aumentato. Immagina la mia sorpresa quando la stessa scena resa in un veloce 120ms! I risultati sono assolutamente gli stessi (poiché gli oggetti nella scena non hanno in realtà riflessi speculari).
Curioso, ho cercato di restringere quale parte del codice lo rendesse effettivamente più veloce. Penso di averlo ristretto a un calcolo che è fatto sia nel componente di riflessione, sia nel componente speculare (calcolando il vettore di riflessione). Per ogni iterazione del ray tracing, entrambi calcolano lo stesso vettore (stessi input, stesso output), ma non c'è condivisione di dati tra i due. Quindi mi stavo chiedendo se C # sta in qualche modo memorizzando nella cache i risultati che spiegherebbero l'aumento delle prestazioni?
Ecco il codice per il rendering del riflesso
private Color TraceReflection(Ray ray, Vector3D normal, Vector3D hitPoint, IPrimitive hitObject, int Level)
{
//Calculate reflection direction
var reflectionDir = (ray.Direction - (2 * (ray.Direction * normal) * normal)).Normalize();
//Create reflection ray from just outside the intersection point, and trace it
var reflectionRay = new Ray(hitPoint + reflectionDir * Globals.Epsilon, reflectionDir);
//Get the color from the reflection
var reflectionColor = RayTrace(reflectionRay, Level + 1);
//Calculate final color
var resultColor = reflectionColor * hitObject.PrimitiveMaterial.ReflectionCoeff;
return resultColor;
}
Ed ecco la funzione di evidenziazione speculare:
public Color GetColor(IPrimitive HitObject, ILight Light, Vector3D ViewDirection, Vector3D LightDirection, Vector3D Normal)
{
//Caulcate reflection vector
var reflectionDirection = (LightDirection - (2 * LightDirection * Normal) * Normal).Normalize();
var dot = reflectionDirection * ViewDirection; //if the dot product is zero or less that means the angle between the two vectors is 90 or more and no highlighting occurs.
if (dot > 0)
{
var specularPower = HitObject.PrimitiveMaterial.SpecularCoeff * Math.Pow(dot, HitObject.PrimitiveMaterial.SpecularExponent);
var highlightColor = HitObject.PrimitiveMaterial.DiffuseColor * specularPower;
return highlightColor;
}
return new Color();
}
UPDATE
I numeri precedenti erano quando entrambi i programmi erano in esecuzione in modalità di debug. Ho appena passato entrambi al rilascio, e i numeri sono quello che mi aspettavo fossero in primo luogo (270 ms senza speculare. 380 ms con speculare). Quindi sembra che la modalità di debug, in qualche modo, sia il colpevole.