2010-12-07 59 views
4

J'ai un problème lors du passage d'attributs vertex au programme shader en cours d'exécution. Je voudrais passer deux attributs, la position et une couleur RGBA. La liaison de l'emplacement de l'attribut fonctionne pour la position. Cependant, cela ne fonctionne pas pour la couleur. Par conséquent, toute la géométrie est finalement rendue noire.GLSL 1.5 & OpenGL 3.3: Le passage de la couleur au vertex shader semble échouer

C'est ce que je fais:

GLuint programHandler; 

// create program 
// compile & attach vertex shader 
// compile & attach fragment shader 

glBindAttribLocation(programHandler, 0, "InPosition"); 
glBindAttribLocation(programHandler, 1, "InColor"); 
glBindFragDataLocation(programHandler, 1, "FragColor"); 

glLinkProgram(programHandler); 
glUseProgram(programHandler); 

// initialize uniform variables 

// I'm trying to get the attribute locations now. 
// I expect location "0" for InPosition and location "1" for InColor. 
// In fact, it gets me a "-1" for InColor. I simply cannot see the reason for that behaviour 

GLint positionLocation = glGetAttribLocation(programHandler, "InPosition"); // returns 0 
GLint colorLocation = glGetAttribLocation(programHandler, "InColor"); // returns -1 

glEnableVertexAttribArray(positionLocation); 
glEnableVertexAttribArray(colorLocation); // fails! 

Mon vertex shader est très basique. Tout ce que je fais vraiment transforme les sommets et passer la couleur au fragment shader:

#version 150 core 

// input 
uniform mat4 ModelviewMatrix; 
uniform mat4 ProjectionMatrix; 
in vec3 InPosition; 
in vec4 InColor; 

// output 
out vec4 PassColor; 

void main(void) { 
    // passing color through to fragment shader 
    PassColor = InColor; 

    // transformation 
    gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(InPosition, 1.0); 
} 

Mon fragment shader ne devrait renvoyer cette couleur:

#version 150 core 
precision highp float; 

// input 
in vec4 PassColor; 

// output 
out vec4 FragColor; 

void main(void) { 
    FragColor = PassColor; 
} 

Pourquoi lier « InPosition » travail et « InColor » ne fait pas? Je suis conscient que le compilateur GLSL optimise le code shader, de sorte que les variables inutilisées ne peuvent pas être liées. Mais, je ne vois pas pourquoi la couleur devrait être optimisée ici. Après tout, je l'utilise en le passant au fragment shader.

+0

Tout 'glGetError()' s existe-t-il? Aussi, quelle est votre version du GPU et du pilote? – Kos

Répondre

1

Un tir aveugle, je crois que cela est faux:

glBindFragDataLocation(programHandler, 1, "FragColor"); 

Il devrait être:

glBindFragDataLocation(programHandler, 0, "FragColor"); 
+0

Je vois. Mais que faire si je veux rendre à plusieurs cibles de rendu. Je rends actuellement à une texture qui est attachée à un objet frame buffer. Je voulais à l'origine attacher plus que cette seule texture en tant que tampons de couleur. C'est la raison du "1" comme deuxième argument. Je crois que le tableau gl_FragData [] est obsolète. Comment le lierais-je correctement et le déclarerais-je dans le fragment shader? – Walter

+0

C'est correct mais c'est le rendu à la deuxième cible de rendu, s'il y en a une. S'il n'y a pas deux cibles de rendu, il y aurait une erreur. –

+0

Donc, je suppose que j'adresserais COLOR_ATTACHMENT1 via FragColor [1] dans mon shader de fragment GLSL. Je suppose que pour faire cela, je devrais déclarer FragColor un peu comme ça: "out vec4 FragColor [8];" (en supposant qu'il y ait 8 tampons de couleur attachés). Est-ce exact? Aurais-je aussi besoin de lier chaque emplacement de données fragment comme "glBindFragDataLocation (programHandler, i," FragColor [i] "); – Walter

0

Si le fragment shader doit écrire sur plusieurs plans de couleurs, puis un tampon de trame doit être créé, qui a attaché plusieurs plans de couleur, où les fragments peuvent être écrits.

Les plans de couleur peuvent être soit rendre des tampons, des

GLuint renderbuffer[2]; 
glGenRenderbuffers(2, &renderbuffer[0]); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[0]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer[1]); 
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height); 

ou ils peuvent être textures.

GLuint colorTexture[2]; 
glGenTextures(2, &colorTexture[0]); 
glBindTexture(GL_TEXTURE_2D, colorTexture[0]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
glBindTexture(GL_TEXTURE_2D, colorTexture[1]); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 

Les textures ou les tampons de rendu doivent être attachés au tampon de trame.

rendu des tampons

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[0]); 
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer[1]); 

textures

GLuint frameBuffer; 
glGenFramebuffers(1, &frameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture[0], 0); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, colorTexture[1], 0); 

Note, bien sûr rendu des tampons et des textures peuvent être mélangés et peut être fixé sur les plans de couleurs différentes d'une seule et même trame tampon.
Si un tampon de profondeur ou même un tampon stencil est requis, un GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT ou GL_DEPTH_STENCIL_ATTACHMENT doit être attaché au tampon de trame.

Si le tampon de farme a été terminé avec succès peut être évalué avec glCheckFramebufferStatus:

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 
{ 
    // error 
} 

Le nombre maximum de tampons de couleurs qui peuvent être fixés à un seul tampon de trame peut être déterminée par la fonction GOL glGetIntegerv, par en utilisant le paramètre GL_MAX_COLOR_ATTACHMENTS:

GLint maxColAttchemnts = 0; 
glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColAttchemnts); 

toutes les pièces jointes de couleur doivent être activés en même temps. Un tableau de tampons dans lequel les sorties des données de fragment shader seront écrites peut être défini avec glDrawBuffers.

GLenum drawBuffers[] = { GL_COLOR_ATTACHMENT1 }; 
glDrawBuffers(1, &drawBuffers[0]); 

Dans le fragment shader a une variable out pour être déclarée pour chaque pièce jointe de couleur active.

out fragColor0; 
out fragColor1; 

void main() 
{ 
    .... 
    fragColor0 = ....; 
    .... 
    fragColor1 = ....; 
} 

La liaison d'une variable out à l'index d'un accessoire de couleur de tampon de trame peut être explicitement spécifié par glBindFragDataLocation. Cela doit être fait avant que le programme shader ne soit lié. Dans l'index de tampon OpenGL moderne sur lequel une sortie particulière est écrite, peut explicitement spécifié par les emplacements de disposition. Cela permet de renoncer à l'utilisation de glBindFragDataLocation.

layout(location = 0) out fragColor0; 
layout(location = 1) out fragColor1;