RayTracing Projekt - Problem mit Normale der Cornell Box Backplane



  • Hallo alle zusammen,
    ich sitze schon seit mehreren Wochen an einem Ray-Tracing Projekt.
    Die Szene zeigt mehrere Kugeln in einer Cornell-Box.
    Die Seiten der Cornell-Boxen passen auch soweit alle bis auf die Backplane.
    Diese zeigt keine Reflektionen und nur eine schwarze (Roughness=1) und graue Textur bei (Metallness=1) an. Ich habe inzwischen das Gefühl, dass es an der Normalen liegt, das die negativ ist. Wenn ich diese jedoch nun flippe, dann ist die Plane nicht mehr sichtbar und der Hintergrund wird gerendert.
    Zuerst hab ich vermutet, dass es die Intersection Funktion ist. Aber dort finde ich einfach nicht die Ursache für diesen Bug.

    Mein Code zur Intersection:

    TrianglePBR(
    		const Vector3& v0,
    		const Vector3& v1,
    		const Vector3& v2,
    		const Vector3& sc,
    		const float metallic = 0, 
    		float roughness = 0, 
    		float ambientOcclusion = 0)
    	{
    		mV0 = v0;
    		mV1 = v1;
    		mV2 = v2;
    		surfaceColor = sc;
    		mMetallic = metallic;
    		mRroughness = roughness;
    		mAmbientOcclusion = ambientOcclusion;
    
    		Vector3 v0v1 = mV1 - mV0;
    		Vector3 v0v2 = mV2 - mV0;
    
    		Vector3 N = cross(v0v1, v0v2);
    
    		normal = unit_vector(N);
    	}
    
    
    bool TrianglePBR::intersect(Ray& ray, float t_min, float t_max, hit_record &rec) const
    {
    	// plane normals
    	//Vector3 v0v1 = mV1 - mV0;
    	//Vector3 v0v2 = mV2 - mV0;
    
    	Vector3 N = normal;//cross(v0v1, v0v2);
    	float area2 = N.length();
    	
    	// Step 1: finding P
    	float NdotRayDirection = dot(N, ray.direction());
    	// calculates the absolute value
    	if (std::fabs(NdotRayDirection) < 1e-8) // near zero
    		return false; // ray and triangle are parallel, so they do not intersect
    
    					  // compute component d
    	float d = dot(N, mV0);
    
    	// compute t
    	rec.t = (dot(N, ray.origin()) + d) / NdotRayDirection;
    
    
    	// check if the triangle is behind the ray
    	if (rec.t < 0) return false;
    
    	rec.p = ray.origin() + rec.t * ray.direction();
    
    	// Step 2: inside, outside test
    	Vector3 C;
    
    	// edge0
    	Vector3 edge0 = mV1 - mV0;
    	Vector3 vp0 = rec.p - mV0;
    	C = cross(edge0, vp0);
    	if (dot(N, C) < 0) return false;
    
    	// edge1
    	Vector3 edge1 = mV2 - mV1;
    	Vector3 vp1 = rec.p - mV1;
    	C = cross(edge1, vp1);
    	if (dot(N, C) < 0) return false;
    
    	// edge2
    	Vector3 edge2 = mV0 - mV2;
    	Vector3 vp2 = rec.p - mV2;
    	C = cross(edge2, vp2);
    	if (dot(N, C) < 0) return false;
    
    	rec.normal = N;
    	/*if (NdotRayDirection < 0)
    	{
    		rec.normal = -N;
    	}
    	else
    	{
    		rec.normal = N;
    	}*/
    
    	return true; // ray hits the triangle
    }
    

    Hier nochmal der Code wo ich meine Objekte erstelle:

    
    #ifdef PBR_SHADING
    	// Physical Based Shading
    	mWorld.Add(new SpherePBR(Vector3(-R - 0.3, -2.0, -1), 1, Vector3(0.933, 0.31, 1), 0.75, 0.35, 0.3));
    	mWorld.Add(new SpherePBR(Vector3(R + 0.9, -1.0, -0.5), R, Vector3(0.65, 0.77, 0.97), 0.25, 0.75, 0.3));
    
    
    	//mWorld.AddCube(Vector3(0, 0, 0), 5, 2, 6, Vector3(0.0, 0.0, 1.0), 0.75, 0.0, 0.3);
    
    	Plane planeBottom =  mWorld.AddPlanePBR(Vector3(0, 0, 0), 5, 6, Vector3(0.0, 0.0, 1.0), 0.75, 0.0, 0.3);
    	planeBottom.Move(Vector3(0,0, 5.0));
    	
    	Plane planeRight = mWorld.AddPlanePBR(Vector3(0, 0, 0), 5, 6, Vector3(0.0, 1.0, 0.0), 0.7, 0.0, 0.3);
    	planeRight.rotateY(90);
    	planeRight.Move(Vector3(-2.5, 0, -2.5));
    
    	Plane planeLeft = mWorld.AddPlanePBR(Vector3(0, 0, 0), 5, 6, Vector3(1.0, 0.0, 0.0), 0.7, 0.0, 0.3);
    	planeLeft.rotateX(180);
    	planeLeft.rotateY(90);
    	planeLeft.Move(Vector3(2.5, 0.0, -2.5));
    
    	Plane planeBack = mWorld.AddPlanePBR(Vector3(0, 0, 0), 2.5, 2.5, Vector3(0.0, 0.0, 1.0), 0.7, 0.0, 0.3);
    	planeBack.rotateX(90);
    	planeBack.Move(Vector3(0, -6.0, -2.5));
    
    	Plane planeTop = mWorld.AddPlanePBR(Vector3(0, 0, 0), 5, 6, Vector3(0.0, 0.0, 1.0), 0.7, 0.0, 0.3);
    	planeTop.rotateX(180);
    	planeTop.Move(Vector3(0, 0, 0.0));
    #endif
    
    mWorld.Add(new Light(Vector3(1.0, 1.0, 1.0), Vector3(-1, -0.0, -2.0), -2));
    

    Falls ihr euch mein komplettes Projekt anschauen wollt und vll. noch weitere Anregungen geben wollt könnt ihr es in meinen öffentlichen Github Repository finden. 🙂
    https://github.com/dekorlp/RayTracer
    (Zur Info: Das Demoimage aus der Readme.md ist veraltet, da ich damals eine Zeile in der Intersection Methode auskommentiert hatte und die Plane hinter der Kamera war. Diese ist jedoch zwingend notwndig für die Schattenberechnung, welche ich noch implementieren will in Zukunft)

    Vielen Dank im Vorraus für eure Hilfe

    Mit freundlichen Grüßen

    Dennis


Anmelden zum Antworten