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

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

1

30.06.2013, 22:10

[C++ & OpenGL] Frage zum OpenGL Shader

Guten Abend,
ich habe beschlossen im zuge eines Spieleprojektes mich auch ein wenig mit der GLSL zu beschäftigen. Die ersten Gehversuche haben auch schon ganz gut geklappt. Nun bin ich aber an eine Grenze gestoßen wo ich nicht weiter komme und auch nichts bei Google finde, aber warscheinlich bin ich auch einfach nur zu blöde um eine Lösung zu finden. Ich habe zwei Würfel, die sich gegeneinander drehen. Beide sollen zwei unterschiedliche Texturen bekommen. Nun habe ich das Problem das wenn ich den Shader zwei mal mit unterschiedlichen TextureUnits aufrufe nichts sehe. Wenn ich aber nur einmal den einen oder den anderen TextureUnite mit dem Shader aufrufe sehe ich nur einen Würfel, was mache ich falsch oder wie machen das ander?
Ich würde mich sehr über Antworten freuen.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

30.06.2013, 22:35

Schwer zu sagen, wenn du uns nicht verraten willst, was genau du tust (Code?). Aber ich lehn mich mal aus dem Fenster und rate, dass du deinen sampler2D Uniforms die id der Texture als Wert übergibst, anstatt den Index der jeweiligen Texture Unit, an die deine Texture gebunden ist...

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

3

01.07.2013, 10:47

Danke schon einmal für deine Antwort, ich verstehe aber grade nur Bahnhof.

Ich erstelle mein Modell und Texture in der ModelClass so:

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
bool ModelClass::InitializeTextureBuffers(OpenGLClass* OpenGL)
{
    VertexType* vertices;
    unsigned int* indices;
    int i;

    // Create the vertex array.
    vertices = new VertexType[m_vertexCount];
    if(!vertices)
    {
        return false;
    }

    // Create the index array.
    indices = new unsigned int[m_indexCount];
    if(!indices)
    {
        return false;
    }

    // Load the vertex array and index array with data.
    for(i=0; i<m_vertexCount; i++)
    {
        vertices[i].x  = m_model[i].x;
        vertices[i].y  = m_model[i].y;
        vertices[i].z  = m_model[i].z;
        vertices[i].tu = m_model[i].tu;
        vertices[i].tv = 1.0f - m_model[i].tv;
        vertices[i].nx = m_model[i].nx;
        vertices[i].ny = m_model[i].ny;
        vertices[i].nz = m_model[i].nz;

        indices[i] = i;
    }

    // Allocate an OpenGL vertex array object.
    OpenGL->glGenVertexArrays(1, &m_vertexArrayId);

    // Bind the vertex array object to store all the buffers and vertex attributes we create here.
    OpenGL->glBindVertexArray(m_vertexArrayId);

    // Generate an ID for the vertex buffer.
    OpenGL->glGenBuffers(1, &m_vertexBufferId);

    // Bind the vertex buffer and load the vertex (position, texture, and normal) data into the vertex buffer.
    OpenGL->glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferId);
    OpenGL->glBufferData(GL_ARRAY_BUFFER, m_vertexCount * sizeof(VertexType), vertices, GL_STATIC_DRAW);

    // Enable the three vertex array attributes.
    OpenGL->glEnableVertexAttribArray(0);  // Vertex position.
    OpenGL->glEnableVertexAttribArray(1);  // Texture coordinates.
    OpenGL->glEnableVertexAttribArray(2);  // Normals.

    // Specify the location and format of the position portion of the vertex buffer.
    OpenGL->glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferId);
    OpenGL->glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(VertexType), 0);

    // Specify the location and format of the texture coordinate portion of the vertex buffer.
    OpenGL->glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferId);
    OpenGL->glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(VertexType), (unsigned char*)NULL + (3 * sizeof(float)));

    // Specify the location and format of the normal vector portion of the vertex buffer.
    OpenGL->glBindBuffer(GL_ARRAY_BUFFER, m_vertexBufferId);
    OpenGL->glVertexAttribPointer(2, 3, GL_FLOAT, false, sizeof(VertexType), (unsigned char*)NULL + (5 * sizeof(float)));

    // Generate an ID for the index buffer.
    OpenGL->glGenBuffers(1, &m_indexBufferId);

    // Bind the index buffer and load the index data into it.
    OpenGL->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferId);
    OpenGL->glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount* sizeof(unsigned int), indices, GL_STATIC_DRAW);
    
    // Now that the buffers have been loaded we can release the array data.
    delete [] vertices;
    vertices = 0;

    delete [] indices;
    indices = 0;

    return true;
}


