# Schattenproblem, JOGL, gluPerspective.



## Kr0e (6. Sep 2008)

Hi, ich habe 2 Probleme, bei haben mit Schatten zu tun, hier das Erste:
Ich zeichne Schatten und wenn sich meine Kamera in diesem Schatten befindet ist der Schatten weg, obwohl ich meines Erachtens die zFail-Methode benutze. Hier der Code:

Ist leider ziemlich viel:




```
//Diese Funktion zeichnet Schatten von Polygonen, jedoch muss vorher
	//findPairs() ausgerufen worden sein
	public static void drawShadow(GL gl, LinkedList<Polygon> polygons, Vector lightPosition, double infinity, double alpha)
	{
		if(gl == null || polygons == null || lightPosition == null)
			return;
		
		//Zuerst werden alle notwendigen Funktionen aufgerufen, die es möglich machen
		//Schatten zu zeichnen 		
		gl.glClear( GL.GL_STENCIL_BUFFER_BIT );
								
		gl.glEnable(GL.GL_CULL_FACE);	
		
	 	gl.glDisable(GL.GL_LIGHTING);
	 	gl.glDepthMask(false);
	 	gl.glEnable(GL.GL_STENCIL_TEST);
	 	gl.glColorMask(false, false, false, false);						
	 	gl.glStencilFunc(GL.GL_ALWAYS, 1, 0xffffffff);
	 	
	 	gl.glFrontFace(GL.GL_CCW);
	 	gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR);
	 	
	 	//Nun den Schatten zeichnen lassen
		Iterator<Polygon> it = polygons.iterator();
		while(it.hasNext())
		{
			Polygon poly = it.next();
			
			if(poly != null && poly.getEdges() != null &&
		       poly.getPosition() != null && poly.getTriangles() != null)
			{
				//Zuerst die sichtbaren Dreiecke berechnen
				poly.calcVisibles(lightPosition);
				calcShadow(gl, poly, lightPosition, infinity);
			}
		}
	 	
	 	gl.glFrontFace(GL.GL_CW);
	 	gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_DECR);

	 	//Und nun den Schatten wieder erneut zeichnen
		it = polygons.iterator();
		while(it.hasNext())
		{
			Polygon poly = it.next();
		
			if(poly != null && poly.getEdges() != null &&
		       poly.getPosition() != null && poly.getTriangles() != null)
				calcShadow(gl, poly, lightPosition, infinity);
		}
		
	 	gl.glFrontFace(GL.GL_CCW);
	 	gl.glColorMask(true, true, true, true);
	 	
	 	gl.glColor4d(0, 0, 0, alpha);
	 	gl.glEnable(GL.GL_BLEND);
	 	gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
	 	gl.glStencilFunc(GL.GL_NOTEQUAL, 0, 0xffffffff);
	 	gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP);
	 	
		gl.glPushMatrix();
		
	 	gl.glLoadIdentity();
	 	gl.glBegin(GL.GL_TRIANGLE_STRIP);
	 		gl.glVertex3f(-0.2f, 0.2f, -0.1f);
	 		gl.glVertex3f(-0.2f,-0.2f, -0.1f);
	 		gl.glVertex3f( 0.2f, 0.2f, -0.1f);
	 		gl.glVertex3f( 0.2f,-0.2f, -0.1f);
	 	gl.glEnd();
	 	
		gl.glPopMatrix();
	 	
	 	gl.glDisable(GL.GL_BLEND);
	 	
	 	gl.glDepthMask(true);
	 	gl.glEnable(GL.GL_LIGHTING);
	 	gl.glDisable(GL.GL_STENCIL_TEST);
	 	
	 	gl.glDisable(GL.GL_CULL_FACE);	
	}
	
	private static void calcShadow(GL gl, Polygon polygon, Vector lightPosition, double infinity)
	{
		if(gl == null || polygon == null || lightPosition == null || polygon.getEdges() == null ||
		   polygon.getPosition() == null || polygon.getTriangles() == null)
			return;
		
		Vector extendDirection1, extendDirection2;
		Vector extendedVertex1, extendedVertex2;
		Vector pos = polygon.getPosition();
		
		//Gehe durch alle Kanten
		Iterator<Edge> it = polygon.getEdges().iterator();

		while(it.hasNext())
		{
			Edge edge = it.next();
			
			//Zuerst die beteiligten Dreiecke rauskopieren
			Triangle t1 = edge.triangles[0];
			Triangle t2 = edge.triangles[1];
			
			//Prüfe die beiden Triangles
			if ( ( t1.isVisible()  &&  !t2.isVisible() ) ||
				 ( !t1.isVisible() &&   t2.isVisible() ) )
			{		
				//Dann die Vektoren sichern
				Vector v1 = t1.getVertices()[ edge.vertIndices[0][0] ].getPosition().add(pos);
				Vector v2 = t1.getVertices()[ edge.vertIndices[0][1] ].getPosition().add(pos);
					
				//Berechne extrudierte Punkte
				extendDirection1 = v1.sub(lightPosition).unitVector();
				extendedVertex1 = v1.add(extendDirection1.mul(infinity));

				extendDirection2 = v2.sub(lightPosition).unitVector();
				extendedVertex2 = v2.add(extendDirection2.mul(infinity));
				
				if(t1.isVisible())
				{
					//Nun wird das Viereck gezeichnet
					gl.glBegin( GL.GL_QUADS );
						gl.glVertex3d( v2.x, v2.y, v2.z );					
						gl.glVertex3d( v1.x, v1.y, v1.z );
						gl.glVertex3d( extendedVertex1.x, extendedVertex1.y, extendedVertex1.z );
						gl.glVertex3d( extendedVertex2.x, extendedVertex2.y, extendedVertex2.z );
					gl.glEnd(); 
				} 
				
				else if(t2.isVisible())
				{
					//Nun wird das Viereck gezeichnet
					gl.glBegin( GL.GL_QUADS );
						gl.glVertex3d( v1.x, v1.y, v1.z );					
						gl.glVertex3d( v2.x, v2.y, v2.z );
						gl.glVertex3d( extendedVertex2.x, extendedVertex2.y, extendedVertex2.z );
						gl.glVertex3d( extendedVertex1.x, extendedVertex1.y, extendedVertex1.z );
					gl.glEnd(); 
				} 
			}
		}
	}
```

