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

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

1

27.05.2015, 22:53

[Solved] OpenGL VAO nach Shader binden

Guten Abend,

wenn ich ein VAO nach dem Shader binde, wird nicht gerendert. Bespiel:

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
void ModelRenderer::update(float delta){
    // [...]
// die 3 Zeilen sollten doch eigentlich reichen?
    shader->bind();
    // [...]
    for(auto entity : entities){
        // [...]
        auto mesh = manager->getComponent<Mesh>(entity).lock();
        auto texture = manager->getComponent<Texture>(entity).lock();
        auto position = manager->getComponent<Positionable>(entity).lock();

        if(mesh->vao.good()){
            mesh->vao.bind(); // hier vorher binden

// folgt kein erneutes Binden wird nichts angezeigt:
            shader->bind();
            // [...]
        }
        else{
            mesh->index.bind(); // hier gibts kein VAO
            // [...]
            mesh->texCoord.vertexAttribPointer(texAtt, 2, GL_FLOAT, false, 0, 0);
        }

        // [...]

        glDrawElements(GL_TRIANGLES, mesh->index.size(), GL_UNSIGNED_INT, 0);
    }
// [...]
}


Woran liegt das und kann mans beheben?

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »DeKugelschieber« (31.05.2015, 16:18)


DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

2

28.05.2015, 11:38

Ah danke, ich konnte nichts finden wo VAO und Shader verwendet werden.
Meine ganzen Methoden wrappen einfach nur die OpenGL Funktionen.
Ich melde mich.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

28.05.2015, 11:57

Ich kann dir versichern, dass es egal ist, ob du zuerst das VAO und dann das Program Object bindest oder umgekehrt. So lange wir davon ausgehen können, dass es sich nicht um einen Bug in deinem Grafikdriver handelt, muss das Problem also irgendwo in deiner OpenGL Kapselung liegen...

Wieso bindest du manchmal nur das Mesh ohne das VAO zu binden?

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

4

28.05.2015, 12:35

Das sind die Standard Universalrenderer, die sollen beides können, also auch rendern wenn kein VAO vorhanden ist.

Wo ich gerade experimentiere um den Fehler zu finden ist der SpriteRenderer. Dort ist nur ein VAO nötig, da alle Sprites auf Quads gerendert werden. Wenn ich den Code so lasse wie er da gerade ist, wird ganz normal gerendert. Wenn ich nun das mesh.vao.bind(); unter das shader->bind(); schreibe funktioniert es nicht mehr.

Hier mal was ich gerade mache (vergleiche hier):

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
35
36
37
38
39
40
41
// Konstruktor
SpriteRenderer::SpriteRenderer(EntityManager* manager, Camera* camera, Shader* shader):
    Renderer(manager, camera, shader),
    texAtt(shader->getAttribLocation(TEXCOORD_ATTR_LOCATION)){
    // create mesh
    mesh.createRect(); // füllt 3 VBOs mit Daten, meine Buffer Objekte werden im Konstruktor erzeugt (also die ID)

    // create VAO
    mesh.vao.bind(); // glBindVertexArray(id);
    mesh.index.bind(); // glBindBuffer(target, id);
    mesh.vertex.bind();
    mesh.vertex.vertexAttribPointer(verAtt, 2, GL_FLOAT, false, 0, 0); // glVertexAttr...
    mesh.texCoord.bind();
    mesh.texCoord.vertexAttribPointer(texAtt, 2, GL_FLOAT, false, 0, 0);
    shader->enableVertexAttribArrays(); // for... glEnableVertexAttribArray(i); wobei i nicht einfach nur eine Zahl ist, sondern alle korrekten indices aus einem vector für diesen Shader
    mesh.vao.unbind();
}

