Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (480)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (546)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Help on Normals  (Read 3447 times)
0 Members and 1 Guest are viewing this topic.
Offline omg_meme

Senior Newbie





« Posted 2009-03-04 00:21:32 »

Hi everyone, I made a cloth simulation using vertex_strip and I'm having hard time with normals.

I have attached an image that will make things more clear...
So if you can see it you can notice that there is a kind of cross between the quads and the quads edges are darker and made of a flat color. I placed a sphere in the scene for collision detection, and it's working perfectly. I also changed two two times shaders and normals calculation , bui tnothing I always get the same problem.
If you have an idea why I got it please let me know.

P.s
Light is done in the  pixel shader

Thanks
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 781
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #1 - Posted 2009-03-04 00:51:21 »

It seems like the normals are just interpolated in the Fragment Shader, yielding normals with a length less than 1.

Are you re-normalizing the normals every fragment?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline omg_meme

Senior Newbie





« Reply #2 - Posted 2009-03-04 01:08:37 »


I wasn't doing it for the spec component. I was passing to it Normal instead of normalizedNormal. So thank you I fixed the specular component. But the the other problem persist. I attached another picture to show you.

Anyway thank you for your help.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Cakey

Junior Member





« Reply #3 - Posted 2009-03-04 01:15:35 »

Looks good! Cheesy
I know your prolly not supposed to post useless things but I figured a compliment is just as important as some code/explanation.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 781
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2009-03-04 01:38:19 »

I hate to say it, but it looks to me the gouraud shading also need re-normalized normals... ?

Because the shade in the corners is good, it just has linear interpolation of the shade over the triangle, which looks weird, but in the end it seems to be exactly the same problem as what you had with specular lighting.

What confuses me, is that you can use the same normal for both gouraud shading and specular shading, so maybe you are not working with the already re-normalized normal, but accessing interpolated (non-normalized) gl_Normal again for gouraud shading?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline omg_meme

Senior Newbie





« Reply #5 - Posted 2009-03-04 01:54:59 »

I'm not sure I completely understood what you say ( because of me...)  so I  posted the shader  code

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
varying vec3 Normal;
varying vec3 Light;
varying vec3 HalfVector;

