Fewer vertices mapped to more vertex normals?

Started by
5 comments, last by pcmaster 5 years, 1 month ago

Hi,

I am wondering.. If I have something like a cube which has 8 vertices which are referenced through an index buffer, Is there a way I would go about assigning unique vertex normals to each vertex which I figure are 24... From my current knowledge I think I would need about 24 normals assigning 4 identical normals to each face for the lighting to work correctly , for this to work I would need 24 vertices which eliminates the need for an index buffer. I figured vertex averging was working wrongly here because of very sharp edges.  Is it possible to still use normals on cube geometry while using an index buffer such that my vertex count remains 8 or the only way this goes is by using a non indexed geometry with just regular DrawInstanced (dx12) ?

Advertisement

Short answer: It isn't possible.

Long answer: Out of your vertices 0-7 on a cube, each vertex participates in multiple triangles. However it won't be re-shaded multiple times (unless it doesn't fit into the cache). So if you have an index buffer with indices 0, 1, 2, 0, 1, 3 for example, vertex 0 is going to be shaded exactly once, as are all the other vertices. When the input assembler sees vertex 0 for the second time it thinks: "Ha, I've already shaded this one!"

Inside the vertex shader, there's no way of telling which triangle (primitive) a vertex belongs to.

So you do have to duplicate all previously shared vertices where you want a sharp edge between triangles, basically.

Thanks for the helpful response again pcmaster.  Would you know a better way on how to resolve complicated meshes which would have both smooth and sharp edges? Would I need to do away with indices to be safe? Or should I detect the angles somehow and somehow use index buffer?

A way around this might be not using indexed rendering at all and also not using any input assembly or fetch shaders, but rather fetching everything yourself. It won't perform very well as it'll circumvent all the caching and prefetching circuitry of the modern GPUs.

You'd issue a Draw(6 * 2 * 3) /* 6 sides, 2 triangles each, 3 vertices each */ and connect a general buffer with a Wavefront-Obj-like independent indices to vertices, indices to normals and/or indices to UVs. You'd index it by SV_VertexID running from 0 to 35 (you've got nothing else in your vertex shader), so in the end you could have just 8 vertices, 6 normals and 8 uv:s, for example. You wouldn't have any VB or IB, just general GPU-readable buffers.

There's been a discussion about something similar in this very forum one or two weeks ago, read through it.

 

3D modelling softwares do this for you. Smoothing groups. Do you want to process your meshes yourself?

7 minutes ago, pcmaster said:

You'd issue a Draw(6 * 2 * 3) /* 6 sides, 2 triangles each, 3 vertices each */ and connect a general buffer with a Wavefront-Obj-like independent indices to vertices, indices to normals and/or indices to UVs. You'd index it by SV_VertexID running from 0 to 35 (you've got nothing else in your vertex shader), so in the end you could have just 8 vertices, 6 normals and 8 uv:s, for example. You wouldn't have any VB or IB, just general GPU-readable buffers.

I think I will read this properly when I settle down ? as it's slightly overwhelming.

8 minutes ago, pcmaster said:

Do you want to process your meshes yourself?

I am actually trying read Obj files into my application. And one file I exported has more vertex normals than there are vertices which was surprising to me because I have yet to know how these are grouped together. I don't have knowledge of smoothing groups but I have used something similar when I used to use 3ds max ? 

6 minutes ago, pcmaster said:

There's been a discussion about something similar in this very forum one or two weeks ago, read through it.

I will look through this, thanks! 

Np :)

Imagine you have just a quad of two triangles, with 1 normal, 4 vertices and 4 UVs.

It might look like


# 4 vertices
v ...
v ...
v ...
v ...
  
# 1 normal
vn 0 1 0
  
# 4 UVs
vt ..
vt ..
vt ..
vt ..
  
# 2 triangles
f 0/0/0 1/1/0 2/2/0
f 0/0/0 2/2/0 3/3/0

And if you want to render it with DrawIndexed, you still have to prepare a structure with 4 vertex-structs (pos+normal+uv) and 6 indices. Already with such a blatantly simple quad, you have to do something about it when parsing it, if you want to go indexed.

Real examples will be more complicated but you'll have to do the same. I'm pretty sure, there are plenty of Wavefront-Obj readers for all programming languages around, although I'm pretty sure many of us wrote plenty of them for ourselves over the years, over and over again :D

 

This topic is closed to new replies.

Advertisement