OpenGL Vertexshader



  • Dir fehlt da irgendwie der Fragment-Shader 🙂

    mit glUniform setzt du den Wert einer uniform-Variablen bzw. Arrays, die für alle Shader gültig ist (beispielsweise könntest du damit die MV-Matrix und Projection-Matrix setzen, damit der VertexShader die Transformationen durchführen kann - es müssen dann natürlich entsprechende uniform-Variablen auch vorhanden sein).
    Du änderst damit nicht im Shader berechnete Werte bzw. definierte Variablen.

    P.S.: Die globale Variable gl_ModelViewMatrix ist seit ver120 deprecated - gewöhn dir am besten gleich an sowas garnicht zu nutzen.
    Und die Multiplikation müsste auch andersrum sein denk ich. Also mat4 * vec4 und nicht vec4*mat4. (<-- Nachtrag: möp, vergiss das 🙂 ist schon spät)



  • inter2k3 schrieb:

    P.S.: Die globale Variable gl_ModelViewMatrix ist seit ver120 deprecated - gewöhn dir am besten gleich an sowas garnicht zu nutzen.
    Und die Multiplikation müsste auch andersrum sein denk ich. Also mat4 * vec4 und nicht vec4*mat4. (<-- Nachtrag: möp, vergiss das 🙂 ist schon spät)

    Soll ich nur das mit der Multiplikation vergessen, oder auch das mit der ModelViewMatrix? Denn was soll ich dann stattdessen benutzen?

    inter2k3 schrieb:

    Dir fehlt da irgendwie der Fragment-Shader 🙂

    Hmm anscheinend hab ich da noch nicht viel verstanden 😕
    Ich hab jetzt mal diesen Fragment-Shader eingebaut:

    void main (void) {
    
     gl_FragColor = vec4(1.0, 0.5, 0.7, 1.0);
    }
    

    Und seh immernoch weiß.
    Kann einer mal erklären, wie genau man dann Zeichnen muss? Man findet im Internet zwar massig darüber, wie man Shader schreibt, und sie einbindet. Aber wie man letzendlich das ganze zu etwas sinnvollem verbindet und dann ein Bild auf den Monitor bekommt findet man nichts.



  • So hab es jetzt hinbekommen, dass alles gezeichnet wird.
    Im Shader hab ich jetzt das hier stehen:

    #version 120
    
    void main(void)
    {
       gl_Position = ftransform();
    }
    

    Und das hier im Code:

    glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, vertex);
    glEnableVertexAttribArray(0);
    glDrawArrays(GL_QUADS, 0, 4);
    

    Allerdings macht der Fragment-Shader mir jetzt alles rosa 😃
    Wie bekomme ich es hin, dass nur dieses Objekt was ich zeichnen eingefärbt wird?



  • Pikkolini schrieb:

    void main (void) {
    
     gl_FragColor = vec4(1.0, 0.5, 0.7, 1.0);
    }
    

    Die Farbe Rosa hast du ja im Fragmentshader eingebaut. Die Tatsache, dass du nur Rosa auf dem Bildschirm siehst könnte daran liegen, dass dein gerendertes Quad den ganzen Bildschirm ausfüllt...



  • Wenn die shader nicht alle Daten verarbeiten sollen, also beispielsweise soll nur ein bestimmtes Objekt der Szene eingefärbt werden, musst du sie entsprechend deaktivieren.

    Vor dem Objekt:
    glUseProgram(programID);

    Nach dem Objekt:
    glUseProgram(0);



  • Danke, das war genau das, was ich gesucht habe.
    Jetzt habe ich nurnoch das Problem, das nur die untere linke Ecke (erster Vektor) coloriert wird. Und dann ein diagonaler Farbverlauf ensteht. Ich habe mal ein Screen gemacht:
    http://img98.imageshack.us/img98/5959/screenup.png



  • So ich habe es jetzt gelöst, in dem ich aus

    GLfloat color[] = {0.1f, 1.0f, 1.0f, 1.0};
    

    das hier gemacht habe

    GLfloat color[] = {0.1f, 1.0f, 1.0f, 1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0.1f, 1.0f, 1.0f, 1.0f, 0.1f, 1.0f, 1.0f, 1.0f};
    

    Also für jeden Vertex die Farbe bestimmt habe. Aber ist das nicht extrem Speicherfressend für jeden Vertex die Farbe zu bestimmen? Gibt es da keine andere Methode?



  • Da ja alle Vertices des Quads ohnehin die gleiche Farbe haben sollen, und du den PixelShader nur für das Quad nutzen willst, brauchst du garkeine Farbwerte angeben.
    Du lässt einfach vom PixelShader die Farbe immer auf den entsprechenden Wert setzen.

    Also sowas in der Art:

    // PIXELSHADER
    #version 130
    out vec4 col;		// final color
    
    void main()
    {
    	col = vec4(0.1,1.0,1.0,1.0);
    }
    


  • Ok danke, alle Fragen beantwortet 🙂



  • Wobei, eine Frage habe ich noch.
    Da uniform ja nicht antwort auf meine Frage war, wie kann ich jetzt z.B. an den Shader neue Werte übergeben, z.B. wenn sich die Position meines Vierecks nach einem Tastendruck um 10 Pixel verschoben hat?



  • Und ich hab direkt noch eine Frage.
    Ich wollte jetzt mal 2 Quads zeichnen und habe mein Array dementsprechend angepasst:

    GLint vertices[] = {100,100,300,100,300,300,100,300, 0, 0, 10, 0, 10, 10, 0, 10};
    

    Allerdings wird mit

    gl_Position = ftransform();
    

    nur das erste Quad gerendert. Muss ich meinen Shader irgendwie anpassen, dass ich soviele Quads rendern kann, wie im Array stehen?



  • Du hast mehrere Möglichkeiten was dsa Verschieben angeht.
    Du könntest den Wert als uniform setzen und im VS zu den entsprechenden Werte des Vertices addieren. Danach würdest du transformieren.

    Du könntest auch gleich die Modelview-Matrix ändern und diese als uniform übergeben um zu transformieren.

    Die Frage ist halt, wie verschoben werden soll - und vorallem in welchem Bezugssystem (Object-Space, World-Space, Viewing-Space)

    Zu Frage 2:
    auch an

    glDrawArrays(GL_QUADS, 0, 8);
    

    gedacht?



  • inter2k3 schrieb:

    Du hast mehrere Möglichkeiten was dsa Verschieben angeht.
    Du könntest den Wert als uniform setzen und im VS zu den entsprechenden Werte des Vertices addieren. Danach würdest du transformieren.

    Du könntest auch gleich die Modelview-Matrix ändern und diese als uniform übergeben um zu transformieren.

    Die Frage ist halt, wie verschoben werden soll - und vorallem in welchem Bezugssystem (Object-Space, World-Space, Viewing-Space)

    Das versteh ich nicht ganz.
    Soweit ich verstanden habe, kann man einer Uniform variable einmal einen Wert zuweisen und dann wars das.
    Was ich aber jetzt z.B. vorhabe ist, dass wenn sich die Position von (10|10) zu (20|10) ändert, das Viereck auch dort gezeichnet wird. Mit glVertexAttribPointer komme ich da irgendwie nicht weit.

    inter2k3 schrieb:

    Zu Frage 2:
    auch an

    glDrawArrays(GL_QUADS, 0, 8);
    

    gedacht?

    Natürlich nicht 🙄



  • Pikkolini schrieb:

    Das versteh ich nicht ganz.
    Soweit ich verstanden habe, kann man einer Uniform variable einmal einen Wert zuweisen und dann wars das.
    Was ich aber jetzt z.B. vorhabe ist, dass wenn sich die Position von (10|10) zu (20|10) ändert, das Viereck auch dort gezeichnet wird. Mit glVertexAttribPointer komme ich da irgendwie nicht weit.

    Nein - du kannst die uniforms in jedem render-Durchlauf neu setzen.
    kleines Beispiel:

    uniform mat4 mvmatrix;		// modelviewmatrix
    uniform mat4 projmatrix;	// projectionmatrix
    
    in vec3 vinvertex;		// incoming vertex
    in vec3 vincolor;		// incoming color
    in vec2 vintex;			// incoming texture-coord
    
    out vec3 voutcolor;		// pass color to frag-shader
    out vec2 vouttex;		// pass texture-coord to frag-shader
    
    void main()
    {
    	vouttex = vintex;
    	voutcolor = vincolor;
    	gl_Position =  projmatrix * ( mvmatrix * vec4(vinvertex,1.0));
    }
    

    mvmatrix und projmatrix werden in jedem render-Durchlauf gesetzt, da es ja durchaus sein kann, dass man Objekte rotiert oder verschiebt 🙂



  • Ich hab jetzt diesen Code im Vertex-Shader:

    #version 120
    
    uniform int in_position;
    
    in vec4 in_color;
    
    varying vec4 ex_color;
    
    void main(void)
    {
     ex_color = in_color;
     if (in_position != 0)
     {
      gl_Position = ftransform() + vec4(100,0,0,0);
     } else {
      gl_Position = ftransform();
     }
    }
    

    Also ich versteh den so, dass wenn in_position ungleich null ist, mein Viereck 100 px versetzt gezeichnet wird.
    Der C++ Code sieht dann so aus:

    glVertexAttribPointer(0, 2, GL_INT, GL_FALSE, 0, vertices);
    glEnableVertexAttribArray(0);
    glUniform1i(glGetUniformLocation(ProgramObject, "in_position"),1);
    

    Aber versetzen tut sich da gar nichts.



  • Musste erstmal nachlesen was ftransform() macht, da ich es nie nutz.

    Versuch mal folgendes:

    ...
    if (in_position != 0)
     {
      gl_Position = ftransform();
      gl_Position = gl_Position + vec4(100,0,0,0);
     }
    ...
    

    oder kürzer:

    gl_Position.x += 100;
    

    Wobei ich sagen muss, ich bin mir nicht sicher, ob man das so machen würde.
    Bin selbst noch Anfänger (beschäftige mich erst seit 3 Tagen mit GLSL und HLSL).



  • Hmm also im RenderMonkey funktioniert der Code so wie er soll. Aber in meinem Programm wenn ich die Variable move so bestimme:

    glUniform1i(glGetUniformLocation(ProgramObject, "move"),1);
    

    passiert nichts.
    Das ist jetzt mein Code vom Vertex-Shader:

    #version 120
    
    uniform int move;
    
    void main(void)
    {
       gl_Position = ftransform();
       if (move != 0)
       {
          gl_Position.x += 10.0f;
       }  
    }
    


  • grübel - funktioniert bei mir einwandfrei.

    Haste dir mal die InfoLogs ausgeben lassen von Shader und Program? Vlt. steht da was interessantes drin.



  • Ja, Infolog ist leer.

    EDIT:
    Vielleicht liegt es ja auch an ftransform(). Wie übergibst du denn die Vektoren an den Shader?

    EDIT 2:
    Ok ich Idiot hab vergessen, dass ich vorher glUseProgram aufrufen muss 🙄
    Allerdings bewegt sich mein Viereck Jetzt 400 Pixel weiter, wenn ich + 1.0f schreibe. Muss ich da noch die Modelview Matrix multiplizieren oder wie?



  • Pikkolini schrieb:

    Ja, Infolog ist leer.

    EDIT:
    Vielleicht liegt es ja auch an ftransform(). Wie übergibst du denn die Vektoren an den Shader?

    Ich setz über glUniformMatrix4fv zwei uniform-Variablen (einmal die ModelViewMatrix und einmal die ProjectionMatrix).
    Mit diesen beiden Matrizen rechne ich dann im VS die Clip-Koordinaten aus, die der VS dann eben ausgibt.

    Pikkolini schrieb:

    EDIT 2:
    Ok ich Idiot hab vergessen, dass ich vorher glUseProgram aufrufen muss 🙄
    Allerdings bewegt sich mein Viereck Jetzt 400 Pixel weiter, wenn ich + 1.0f schreibe. Muss ich da noch die Modelview Matrix multiplizieren oder wie?

    [/quote]
    ftransform() hat dies schon für dich erledigt. Soweit ich das verstanden hat macht die Funktion genau das, was ich selber mache (s.o.) - ist aber seit GLSL1.20 als deprecated markiert (weswegen ich sie nicht benutzte).

    Da addierst im Endeffekt einen Wert auf die Clip-Space-Koordinaten. Diese werden ja später noch weiter verarbeitet (clipping, Rasterization etc.)
    Deswegen würde ich wie gesagt die Translation im Object-Space machen, da es dann am leichtesten nachzuvollziehen ist.


Anmelden zum Antworten