2014-06-15 5 views
2

Bonjour et désolé de poser une question si spécifique.OpenGL, pourquoi ce code ne fonctionne pas comme prévu?

je le vertex shader GLSL suivant:

#version 140 

uniform vec2 viewport_size; 

in vec2 vertex_position; 

in vec2 in_texture_uv; 
varying vec2 texture_uv; 


void main(void) 
{ 
    texture_uv = in_texture_uv; 

    gl_Position = vec4(vertex_position/viewport_size, 0, 1); 
} 

et le fragment shader correspondant:

#version 140 

uniform sampler2D texture_image; 

out vec4 out_frag_color; 

varying vec2 texture_uv; 


void main(void) 
{ 
    out_frag_color = texture(texture_image, texture_uv); 
} 

qui produit cette sortie (notez le petit point bleu sur le coin inférieur gauche): La chose étrange est que si je remplace

La chose étrange est que si je remplace
texture_uv = in_texture_uv; 

avec

texture_uv = vertex_position; 

la sortie devient: output_vertpos (noter les frontières sur le fond et à gauche).

Et enfin, si j'écris:

texture_uv = vertex_position; 
texture_uv = in_texture_uv; 

la sortie est correcte: output_correct, et cela ne fait aucun sens pour moi pas ...

Quelqu'un pourrait-il expliquer pourquoi cette chose arrive? Merci pour votre temps!


extraits de code pertinents:

float[] positionVboData = new float[] { 
    // X  Y  U  V 
    0.0f, 0.0f, 0f,  0f, 
    50.0f, 0.0f, 1f,  0f, 
    50.0f, 25.0f, 1f, .5f, 
    0.0f, 50.0f, 0f,  1f, 
}; 

.

// vertices 
GL.GenBuffers(1, out verticesHandle); 
GL.BindBuffer(BufferTarget.ArrayBuffer, verticesHandle); 
GL.BufferData<float>(BufferTarget.ArrayBuffer, new IntPtr(vertices.Length * sizeof(float)), vertices, BufferUsageHint.StaticDraw); 

// vertices: vertex_position 
GL.EnableVertexAttribArray(0); 
GL.BindAttribLocation(program, 0, "vertex_position"); 
GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, 0); 

// vertices: texture_uv 
GL.EnableVertexAttribArray(1); 
GL.BindAttribLocation(program, 1, "in_texture_uv"); 
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, sizeof(float)*4, sizeof(float) * 2); 

Texture:

sample_texture

+1

Je ne pense pas que cela devrait être le problème, mais vous devriez éviter de mélanger 'vary' /' attribute' (_deprecated_) et 'in' /' out' –

+0

Ok, j'ai juste essayé de remplacer "variable" par "out" "dans le vertex shader, et avec" in "dans le fragment shader. Aucun changement du tout. –

+1

Qu'est-ce que vous essayez d'accomplir avec 'vertex_position/viewport_size'? Ce n'est pas la bonne façon de transformer en fenêtre-espace. –

Répondre

2

Votre principal problème est plus probable que vos BindAttribLocation() appels arrivent trop tard:

GL.BindAttribLocation(program, 0, "vertex_position"); 
... 
GL.BindAttribLocation(program, 1, "in_texture_uv"); 

Nous ne voyons pas où et comment vous construisez votre programme de shader, mais en fonction du contexte, je suppose que vous avez déjà construit votre programme shader à ce stade. Vous devez effectuer les appels BindAttribLocation()avant de lier le programme de shaders. Sinon, ces emplacements ne prendront pas effet.

Si vous souhaitez que la version de shader soit étendue à 330, vous pouvez également spécifier l'emplacement de vos entrées de vertex shader dans le code de shader lui-même, en utilisant les directives layout (location=...).

+0

Merci beaucoup, vous avez résolu un problème qui m'a fait mal à la tête pendant toute une journée! –

+0

note que certaines plates-formes (OSX, à savoir) ont aussi l'extension 'GL_ARB_explicit_attrib_location' de sorte que vous pouvez utiliser' layout (location = ...) 'même avec la version shader' 150' –

3

Besoin de plus d'espace que celui que j'ai dans un commentaire ...


En supposant que GL.Viewport est en fait une enveloppe pour glViewport, puis

GL.Viewport(-Width, -Height, Width*2, Height*2) 

a peu de sens car il apporte 3/4 de la fenêtre en dehors de la surface de votre fenêtre. Il suffit de passer (0, 0, width, height) pour peindre sur l'ensemble de votre fenêtre, 0, 0 étant dans le coin inférieur gauche. Si vous souhaitez restreindre la sortie GL à un sous-ensemble de votre fenêtre, ajustez le paramètre en conséquence.

Techniquement, glViewport définit le périphérique Normalisée Coordonnées à fenêtre Coordonnées transformation pour X et Y. Il est important de se renseigner sur les espaces dans OpenGL. Passer du temps là-dessus. Cela étant dit, la sortie du vertex shader est également étrange.Si vous voulez « remplir la fenêtre » avec votre polygon¹, vous n'avez pas besoin de faire cette étrange

vertex_position/viewport_size 
division

dans votre vertex shader.

Rappelez-vous que les sorties Vertex shader en pince coordonnées, après quoi OpenGL apporte vos coordonnées dans dispositif normalisée en divisant les coordonnées X, Y, Z par W. dispositif Normalized coordonnées plage de -1 à 1 dans les trois dimensions. Seuls les points situés à l'intérieur de ce cube 2x2x2 seront réellement pixellisés.

Rappelez-vous ce que j'ai dit à propos de glViewport?

Alors, quel est le problème? Juste les coordonnées de sortie avec W = 1 de sorte qu'ils sont déjà déjà effectivement dans NDC. Donc, si vous voulez un quadrilatérale pour couvrir toute la zone de la fenêtre dessiné par GL, juste construire quelque chose comme

float coords[] = { -1, -1, 
        1, -1, 
        1, 1, 
        -1, 1 }; 

Ou, selon votre code d'origine, si vous voulez un trapézoïde, utilisez quelque chose comme

float coords[] = { -1, -1, 
        1, -1, 
        1, 0, 
        -1, 1 }; 

Et puis les passer à travers le vertex shader:

in vec2 position; 

void main() { 
    gl_Position = vec4(position, 0, 1); 
} 

Résultat:

result


¹ S'il vous plaît, faites ce soit un GL_TRIANGLE_FAN, pas un GL_QUAD ni GL_POLYGON

+0

'En supposant que GL.Viewport est en fait un wrapper pour glViewport', j'utilise du code managé, mais l'encapsulation est directe. Je travaille avec ces chiffres parce que je viens d'interfaces graphiques qui préfèrent les entiers plutôt que les flottants, et je voulais vraiment que cette image ne soit que de 50 pixels de large. Je vais déléguer ces calculs au GPU et éviter le 'uniforme uniforme vec2 viewport_size;' alors. Merci pour la bonne explication! –

Questions connexes