Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Mai 18, 2024 19:33

Foren-Übersicht » English » English Programming Forum
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 48 Beiträge ]  Gehe zu Seite 1, 2, 3, 4  Nächste
Autor Nachricht
 Betreff des Beitrags: stencil shadow volumes
BeitragVerfasst: So Sep 05, 2004 18:34 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
I started adding stencil shadows to a gl3ds scene. I thougt the stencil shadow example from the sulaco site would be a great starting point. But then i realized that shadows there are only cast upon flat surfaces. But a mesh consists of many surfaces, would not this get very slow? I propably did something way wrong, all i get is a drop to 18fps (from 500fps) and no shadows.
Are there other (better) ways of getting shadows (easy ones?) Also some good plain english docs (i am not a math loving person)

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: So Sep 05, 2004 18:45 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
I have used this article to implement shadow volumes based (using 3DS-Scenes). And if you want real shadows, there's no way around stencil shadow volumes. You may use shadow mapping, but that technique has some serious problems as of now (it's hard to find the right polygonoffset cause it depends on your scene, Omni-Lighs need 6 Shadowmaps, you'll get aliasing due to the limited texture size and so on). Although there are tecchniques (Perspective Shadow Maps and so on) to get rid of the problems with SMs, I'd (for now) suggest shadow volumes. The good thing about shadow mapping is the fact (and that's what's the hardest part of shadow volumes) you don't need to know the underlying geometry, whereas you need for SVs to calculate connectivity, silhouettes, etc.

P.S. : I've wrapped stencil shadow functionality into an easy to use class that get's all infos from a 3DS-File. But I (as of now) don't want to make that available to public (it's GPL, but I'm sure that most ppl using it just would ignore the license). So if you have questions regarding implementation of shadow volumes, just ask (in this thread) and I'll help.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 06, 2004 17:05 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
first i need to get the logics right...

First i do a normal render of the scene filling depth mask etc..., but with setting first glColorMask( FALSE, FALSE, FALSE, FALSE );

Now i set stencil rendering with no depth mask
glEnable( GL_STENCIL_TEST );
glDepthMask( FALSE );
glStencilFunc( GL_ALWAYS, 0, 0 );

Next i do a showdow render (needs some calculation with regard to the light position?):
glStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
glCullFace( GL_BACK );
buildShadowVolume( 10, objlightpos, 0 ); //10 is mesh with id 10 objlight pos is the light position 0 is optional
So the buildshadowvolume needs to be done for each mesh that casts shadows....
This should have written a shadow in the stencil buffer, but it looks wrong

Now i reset rendering to normal:
glDepthMask( TRUE );
glDepthFunc( GL_LEQUAL );
glColorMask( TRUE, TRUE, TRUE, TRUE );
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

Nexit i do a render of the scene for the shadows parts (lights of) glStencilFunc( GL_EQUAL, 1, 1 );

Next i do normal render (lights on) glStencilFunc( GL_EQUAL, 0, 1 );