Dabei ist der TextureUnit ein Intiger den ich mir aus einer anderen Klasse hole.
Dann übergebe ich alle Parameter dem Shader:

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
bool LightShaderClass::SetShaderParameters(OpenGLClass* OpenGL, float* worldMatrix, float* viewMatrix, float* projectionMatrix,
                                           int textureUnit, float* lightDirection, float* diffuseLightColor, float* ambientLight)
{
    unsigned int location;


    // Set the world matrix in the vertex shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "worldMatrix");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniformMatrix4fv(location, 1, false, worldMatrix);

    // Set the view matrix in the vertex shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "viewMatrix");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniformMatrix4fv(location, 1, false, viewMatrix);

    // Set the projection matrix in the vertex shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "projectionMatrix");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniformMatrix4fv(location, 1, false, projectionMatrix);

    // Set the texture in the pixel shader to use the data from the first texture unit.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "shaderTexture");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniform1i(location, textureUnit);

    // Set the light direction in the pixel shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "lightDirection");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniform3fv(location, 1, lightDirection);

    // Set the light direction in the pixel shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "diffuseLightColor");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniform4fv(location, 1, diffuseLightColor);

    // Set the ambient light in the pixel shader.
    location = OpenGL->glGetUniformLocation(m_shaderProgram, "ambientLight");
    if(location == -1)
    {
        return false;
    }
    OpenGL->glUniform4fv(location, 1, ambientLight);

    return true;
}


Und zu guter letzt die beiden Shader

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
//////////////////////
// OUTPUT VARIABLES //
//////////////////////
out vec4 outputColor;


///////////////////////
// UNIFORM VARIABLES //
///////////////////////
uniform sampler2D shaderTexture;
uniform vec3 lightDirection;
uniform vec4 diffuseLightColor;
uniform vec4 ambientLight;


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
    vec4 textureColor;
    vec4 color;
    vec3 lightDir;
    float lightIntensity;


    // Sample the pixel color from the texture using the sampler at this texture coordinate location.
    textureColor = texture(shaderTexture, texCoord);

    // Set the default output color to the ambient light value for all pixels.
    color = ambientLight;

    // Invert the light direction for calculations.
    lightDir = -lightDirection;

    // Calculate the amount of light on this pixel.
    lightIntensity = clamp(dot(normal, lightDir), 0.0f, 1.0f);

    if(lightIntensity > 0.0f)
    {
        // Determine the final diffuse color based on the diffuse color and the amount of light intensity.
        color += (diffuseLightColor * lightIntensity);
    }

    // Clamp the final light color.
    color = clamp(color, 0.0f, 1.0f);

    // Multiply the texture pixel and the final diffuse color to get the final pixel color result.
    outputColor = color * textureColor;
}

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
////////////////////////////////////////////////////////////////////////////////
// Filename: light.vs
////////////////////////////////////////////////////////////////////////////////
#version 400


/////////////////////
// INPUT VARIABLES //
/////////////////////
in vec3 inputPosition;
in vec2 inputTexCoord;
in vec3 inputNormal;


//////////////////////
// OUTPUT VARIABLES //
//////////////////////
out vec2 texCoord;
out vec3 normal;


