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

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

1

31.08.2014, 21:02

[OpenGL] Anfänger: 2D Rendern

Hi,

ich beschäftige mit seit kurzem (nach einer langen Pause) mal wieder mit OpenGL, und will eigentlich nur zum Test mal eine 2D Texture rendern. (als Teil einer Font-Engine)

Allerdings bleibt der Bildschirm schwarz.
Beim Debuggen ist mir dann aufgefallen, dass

C-/C++-Quelltext

1
int location = glGetAttribLocation(this->ShaderProgram,"texCoord0");

-1 zurück gibt.

Mein Programm ist im Prinzip folgendermaßen aufgebaut:

INIT:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
[...] OpenGL initialisieren [...]
[...] Shader Erstellen [...]

[...] IndexBuffer erstellen[...]
[...] PositionsBuffer erstellen [...]
[...] TextureCoordsBuffer erstellen [...]

glBindAttribLocation(this->ShaderProgram, 0, "vertex0");
glBindAttribLocation(this->ShaderProgram, 1, "texCoord0");


RENDERN:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
glUseProgram(this->ShaderProgram);

[...] IndexBuffer binden [...]

[...] PositionsBuffer binden [...]
glVertexAttribPointer(location_von_vertex0, 2 , GL_FLOAT, false, 0, 0);

[...] TextureCoordsBuffer binden [...]
glVertexAttribPointer(location_von_texCoord0, 2 , GL_FLOAT, false, 0, 0); // --> Hier ist die location_von_texCoord0 == -1

[...] Texture binden [...]

int loc_von_pm = glGetAttribLocation(this->ShaderProgram,"pm");
pm = Ortho_matrix * ModelMatrix_vom_Text;
glUniformMatrix3fv(loc_von_pm, 1, false, floatArray_von_pm);

glDrawElements(GL_TRIANGLES, IndexBuffer->Size, GL_UNSIGNED_INT, 0);

[...] alles unbinden [...]


Vielleicht sei noch erwähnt, dass der Positions- und TextureCoords-Buffer jeweils so gefüllt wird:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool Buffer::Vector2Buffer::Fill(glm::vec2* data, const unsigned int numelements, const unsigned int use)
{
    if (data)
    {
        this->Bind();
        glBufferData(this->Target, numelements*sizeof(glm::vec2), &data[0], use);
        this->Unbind();

        this->BufferSize = numelements;

        return true;
    }
    return false;
}


Durch debuggen kann ich davon ausgehen, dass die Daten in den Buffern korrekt sind. Das Problem liegt wohl daran, dass glGetAttribLocation(this->ShaderProgram,"texCoord0") -1 zurückgibt.

Kann mir jemand weiterhelfen, woran das ggf. liegen kann?


Gruß

2

31.08.2014, 21:27

Wie sieht denn dein Shader aus?
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

3

01.09.2014, 09:45

Hi,

meinst du die TextShader Klasse, oder den Quellcode der Vertex-/Fragment-Shaders?


Ich poste den Code dann heut Nachmittag, wenn ich zuhause bin.



Gruß

4

01.09.2014, 14:40

Ich meine den shader Code hinter ShaderProgram
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

5

01.09.2014, 15:27

Hi,

hier ist er:

VertexShader

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#version 330

//Shader Parameter
uniform mat3 pm;

in vec2 vertex0;
in vec2 texCoord0;

out vec2 texCoords;

void main()
{
    texCoords = texCoord0;
    gl_Position = vec4(pm * vec3(vertex0, 1.0), 1.0);
}



FragmentShader

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
#version 330

precision highp float;

uniform sampler2D texture0;

in vec2 texCoord;

out vec4 outputColor;

void main(){
    outputColor = vec4(1.0, 1.0, 1.0, 1.0);
}


Der FragmentShader ist nur zum Debuggen, im Prinzip sollte ja ein weißes Rechteck gerendert werden (da wo der Text stehn sollte)


Gruß

6

01.09.2014, 17:23

