Lazarus - OpenGL 3.3 Tutorial - Shader - Punkte verschieden darstellen: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Die Seite wurde neu angelegt: „200px<br><br> =Shader - Punkte verschieden darstellen = == Einleitung == B…“)
 
 
Zeile 2: Zeile 2:
 
=Shader - Punkte verschieden darstellen =
 
=Shader - Punkte verschieden darstellen =
 
== Einleitung ==
 
== Einleitung ==
Bis jetzt wurde alles mit kompletten Dreiecken gerendert und gezeichnet. Es gibt aber noch zwei andere Varianten um Dreiecke zu rendern.<br>
+
Man kann auch Punkte mit dem Shader darstellen, dies kann man auf verschiedene Weise.<br>
Dies wurde beim Zeichnen mit '''glDrawArrays(GL_TRIANGLES, ...''' veranlasst. Diese Version wird in der Paraxis am meisten angewendet.<br>
+
Im Fragment-Shader kann man das Zeichen der Punkte manipulieren.<br>
Man kann die Dreiecke auch als Streifen hintereinander rendern, dies gerschieht mit '''glDrawArrays(GL_TRIANGLES_STRIP, ...'''.<br>
 
Oder wie ein Wedel, dabei ist der erste Vektor die Mitte, und der Rest die Eckpunkte. Dies geschieht dann mit '''glDrawArrays(GL_TRIANGLES_FAN, ...'''.<br>
 
<br>
 
Das schreiben in die Grafikkarte, ist bei allen Varianten gleich, der Unterschied ist legendlich beim Zeichenen mit '''glDrawArrays(...'''.<br>
 
 
<br><br>
 
<br><br>
Die Deklaration der Vektor-Koordianten Konstanten, zur Vereinfachung habe ich nur 2D-Vektoren genommen. Natürlich können diese auch 3D sein.<br>
+
Die Deklaration der Koordianten und Punktgrösse.<br>
 
<syntaxhighlight lang="pascal">var
 
<syntaxhighlight lang="pascal">var
   // Normale Dreiecke        ( Gelb )
+
   Point: array of TVertex2f;
  Triangles: array of TVertex2f;
+
   PointSize: array of GLfloat;</syntaxhighlight>
   TrianglesSize: array of GLfloat;</syntaxhighlight>
+
Daten für die Punkte in die Grafikkarte übertragen<br>
Hier werden die Daten in die Grafikkarte geschrieben.<br>
 
Es hat nichts besonderes.<br>
 
 
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 
<syntaxhighlight lang="pascal">procedure TForm1.InitScene;
 
begin
 
begin
 
   glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe
 
   glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe
  
   // Daten für GL_TRIANGLE
+
   // Daten für Punkt Position
   glBindVertexArray(VBTriangle.VAO);
+
   glBindVertexArray(VBPoint.VAO);
   glBindBuffer(GL_ARRAY_BUFFER, VBTriangle.VBO);
+
   glBindBuffer(GL_ARRAY_BUFFER, VBPoint.VBO);
   glBufferData(GL_ARRAY_BUFFER, sizeof(TVertex2f) * Length(Triangles), Pointer(Triangles), GL_STATIC_DRAW);
+
   glBufferData(GL_ARRAY_BUFFER, sizeof(TVertex2f) * Length(Point), Pointer(Point), GL_STATIC_DRAW);
 
   glEnableVertexAttribArray(10);
 
   glEnableVertexAttribArray(10);
 
   glVertexAttribPointer(10, 2, GL_FLOAT, False, 0, nil);
 
   glVertexAttribPointer(10, 2, GL_FLOAT, False, 0, nil);
  
   // Daten für GL_TRIANGLE
+
   // Daten für Punkt Grösse
   glBindVertexArray(VBTriangle.VAO);
+
   glBindVertexArray(VBPoint.VAO);
   glBindBuffer(GL_ARRAY_BUFFER, VBTriangle.VBO_Size);
+
   glBindBuffer(GL_ARRAY_BUFFER, VBPoint.VBO_Size);
   glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * Length(TrianglesSize), Pointer(TrianglesSize), GL_STATIC_DRAW);
+
   glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * Length(PointSize), Pointer(PointSize), GL_STATIC_DRAW);
 
   glEnableVertexAttribArray(11);
 
   glEnableVertexAttribArray(11);
 
   glVertexAttribPointer(11, 1, GL_FLOAT, False, 0, nil);
 
   glVertexAttribPointer(11, 1, GL_FLOAT, False, 0, nil);
 
 
