Flat-shading
Blitz3D Forums/Blitz3D Programming/Flat-shading
| ||
(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? |
| ||
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()! ) |
| ||
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. |
| ||
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. |
| ||
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. |
| ||
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)? |
| ||
John, is your mobile switeched on? ;) IPete2. |
| ||
Pete try my home number |
| ||
<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. |
| ||
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). |
| ||
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. |
| ||
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 |
| ||
Vertex Normals effect lighting. UpdateNormals VertexNormal |
| ||
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 |
| ||
Puki, your reputation precedes you. Need I say more? |
| ||
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. |
| ||
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! |