///////////////////////
// UNIFORM VARIABLES //
///////////////////////
uniform mat4 worldMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
void main(void)
{
    // Calculate the position of the vertex against the world, view, and projection matrices.
    gl_Position = worldMatrix * vec4(inputPosition, 1.0f);
    gl_Position = viewMatrix * gl_Position;
    gl_Position = projectionMatrix * gl_Position;

    // Store the texture coordinates for the pixel shader.
    texCoord = inputTexCoord;

    // Calculate the normal vector against the world matrix only.
    normal = mat3(worldMatrix) * inputNormal;

    // Normalize the normal vector.
    normal = normalize(normal);
}

Vieleicht hilft euch das dabei mir meinen Fehler zu verstehen
Danke :D

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

01.07.2013, 13:05

Und welchen Wert hat TextureUnit genau und wo renderst du das alles eigentlich?

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

5

01.07.2013, 13:12

Die TextureUnits haben die werte 1 und 2.
Gerendert wird das alles in der TextureUnitClass

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
void TextureUnitClass::Render(LightShaderClass* Shader, OpenGLClass* OpenGL, float* worldMatrix, float* viewMatrix,
                              float* projectionMatrix, float* lightDirection, float* diffuseLightColor, float* ambientLight)
{
    for (VectorGlobTextureUnitIter = VectorGlobTextureUnit.begin(); VectorGlobTextureUnitIter != VectorGlobTextureUnit.end();
        VectorGlobTextureUnitIter ++)
    {
        Shader->SetShaderParameters(OpenGL, worldMatrix, viewMatrix, projectionMatrix, *VectorGlobTextureUnitIter,
                                    lightDirection, diffuseLightColor, ambientLight);
    }
    return;
}

Die wird aufgerufen durch die GraphicClass

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
bool GraphicsClass::Render()
{
    float worldMatrix[16];
    float viewMatrix[16];
    float projectionMatrix[16];

    float lightDirection[3];
    float diffuseLightColor[4];
    float ambientLight[4];

    // Clear the buffers to begin the scene.
    m_OpenGL->BeginScene(0.0f, 0.0f, 0.0f, 1.0f);

    // Generate the view matrix based on the camera's position.
    m_Camera->Render();

    // Get the world, view, and projection matrices from the opengl and camera objects.
    m_OpenGL->GetWorldMatrix(worldMatrix);
    m_Camera->GetViewMatrix(viewMatrix);
    m_OpenGL->GetProjectionMatrix(projectionMatrix);

    // Get the light properties.
    m_Light->GetDirection(lightDirection);
    m_Light->GetDiffuseColor(diffuseLightColor);
    m_Light->GetAmbientLight(ambientLight);

    // Render the model using the texture and color shader.
    //m_Model->Render(m_OpenGL);

    //Render Game Models and other Stuff
    m_Game->Render (worldMatrix);
    
    // Set the light shader as the current shader program and set the matrices that it will use for rendering.
    m_LightShader->SetShader(m_OpenGL);
    m_TextureUnit->Render(m_LightShader, m_OpenGL, worldMatrix, viewMatrix, projectionMatrix, lightDirection, diffuseLightColor, ambientLight);
    //m_LightShader->SetShaderParameters(m_OpenGL, worldMatrix, viewMatrix, projectionMatrix, 0, lightDirection, diffuseLightColor, ambientLight);

    // Present the rendered scene to the screen.
    m_OpenGL->EndScene();

    return true;
}

Dort sind auch noch rückstände frühere Versuche die ich aber noch nicht entgültig löschen möchte.
Der Render Aufruf der ModelClass sieht so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
void ModelClass::RenderBuffers(OpenGLClass* OpenGL)
{
    // Bind the vertex array object that stored all the information about the vertex and index buffers.
    OpenGL->glBindVertexArray(m_vertexArrayId);

    // Render the vertex buffer using the index buffer.
    glDrawElements(GL_TRIANGLES, m_indexCount, GL_UNSIGNED_INT, 0);

    return;
}

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

01.07.2013, 13:20

Irgendwie vermiss ich in deinem Code immer noch ein glActiveTexture() gefolgt von glBindTexture()...

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

7

01.07.2013, 13:25