// draw loop
void SpriteRenderer::update(float delta){
    camera->calculateOrtho3x3();

    shader->bind(false); // glUseProgram(id); das false sorgt dafür dass kein glVertexAttrib... aufgerufen wird
    shader->sendUniform(ORTHO_UNIFORM, camera->ortho2D); // glUniformMatrix3fv...
    shader->sendUniform(TEXTURE_UNIFORM, 0); // glUniform...

    mesh.vao.bind(); // glBindVertexArray(id);

    for(auto entity : entities){
        // unwichtig

        position->calculateModel3x3();
        shader->sendUniform(MODEL_UNIFORM, position->model2D); // glUniform...
        texture->bind(); // glActiveTexture(activeTexture); glBindTexture(target, id);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }

    mesh.vao.unbind(); // alles bind(0)
    shader->unbind(false);
}


Ich sehe den Unterschied zu dem Tutorial nicht.

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

5

28.05.2015, 17:18

Rendern ohne VAO ist übrigens obsolet und ist nicht Teil des Core Profiles von modernen OpenGL.

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

6

28.05.2015, 18:12

Okay, glVertexAttribArray und Co bracht man dann nur noch für VAOs?

Beiträge: 1 223

Wohnort: Deutschland Bayern

Beruf: Schüler

  • Private Nachricht senden

7

28.05.2015, 19:40

Ja genau.
Das ist dann Teil des Core Profiles.
In gewisser Weise ist aber das sogar schon wieder mit ARB_vertex_attrib_binding in OpenGL 4.3 und ARB_direct_state_accessin OpenGL 4.5 überholt.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Spiele Programmierer« (28.05.2015, 19:45)


DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

8

28.05.2015, 20:05

Ah pff, ich wechsel jetzt erstmal auf VAOs bis Vulkan kommt. Dann ist eh alles obsolet :D

DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

9

30.05.2015, 00:43

Hmm also wenn ich es noch mal aus dem ganzen System rausnehme und separat teste funktioniert es...
So gehts:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
bb::Shader* shader;
bb::Camera* camera;
bb::mat3 m;
bb::Texture* texture;
bb::Mesh* mesh;

void setup(){
    bb::ResourceManager::addDefaultLoader(resource);

    shader = new bb::Shader(bb::basic2DVertex, bb::basic2DFragment);
    shader->bindAttrib("vertex");
    shader->bindAttrib("texCoord");

    std::cout<<"1 "<<glGetError()<<std::endl;

    camera = new bb::Camera();
    m.identity();
    m.scale(100, 100);

    std::cout<<"2 "<<glGetError()<<std::endl;

    resource.load("texture", "src/test/assets/test.tga");
    texture = resource.get<bb::Texture>("texture").get();

    std::cout<<"3 "<<glGetError()<<std::endl;

    mesh = new bb::Mesh();
    mesh->createRect();

    std::cout<<"4 "<<glGetError()<<std::endl;

    mesh->vao.bind();
    mesh->index.bind();
    mesh->vertex.bind();
    mesh->vertex.vertexAttribPointer(shader->getAttribLocation("vertex"), 2, GL_FLOAT, false, 0, 0);
    mesh->texCoord.bind();
    mesh->texCoord.vertexAttribPointer(shader->getAttribLocation("texCoord"), 2, GL_FLOAT, false, 0, 0);
    mesh->vao.unbind();

    std::cout<<"5 "<<glGetError()<<std::endl;
}

void mainLoop(){
    shader->bind();
    shader->sendUniform("o", camera->ortho2D);
    shader->sendUniform("m", m);
    shader->sendUniform("tex", 0);

    mesh->vao.bind();
    texture->bind();

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glutSwapBuffers();
}

void reshape(const int width, const int height){
    glViewport(0, 0, width, height);
    camera->setViewport(0, 0, width, height);
    camera->calculateOrtho3x3();
}


Mal sehen wo der Haken innerhalb der Render Systeme ist.
Wenn jemand zufällig den Unterschied sieht kann er mir gerne bescheid sagen. Aufgesetzt wird in Test2D und gerendert im SpriteRenderer.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »DeKugelschieber« (30.05.2015, 00:55)


DeKugelschieber

Community-Fossil

  • »DeKugelschieber« ist der Autor dieses Themas

Beiträge: 2 641

Wohnort: Rheda-Wiedenbrück

Beruf: Software-Entwickler

  • Private Nachricht senden

10

31.05.2015, 16:13

Hmm ich habs hinbekommen dass die Reihenfolge keine Rolle mehr spielt:

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
void SpriteRenderer::update(float delta){
    camera->calculateOrtho3x3();

    shader->bind();
    shader->sendUniform(ORTHO_UNIFORM, camera->ortho2D);
    shader->sendUniform(TEXTURE_UNIFORM, 0);
    mesh.vao.bind();

    for(auto entity : entities){
        if(!Visibility::isVisible(manager, entity)){
            continue;
        }

        auto texture = manager->getComponent<Texture>(entity).lock();
        auto position = manager->getComponent<Positionable>(entity).lock();

        position->calculateModel3x3();
        shader->sendUniform(MODEL_UNIFORM, position->model2D);
        texture->bind();

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    }
}

Wenn ich jedoch nach binden des Shaders das VAO wechseln möchte, so wie z.B. im ModelRenderer, funktioniert es nicht. Dann wird nur das letzte Objekt das eingefügt wurde gerendert. Wenn ich den Shader und das VAO neu binde funktioniert es. Jemand eine Idee?

[Edit] Alles klar, die Vertex Attribute Arrays müssen aktiviert sein wenn das VAO gebunden ist :rolleyes:
Like so:

C-/C++-Quelltext

1
2
3
4
5
6
mesh->vao.bind();
shader->enableVertexAttribArrays();
mesh->index.bind();
mesh->vertex.bind();
mesh->vertex.vertexAttribPointer(shader->getAttribLocation("vertex"), 2, GL_FLOAT, false, 0, 0);
mesh->vao.unbind();

Werbeanzeige

Ähnliche Themen