1

J'essaie de comprendre les différents types de shaders GLSL dans OpenGL. En ce moment, je suis aux prises avec une implémentation en 2d couches. Pour une raison quelconque, les valeurs int qui sont passées dans mon shader sont toujours 0 (ou plus probable, null). J'ai actuellement une texture 2D de 2048x2048px composée de 20x20 tuiles. J'essaye de texturer un quad avec lui et de changer l'index de la tuile en me basant sur le bloc d'ints que je passe dans le vertex shader.Impossible de lire les valeurs transmises à Vertex Shader

Je passe dans un vec2 de flotteurs pour la position du quad (vraiment un TRIANGLE_STRIP). J'essaie aussi de faire passer 6 ints qui représenteront les 6 couches de tuiles.

Mon entrée:

// Build and compile our shader program 
Shader ourShader("b_vertex.vertexShader", "b_fragment.fragmentShader"); 

const int floatsPerPosition = 2; 
const int intsPerTriangle = 6; 
const int numVertices = 4; 
const int sizeOfPositions = sizeof(float) * numVertices * floatsPerPosition; 
const int sizeOfColors = sizeof(int) * numVertices * intsPerTriangle; 
const int numIndices = 4; 
const int sizeOfIndices = sizeof(int) * numIndices; 

float positions[numVertices][floatsPerPosition] = 
{ 
    { -1, 1 }, 
    { -1, -1 }, 
    { 1, 1 }, 
    { 1, -1 }, 
}; 

// ints indicating Tile Index 
int colors[numVertices][intsPerTriangle] = 
{ 
    { 1, 2, 3, 4, 5, 6 }, 
    { 1, 2, 3, 4, 5, 6 }, 
    { 1, 2, 3, 4, 5, 6 }, 
    { 1, 2, 3, 4, 5, 6 }, 
}; 

// Indexes on CPU 
int indices[numVertices] = 
{ 
    0, 1, 2, 3, 
}; 

Ma configuration:

GLuint vao, vbo1, vbo2, ebo; // Identifiers of OpenGL objects 

glGenVertexArrays(1, &vao); // Create new VAO 
          // Binded VAO will store connections between VBOs and attributes 
glBindVertexArray(vao); 

glGenBuffers(1, &vbo1); // Create new VBO 
glBindBuffer(GL_ARRAY_BUFFER, vbo1); // Bind vbo1 as current vertex buffer 
            // initialize vertex buffer, allocate memory, fill it with data 
glBufferData(GL_ARRAY_BUFFER, sizeOfPositions, positions, GL_STATIC_DRAW); 
// indicate that current VBO should be used with vertex attribute with index 0 
glEnableVertexAttribArray(0); 
// indicate how vertex attribute 0 should interpret data in connected VBO 
glVertexAttribPointer(0, floatsPerPosition, GL_FLOAT, GL_FALSE, 0, 0); 

glGenBuffers(1, &vbo2); // Create new VBO 
glBindBuffer(GL_ARRAY_BUFFER, vbo2); // Bind vbo2 as current vertex buffer 
            // initialize vertex buffer, allocate memory, fill it with data 
glBufferData(GL_ARRAY_BUFFER, sizeOfColors, colors, GL_STATIC_DRAW); 
// indicate that current VBO should be used with vertex attribute with index 1 
glEnableVertexAttribArray(1); 
// indicate how vertex attribute 1 should interpret data in connected VBO 
glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0); 

// Create new buffer that will be used to store indices 
glGenBuffers(1, &ebo); 
// Bind index buffer to corresponding target 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); 
// ititialize index buffer, allocate memory, fill it with data 
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfIndices, indices, GL_STATIC_DRAW); 

// reset bindings for VAO, VBO and EBO 
glBindVertexArray(0); 
glBindBuffer(GL_ARRAY_BUFFER, 0); 
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 



// Load and create a texture 
GLuint texture1 = loadBMP_custom("uvtemplate3.bmp"); 

GLuint texture2 = loadBMP_custom("texture1.bmp"); 

Mon tirage:

// Game loop 
while (!glfwWindowShouldClose(window)) 
{ 
    // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions 
    glfwPollEvents(); 

    // Render 
    // Clear the colorbuffer 
    glClearColor(1.f, 0.0f, 1.0f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT); 

    // Activate shader 
    ourShader.Use(); 

    // Bind Textures using texture units 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture1); 

    //add some cool params 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); 
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); 
    float borderColor[] = { 0.45f, 0.25f, 0.25f, 0.25f }; 
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); 

    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture1"), 0); 
    glActiveTexture(GL_TEXTURE1); 
    glBindTexture(GL_TEXTURE_2D, texture2); 
    glUniform1i(glGetUniformLocation(ourShader.Program, "ourTexture2"), 1); 

    // Draw container 
    //glBindVertexArray(VAO); 
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 
    glBindVertexArray(vao); 
    //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 
    glDrawElements(GL_TRIANGLE_STRIP, numIndices, GL_UNSIGNED_INT, NULL); 

    glBindVertexArray(0); 

    // Swap the screen buffers 
    glfwSwapBuffers(window); 
} 

Mon shaders fonctionne très certainement, comme je peux régler la sortie par codage en dur les valeurs à partir de vertexShader. Mon soupçon est que je ne passe pas les valeurs correctement/dans le bon format ou n'indique pas quelque part que int [6] doit être inclus par vertex.

Je ne peux rien lire de mon layout (location = 1) dans int Base [6]; J'ai essayé à peu près tout ce que je peux penser. Déclarant chaque int individuellement, en essayant de lire deux années ivec3, uint et ce que jamais que je pouvais penser, mais tout revient avec 0.

Voici mon sommet et fragment shader complet:

#version 330 core 
layout (location = 0) in vec2 position; 
layout (location = 1) in int Base[6]; 

out vec2 TexCoord; 
out vec2 TexCoord2; 
out vec2 TexCoord3; 
out vec2 TexCoord4; 
out vec2 TexCoord5; 
out vec2 TexCoord6; 

// 0.5f, 0.5f,// 0.0f, 118.0f, 0.0f, 0.0f, 0.0f, 0.0f, // Top Right 
// 0.5f, -0.5f,// 0.0f, 118.0f, 1.0f, 0.0f, 0.0f,0.009765625f, // Bottom Right 
// -0.5f, -0.5f,// 0.0f, 118.0f, 0.0f, 1.0f, 0.009765625f, 0.009765625f, // Bottom Left 
// -0.5f, 0.5f//, 0.0f, 118.0f, 1.0f, 0.0f, 0.009765625f, 0.0f // Top Left 

void main() 
{ 

int curBase = Base[5]; 

int curVertex = gl_VertexID % 4; 
vec2 texCoord = (curVertex == 0? 
vec2(0.0,0.0):(
curVertex == 1? 
vec2(0.0,0.009765625):(
curVertex == 2? 
vec2(0.009765625,0.0):(
curVertex == 3? 
vec2(0.009765625,0.009765625):(
vec2(0.0,0.0))))) 
); 
gl_Position = vec4(position, 0.0f, 1.0f); 

TexCoord = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f) 
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f)); 
//curBase = Base+1; 
TexCoord2 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f) 
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f)); 
//curBase = Base+2; 
TexCoord3 = vec2(texCoord.x + ((int(curBase)%102)*0.009765625f) 
, (1.0 - texCoord.y) - ((int(curBase)/102)*0.009765625f)); 
} 

Fragment :

#version 330 core 
//in vec3 ourColor; 
in vec2 TexCoord; 
in vec2 TexCoord2; 
in vec2 TexCoord3; 
in vec2 TexCoord4; 
in vec2 TexCoord5; 
in vec2 TexCoord6; 