Ah wird nachgeliefert

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
// Set the unique texture unit in which to store the data.
    OpenGL->glActiveTexture(GL_TEXTURE0 + textureUnit);

    // Generate an ID for the texture.
    glGenTextures(1, &m_textureID);

    // Bind the texture as a 2D texture.
    glBindTexture(GL_TEXTURE_2D, m_textureID);

    // Load the image data into the texture unit.
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, targaImage);


    // Set the texture color to either wrap around or clamp to the edge.
    if(wrap)
    {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }
    else
    {
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    }

    // Set the texture filtering.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    // Generate mipmaps for the texture.
    OpenGL->glGenerateMipmap(GL_TEXTURE_2D);

    // Release the targa image data.
    delete [] targaImage;
    targaImage = 0;

    // Set that the texture is loaded.
    loaded = true;

    return true;
}

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

8

02.07.2013, 12:16

Ich wollte noch einmal fragen ob jemand die Lösung für mein Porblem kennt?
Ich habe einen simplen OpenGL Shader, doch ich kriege es nicht hin auf zwei Würfel zwei verschiedene Texturen zu legen. Wenn ich den Shader mehrmals aufrufe sehe ich nichts wenn ich ihn nur einmal mit einem TextureUnit aufrufe sehe ich nur eine Texture was mache ich flalsch?

Volker_Neff

Treue Seele

  • »Volker_Neff« ist der Autor dieses Themas

Beiträge: 249

Wohnort: Hamburg

  • Private Nachricht senden

9

04.07.2013, 14:05

Hallo noch einmal, entschuldigt wegen des dreifach Postes. Doch ich stehe aufm Schlauch und komme echt nicht weiter. Ich glaube die Antwort auf meine Frage hat Dot schon gebracht ich habe sie nur nicht verstande. ?(
Aber ich lehn mich mal aus dem Fenster und rate, dass du deinen sampler2D Uniforms die id der Texture als Wert übergibst, anstatt den Index der jeweiligen Texture Unit, an die deine Texture gebunden ist...
Ich glaube das mein Fehler genau der hier beschriebene ist, doch wo liegt der Unterschied ob ich dem Shader den Textrue Unit oder den Index des Texture Units übergebe und wie sehen die beiden möglichkeiten im Quellcode aus? Und noch eine letzte Frage, wo liegen die Vorteile der beiden varianten?

Ich wäre euch über eine Antwort sehr Dankbar.

Powerpaule

Treue Seele

Beiträge: 162

Wohnort: Berlin

Beruf: Softwareentwickler

  • Private Nachricht senden

10

04.07.2013, 22:42

Wie/wo wird die Texturgeneration aufgerufen? Was steht in deinem VectorGlobTextureUnit-Array?

wo liegt der Unterschied ob ich dem Shader den Textrue Unit oder den Index des Texture Units übergebe und wie sehen die beiden möglichkeiten im Quellcode aus?
Das hat dot nicht ganz gemeint. Es gibt zum Einen eine eindeutige ID für jede Textur:

C-/C++-Quelltext

1
glGenTextures(1, &m_textureID);

in m_textureID steht dann diese ID. Die darfst du aber nicht dem Shader übergeben, sondern diese ID verwendest du immer bei glBindTexture(), womit du auf die aktuellen Texture-Unit diese Textur aktivierst (bzw. dafür erstellst, eine Anwendung auf anderen Units ist nicht möglich). An den Shader übergibst du die Texture Unit, die verwendet werden soll. Die dort vorher mit glBindTexture aktivierte Textur wird dann gerendert. Mit den Units zu arbeiten macht aber auch nur Sinn, wenn du mehr als 1 Textur pro Drawcall verwenden willst. Das ist ja glaube ich bei dir nicht der Fall, insofern kannst du beide Texturen auf die selbe Unit (GL_TEXTURE0) binden, dann musst du im Shader den Wert vom Sampler nur einmal auf 0 setzen und setzt vor jedem Würfel mti glBindTexture() die richtige Textur.

Werbeanzeige