Du verwendest texCoords im Fragment Shader nicht. Die Berechnung dieses Werts und damit auch die Verwendung von texCoord0 wird vom Shader Compiler "wegoptimiert". Daher kann das Attribut nicht verwendet werden.

Schau dir auch mal glBindAttribLocation(GLuint program, GLuint index, const GLchar *name) an, um dem Compiler vor dem Linken einen index für dein Attribut zu übergeben.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

7

01.09.2014, 18:28

Hi,

Zitat

Schau dir auch mal glBindAttribLocation(GLuint program, GLuint index, const GLchar *name) an, um dem Compiler vor dem Linken einen index für dein Attribut zu übergeben.

Jo, dass verwende ich ja schon (Siehe 1. Post)


Zitat

Du verwendest texCoords im Fragment Shader nicht. Die Berechnung dieses Werts und damit auch die Verwendung von texCoord0 wird vom Shader Compiler "wegoptimiert". Daher kann das Attribut nicht verwendet werden.

Das Problem liegt ja nicht an "texCoords", sondern an

C-/C++-Quelltext

1
int location = glGetAttribLocation(this->ShaderProgram,"texCoord0");


"texCoords" ist ja nur die Variable, die vom Vertex- an den Fragmentshader übergeben wird, "texCoord0" ist eine Uniform in Shader. Ist vielleicht etwas verwirrend, weil beide Variablen fast gleich heisen ;)



Gruß

8

01.09.2014, 20:01

Es ist so wie ich es gemeint habe, ich habe die variablen nicht vertauscht ;)
Mach irgendwas mit texCoords im PS und es wird gehen ;)

glBindAttribLocation muss vor dem linken den Shaders aufgerufen werden.
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »iSmokiieZz« (01.09.2014, 20:17)


Schwarzefee

Treue Seele

  • »Schwarzefee« ist der Autor dieses Themas

Beiträge: 155

Wohnort: Ost-Sachsen

Beruf: Programmierer

  • Private Nachricht senden

9

01.09.2014, 20:26

Hi,

ich hab den FragmentShader jetzt mal wieder "richtig" gemacht

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#version 330

precision highp float;

uniform sampler2D texture0;
uniform vec4 textcolor;

in vec2 texCoords;

out vec4 outputColor;

void main(){
    outputColor = texture(texture0, texCoords);
    outputColor = outputColor * textcolor;
}

Funktioniert trotzdem nicht.


Wenn ich beim Rendern nichts grundlegendes falsch gemacht habe, kann der Fehler ja eigentlich nurnoch an den Berechnungen von pm liegen.

Da ich bei GLM keine Berechnungsfunktionen für eine 3x3 Matrix gefunden habe, habe ich mir selber eine Helper Klasse gebastelt.

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "../../stdafx.h"
#include "Mat3x3.h"

glm::mat3 Math::Mat3x3::Translate(const glm::mat3 matrix, const float x, const float y)
{
    glm::mat3x3 m = Math::Mat3x3::Identity();
    m[2][0] = x;
    m[2][1] = y;

    glm::mat3 ret = matrix;

    ret *= m;

    return ret;
}

glm::mat3 Math::Mat3x3::Rotate(const glm::mat3 matrix, float angle)
{
    glm::mat3 m = glm::mat3(0.0f);

    float co, si;

    angle = angle * ((float)M_PI/180.0f);
    si = sinf(angle);
    co = cosf(angle);

    m[0][0] = co;
    m[0][1] = si;
    m[0][2] = 0;
    m[1][0] = -si;
    m[1][1] = co;
    m[1][2] = 0;
    m[2][0] = 0;
    m[2][1] = 0;
    m[2][2] = 1;

    glm::mat3 ret = matrix;
    ret *= m;

    return ret;
}

glm::mat3 Math::Mat3x3::Scale(const glm::mat3 matrix, const float x, const float y)
{
    glm::mat3 m = STEngine::Math::Mat3x3::Identity();

    m[0][0] = x;
    m[1][1] = y;

    glm::mat3 ret = matrix;

    ret *= m;

    return ret;
}

