0
\$\begingroup\$

I'm trying to draw a smooth cloth surface and I have a per-pixel shader. I expect to have a smooth surface but it's not the case. I think the problem comes from my normals.

The image show the surface drawn with multiple triangles. The surface is lit; the white zone are specular reflection.

enter image description here

Here is the way I calculate normals

ofVec3f v0(ps[i].pos.x, ps[i].pos.y, ps[i].pos.z);          
ofVec3f v3(ps[i+cols+1].pos.x, ps[i+cols+1].pos.y, ps[i+cols+1].pos.z);         
ofVec3f v1(ps[i+1].pos.x, ps[i+1].pos.y, ps[i+1].pos.z);
ofVec3f v2(ps[i+cols].pos.x, ps[i+cols].pos.y, ps[i+cols].pos.z);

    ofVec3f n0 = (v1-v0).cross(v3-v0);
    n0.normalize();
    ofVec3f n2 = (v0-v2).cross(v3-v2);      
    n2.normalize();
    ofVec3f n3 = (v0-v3).cross(v1-v3);      
    n3.normalize();
    ofVec3f n1 = -(v0-v1).cross(v3-v1);     
    n1.normalize();

Here is the code to draw my surface. It's a 64x64 array of double triangles

glBegin(GL_TRIANGLES);

for (int i=0; i<ps.size()-(cols+1); i++) { 
//  v0 - v1
//  | \  |
//  v2 - v3

// v0
glNormal3f(n0.x, n0.y, n0.z);
glVertex3f(ps[i].pos.x, ps[i].pos.y, ps[i].pos.z);

//v3
glNormal3f(n3.x, n3.y, n3.z);
glVertex3f(ps[i+cols+1].pos.x, ps[i+cols+1].pos.y, ps[i+cols+1].pos.z);


//v1
glNormal3f(n1.x, n1.y, n1.z);
glVertex3f(ps[i+1].pos.x, ps[i+1].pos.y, ps[i+1].pos.z);


//v0
glNormal3f(n0.x, n0.y, n0.z);
glVertex3f(ps[i].pos.x, ps[i].pos.y, ps[i].pos.z);

//v2
glNormal3f(n2.x, n2.y, n2.z);
glVertex3f(ps[i+cols].pos.x, ps[i+cols].pos.y, ps[i+cols].pos.z);

//v3
glNormal3f(n3.x, n3.y, n3.z);
glVertex3f(ps[i+cols+1].pos.x, ps[i+cols+1].pos.y, ps[i+cols+1].pos.z);

I don't know how many normals I need and where to put them: at each vertex, one by face ? four by vertex ? I still have a flat triangulated surface although I have a per pixel glsl shader

Thanks for help.

\$\endgroup\$
6
  • \$\begingroup\$ Looks quite smooth to me, apart from those holes in the top right. Is that what you want to fix? \$\endgroup\$
    – Anko
    Commented Aug 14, 2014 at 11:06
  • \$\begingroup\$ @Anko I expect not to see the triangles nor the quads but a uniform smooth surface \$\endgroup\$
    – user46759
    Commented Aug 14, 2014 at 11:24
  • 1
    \$\begingroup\$ You've shown us a fragment of code for drawing six vertices, each of which have a texture coordinate and three of which have normals. What primitive type are you drawing? What is your screenshot showing? Is that a screenshot of a single quad, or a pair of triangles, or a lot of triangles? Or something else? Are the colors we see in the screenshot coming from the texture? And why are you only putting normals on three of your six vertices? Give us at least a little help in terms of what you're doing, or we can't have any real idea of what's going wrong. \$\endgroup\$ Commented Aug 14, 2014 at 13:01
  • \$\begingroup\$ @TrevorPowell you're right. So I edited a little. I put only normals on three vertices because I'm not sure how and where to put normals in such a case. So I added three more and the result is the same \$\endgroup\$
    – user46759
    Commented Aug 14, 2014 at 14:23
  • \$\begingroup\$ You might want to look into VBOs and VAOs. That probably doesn't have anything to do with your question, but using newer "techniques" might help people answer your questions, as they might be more familiar with newer and possibly not deprecated stuff. \$\endgroup\$
    – user35344
    Commented Aug 14, 2014 at 15:12

2 Answers 2

3
\$\begingroup\$

The way you are computing vertex normals only considers an individual quad and not its neighbours. Thus you get the discontinuities between the somewhat flat quads.

If you want smooth normals, the way to compute them is to consider the gradient of nearby vertices on your grid.

If you've got points on the form

a-b-c
| | |
d-e-f
| | |
g-h-i

then you want to use the gradient between b,h and d,f when computing your normal for the vertex e. Alternatively, you can compute face normals for each surrounding quad and normalize the average of them to be your vertex normal.

All in all, you need to consider the neighbourhood of your vertices in order to get smooth shading across them. No amount of per-pixel shading will help you if the interpolated quantities are essentially constant.

\$\endgroup\$
1
  • \$\begingroup\$ I think you got it. I'll give a try. What do you mean by gradient? average ? \$\endgroup\$
    – user46759
    Commented Aug 14, 2014 at 18:59
0
\$\begingroup\$

Smooth shading can be enabled with glShadeModel(GL_SMOOTH) which is, however, the default. Your screenshot does look like you have the flat shading set.

\$\endgroup\$
1
  • \$\begingroup\$ I've enabled smooth shading \$\endgroup\$
    – user46759
    Commented Aug 14, 2014 at 14:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .