43
(9) Modernes OpenGL Vorlesung „Computergraphik III“ U N I V E R S I T Ä T KOBLENZ · LANDAU „Computergraphik III“ S. Müller

(9) Modernes OpenGL - userpages.uni-koblenz.decg/ss13/cg3/09_Modernes OpenGL.pdf · einer unified shader Architektur aufgegeben Den Kern bilden dabei Streaming-Prozessoren (SM) Diese

  • 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 und GLEW

U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 6 -

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);

Variablen im/an den Shader

U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 24 -

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 -

Framebuffer Objekte

U N I V E R S I T Ä TKOBLENZ · LANDAU S. Müller - 29 -

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

U N I V E R S I T Ä TKOBLENZ · LANDAU

U N I V E R S I T Ä TKOBLENZ · LANDAU