So, das 2te ist das ich bei gluPerspective als ersten Parameter 45 eintrage. Doch dann werden die Schatten ziemlich "zahnrädig" und flackern. Woran könnte das liegen ? Bei 90 ist es weg, dafür sehen jedoch die Kugeln bei bestimmten Winkel "eiförmig" aus....

Gruß Chris


----------



## Fancy (7. Sep 2008)

Moin,

bin zwar auch nicht der Stencil Shadow Volume Experte, aber mal ein Schuss ins blaue:


```
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
```

Dann sollte gelten: zPass (mit Problemen der near plane im shadow volume)

```
// front face
gl.glFrontFace(GL.GL_CCW); 
gl.glStencilOp(GL.GL_KEEP, G.GL_KEEP, GL.GL_INCR);
// [..]

// back face
gl.glFrontFace(GL.GL_CW);
gl.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_DECR);
//[..]
```

Dann sollte gelten: zFail (mit Problemen der far plane im shadow volume)

```
// back face
gl.glFrontFace(GL.GL_CW);
gl.glStencilOp(GL.GL_KEEP, GL.GL_INCR, GL.GL_KEEP);
//[..]

// front face
gl.glFrontFace(GL.GL_CCW); 
gl.glStencilOp(GL.GL_KEEP, GL.GL_DECR, GL.GL_KEEP);
// [..]
```

Bei Deinem Code, sieht mir das, zumindest auf den ersten Blick, also nach zPass und nicht nach zFail aus. Das würde dann erklären warum der Schatten aus dem tritt kommt sobald die near plane ins shadow volume eintritt. 

Warum die Qualität der Schatten bei Dir aber von gluPerspective abhängt, kann ich Dir auf Anhieb allerdings auch nicht sagen.

Gruß,
Michael


----------



## Kr0e (7. Sep 2008)

Hallo Michael,

danek für die Hinweise, ich probiers direkt mal aus ! Das mit der Qualität hat sich geklärt. Bei gluPerspective hatte ich die far und near zu extrem gesetzt... near = 0.001, far = 100, da ja far/near geteilt wird, um die GEnauigkeit des Buffers zu bestimmen, trat hier der Fehler auf!

Gruß Chris


----------