end;</syntaxhighlight>
 
end;</syntaxhighlight>
Bei '''glDrawArrays(...''' ist der erste Parameter das wichtigste, hier wird angegeben, wie die Vektor-Koordinaten gezeichnet werden.<br>
+
Zeichnen der Punkte<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 
const
 
const
Zeile 45: Zeile 38:
 
   Shader.UseProgram;
 
   Shader.UseProgram;
  
   glBindVertexArray(VBTriangle.VAO);
+
   glBindVertexArray(VBPoint.VAO);
   // Zeichne GL_TRIANGLE
+
   // gelb
 
   glUniform1i(PointTyp_ID, 0);
 
   glUniform1i(PointTyp_ID, 0);
   glUniform3f(Color_ID, 1.0, 1.0, 0.0); // Gelb
+
   glUniform3f(Color_ID, 1.0, 1.0, 0.0);
 
   glUniform1f(X_ID, -ofs);
 
   glUniform1f(X_ID, -ofs);
 
   glUniform1f(Y_ID, -ofs);
 
   glUniform1f(Y_ID, -ofs);
   glDrawArrays(GL_POINTS, 0, Length(Triangles));
+
   glDrawArrays(GL_POINTS, 0, Length(Point));
  
   // Zeichne GL_TRIANGLE_STRIP
+
   // rot
 
   glUniform1i(PointTyp_ID, 1);
 
   glUniform1i(PointTyp_ID, 1);
   glUniform3f(Color_ID, 1.0, 0.0, 0.0); // Rot
+
   glUniform3f(Color_ID, 1.0, 0.0, 0.0);
 
   glUniform1f(X_ID, ofs);
 
   glUniform1f(X_ID, ofs);
 
   glUniform1f(Y_ID, -ofs);
 
   glUniform1f(Y_ID, -ofs);
   glDrawArrays(GL_POINTS, 0, Length(Triangles));
+
   glDrawArrays(GL_POINTS, 0, Length(Point));
  
   // Zeichne GL_TRIANGLE_FAN
+
   // grün
 
   glUniform1i(PointTyp_ID, 2);
 
   glUniform1i(PointTyp_ID, 2);
   glUniform3f(Color_ID, 0.0, 1.0, 0.0); // Grün
+
   glUniform3f(Color_ID, 0.0, 1.0, 0.0);
 
   glUniform1f(X_ID, ofs);
 
   glUniform1f(X_ID, ofs);
 
   glUniform1f(Y_ID, ofs);
 
   glUniform1f(Y_ID, ofs);
   glDrawArrays(GL_POINTS, 0, Length(Triangles));
+
   glDrawArrays(GL_POINTS, 0, Length(Point));
 
 
  // Zeichne GL_TRIANGLE_FAN
 
  
 +
  // blau
 
   glUniform1i(PointTyp_ID, 3);
 
   glUniform1i(PointTyp_ID, 3);
   glUniform3f(Color_ID, 0.0, 0.0, 1.0); // Blau
+
   glUniform3f(Color_ID, 0.0, 0.0, 1.0);
 
   glUniform1f(X_ID, -ofs);
 
   glUniform1f(X_ID, -ofs);
 
   glUniform1f(Y_ID, ofs);
 
   glUniform1f(Y_ID, ofs);
   glDrawArrays(GL_POINTS, 0, Length(Triangles));</syntaxhighlight>
+
   glDrawArrays(GL_POINTS, 0, Length(Point));
 +
 
 +
  ogc.SwapBuffers;
 +
end;</syntaxhighlight>
 
<br><br>
 
<br><br>
 
==Vertex-Shader:==
 
==Vertex-Shader:==
<br>
 
Da die Koordinaten nur als 2D gespeichert sind, wird im Vertex-Shader der Z-Wert auf 0.0 gesetzt.<br>
 
 
<syntaxhighlight lang="glsl">#version 330
 
<syntaxhighlight lang="glsl">#version 330
  

Aktuelle Version vom 23. Juli 2018, 20:43 Uhr

Lazarus - OpenGL 3.3 Tutorial - Shader - Punkte verschieden darstellen.png

Shader - Punkte verschieden darstellen

Einleitung

Man kann auch Punkte mit dem Shader darstellen, dies kann man auf verschiedene Weise.
Im Fragment-Shader kann man das Zeichen der Punkte manipulieren.


Die Deklaration der Koordianten und Punktgrösse.