glm::mat3 Math::Mat3x3::Ortho(const int left, const int right, const int bottom, const int top)
{
    glm::mat3 ret = Math::Mat3x3::Identity();

    if (left != right && bottom != top)
    {
        ret[0][0] = 2 / (float(right - left));
        ret[1][1] = 2 / (float(top - bottom));
        ret[2][0] = -(float(right + left)) / (float(right - left));
        ret[2][1] = -(float(top + bottom)) / (float(top - bottom));
        ret[2][2] = 1;
    }

    return ret;
}

float* Math::Mat3x3::GetArray(const glm::mat3 matrix)
{
    std::vector<float> values;
    values.push_back(matrix[0][0]);
    values.push_back(matrix[0][1]);
    values.push_back(matrix[0][2]);
    values.push_back(matrix[1][0]);
    values.push_back(matrix[1][1]);
    values.push_back(matrix[1][2]);
    values.push_back(matrix[2][0]);
    values.push_back(matrix[2][1]);
    values.push_back(matrix[2][2]);

    return &values[0];
}

glm::mat3 Math::Mat3x3::Identity()
{
    glm::mat3 ident = glm::mat3(0.0f);

    ident[0][0] = 1.0f;
    ident[1][1] = 1.0f;
    ident[2][2] = 1.0f;

    return ident;
}


Beim Rendern:

Zuerst berechne ich die Orthologie-Matrix für das Fenster:

C-/C++-Quelltext

1
this->OrthoMatrix = Math::Mat3x3::Ortho(0, (int)width, 0, (int)height);


Die ModelMatrix für das TextObjekt berechne ich

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Identity Matrix
this->ModelMatrix = Math::Mat3x3::Identity();

//zur Rotation an den Rotationspunkt verschieben
this->ModelMatrix = Math::Mat3x3::Translate(this->ModelMatrix, this->Position + this->Rotationpoint);
//Rotieren
this->ModelMatrix = Math::Mat3x3::Rotate(this->ModelMatrix, this->Rotation);

//zurück Verschieben
this->ModelMatrix = Math::Mat3x3::Translate(this->ModelMatrix, -this->Rotationpoint.x, -this->Rotationpoint.y);

//Skalieren
this->ModelMatrix = Math::Mat3x3::Scale(this->ModelMatrix, this->Size);
this->ModelMatrix = Math::Mat3x3::Scale(this->ModelMatrix, this->Scale);


Und zum Ende berechne ich dann pm für den Shader

C-/C++-Quelltext

1
this->TextShader->sendUniform3x3("pm", Math::Mat3x3::GetArray(this->OrthoMatrix * text->GetModelMatrix()));


Hab ich da vielleicht schon irgendwo nen Fehler drin?
Mein Problem im Moment ist, dass ich nicht wirklich richtig debuggen kann, weil ich halt nicht weis, wie am Ende die Werte der pm-Matrix richtig aussehen müssen, bevor sie an den Shader gehen.


Gruß


EDIT: Ich habe mir mal GLSLDevil runtergeladen. Ich glaube das Problem entdeckt zu haben. Irgendwie wird das glGetAttribLocation() aufgerufen, bevor das ShaderProgram überhaupt gelinkt wird. Das sollte ja sicher nicht so sein. Deshalb gibt mir die Funktion immer -1 zurück.
Jetzt ist also erstmal debuggen angesagt, aber vielleicht kann doch jemand kurz über meine Mat3x3 Helper Klasse drübergucken, ob das alles soweit korrekt ist.

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Schwarzefee« (01.09.2014, 20:50)


10

02.09.2014, 01:28

Mit der Berechnung hat das nichts zu tun. Die Werte sind GLSL völlig egal.

Wo rufst du denn eigentlich int location = glGetAttribLocation(this->ShaderProgram,"texCoord0");
EnvisionGame(); EnableGame(); AchieveGame(); - Visionen kann man viele haben. Sie umzusetzen und auf das Ergebnis stolz zu sein ist die eigentliche Kunst.

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »iSmokiieZz« (02.09.2014, 01:40)


Werbeanzeige