void main(void)
{
    Normal = normalize(gl_NormalMatrix * gl_Normal);

    Light = normalize(gl_LightSource[0].position.xyz);

    HalfVector = normalize(gl_LightSource[0].halfVector.xyz);

   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


Fragment

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
varying vec3 Normal;
varying vec3 Light;
varying vec3 HalfVector;

void main(void)
{


vec3 lightNorm = normalize(Light);

vec3 normalizedNormal = normalize(Normal);


vec3 Diffuse = gl_FrontMaterial.diffuse.xyz*gl_LightSource[0].diffuse.xyz * max(dot(normalizedNormal.xyz, lightNorm.xyz),0.0);

vec3 Ambient = gl_FrontMaterial.ambient.xyz * gl_LightSource[0].ambient.xyz;

vec3 Specular = gl_FrontMaterial.specular.xyz * gl_LightSource[0].specular.xyz * pow(max(dot(normalizedNormal,HalfVector),0.0),gl_FrontMaterial.shininess);

vec3 total= Ambient + Diffuse  + Specular;
gl_FragColor = vec4(total,1.0);
}



Offline omg_meme

Senior Newbie





« Reply #6 - Posted 2009-03-04 01:58:55 »

Looks good! Cheesy
I know your prolly not supposed to post useless things but I figured a compliment is just as important as some code/explanation.

Thank you...
Offline lhkbob

JGO Knight


Medals: 32



« Reply #7 - Posted 2009-03-04 06:24:01 »

At first glance the shader code seems fine to me.  Are you sure you're computing the normals of the mesh correctly when you update the simulation? (you did say the sphere was shaded correctly, right?)

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 781
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #8 - Posted 2009-03-04 07:29:28 »

Are the normals calculated by taking one triangle's normal, or by calculating the average of all normals of the connecting triangles?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline omg_meme

Senior Newbie





« Reply #9 - Posted 2009-03-04 14:22:38 »

Are the normals calculated by taking one triangle's normal, or by calculating the average of all normals of the connecting triangles?

Vertex normals are calculated by taking the average of the triangles faces connected.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline omg_meme

Senior Newbie





« Reply #10 - Posted 2009-03-04 14:24:00 »

At first glance the shader code seems fine to me.  Are you sure you're computing the normals of the mesh correctly when you update the simulation? (you did say the sphere was shaded correctly, right?)

I'm not sure I'm doing it correctly, but  I changed to different algorithm and I got always the same problem.
Offline omg_meme

Senior Newbie





« Reply #11 - Posted 2009-03-04 14:28:23 »

As you can see from the image , you can perfectly notice the grid path darker, and that's really weird to me and a brighter cross in the middle. I don't no I tried everything but I work that out.
Offline lhkbob

JGO Knight


Medals: 32



« Reply #12 - Posted 2009-03-04 19:11:07 »

This is puzzling, but here are some suggestions:
1. What does it look like with standard ffp flat and smooth shading?
2. Try computing the half-vector on the fragment stage.
3. Visualize the normals:
   a. Actually draw all of the vertex normals as small lines
   b. Instead of computing lighting, just set gl_FragColor to the normal vector.

Offline omg_meme

Senior Newbie





« Reply #13 - Posted 2009-03-05 00:33:47 »


So... that is what I found out following your suggestions:

1 standard ffp smooth shading: same problem
2 flat shading: no problems ( see picture attached)
3 half vector in the fragment: same problem;
4 gl_FragColor to the normal: same problem( see picture attached)

I think it's because normals are calculate or assigned
Do you think the the cross could be due to the fact that opposite vertex in the quad have the same normal value ?

I don't wan to bother you with code but please if you could check how I calculate normals I would really appreciate:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
      Vec3 diff0=new Vec3(0,0,0);
      Vec3 diff1=new Vec3(0,0,0);
      Vec3 diff2=new Vec3(0,0,0);
      Vec3 diff3=new Vec3(0,0,0);
      Vec3 diff4=new Vec3(0,0,0);
      Vec3 diff5=new Vec3(0,0,0);
     
      if((col+1)<numberOfParticles)
          diff0=Vec3.subtract(getPosition(row, col+1), getPosition(row, col));
      if(((col+1)<numberOfParticles) && ((row+1)<numberOfParticles))
         diff1=Vec3.subtract(getPosition(row+1, col+1), getPosition(row, col));
      if((row+1)<numberOfParticles)
         diff2=Vec3.subtract(getPosition(row+1, col), getPosition(row, col));
      if((col-1)>-1)
       diff3=Vec3.subtract(getPosition(row, col-1), getPosition(row, col));
      if(((col-1)>-1) && ((row-1)>-1))
         diff4=Vec3.subtract(getPosition(row-1, col-1), getPosition(row, col));
      if(((col+1)<numberOfParticles) && ((row-1)>-1))
         diff5=Vec3.subtract(getPosition(row-1, col+1), getPosition(row, col));
     
      Vec3 normSum=Vec3.crossProduct(diff1, diff0).toVersor().sum(Vec3.crossProduct(diff2, diff1).toVersor()
            .sum(Vec3.crossProduct(diff3, diff2).toVersor()
                  .sum(Vec3.crossProduct(diff4, diff3).toVersor().sum(Vec3.crossProduct(diff5, diff4).toVersor()))));

     
      Vec3 normal = normSum.toVersor();
      normSum.glNormal3d(gl);
      getPosition(row, col).glVertex3d(gl);



Thank you
Offline bienator

Senior Member




OutOfCoffeeException


« Reply #14 - Posted 2009-03-05 02:17:52 »

1 standard ffp smooth shading: same problem
ffp smooth shading should give better results. Please double check if you are calculating the normls correctly and/or uploaded your VBO properly.

i think the easiest way to calculate per vertex normals is to first calculate them per face and interpolate in a second pass between all six faces in the neighborhood of each vertex. (haven't looked at your code, currently a bit busy)

i attached my ffp smooth shaded flag

Offline omg_meme

Senior Newbie





« Reply #15 - Posted 2009-03-05 05:02:10 »

I think I have to re calculate the normal form scratch... That really bother me...
Anyway bienator I saw your simulation looks great I can almost achieve that result only with about 60x60 and my solver (a simple verlet) but i need to get a lower step and my framerate go down to 15fps...

Did you use an implicit solver? like implicit euler for example?
Did you perform collision within the cloth mesh?

last question ... you said about VBO I did not know what it was so I checked and I was wondering : will be the simulation faster even if I have to fill the VBO every frame with new vertex?


Offline lhkbob

JGO Knight


Medals: 32



« Reply #16 - Posted 2009-03-05 05:49:37 »

Those results are, unfortunately, what I expected :|

1  
2  
3  
      Vec3 normal = normSum.toVersor();
      normSum.glNormal3d(gl);
      getPosition(row, col).glVertex3d(gl);



At first glance, late at night, your algorithm looks okay, with a few questions:
1. Why do you use only 6 difference vectors, instead of 8?  It looks like you're missing (row-1, col) and (row+1, col-1).
2. You calculate normSum.toVersor() but you don't pass that in to openGL.  If  you're passing in unnormalized normals, it may be screwing up your card's interpolator??  It's just a thought.

Offline Riven
« League of Dukes »

JGO Overlord


Medals: 781
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #17 - Posted 2009-03-05 07:12:05 »

I think he used 6 out of 8 as only 6 triangles actually connect to the center.

In theory 6 would be enough, because those other 2 would, in reality, not affect the normal.

If you are averaging the results (smoothing pass) you *do* care about the remaining 2.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline omg_meme

Senior Newbie





« Reply #18 - Posted 2009-03-05 08:54:54 »

yes exactly I thought I had to sum only the faces connected to the vertex.
This is the other way I calculated the normals obtaining the same result... I really don't know what to do... I'm really sorry again to bother you with long pieces of code but please take a look at it ....

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
   //--------------------------------------------------------------
  // Drawing particleGrid
  //--------------------------------------------------------------
 
   public void draw(GL gl)
   {
      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();
     
      clearNormals();
      for (int row = 0; row < numberOfParticlesLessOne; row++)
      {
         gl.glBegin(GL.GL_TRIANGLE_STRIP);
         for (int col = 0; col < numberOfParticles; col++)
         {
            drawVertex(row, col, gl);

            drawVertex(row + 1, col, gl);
         }

         gl.glEnd();
      }

   }
   
   
   private void drawVertex(int row, int col, GL gl)
   {
      Vec3 normal = getVertexNormal(row, col);
      normal.toVersor().glNormal3d(gl);
      getPosition(row, col).glVertex3d(gl);
   }
   
   private Vec3 getPosition(int row, int col)
   {
      return getParticles().get(col + (row * numberOfParticles)).getPosition();
   }
   
   private Vec3 getFaceNormal(int row, int col, int half)
   {
      Vec3 faceNormal = faceNormals[row][col][half];
      if (faceNormal == null)
      {
         Vec3 a = getPosition(row + 1, col);
         Vec3 b = getPosition(row, col + 1);
         Vec3 c = null;
         if (half == 0)
         {
            c = getPosition(row, col);
         }
         else
         {
            c = getPosition(row + 1, col + 1);
         }
         Vec3 v1 = Vec3.subtract(b, a);
         Vec3 v2 = Vec3.subtract(c, a);
         faceNormal = (half == 0) ? v1.crossProduct(v2).toVersor() : v2
               .crossProduct(v1).toVersor();
         faceNormals[row][col][half] = faceNormal.toVersor();
      }
      return faceNormal;
   }
   
   

   private Vec3 getVertexNormal(int row, int col)
   {
      Vec3 vertexNormal = vertexNormals[row][col];
      if (vertexNormal == null)
      {
         vertexNormal = new Vec3();

         if ((row > 0) && (col < numberOfParticlesLessOne))
         {
            vertexNormal.sum(getFaceNormal(row - 1, col, 0));
            vertexNormal.sum(getFaceNormal(row - 1, col, 1));
         }

         if ((row < numberOfParticlesLessOne) && (col > 0))
         {
            vertexNormal.sum(getFaceNormal(row, col - 1, 0));
            vertexNormal.sum(getFaceNormal(row, col - 1, 1));
         }

         vertexNormal.quotient(2D);

         if ((row > 0) && (col > 0))
         {
            vertexNormal.sum(getFaceNormal(row - 1, col - 1, 1));
         }

         if ((row < numberOfParticlesLessOne)
               && (col < numberOfParticlesLessOne))
         {
            vertexNormal.sum(getFaceNormal(row, col, 0));
         }

         vertexNormal.toVersor();
         vertexNormals[row][col] = vertexNormal;
      }
      return vertexNormal;
   }
   
   private void clearNormals()
   {
      for (int i = 0; i < numberOfParticles; i++)
      {
         for (int j = 0; j < numberOfParticles; j++)
         {
            vertexNormals[i][j] = null;
            if ((i < numberOfParticlesLessOne)
                  && (j < numberOfParticlesLessOne))
            {
               faceNormals[i][j][0] = null;
               faceNormals[i][j][1] = null;
            }
         }
      }
Offline DzzD
« Reply #19 - Posted 2009-03-05 10:02:02 »

Quote
Vertex normals are calculated by taking the average of the triangles faces connected

this may not work properly, when you compute a vertex normal you must consider that all adjacent face doesn't affect it the same, you have to use the size of the angle that touch the vertex to know how much it affect the vertex normal, at least it gave me better result.

Offline cylab

JGO Ninja


Medals: 43



« Reply #20 - Posted 2009-03-05 11:00:39 »

this may not work properly, when you compute a vertex normal you must consider that all adjacent face doesn't affect it the same, you have to use the size of the angle that touch the vertex to know how much it affect the vertex normal, at least it gave me better result.

Despite you are right, this shouldn't matter (much) in a (semi-)regular grid.

Mathias - I Know What [you] Did Last Summer!
Offline DzzD
« Reply #21 - Posted 2009-03-05 13:23:00 »

yup but this is only true until the grid is deformed as a cloth, then it become absolutly not regular, I am sure the shading is ok when all the cloth is flat.

in the exemple below "c" & "b" normals must be divided by two, "a" have twice more influence then c & b

EDIT: note that dividing c & b normals also work when grid is flat

Offline cylab

JGO Ninja


Medals: 43



« Reply #22 - Posted 2009-03-05 14:12:29 »

In this way you are right. I wouldn't however calclulate vertex normals in a grid from the "real" faces, but from 4 pyramid faces formed by the 4 surrounding vertices with the target vertex in the center.


Mathias - I Know What [you] Did Last Summer!
Offline DzzD
« Reply #23 - Posted 2009-03-05 15:10:25 »

Quote
I wouldn't however calclulate vertex normals in a grid from the "real" faces, but from 4 pyramid faces formed by the 4 surrounding vertices with the target vertex in the center.
I never thought about this, that could be interresting

The angle technic was the final technic I choosen for 3dzzd smoothgroups because the results was far away better then the others tehcnics I tried ( but it is a little more complex to implement). It give the same result on rendering then 3ds max when dealing with smoothgroups, so this is probably a good choice.

NB: ... maybe in some special case (not arbitrary mesh => deformed grid by a math function) computing new normals mathematicaly using the deform equation could be better. I mean if you know the 2d function that deform the flat grid you can mathematicaly compute normal of the "waves" at any points and get a nice normal for each vertex, this could also be very efficient.

Offline cylab

JGO Ninja


Medals: 43



« Reply #24 - Posted 2009-03-05 15:32:09 »

...I'm really sorry again to bother you with long pieces of code but please take a look at it ....

Your getFaceNormal is wrong. For half=1 you just switch the c-point, effectively reverting winding order. This way all your normals with half=1 point in the wrong direction.

Mathias - I Know What [you] Did Last Summer!
Offline omg_meme

Senior Newbie





« Reply #25 - Posted 2009-03-05 16:27:18 »

Your getFaceNormal is wrong. For half=1 you just switch the c-point, effectively reverting winding order. This way all your normals with half=1 point in the wrong direction.

I'm not sure I got it ... what shoud I do instead of c = getPosition(row + 1, col + 1); for half = 1?

Offline cylab

JGO Ninja


Medals: 43



« Reply #26 - Posted 2009-03-05 16:32:55 »

You have to switch the other two.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
   private Vec3 getFaceNormal(int row, int col, int half)
   {
      Vec3 faceNormal = faceNormals[row][col][half];
      if (faceNormal == null)
      {
         Vec3 a = null;
         Vec3 b = null;
         Vec3 c = null;
         if (half == 0)
         {
            a = getPosition(row + 1, col);
            b = getPosition(row, col + 1);
            c = getPosition(row, col);
         }
         else
         {
            a = getPosition(row, col + 1);
            b = getPosition(row + 1, col);
            c = getPosition(row + 1, col + 1);
         }
         Vec3 v1 = Vec3.subtract(b, a);
         Vec3 v2 = Vec3.subtract(c, a);
         faceNormal = v1.crossProduct(v2).toVersor();
         faceNormals[row][col][half] = faceNormal;
      }
      return faceNormal;
   }


Edit: I overlooked the (half==0), so your getFaceNormal should have been correct too...

Mathias - I Know What [you] Did Last Summer!
Offline omg_meme

Senior Newbie





« Reply #27 - Posted 2009-03-05 17:05:15 »

I was doing that because I was switching the cross product:

1  
2  
 faceNormal = (half == 0) ? v1.crossProduct(v2).toVersor() : v2
               .crossProduct(v1).toVersor();


in fact I obtain the same result.

Anyway thank you for have checked my code.


Offline Glex

Senior Newbie





« Reply #28 - Posted 2009-04-25 03:54:35 »

Cool, I was having the same problem without shaders.
Then folks from opengl.org explained that this glitch will always be present unless you use shaders.
Now someone is using shader, but the problem persists.
Hence, the problem is likely to be in the shader Smiley
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

atombrot (20 views)
2014-08-19 09:29:53

Tekkerue (21 views)
2014-08-16 06:45:27

Tekkerue (21 views)
2014-08-16 06:22:17

Tekkerue (12 views)
2014-08-16 06:20:21

Tekkerue (19 views)
2014-08-16 06:12:11

Rayexar (55 views)
2014-08-11 02:49:23

BurntPizza (37 views)
2014-08-09 21:09:32

BurntPizza (28 views)
2014-08-08 02:01:56

Norakomi (35 views)
2014-08-06 19:49:38

BurntPizza (64 views)
2014-08-03 02:57:17
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!