var
  Point: array of TVertex2f;
  PointSize: array of GLfloat;

Daten für die Punkte in die Grafikkarte übertragen

procedure TForm1.InitScene;
begin
  glClearColor(0.6, 0.6, 0.4, 1.0); // Hintergrundfarbe

  // Daten für Punkt Position
  glBindVertexArray(VBPoint.VAO);
  glBindBuffer(GL_ARRAY_BUFFER, VBPoint.VBO);
  glBufferData(GL_ARRAY_BUFFER, sizeof(TVertex2f) * Length(Point), Pointer(Point), GL_STATIC_DRAW);
  glEnableVertexAttribArray(10);
  glVertexAttribPointer(10, 2, GL_FLOAT, False, 0, nil);

  // Daten für Punkt Grösse
  glBindVertexArray(VBPoint.VAO);
  glBindBuffer(GL_ARRAY_BUFFER, VBPoint.VBO_Size);
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * Length(PointSize), Pointer(PointSize), GL_STATIC_DRAW);
  glEnableVertexAttribArray(11);
  glVertexAttribPointer(11, 1, GL_FLOAT, False, 0, nil);
end;

Zeichnen der Punkte

procedure TForm1.ogcDrawScene(Sender: TObject);
const
  ofs = 0.4;
begin
  glEnable(GL_PROGRAM_POINT_SIZE);

  glClear(GL_COLOR_BUFFER_BIT);
  Shader.UseProgram;

  glBindVertexArray(VBPoint.VAO);
  // gelb
  glUniform1i(PointTyp_ID, 0);
  glUniform3f(Color_ID, 1.0, 1.0, 0.0);
  glUniform1f(X_ID, -ofs);
  glUniform1f(Y_ID, -ofs);
  glDrawArrays(GL_POINTS, 0, Length(Point));

  // rot
  glUniform1i(PointTyp_ID, 1);
  glUniform3f(Color_ID, 1.0, 0.0, 0.0);
  glUniform1f(X_ID, ofs);
  glUniform1f(Y_ID, -ofs);
  glDrawArrays(GL_POINTS, 0, Length(Point));

  // grün
  glUniform1i(PointTyp_ID, 2);
  glUniform3f(Color_ID, 0.0, 1.0, 0.0);
  glUniform1f(X_ID, ofs);
  glUniform1f(Y_ID, ofs);
  glDrawArrays(GL_POINTS, 0, Length(Point));

  // blau
  glUniform1i(PointTyp_ID, 3);
  glUniform3f(Color_ID, 0.0, 0.0, 1.0);
  glUniform1f(X_ID, -ofs);
  glUniform1f(Y_ID, ofs);
  glDrawArrays(GL_POINTS, 0, Length(Point));

  ogc.SwapBuffers;
end;



Vertex-Shader:

#version 330

layout (location = 10) in vec2  inPos;  // Vertex-Koordinaten in 2D
layout (location = 11) in float inSize; // Vertex-Koordinaten in 2D
uniform float x;                        // Richtung von Uniform
uniform float y;
 
void main(void)
{
  vec2 pos = inPos;
  pos.x = pos.x + x;
  pos.y = pos.y + y;
  gl_PointSize = inSize;
  gl_Position  = vec4(pos, 0.0, 1.0);   // Der zweiter Parameter (Z) auf 0.0
}



Fragment-Shader:

#version 330

uniform vec3 Color  ;  // Farbe von Uniform
out     vec4 outColor; // ausgegebene Farbe

uniform int PointTyp;

void main(void)
{
  vec2  p = gl_PointCoord * 2.0 - vec2(1.0);
  float r = sqrt(dot(p, p));

  float theta = atan(p.y, p.x);

  switch (PointTyp){
    case 0: if(dot(gl_PointCoord - 0.5, gl_PointCoord - 0.5) > 0.25)
              discard;
            else
              outColor = vec4(Color, 1.0);
            break;
    case 1: if(dot(p, p) > cos(theta * 5))
              discard;
            else
              outColor = vec4(Color, 1.0);
            break;
    case 2: if(dot(p, p) > r || dot(p, p) < r * 0.75)
              discard;
            else
              outColor = vec4(Color, 1.0);
            break;
    case 3: if(dot(p, p) > 5.0 / cos(theta - 20 * r))
              discard;
            else
              outColor = vec4(Color, 1.0);
            break;
    default: discard;

  }
}


Autor: Mathias

Siehe auch