Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

BlackSnake

Community-Fossil

  • »BlackSnake« ist der Autor dieses Themas

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

11

12.03.2008, 12:31

ich habe den shader jetzt mal ein wenig abgewandelt. zwar nicht mehr der mit der besten performance, aber er dient als testwerkzeug^^:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    // Calculate normals

    float3 faceEdgeA = IN[0].position - IN[2].position;
    float3 faceEdgeB = IN[1].position - IN[2].position;
    float3 faceNormalA = normalize(cross(faceEdgeA, faceEdgeB));

    float3 faceEdgeC = IN[1].position - IN[0].position;
    float3 faceEdgeD = IN[2].position - IN[0].position;
    float3 faceNormalB = normalize(cross(faceEdgeC, faceEdgeD));

    float3 faceEdgeE = IN[0].position - IN[1].position;
    float3 faceEdgeF = IN[2].position - IN[1].position;
    float3 faceNormalC = normalize(cross(faceEdgeE, faceEdgeF));

    // Output the vertices

    OUT.position = IN[0].position;
    OUT.worldPosition = IN[0].worldPosition;
    OUT.tex0 = IN[0].tex0;
    OUT.normal = faceNormalA;
    STREAM.Append(OUT);

    OUT.position = IN[1].position;
    OUT.worldPosition = IN[1].worldPosition;
    OUT.tex0 = IN[1].tex0;
    OUT.normal = faceNormalB;
    STREAM.Append(OUT);

    OUT.position = IN[2].position;
    OUT.worldPosition = IN[2].worldPosition;
    OUT.tex0 = IN[2].tex0;
    OUT.normal = faceNormalC;
    STREAM.Append(OUT);

    // Restart

    STREAM.RestartStrip();

so hat ja jeder vertex seinen eigenen normalvektor.

EDIT:
die methode bringt ein geflecktes bild. die kugeln etc.. sehe jetzt aus wie kühe ;)

S.Seegel

2x Contest-Sieger

  • Private Nachricht senden

12

12.03.2008, 12:31

Per Face Normalen funktionieren immer dann, wenn du einen harten Bruch an den Kanten zwischen zwei Faces (i.A. Dreiecken) habe willst.
Wie z.B. bei eine Würfel, Quader, Pyramide, ...
Also immer da, wo die Dreiecke exakt der Oberfläche der darzustellenden geometrischen Form entsprechen.

Sobald die Dreiecke aber eine gekrümmte Fläche annähern, benötigt man der korrekten Form entsprechende Normalen, um bei der Beleuchtungsberechnung den durch die Approximation entstandenen Fehler vertuschen zu können.
Am besten gelingt das immer dann, wenn du die korrekte Normale analytisch berechnen kann, wie z.B. einer Kugel, Zylinder, Torus, ...

Es gibt nicht die eine Formel zur Berechnung der Normalen.

Denke doch nur mal an einen Kegel: um den darzustellen, benötigst du sowohl per Vertex Normalen für die gekrümmte Oberfläche, als auch per Face Normalen an der Spitze bzw. der Kante zum Boden.

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

13

12.03.2008, 12:49

Es nützt dir nichts, dreimal den gleichen Normal zu berechnen. Was ich meinte, war, zunächst für jedes Face den Normal zu bestimmen, anschließend für jeden Vertex alle Normals derjenigen Faces, die er begrenzt, aufzusummieren und dann zu normalisieren.

Daraus ergibt sich dann allerdings das Problem, dass du keine harten Kanten mehr hast, d.h. auch ein Würfel würde "rund" beleuchtet. Eine Möglichkeit, relativ schnell mit relativ hoher Wahrscheinlichkeit gute Ergebnisse zu erzielen, ist die Definition eines Grenzwinkels, der darüber entscheidet, ob eine Kante weich oder hart zu beleuchten ist.

Um vollständige Kontrolle über korrekte Ergebnisse zu haben, kannst du das Modell aber letztendlich nur mit bereits korrekten Normals aus dem Modeller deiner Wahl exportieren.

