Wystąpiłem kilka rozwiązań tutaj i innych stron do obliczania normalnych wierzchołków. Wspólne rozwiązanie, które wydaje się najlepsze dla mojej własnej implementacji, która sprawia, że teren 3D jest obliczenie normalności twarzy, która nie jest problemem. A potem przejdź na każdą twarz i dodaj to normalne do wierzchołków, które to podejmują, a następnie znormalizują te, gdy skończysz. Wydaje się, że działa w większości, ale mam dziwne problemy graficzne, głównie gdzie światła przejścia z lekkiego do ciemnego, możesz powiedzieć, gdzie są twarze. Na poniższym obrazie widać to w pobliżu po prawej stronie, na szczycie tego wzgórza.

Więc zastanawiam się, co powoduje ten dziwny wzór. Ma coś wspólnego z tym, jak obliczę normalne, ale nie widzę, gdzie jest problem. Wszelka pomoc byłaby doceniona. Księżycowy teren render

Kod do obliczenia normalnych jest ...

// Calclulate surface normals
vec3 v1, v2, v3, vec1, vec2;
for(GLuint i = 0; i < terrain->NumFaces; i++) {
   v1 = terrain->Vertices[terrain->Faces[i].vert_indices[0]];
   v2 = terrain->Vertices[terrain->Faces[i].vert_indices[1]];
   vec1 = vector(&v2, &v1);

   v3 = terrain->Vertices[terrain->Faces[i].vert_indices[2]];
   vec2 = vector(&v3, &v1);

   terrain->Faces[i].surface_normal = crossProduct(&vec1, &vec2);

   normalize(&terrain->Faces[i].surface_normal);
}


// Calculate vertex normals...
// Add all the surface normals to their attached vertex normals
for(GLuint currentFace = 0; currentFace < terrain->NumFaces; currentFace++) {
   vec3 *f = &terrain->Faces[currentFace].surface_normal;
   for(GLuint faceVertex = 0; faceVertex < 3; faceVertex++) {
      vec3 *n = &terrain->Normals[terrain->Faces[currentFace].vert_indices[faceVertex]];
      *n = vec3Add(n, f); // adds vector f to n
   }
}

// Go over all vertices and normalize them
for(GLuint currentVertice = 0; currentVertice < terrain->NumVertices; currentVertice++)
   normalize(&terrain->Normals[currentVertice]);

Inne funkcje użytkowe Używane w powyższym kodzie są ...

// Returns the vector between two vertices
vec3 vector(const vec3 *vp1, const vec3 *vp2)
{
    vec3 ret;
   ret.x = vp1->x - vp2->x;
   ret.y = vp1->y - vp2->y;
   ret.z = vp1->z - vp2->z;
    return ret;
}


// Returns the normal of two vectors
vec3 crossProduct(const vec3 *v1, const vec3 *v2)
{
   vec3 normal;
   normal.x = v1->y * v2->z - v1->z * v2->y;
   normal.y = v1->z * v2->x - v1->x * v2->z;
   normal.z = v1->x * v2->y - v1->y * v2->x;

   return normal;
}


// Returns the length of a vector
float vec3Length(vec3 *v1) {
   return sqrt(v1->x * v1->x + v1->y * v1->y + v1->z * v1->z);
}


// Normalizes a vector
void normalize(vec3 *v1)
{
   float len = vec3Length(v1);
   if(len < EPSILON) return;
   float inv = 1.0f / len;
   v1->x *= inv;
   v1->y *= inv;
   v1->z *= inv;
}


// Adds vector v2 to v1
vec3 vec3Add(vec3 *v1, vec3 *v2)
{
   vec3 v;

   v.x = v1->x + v2->x;
   v.y = v1->y + v2->y;
   v.z = v1->z + v2->z;

   return v;
}
0
Neil Roy 24 luty 2019, 23:10

2 odpowiedzi

Najlepsza odpowiedź

Po eksperymentowaniu z różnymi rozwiązaniami odkryłem, że moje własne zwykłe pokolenie w tym poście działa niezwykle dobrze, to praktycznie natychmiastowe i nie było problemem. Problem wydawał się używać dużej tekstury dla terenu. Zmieniłem teksturę, którą użyłem do terenu, aby użyć kafelkowej tekstury, która nie zostałaby rozciągnięta, a kwestia graficzna wydaje się odeszła. Była to ulga, że normalne pokolenie, które zamieszczałem, działa dobrze, ponieważ inne rozwiązania były strasznie powolne. To właśnie skończyło się, a jak widać, nie ma problemów graficznych. Plus wygląda lepiej bardziej szczegółowo. Chciałem opublikować to, co dowiedziałem się, gdyby ktoś inny widzi ten sam problem.

Lunar 3D Terrain

0
Neil Roy 1 marzec 2019, 00:45

Jednym z problemów z zastosowaniem średniej normalności twarzy w celu obliczenia normalnych wierzchołków jest to, że obliczone normalne mogą być stronnicze. Na przykład wyobraź sobie, że znajduje się grzbiet, który biegnie na północ / południe. Jeden wierzchołek na szczycie grzbietu ma trzy wielokąty po wschodniej stronie, a dwa na zachodzie. Normalny wierzchołek będzie wędrowany na wschód. Może to spowodować ciemniejsze oświetlenie w tym momencie, gdy oświetlenie pochodzi z Zachodu.

Możliwą poprawą byłoby zastosowanie wagi do normalnej powierzchni, proporcjonalnej do kąta, który róg twarzy ma w tym wierzchołku, ale nie pozbywa się wszystkich stronniczości.

2
1201ProgramAlarm 24 luty 2019, 23:02