The buildshadowvolume looks like this
Code:
  1.  
  2. procedure buildShadowVolume( MeshID: Integer;lightposit: T3DPoint; ext: GlfLoat );
  3. var
  4.  i: integer;
  5.  e0, e1: integer;
  6.  vExtended: T3DPoint;
  7.  v1: T3DPoint;
  8. begin
  9.    glDisable( GL_LIGHTING );
  10.    glBegin( GL_TRIANGLES );
  11.    glColor3f( 0.2, 0.8, 0.4 ); //set shadow color
  12.  
  13.     //
  14.     // For each vertex of the shadow casting object, find the edge
  15.     // that it helps define and extrude a quad out from that edge.
  16.     //
  17.  
  18.    for i:=0 to scene.Mesh[meshid].NumFaces-1 do
  19.    begin
  20.         // Define the edge we're currently working on extruding...
  21.         e0 := i;
  22.         e1 := i+1;
  23.  
  24.         // If the edge's second vertex is out of array range,
  25.         // place it back at 0
  26.         if( e1 >= scene.Mesh[meshid].NumFaces-1 ) then e1 := 0;
  27.  
  28.         // v0 of our extruded quad will simply use the edge's first
  29.         // vertex or e0.
  30.  
  31.  
  32.         glVertex3f( scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e0]].x,
  33.                          scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e0]].y,
  34.                          scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e0]].z );
  35.  
  36.         // v1 of our quad is created by taking the edge's first
  37.         // vertex and extending it out by some amount.
  38.         vExtended:=extendVertex(  lightPosit, scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e0]], ext );
  39.         glVertex3f( vExtended.x, vExtended.y, vExtended.z );
  40.  
  41.         // v2 of our quad is created by taking the edge's second
  42.         // vertex and extending it out by some amount.
  43.         vExtended:=extendVertex( lightPosit, scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e1]], ext );
  44.         glVertex3f( vExtended.x, vExtended.y, vExtended.z );
  45.  
  46.         // v3 of our extruded quad will simply use the edge's second
  47.         // vertex or e1.
  48.         glVertex3f( scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e1]].x,
  49.                          scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e1]].x,
  50.                          scene.Mesh[meshid].Vertex[scene.Mesh[meshid].Face[e1]].x );
  51.     end;
  52.     glEnd();
  53.     glEnable( GL_LIGHTING );
  54. end;
  55.  


the extendVertex looks like:

Code:
  1.  
  2. function extendVertex( lightPosit, vert: T3DPoint; ext: GLFLoat ): T3DPoint;
  3. var
  4.   lightdir: T3DPoint;
  5. begin
  6.   // Create a vector that points from the light's position to the original vertex.
  7.   lightDir.x := vert.x - lightPosit.x;
  8.   lightDir.y := vert.y - lightPosit.y;
  9.   lightDir.z := vert.z - lightPosit.z;
  10.  
  11.   // Then use that vector to extend the original vertex out to a new position.
  12.   // The distance to extend or extrude the new vector is specified by t.
  13.   result.x := lightPosit.x + lightDir.x * ext;
  14.   result.y := lightPosit.y + lightDir.y * ext;
  15.   result.z := lightPosit.z + lightDir.z * ext;
  16. end;
  17.  


Obviously i am doing something wrong as all i get is wild bunch of triangles, but no shadow....
Any ideas on what i do wrong, most probably i am doing the calculations for rendering the shadows wrong.

PS: this is on of these things that look simple when you start.......

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Sep 06, 2004 17:56 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
You forgot something very important : [b]Connectivity[/url]! For shadow volumes, you need a silhouette that forms the edge of an object from the lights point of view. And to calculate that silhouette, you need to precalculate connectivity information for your meshes. You (best done at loading) therefore create an edgelist that stores how your vertices are connected together, so that you can later find the silhouette. A silhouette edge occurs, as soon as you have two triangles that share one edge, and on of those triangles is backfacing (away from the light) and the other is frontfacing (to the ligt). That's one of the hardest parts of shadow volumes, but if you get that done, then you're almost there. I'd suggest you take a look at http://www.delphi3d.net, where you can get a demo with source for shadow volumes, that does all those things, is good documented and loads it's data from an ASE-File. I also got some functions from that demo.

And as for the rendering procedure, it should go like this :
Code:
  1. for every light
  2.  Render ambient part (no lights enabled)
  3. for every light
  4.  Disable depth mask
  5.  Disable color writes
  6.  Clear stencil
  7.  Setup stencil
  8.  Render shadow volumes
  9.  Set stencil so that only fragments get drawn where stencil is = 0
  10.  Render diffuse part of the scene (i.e. lights enabled)
  11.  


That's what basically get's done for rendering stencil shadows. Alos note that stencil normally only works with closed meshes, otherwise you may get shadows that aren't right.