BlackSnake

Community-Fossil

  • »BlackSnake« ist der Autor dieses Themas

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

14

12.03.2008, 12:56

k, das macht am meisten sinn. nur hat das modellformat 3ds keine normals drin :?

BlackSnake

Community-Fossil

  • »BlackSnake« ist der Autor dieses Themas

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

15

30.03.2008, 19:40

habe es jetzt mal ein wenig rumprobiert. allerdings bilden sich kleine artefakte, die doch schon ein wenig störend sind. zudem kommt es zu dem problem, dass keine harten kanten mehr gebildet werden können. das wurde aber hier ja schonmal angesprochen.

zu erst die brechnugsweise der nomalvektoren.
zu allererst lese ich die vertice aus dem format:

C-/C++-Quelltext

1
2
3
4
5
6
7
                    // Read 

                    fread(&vertex, sizeof(float), 3, file);

                    // Copy

                    verticesExTemp[normalRun].position.x    = vertex.vertex[0];
                    verticesExTemp[normalRun].position.z    = vertex.vertex[1];
                    verticesExTemp[normalRun].position.y    = vertex.vertex[2];


wenn das geschehen ist, komm ich zu den indices. während ich die auslese, berechne ich gleich die normalvektoren.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
                    // Read 

                    fread(&index, sizeof(unsigned short), 4, file);

                    // Copy

                    indices[indexRun + indexFactor]     = index.index[0];
                    indices[indexRun + indexFactor + 1] = index.index[2];
                    indices[indexRun + indexFactor + 2] = index.index[1];

                    // Calculate normals

                    a = verticesExTemp[index.index[0]].position;
                    b = verticesExTemp[index.index[2]].position;
                    c = verticesExTemp[index.index[1]].position;
                    normal = BlackUtilityManager::GetSingleton()->CalculateTriangleNormal(a, b, c);

                    // Add normals to vertices

                    verticesExTemp[index.index[0]].normal += normal;
                    verticesExTemp[index.index[2]].normal += normal;
                    verticesExTemp[index.index[1]].normal += normal;

                    // Normalize

                    verticesExTemp[index.index[0]].normal.Normalize();
                    verticesExTemp[index.index[2]].normal.Normalize();
                    verticesExTemp[index.index[1]].normal.Normalize();


die funktion zum berechnen der normalvektoren sieht so aus.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
    // Variables

    BlackVec3Float temp1, temp2, temp3;

    // Calculate temp vecs

    temp1 = _p1 - _pointOfOrigin;
    temp2 = _p2 - _pointOfOrigin;

    // Calculate normal with crossproduct

    temp3 = temp1.Cross(temp2);
    
    // Normalize normal

    temp3.Normalize();


das ist meine vorgehensweise bis jetzt. soweit sollte eigentlich alles richtig sein. nur bilden sich jetzt die oben angesprochenden artefakte.

(Link)


(Link)


evtl. fällt jemanden der fehler ja auf. wenn ja, bitte sofort bescheid sagen. danke ;)

CodingCat

1x Contest-Sieger

Beiträge: 420

Beruf: Student (KIT)

  • Private Nachricht senden

16

31.03.2008, 15:44

Du normalisierst zu oft, du darfst erst zum Schluss normalisieren, wenn alle normalisierten Einzelnormals zusammenaddiert wurden, ansonsten erhalten die Normals verschiedener Faces je nach Reihenfolge verschiedene Gewichtungen, was nicht der Sinn der Sache ist. Außerdem musst du natürlich sicherstellen, dass alle Vertices miteinander verbunden sind, also keine Doppelvertices auf der selben Position existieren.

BlackSnake

Community-Fossil

  • »BlackSnake« ist der Autor dieses Themas

Beiträge: 1 549

Beruf: Student

  • Private Nachricht senden

17

31.03.2008, 18:12

danke,
ich weiß, dass doppelte vertizes existieren. werde ich mir mal ansehen.

Werbeanzeige