Upload
others
View
45
Download
0
Embed Size (px)
Citation preview
(9) Modernes OpenGL
Vorlesung„Computergraphik III“
U N I V E R S I T Ä TKOBLENZ · LANDAU
„Computergraphik III“S. Müller
OpenGL Shading Language (GLSL)
� Teil des OpenGL 2.0 Standards� Syntax orientiert sich an C / C++
� Funktionen� Einfache Datentypen (float, int, bool)� Strukturen� Arrays
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 2 -
� Arrays� Bedingungen � Schleifen� Aber: Keine Zeiger
� Beliebige Länge der Shader-Programme
NVIDIA
U N I V E R S I T Ä TKOBLENZ · LANDAU
� Im Laufe der Zeit wurde die dedizierte Hardware (2D/3D) zu Gunsten einer unified shader Architektur aufgegeben
� Den Kern bilden dabei Streaming-Prozessoren (SM)� Diese Anforderungen kamen u.a. auch aus dem GPGPU-Bereich
(General Purpose GPU) und HPC-Bereich (high performance computing)
S. Müller - 3 -
Beispiel: Kepler
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 4 -
Quelle: Nvidia
SMX: 192 single‐precision CUDA cores, 64 double‐precision units, 32 special function units (SFU), and 32 load/store units (LD/ST).
OpenGL 3.3
� OpenGL 3.0 (2008)� OpenGL Shading Language 1.30� Entfernen von Altlasten (glBegin /
glEnd, Fixed-Function-Pipeline, T&L etc.)
� erstmals weitestgehender Verzicht auf explizite Abwärtskompatibilität
� OpenGL 3.2 (2009)� OpenGL Shading Language 1.50� Geometry-Shader werden bei
Programmierung von Grafikpipelines jetzt auch direkt im OpenGL-Kern unterstützt
� OpenGL 3.3 (2010)
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 5 -
� OpenGL 3.1 (2009)� weiteres Entfernen von Altlasten
(z. B. Fixed-Function-Optionen, Direct-Mode und Color-Index-Mode), diese sind nur noch über die optionale „compatibilityextension“ verfügbar
� OpenGL Shading Language 1.40
� OpenGL 3.3 (2010)� OpenGL Shading Language 3.30
GLFW
� GLUT wird leider weiterhin nicht mehr unterstützt (Alternative freeGlut)
� Wir verwenden daher ab jetzt glfw, der genauso einfach ist
� www.glfw.org
U N I V E R S I T Ä TKOBLENZ · LANDAU
� www.glfw.org
S. Müller - 7 -
GLFW
� Fensterkommandosvoid glfwSetWindowTitle( const char *title )
void glfwSetWindowSize( int width, int height )
void glfwSetWindowPos( int x, int y )
� KeyboardPull: int glfwGetKey( int key ) liefert 1 wenn Taste key gedrückt, sonst 0Callback: void glfwSetKeyCallback ( GLFWkeyfun cbfun ) wie bei GLUT
U N I V E R S I T Ä TKOBLENZ · LANDAU
Callback: void glfwSetKeyCallback ( GLFWkeyfun cbfun ) wie bei GLUT
� MausPull: void glfwGetMousePos( int *x, int *y ) liefert MauspositionCB: void glfwSetMousePosCallback( GLFWmouseposfun cbfun ) wie bei GLUTPull: int glfwGetMouseButton( int button ) liefert Status der MausknöpfeCB: void glfwSetMouseButtonCallback( GLFWmousebuttonfun f un ) wie bei GLUT
� Sonstiges� Mausrad, glfwGetTime, glfwSleep, Texture Loading, Multi-thraeding
S. Müller - 8 -
Simples Programm#include <glew.h> #include <GL/glfw.h>...int main(int argc, char** argv) {
glfwInit();
glfwOpenWindow(800,600,8,8,8,0,24,0,GLFW_WINDOW);
glewInit();
Extension Wrangler
U N I V E R S I T Ä TKOBLENZ · LANDAU
glClearColor(0, 0, 0, 1);
while(GLFW_OPENED) {
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
...
glfwSwapBuffers();
}
glfwTerminate();
}
S. Müller - 9 -
Pull-Modus
Die guten alten Zeiten 1 void init()
{
glClearColor(1,1,1,1);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(…);
glMatrixMode(GL_MODELVIEW);
}
void terrain()
void display()
{
glLoadIdentity();
gluLookAt( …);
glRotate(…)
glClear( …_BIT|GL_DEPTH…);
glColor3f(1.0,1.0,1.0);
U N I V E R S I T Ä TKOBLENZ · LANDAU
void terrain()
{
glBegin(GL_POLYGON);
glVertex3f(x, y, z);
glNormal3f( …);
…;
glEnd();
}
glColor3f(1.0,1.0,1.0);
draw_terrain();
glutSwapBuffers();
}
S. Müller - 10 -
Die guten alten Zeiten 2
� MaterialGLfloat mat_emission[] = {…};
GLfloat mat_ambient[] = {…};
GLfloat mat_diffuse[] = {…};
GLfloat mat_specular[] = {…};
glMaterialfv(GL_FRONT,…);
glMaterialfv(…,GL_AMBIENT,…);
� LichtGLfloat ambient[] = {…};
GLfloat diffuse[] = {…};
GLfloat specular[] = {…};
glLightfv( GL_LIGHT0, GL_POSITION, …);
glLightfv( GL_LIGHT0, GL_AMBIENT, …);
glLightfv( GL_LIGHT0, GL_DIFFUSE, …);
U N I V E R S I T Ä TKOBLENZ · LANDAU
glMaterialfv(…,GL_AMBIENT,…);
glMaterialfv(…,mat_diffuse);
glLightfv( GL_LIGHT0, GL_DIFFUSE, …);
glLightModelfv( GL_LIGHT_MODEL_AMBIENT,
lmodel_ambient );
glLightModelfv( GL_LIGHT_MODEL_LOCAL_VIEWER,
local_view );
glLightModeli( GL_LIGHT_MODEL_TWO_SIDE,
GL_FALSE);
glEnable( GL_LIGHTING);
glEnable( GL_LIGHT0);
S. Müller - 11 -
Vertex Attribute
Kein glBegin … glEnd mehr…
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 12 -
void terrain(){
glBegin(GL_POLYGON);glVertex3f(x, y, z); glVertex3f( …);…;
glEnd();…}
Vertex Attributes
� Da GL_Begin … GL_End (immediate mode) zu unperformant sind, werden für die Daten Objekte angelegt, wie wir sie von den Texturen kennen.
� Die Vertices bestehen aus Attributen (Position, Normale, Farbe etc.) mit 1-4 Werten pro Eintrag
U N I V E R S I T Ä TKOBLENZ · LANDAU
� Diese werden jeweils in Arrays (ARRAY_BUFFER) abgelegt, auch Buffer-Objekte genannt.
� Entsprechend hat sich für die Liste der Positionen eines Objekts auch der Name Vertex-Buffer-Objekt etabliert
S. Müller - 13 -
Attribute: nicht indizierte ListeGLuint VBO;
Glfloat Vertices[] = { -0.4, -0.4, -0.4, 0.4, 0.4 , 0.4 };
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Ver tices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
size stride
U N I V E R S I T Ä TKOBLENZ · LANDAU
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
//Renderschleife
…
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
S. Müller - 14 -
void terrain(){
glBegin(GL_POLYGON);glVertex3f(x, y, z); glVertex3f( …);…;
glEnd();…}
Indizierte ListeGLuint VBO;
GLuint IBO;
GLfloat Vertices[] = { -0.4, -0.4, -0.4, 0.4, 0.4 , 0.4 };
GLuint Indices[] = {0, 1, 2};
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 15 -
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Ver tices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(Indices ),Indices,GL_STATIC_DRAW);
//Renderschleife
…
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0) ;
Mehrere AttributeGLuint BufferObjectHandles[2];
GLfloat Vertices[] = { -0.4, -0.4, -0.4, 0.4, 0.4 , 0.4 };
GLfloat Colours[] = { 1, 0, 0, 0, 1, 0, 0, 0, 1};
glGenBuffers(2, BufferObjectHandles);
glBindBuffer(GL_ARRAY_BUFFER, BufferObjectHandles[0 ]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Ver tices, GL_STATIC_DRAW);
U N I V E R S I T Ä TKOBLENZ · LANDAU
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Ver tices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, BufferObjectHandles[1 ]);
glBufferData(GL_ARRAY_BUFFER, sizeof(Colours), Colo urs, GL_STATIC_DRAW);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
//Renderschleife
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
S. Müller - 16 -
Transformationen
Keine OpenGL Matrizen mehr…
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 17 -
void display(){
glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(…);
glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt( …);glRotate(…)
…}
glm (OpenGL Mathematics)
� Da es keine OpenGL Matrix Kommandos mehr gibt, brauchen wir eine Mathe-Lib
� Als Mathe-Lib nehmen wir glm(OpenGL Mathematics), die sich an GLSL orientiert.
� http://glm.g-truc.net
Bsp.� Generell: glm.hpp
� gtc/matrix_transform.hpp
� Matrixtransformationen
� gtc/matrix_inverse.hpp
� Matrixinvertierung
glm/gtc/type_ptr.hpp
U N I V E R S I T Ä TKOBLENZ · LANDAU
� http://glm.g-truc.net� Dies ist eine include-Lib, d.h.
dass man je nach Verwendung von Kommandos auch die entsprechen „.h“ Datei includen muss.
S. Müller - 18 -
� glm/gtc/type_ptr.hpp
� Sinnvoll, um glm-Vektoren und -Matrizen als GLSL-Parameter zu übergeben
vec3 aVector(3); mat4 someMatrix(1.0); glUniform3fv(…, value_ptr(aVector)); glUniformMatrix4fv(…, value_ptr(someMatrix));
glm#include <glm/glm.hpp> // alles notwendige
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
mat4(1.0f); //LoadIdentity
mat4 modelMat = rotate(mat4(1.0f), degrees(angle), vec3(1.0f,1.0f,0.0f));
mat4 scaleMat = scale(mat4(1.0f), vec3(2.0f,1.0f,1.0f));
Multiplikation von rechts
U N I V E R S I T Ä TKOBLENZ · LANDAU
mat4 scaleMat = scale(mat4(1.0f), vec3(2.0f,1.0f,1.0f));
mat4 transMat = translate(mat4(1.0f), vec3(2.0f,1.0f,1.0f));
mat4 …= rotate(transMat, degrees(angle), vec3(2.0f,1.0f,1.0f));
mat4 frustum(float left, float right, float bottom, float top, float zNear, float zFar);
mat4 ortho(float left, float right, float bottom, float top, float zNear, float zFar);
mat4 lookAt( vec3 eye, vec3 center, vec3 up);
mat4 perspective( float fovy, float aspect, float zNear, float zFar );
S. Müller - 19 -
RT ⋅=
Übergabe der Vertex-Attribute an Shader
Keine Fixed Function Pipeline mehr(Ohne Shader kein Rendering)
U N I V E R S I T Ä TKOBLENZ · LANDAU
(Ohne Shader kein Rendering)
S. Müller - 20 -
Einfache Variante (Variante 1)
� Im Vertex-Shader werden die Stream-Daten auf eine „in“-Variable abgebildet.
� Durch die Reihenfolge in der Shaderprogrammierung ergibt sich eine default-Location (Index).
#version 330 //Vertex-Shader
in vec2 position;
in vec4 colour;
out vec4 OutColour;
void main(){
gl_Position = position;
location
01
Wir kennen die Location im Shader
U N I V E R S I T Ä TKOBLENZ · LANDAU
(Index).� Auf der OpenGL-Seite muss
man den jeweiligen Buffer nur der jeweilige Location zuweisen.
� Diese entspricht auch dem Index zum Einschalten des Attributes
gl_Position = position;
OutColour = colour;
}
S. Müller - 21 -
glBindBuffer(GL_ARRAY_BUFFER, vertexbufferhandle);glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);glEnableVertexAttribArray(0);
Variante 2: Eigenes Layout#version 330 //Vertex-Shader
layout (location = 4) in vec2 position;
layout (location = 7) in vec4 colour;
out vec4 OutColour;
void main(){
gl_Position = position;
OutColour = colour;
Wir setzen die Location im Shader
U N I V E R S I T Ä TKOBLENZ · LANDAU
OutColour = colour;
}
� OpenGL…
glBindBuffer(GL_ARRAY_BUFFER, vertexbufferhandle);
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, colourbufferhandle);
glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(7);
S. Müller - 22 -
Variante 3: Auf OpenGL-Seite#version 330 //Vertex-Shader
in vec4 position;
in vec4 colour;
out vec4 OutColour;
…
� OpenGL…
glBindAttribLocation( programHandle, 5, "position") ;
Wichtig: vor dem Linken!
Wir suchen die Variable im Shader und definieren eine Location
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 23 -
glBindAttribLocation( programHandle, 5, "position") ;
glBindAttribLocation( programHandle, 9, "colour");
glLinkProgram(programHandle);
glBindBuffer(GL_ARRAY_BUFFER, vertexbufferhandle);
glVertexAttribPointer(5, 2, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, colourbufferhandle);
glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(9);
Built-In Variablen
� Es gibt eine Reihe von vordefinierten input- und output-Variablen.
� Vertex-Shaderin int gl_VertexID;
out vec4 gl_Position;
� Fragment-Shader
#version 330 //Vertex
in vec4 position;
void main(){
gl_Position = position;
}
#version 330 //Fragment
U N I V E R S I T Ä TKOBLENZ · LANDAU
� Fragment-Shaderin vec4 gl_FragCoord;
in int gl_SampleID;
out vec4 gl_FragColor
� Genaue Aufstellung:
#version 330 //Fragment
void main(){
gl_FragColor = vec4(1,1,0,1);
}
S. Müller - 25 -
http://www.khronos.org/files/opengl41-quick-reference-card.pdf
Uniform Variablen
� Neben den Stream-Werten (pro Vertex bzw. pro Fragment) kann man dem Shader noch uniforme (konstante) Variablen zuweisen
#version 330 //Vertex-Shader
in vec4 position;
uniform vec4 colour;
out vec4 OutColour;
void main(){
gl_Position = position;
U N I V E R S I T Ä TKOBLENZ · LANDAU
gl_Position = position;
OutColour = colour;
}
S. Müller - 26 -
GLuint unifColourHandle = glGetUniformLocation( pro grHandle, "colour");GLfloat blue[] = { 0, 0, 1, 1};glUniform4fv( unifColourHandle, 1, blue);
OpenGL Pipeline (Vertex-Shader)#version 330 //Vertex
in vec4 positionAttribute;
in vec4 normalAttribute;
uniform mat4 uniformModel;
uniform mat4 uniformView;
uniform mat4 uniformNormal;
U N I V E R S I T Ä TKOBLENZ · LANDAU
uniform mat4 uniformNormal;
uniform mat4 uniformProjection;
void main(){
vec4 modelViewPosition = uniformView * uniformModel * positionAttribute;
vec3 passNormal = normalize((uniformNormal * normal Attribute).xyz);
gl_Position = uniformProjection * modelViewPosition ;
}
S. Müller - 27 -
OpenGL Pipeline (Appl.)Gluint ModelHandle = glGetUniformLocation(programHa ndle, "uniformModel");
Gluint ViewHandle = glGetUniformLocation(programHan dle, "uniformView");
Gluint NormalHandle = glGetUniformLocation(programH andle, "uniformNormal");
Gluint ProjHandle = glGetUniformLocation(programHan dle, "uniformProjection");
mat4 modelMatrix = rotate(mat4(1.0f), degrees(angle ), vec3(1.0f,1.0f,0.0f));
glUniformMatrix4fv( ModelHandle, 1, GL_FALSE, value _ptr(modelMatrix));
U N I V E R S I T Ä TKOBLENZ · LANDAU
mat4 viewMatrix = lookAt(vec3(0.0f,2.0f,3.0f), vec3 (0.0f,0.0f,0.0f), vec3(0.0f,1.0f,0.0f));
glUniformMatrix4fv(ViewHandle, 1, GL_FALSE, value_p tr(viewMatrix));
mat4 projectionMatrix = perspective(60.0f, 4.0f / 3 .0f, 0.1f, 100.f);
glUniformMatrix4fv(ProjHandle, 1, GL_FALSE, value_p tr(projectionMatrix));
mat4 normalMatrix = transpose(inverse(viewMatrix * modelMatrix));
glUniformMatrix4fv(NormalHandle, 1, GL_FALSE, value _ptr(normalMatrix));
}
S. Müller - 28 -
Framebufferobjects (FBOs)
� Statt in den Framebuffer direkt zu rendern, kann man Texturen „attachen“, in die gerendert werden soll (render to texture )
� Ein Framebuffer-Objekt kann mehrere Rendering-Ziele beinhalten
U N I V E R S I T Ä TKOBLENZ · LANDAU
beinhalten- GL_COLOR_ATTACHMENT0
…
- GL_COLOR_ATTACHMENTn
- GL_DEPTH_ATTACHMENT
- GL_STENCIL_ATTACHMENT
- Default Framebuffer wird vom Windows-Manager eingerichtet (Color, Depth und Stencil).
S. Müller - 30 -
FBOs
� Wie beim Vertex-Shader können auch dem FragmentShader Objekte zugeordnet werden
� Statt in den Framebuffer direkt zu rendern, kann man Texturen „attachen“, in die gerendert werden soll (render to texture )
� Ein Framebuffer-Objekt kann mehrere Rendering-Ziele beinhalten- GL_COLOR_ATTACHMENT0 …
U N I V E R S I T Ä TKOBLENZ · LANDAU
- GL_COLOR_ATTACHMENT0 …
- GL_COLOR_ATTACHMENTn
- GL_DEPTH_ATTACHMENT
- GL_STENCIL_ATTACHMENT
- Default Framebuffer wird vom Windows-Manager eingerichtet (Color, Depth und Stencil).
S. Müller - 31 -
FBOs
� FBO generieren und bindenglGenFramebuffers(…)
glBindFramebuffer(…)
� Texturobj anlegen + bindenglGenTextures(…);
� Textur an FBO attachenglFramebufferTexture2D(…);
� Parameter legen fest, als was attached wirdGL_COLOR_ATTACHMENT0
GL_COLOR_ATTACHMENTn
U N I V E R S I T Ä TKOBLENZ · LANDAU
glGenTextures(…);
glBindTexture(…);
� Textur anlegen und Parameter setzenglTexImage2D(…); glTexParameteri(…);//Min/Mag-Filter wrap_s, wrap_t
GL_COLOR_ATTACHMENTn
GL_DEPTH_ATTACHMENT
GL_STENCIL_ATTACHMENT
� Wichtig: Legt man eigenes FBO an, gehen die Defaults verloren. Also ohne eigenes Depth-Attachement gibt es keinen Sichtbarkeitstest.
S. Müller - 32 -
Beispiel: Shadowmap//creation of the framebuffer object
GLuint framebufferHandle = 0;
glGenFramebuffers(1, &framebufferHandle);
glBindFramebuffer(GL_FRAMEBUFFER, framebufferHandle );
//creation of the depth texture
GLuint depthTextureHandle;
glGenTextures(1, &depthTextureHandle);
glBindTexture(GL_TEXTURE_2D, depthTextureHandle);
U N I V E R S I T Ä TKOBLENZ · LANDAU
glBindTexture(GL_TEXTURE_2D, depthTextureHandle);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTE R, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, G L_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, G L_CLAMP_TO_EDGE);
//bind the depth texture to the framebuffer
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureHandle, 0);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
S. Müller - 33 -
ShadowMap Hauptschleifewhile…
//bind framebuffer and draw on it
glBindFramebuffer(GL_FRAMEBUFFER, framebufferHandle );
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0,0,1024,1024);
glUseProgram(depthwriteProgramHandle); //use shader set 1
…
glDrawArrays(…); //draw scene from light source
U N I V E R S I T Ä TKOBLENZ · LANDAU
glDrawArrays(…); //draw scene from light source
//unbind the framebuffer object, render into the wi ndow instead
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0,800,600);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shadowingProgramHandle); //use shader set 2
//bind the depth texture
glBindTexture(GL_TEXTURE_2D, depthTextureHandle);
…
glDrawArrays(…); //draw scene from camera
glfwSwapBuffers();
}
S. Müller - 34 -
Shader Set 1 (Tiefenmap generieren)
Vertex Shaderin vec3 pos;
uniform mat4 Light_MVP;
void main(){
gl_Position = Light_MVP * pos;
}
Fragment Shaderout float fragmentdepth;
void main(){
fragmentdepth = gl_FragCoord.z;
}
Built-In Variable
U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 35 -
Built-In Variable
Shader Set
Vertex Shaderin vec3 pos;
uniform mat4 MVP;
uniform mat4 Light_MVP;
out vec4 pos_LKS;
void main(){
gl_Position = MVP * pos;
Fragment Shaderin vec4 pos_LKS;
uniform sampler2D tex;
void main(){
vec3 p = pos_LKS.xyz / pos_LKS.w;
float depth =
texture( tex, vec2(p.s,p.t)).x;
100021
21
00
21
021
0
21
0021
U N I V E R S I T Ä TKOBLENZ · LANDAU
gl_Position = MVP * pos;
pos_LKS = … * Light_MVP * pos;
}
texture( tex, vec2(p.s,p.t)).x;
if (depth < (p.z-0.0005))
//Schatten
else
//Kein Schatten
…
}
S. Müller - 36 -
Computer Shader
Eine kleine EinführungJochen Hunz
U N I V E R S I T Ä TKOBLENZ · LANDAU
Jochen Hunz
S. Müller - 37 -
Folien angelehnt an:Mark Kilgard, Nvidia Corporation, „OpenGL 4.3 and Beyond“ SIGGRAPH Asia 2012
Mike Bailey, Oregon State University
OpenGL 4.3 Compute Shader
� „Grid-oriented Single Program, Multiple Data (SPMD) execution model“
� Ermöglicht beliebige Berechnungen auf GPU� Raytracing� Partikel Physik
U N I V E R S I T Ä TKOBLENZ · LANDAU
� Partikel Physik� Fluide� Filterung� ...� Allgemein parallelisierbare Algorithmen
� Unabhängig von bekannten Shadern „dispatchbar“� Kann Buffer, Texture Images, … schreiben
Single Program, Multiple Data (SPMD) execution model„Threads in Groups in Dispatches“
� Jeder Thread hat eigene InvocationID
gl_GlobalInvocationID = gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID
GlobalInvocationID sagt Thread „wer bin ich?“
U N I V E R S I T Ä TKOBLENZ · LANDAU
work group dispatchInvocation (thread)
� GlobalInvocationID sagt Thread „wer bin ich?“� Super für z.B. Array / Buffer Indizierung
Einfaches Partikel-System: Compute Shader
#version 430
layout(std140,binding=0) buffer Pos { vec4 Positions []; }
layout(std140,binding=1) buffer Vel { vec4 Velocities[]; }
const float dT = 0.0016;
const vec3 gravity = vec3(0.0, -9.8, 0.0);
Zeit und Schwerkraft
Eingabe-Buffer
U N I V E R S I T Ä TKOBLENZ · LANDAU
layout( local_size_x = 64, local_size_y = 1, local_size_z = 1 ) in;
void main() {
uint gid = gl_GlobalInvocationID.x;
vec3 p = Positions[gid].xyz;
vec3 v = Velocities[gid].xyz;
vec3 pp = p + v * dT + 0.5 * dT * dT * gravity;
vec3 vp = v + gravity * dT;
CheckAndHandleCollisions();
Positions[gid].xyz = pp;
Velocities[gid].xyz = vp;
}
p' = p + v * t + 0.5G * t²v' = v + G * t
64 Threads pro Gruppe
Beschreibe die Eingabe-Buffer mit neuen Werten
work group
1) Buffer für Positions und Velocities initialisieren u nd füllen glGenBuffers, glBufferData, glMapBufferRange
2) Buffer an layout bindenglBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, positionBuffer);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, velocityBuffer);
3) Compute Shader schreiben, laden, attachen, linkenGLuint compute_shader = glCreateShader(GL_COMPUTE_SHADER);
glCreateProgram/glAttachShader/glLinkProgram
4) Programm benutzenglUseProgram(compute_shader);
Einfaches Partikel-System: Anwendung
Nicht mit Render-Shadern kombinieren
U N I V E R S I T Ä TKOBLENZ · LANDAU
glUseProgram(compute_shader);
5) Dispatchen an beliebiger StelleglDispatchCompute(anzahlPartikel/64,1,1);
6) Partikel zeichnenglUseProgram(render_shader);
glEnableVertexAttribArray, glBindBuffer, glVertexAttribPointer
glDrawArrays
glDisableVertexAttribArrayGleiche Buffer, z.B.positionBuffer
dispatch
Beispiel 1024 Partikel:Dispatche 1024 / 64 = 16 WorkgroupsJede Workgroup hat 64 Threads (siehe Folie vorher)Insgesamt also 16 * 64 = 1024 Threads => 1 Thread/Partikel