And as for the rendering of the shadow volume itself : It depends what you want to do. If you want to render them using ZPass, you do it like this :
Code:
  1. glCullFace(GL_FRONT);
  2. glStencilOp(GL_KEEP, GL_KEEP, GL_INCR_WRAP);
  3. RenderV;
  4. glCullFace(GL_BACK);
  5. glStencilOp(GL_KEEP, GL_KEEP, GL_DECR_WRAP);
  6. Render;

For ZFail (needed when you're in the shadow volume) it looks this way :
Code:
  1. glCullFace(GL_FRONT);
  2. glStencilOp(GL_KEEP, GL_INCR_WRAP, GL_KEEP);
  3. Render;
  4. glCullFace(GL_BACK);
  5. glStencilOp(GL_KEEP, GL_DECR_WRAP, GL_KEEP);
  6. Render;

But to speed it up, you can use an extension like ATI's separate stencil, so that you only need to render the volume once.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Sep 07, 2004 17:04 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
what is with the connectivity? Do you know some tutorials explaining that?
Arent all faces edges? And what is an edge?

In plain english i think i need to do the following:

For a mesh i need to read out a triangle(3 vertices)
Store the three vertices used for that
Store if it is front or back facing? (what if the light changes?) Or is the same as the inside and outside of an cube?
Read out the next triangle (next 3 vertices)
Check front or back facing
Compare those with the stored 3 vertices(triangle)
If 2 vertices are the same and one triangle is backfacing and the other is frontfacing i need to store an index to these 2 vertices

So i get a list of edges each with indexes to the 2 vertices used for it. :roll:

PS: projective stencil shadows are much easier, it is a pitty they only work on a plane object like a floor or wall....

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Sep 07, 2004 17:23 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
I don't know of any tuts explaining the connectivity-thing, because it ain't that hard. As I said above, you need to know the silhouette of an object (silhouette = outline of the object that faces the ligt. For a sphere i.e. the silhouette towards a light looks like a sphere). And for that, you need to know what triangles share the same edge, and an edge is NOT the same as a triangle. The edge is a line that is shared across two triangles and marks the "border" between them. Take a look at this :
Bild

The red line for example is the edge between the blue and the the green triangle. So you first need to get a list of all those edges (= all white lines in the shot above) and store them somewhere. This is your edge-list. (This is what's meant with building the connectivity info for a mesh)

The next step is to build the silhouette of your object, EVERY time the ligth changes, or the object's position/rotation changes. For that, you need the above edgelist. You now go through all your faces and look if they are front-facing (let's for example say the green one faces the light). So now you know that the red line is an edge shared by the green and blue triangle. Yow now look if the blue triangle is backfacing (away from the light). If that's the case, you add that edge to your silhouette-edgelist (cause that edge now is an edge between light and shadow). If the blue triangle also faces the light, you don't need to do anything. If you have done that for all your triangles, you have the silhouette-edge that "describes" the object from the lights point of view. This could for example (if the light is right behind the viewer) look like this :
Bild

So at last, you have to construct the shadow volume, but that's not hard anymore. You have the silhouette edge, and the position of the light source. So you now just have to extrude those edges away from the light source (at best towards infinity, with w=0 or an inifnite projection matrix) and you have a shadow volume that works with zPass-Shadows. For zFail-Shadows, you need to cap your volume, that means you have to add the front side of your object to the shadow volume and also have to extrude that frontside back to get a backcap. And if you have finished the shadowvolume, it should look something like this :
Bild

I hope that helped to clear things up a bit. If not, just ask. But if you got that part right, the rest is an easy task.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Sep 10, 2004 23:45 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
i changed the way gl3ds handles faces. I added a tface structure. It contains the 3 vertexes indexes, the 3 normals indexes, a plane equation, and a visible state and indexes to the neighbours of the face.
i am slowly getting there, but for the moment i am only able to render the volume, not the resulting shadow. Also the framerate is quite low. SOS: Using your 2sided building 3ds i get 83~140fps. What is your framerate with that mesh using volume shadows SOS?

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 00:02 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
@ Speed :
Can't tell you that (I don't use that model anymore), but stencil shadows are usually very heavy on the framerate. That's normal cause they burn a lot of fillrate, which especially older videocards don't have that much. So speed very much depends on how much shadows you see. The more parts of your screen are in shadows, the harder your framerate drops. But depending on your scene, you can easily optimize them by using for example scissoring.

