Lazarus - OpenGL 3.3 Tutorial - Erster Shader: Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Die Seite wurde geleert.)
 
Zeile 1: Zeile 1:
= Einrichten und Einstieg -  Erster Shader =
 
[[Image: Einrichten und Einstieg -  Erster Shader.png|200px]]<br><br>
 
== Einleitung ==
 
Hier wird zum ersten Mal ein Shader geladen, ohne solchen macht OpenGL >= 3.3 keinen Sinn.<br>
 
Nähere Details dazu im Kapitel Shader. Hier geht es in erster Linie mal darum, dass man etwas rendern kann.<br>
 
<br>
 
In diesem Beispiel wird ein sehr einfacher Shader verwendet. Dieser macht nichts anderes, als das Mesh rot darzustellen.<br>
 
<br><br>
 
Die ID, welche auf den Shader zeigt.<br>
 
<syntaxhighlight lang="pascal">var
 
  ProgramID: GLuint;</syntaxhighlight>
 
Lädt den Vertex- und Fragment-Shader in die Grafikkarte.<br>
 
In diesem Beispiel sind die beiden Shader in einer Textdatei.<br>
 
Natürlich kann man diese auch direkt als String-Konstante im Quellcode deklarieren.<br>
 
<syntaxhighlight lang="pascal">function Initshader(VertexDatei, FragmentDatei: string): GLuint;
 
var
 
  sl: TStringList;
 
  s: string;
 
  
  ProgramObject: GLhandle;
 
  VertexShaderObject: GLhandle;
 
  FragmentShaderObject: GLhandle;
 
 
  ErrorStatus, InfoLogLength: integer;
 
 
begin
 
  sl := TStringList.Create;
 
  ProgramObject := glCreateProgram();
 
 
  // Vertex - Shader
 
 
  VertexShaderObject := glCreateShader(GL_VERTEX_SHADER);
 
  sl.LoadFromFile(VertexDatei);
 
  s := sl.Text;
 
  glShaderSource(VertexShaderObject, 1, @s, nil);
 
  glCompileShader(VertexShaderObject);
 
  glAttachShader(ProgramObject, VertexShaderObject);
 
 
  // Check Shader
 
 
  glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, @ErrorStatus);
 
  if ErrorStatus = 0 then begin
 
    glGetShaderiv(VertexShaderObject, GL_INFO_LOG_LENGTH, @InfoLogLength);
 
    SetLength(s, InfoLogLength + 1);
 
    glGetShaderInfoLog(VertexShaderObject, InfoLogLength, nil, @s[1]);
 
    Application.MessageBox(PChar(s), 'OpenGL Vertex Fehler', 48);
 
    Halt;
 
  end;
 
 
  glDeleteShader(VertexShaderObject);
 
 
  // Fragment - Shader
 
 
  FragmentShaderObject := glCreateShader(GL_FRAGMENT_SHADER);
 
  sl.LoadFromFile(FragmentDatei);
 
  s := sl.Text;
 
  glShaderSource(FragmentShaderObject, 1, @s, nil);
 
  glCompileShader(FragmentShaderObject);
 
  glAttachShader(ProgramObject, FragmentShaderObject);
 
 
  // Check Shader
 
 
  glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, @ErrorStatus);
 
  if ErrorStatus = 0 then begin
 
    glGetShaderiv(FragmentShaderObject, GL_INFO_LOG_LENGTH, @InfoLogLength);
 
    SetLength(s, InfoLogLength + 1);
 
    glGetShaderInfoLog(FragmentShaderObject, InfoLogLength, nil, @s[1]);
 
    Application.MessageBox(PChar(s), 'OpenGL Fragment Fehler', 48);
 
    Halt;
 
  end;
 
 
  glDeleteShader(FragmentShaderObject);
 
  glLinkProgram(ProgramObject);    // Die beiden Shader zusammen linken
 
 
  // Check Link
 
  glGetProgramiv(ProgramObject, GL_LINK_STATUS, @ErrorStatus);
 
  if ErrorStatus = 0 then begin
 
    glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH, @InfoLogLength);
 
    SetLength(s, InfoLogLength + 1);
 
    glGetProgramInfoLog(ProgramObject, InfoLogLength, nil, @s[1]);
 
    Application.MessageBox(PChar(s), 'OpenGL ShaderLink Fehler', 48);
 
    Halt;
 
  end;
 
 
  Result := ProgramObject;
 
  sl.Free;
 
end;</syntaxhighlight>
 
Dieser Code wurde um 2 Zeilen erweitert.<br>
 
<br>
 
In der ersten Zeile wird der Shader in die Grafikkarte geladen.<br>
 
Die zweite Zeile aktiviert den Shader.<br>
 
Dies wird spätestens dann interessant, wenn man mehrere Shader verwendet.<br>
 
Näheres im Kapitel Shader.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.CreateScene;
 
begin
 
  ProgramID := InitShader('Vertexshader.glsl', 'Fragmentshader.glsl');
 
  glUseProgram(programID);</syntaxhighlight>
 
Beim Zeichnen muss man auch mit '''glUseProgram(...''' den Shader wählen, mit welchem das Mesh gezeichnet wird.<br>
 
Bei diesem Mini-Code könnte dies weggelassen werden, da nur ein Shader verwendet wird und dieser bereits in TForm1.CreateScene aktiviert wurde.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.ogcDrawScene(Sender: TObject);
 
begin
 
  glClear(GL_COLOR_BUFFER_BIT);
 
 
  glUseProgram(programID);</syntaxhighlight>
 
Am Ende noch mit '''glDeleteShader(...''' die Shader in der Grafikkarte wieder freigeben.<br>
 
In diesem Code ist dies nur einer.<br>
 
<syntaxhighlight lang="pascal">procedure TForm1.FormDestroy(Sender: TObject);
 
begin
 
  glDeleteProgram(ProgramID);</syntaxhighlight>
 
<br><br>
 
Die beiden verwendeten Shader, Details dazu im Kapitel Shader.<br>
 
<br>
 
==Vertex-Shader:==
 
<syntaxhighlight lang="glsl">#version 330
 
 
layout (location = 0) in vec3 inPos;
 
 
void main(void)
 
{
 
  gl_Position = vec4(inPos, 1.0);
 
}
 
</syntaxhighlight>
 
<br><br>
 
==Fragment-Shader:==
 
<syntaxhighlight lang="glsl">#version 330
 
 
out vec4 outColor; // ausgegebene Farbe
 
 
void main(void)
 
{
 
  outColor = vec4(1.0, 0.0, 0.0, 1.0);
 
}
 
</syntaxhighlight>
 
 
<br>Autor: [[Mathias]]
 
== Siehe auch ==
 
* Übersichtseite [[Lazarus - OpenGL 3.3 Tutorial]]
 

Aktuelle Version vom 12. Dezember 2017, 21:28 Uhr