Flat-shading

Blitz3D Forums/Blitz3D Programming/Flat-shading

John Blackledge(Posted 2005) [#1]
(I've bumped this coz I lost my image in the other thread, but it needs answering anyway;)

I'm trying to write an app which will display other people's models.

This flat-shading (or lack of it) has been a constant bug-bear. (Obviously when I make my own I weld all my vertices - I'm a good boy.)

I've tried the suggestion of EntityFx ent,4 but it made no difference as you can see below. Any other ideas?




Difference(Posted 2005) [#2]
Forget about flag 4.

This is the first thinng I wrote in Blitz, so excuse the coding. It's not very stable, but it should show you what you need to do : http://www.blitzbasic.com/codearcs/codearcs.php?code=273

Try it out on some simple primitive.

Remember: For a cube you need 24 vertices, and your own normals (stay away from Updatenormals()! )


big10p(Posted 2005) [#3]
Yep, flag 4 is a bodge. To do flat shading properly, you need surface normals to light it, which blitz meshes (or is it DX?) doesn't support. Flag 4 simply causes each triangle to be lit using one of it's vertex normals, as if it were a surface normal. Unfortunately, vertex normals are usually smoothed and so will not be perpendicular to the triangle.

John, if you simply want to load a mesh in your app and have it display using flat shading, then you're out of luck, I'm afraid. Your only real option is to do what Peter says and rebuild the mesh.


John Blackledge(Posted 2005) [#4]
Brilliant response, thanks guys.

Vertices have normals?
I think I'm out of my depth here.
Peter I'll try your code, thanks.

So what's actually causing the problem in the picture above? Unwelded vertices? - Or is that incidental, and it's actually the vertex normals?

Normally, as a matter of course, I weld any vertices which occur at the same point in space - that seems to cure this effect in my own models.
But as I say, I'm trying to allow other people's models to be loaded. Is there an easy description for what has happened, and can I tell them to do 'such and such' when creating their own models, to prevent this.


TeraBit(Posted 2005) [#5]
Vertices have normals which would point in the same direction as the face normals (Point the same way as the triangle face). When they share more than one triangle (as in welded vertices), the normals are averaged between the face normals of each face.

In Blitz, it appears, they are even averaged between vertices which share the same point in space even if they're not physically connected to the face.

You can specify normals in many model formats, and the best way to get exact results is to get the vertex normals included in the file format (.B3D for example).

There are also entries in the Code Archives to calculate vertex normals for a mesh which would give hard edges.


John Blackledge(Posted 2005) [#6]
Thanks, Lee.

I would say that I'm a fair modeller, but even so a lot of what has been said goes over my head.

Would there be a simple statement I could offer to potential users of my app, such as 'to prevent this effect you should <make sure that your vertext normals point in the same direction as your face normals>' (- or some such)?


IPete2(Posted 2005) [#7]
John,

is your mobile switeched on? ;)

IPete2.


John Blackledge(Posted 2005) [#8]
Pete try my home number


TeraBit(Posted 2005) [#9]
<make sure that your vertext normals point in the same direction as your face normals>


You could do, but unless the file format has the normals embedded, it wouldn't do much good.

Give this routine a try:

http://www.blitzbasic.co.nz/codearcs/codearcs.php?code=975

And tell the users 'If you want a hard edge between polygons, unweld the vertices'.

Hopefully that should sort it out.


John Blackledge(Posted 2005) [#10]
That'll do nicely thanks Terabit.

Peter, the code works, but the offending model is 20 megs in size, so crashes on RenderWorld after changes implemented (hey-ho, not your fault).


John Blackledge(Posted 2005) [#11]
I think it is worth adding here, that the heart of the problem is that the light changes across the quad in a way that it should not. The two tris _are_ flat to each other, so it must be the vertex normals which are playing with the light effect.


big10p(Posted 2005) [#12]
The two tris _are_ flat to each other, so it must be the vertex normals which are playing with the light effect.
Correct.

Try this little lib if you want to actually see which way the vertex normals are pointing:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1085


Techlord(Posted 2005) [#13]
Vertex Normals effect lighting.

UpdateNormals

VertexNormal


puki(Posted 2005) [#14]
Might be worth cleaning your screen - dirt can affect shading.

; Monitor screen cleaning utility
; designed by "puki" - 29/08/05 

Graphics 640,480,16,1
WaitKey
ClsColor 255,255,255
Cls
WaitKey
End



John Blackledge(Posted 2005) [#15]
Puki, your reputation precedes you.
Need I say more?


Shifty Geezer(Posted 2005) [#16]
In Blitz, it appears, they are even averaged between vertices which share the same point in space even if they're not physically connected to the face.
That seems to be the case. I created a box of 8 verts, 12 tris, and another of 6 separate 4 vert 2 tri squares. Both had the same progessive shading over the surface despite the vertex norms all being the same a the faces. I then exploded the model so the faces had some space between them and the object's faces were flat shaded. Note that the distance they were exploded could n't be too small. At 1x10^-5 provided flat shading. Less then that and the vertices were averaged.


John Blackledge(Posted 2005) [#17]
I think I can quite happily finish off this thread.

The link TeraBit gave to sswift's code:
www.blitzbasic.co.nz/codearcs/codearcs.php?code=975
did the business!

This code works beautifully, and 'forces' a non-smooth look on meshes - particularly impressive if you want the edges of a vehicle or a building to have 'clean edges', instead of looking like it's been shaped from blancmange.

The only thing I changed was
Const swiftmax = 32768
Const maxtris = 32*4
Dim Face_NX#(swiftmax)
Dim Face_NY#(swiftmax)
Dim Face_NZ#(swiftmax)
Dim Vertex_ConnectedTris(swiftmax)
Dim Vertex_TriList(swiftmax, maxtris)

32*4 - to allow for more tris potentially attached to each vertex.

Cheers everyone!