@ Shadows + 3DS :
You should store your shadow volumes separate, cause you normally have to optimize your mesh if you want to display your shadows correct. 3DS often stores same vertices in the vertexlist and that may lead to problems. I myself have an own unit that has TShadowVolume class that can load it's data from a T3DSMesh. And after it loaded the data from that mesh, it optimizes the vertex list using this function I've taken from a demo of Tom Nuydens :
Code:
  1. procedure OptimizeTriangleList(var lst: TTriangleList; const va: array of TglVertex4f);
  2. var
  3.   itri: Integer;
  4.   function FindVertex(const v: TglVertex4f): Cardinal;
  5.   var
  6.     ivert: Integer;
  7.   begin
  8.     Result := 0;
  9.     for ivert := 0 to High(va) do
  10.     begin
  11.       if glCompareVertex(v, va[ivert], 0.0001) then
  12.       begin
  13.         Result := ivert;
  14.         Exit;
  15.       end;
  16.     end;
  17.   end;
  18. begin
  19. for itri := 0 to High(lst) do
  20.  begin
  21.  lst[itri,0] := FindVertex(va[lst[itri,0]]);
  22.  lst[itri,1] := FindVertex(va[lst[itri,1]]);
  23.  lst[itri,2] := FindVertex(va[lst[itri,2]]);
  24.  end;
  25. end;

I don't think that you always need to optimize the vertex list of a 3DS mesh, but when doing shadow volumes first I encountered that many 3DS meshes wouldn't give me proper shadows until I optimized the vertex list with the above function.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 09:59 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
this is how it looks now, it only draws the end shadow, but there are holes in them? See the 3 cubes. Could this be a stencil error or do i need an extra render pass?


Dateianhänge:
Dateikommentar: holes in shadows?
ws.jpg
ws.jpg [ 35.55 KiB | 7167-mal betrachtet ]

_________________
http://3das.noeska.com - create adventure games without programming
Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 10:35 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
That's a clear error. The "unshadowed" parts of in the shadow are there cause something with the stencil count is wrong. Have you used the above function to optimize the mesh and tried again? As I said, I had do to that to, because otherwise the shadows wouldn't work right.

And I've also noticed that I was smart enough to zip an older shadow volume demo that uses the mesh I send to you. So this is how it looks in my app :

Bild

The green lines are the silhouette edge, the blue polyongs are the shadow volumes. And this is how the shadowed scene should look like :

Bild

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 14:09 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
something else: i cannot seem to use glDepthMask(GL_FALSE);? In other demos i looked at it works, but not in my program? When i use it i get no shadows at all anymore?

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 16:14 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
That shouldn't happen. Maybe you did something wrong with the winding of your faces, so try changing that. Or you have set the depth test wrong. You normally set it to GL_LEQUAL (or GL_LESS) when rendering ambient and shadows and to GL_EQUAL when rendering the diffuse part of the scene.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 17:25 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 01, 2003 18:59
Beiträge: 887
Wohnort: (The Netherlands)
Programmiersprache: fpc/delphi/java/c#
In some examples i see using ~0 as stencil mask? How does that translate to delphi? Don't know if it is related?

_________________
http://3das.noeska.com - create adventure games without programming


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 17:30 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
You should use 255 for the stencilmask (glStencilMask($FF)).

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Sa Sep 11, 2004 18:37 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Never use GL_EQUAL with ATI cards. It disables the depth buffer optimization.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 48 Beiträge ]  Gehe zu Seite 1, 2, 3, 4  Nächste
Foren-Übersicht » English » English Programming Forum


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.011s | 16 Queries | GZIP : On ]