out vec4 color; 

// Texture samplers 
uniform sampler2D ourTexture1; 
uniform sampler2D ourTexture2; 

void main() 
{ 
color = (texture(ourTexture2, TexCoord)== vec4(1.0,0.0,1.0,1.0)? 
(texture(ourTexture2, TexCoord2)== vec4(1.0,0.0,1.0,1.0)? 
(texture(ourTexture2, TexCoord3)== vec4(1.0,0.0,1.0,1.0)? 
(texture(ourTexture2, TexCoord4)== vec4(1.0,0.0,1.0,1.0)? 
(texture(ourTexture2, TexCoord5)== vec4(1.0,0.0,1.0,1.0)? 
(texture(ourTexture2, TexCoord6)== vec4(1.0,0.0,1.0,1.0)? 
    vec4(0.0f,0.0f,0.0f,0.0f) 
:texture(ourTexture2, TexCoord6)) 
:texture(ourTexture2, TexCoord5)) 
:texture(ourTexture2, TexCoord4)) 
:texture(ourTexture2, TexCoord3)) 
:texture(ourTexture2, TexCoord2)) 
:texture(ourTexture2, TexCoord)); 
} 

Répondre

3

Ceci est faux de deux façons différentes:

glVertexAttribPointer(1, intsPerTriangle, GL_INT, GL_FALSE, 0, 0); 

Les attributs de sommet dans la GL peuvent être des scalaires ou des vecteurs de 2 à 4 composantes. Par conséquent, le paramètre size de glVertexAttribPointer peut prendre les valeurs 1, 2, 3 ou 4. L'utilisation d'une valeur différente (intsPerTriangle == 6) signifie que l'appel génère simplement une erreur GL_INVALID_VALUE et n'a aucun effet, donc vous ne définissez même pas un pointeur. Si vous voulez passer 6 valeurs par sommet, vous pouvez soit utiliser 6 attributs scalr différents (consommant 6 attributs), soit les intégrer dans certains vecteurs, comme 2 vecteurs 3d (ne consommant que 2 slots). Peu importe l'emballage que vous avez choisi, vous aurez besoin d'une bonne configuration de pointeur d'attribut pour chaque emplacement d'attribut utilisé. Toutefois, glVertexAttribPointer est également la mauvaise fonction pour votre cas d'utilisation. Il définit les attributs en virgule flottante, qui doivent correspondre aux déclarations float/vec* dans le nuanceur. Le fait que vous pouvez entrer GL_INT signifie simplement que le GPU peut faire la conversion en virgule flottante à la volée pour vous.

Si vous souhaitez utiliser un attribut int ou ivec (ou leurs homologues non signés), vous devez utiliser glVertexAttribIPointer (notez le Je en ce nom de fonction) lors de la configuration de l'attribut.

+0

Merci! Je l'ai eu travailler avec les trois premiers. Donc si je voulais passer les 6 ints comme deux ivec3, devrais-je faire un autre vbo pour le second ivec3? – RIanGillis

+0

@RIanGillis: \ * sigh \ * Des questions comme la vôtre sont la raison pour laquelle je * méprise * les didacticiels qui mélangent la création d'un objet tampon et le code de désignation d'un attribut de sommet. Le nombre d'attributs de vertex que vous utilisez n'a * rien * à voir avec le nombre d'objets tampons dont ces attributs proviennent (eh bien, sauf qu'un attribut ne peut pas provenir de plusieurs tampons, évidemment). Vous pouvez mettre toutes vos données de vertex dans un tampon si vous le souhaitez. –

+0

Donc ce que vous dites est que je devrais plutôt ajuster la foulée et le décalage du glVertexAttribPointer pour sauter les trois dernières ints puis créer un autre glVertexAttribPointer pointant vers les mêmes données, mais avec un décalage différent afin qu'il ne prenne que les trois derniers. Merci! – RIanGillis