TAM
Ústav počítačové grafiky a multimédií
Prezentace p řednášek
OpenGL ES 2.0
Grafika na mobilních za řízeních
IVS / Urychlování výpočtů, možnosti paralelizace 3
Motto
„If Edison had a needle to find in a haystack, hewould proceed at once with the diligence of the bee to examine straw after straw until he found the object of his search.I was a sorry witness of such doings, knowing that a little theory and calculation would have saved him ninety per cent of his labor.“
- Nikola Tesla
IVS / Urychlování výpočtů, možnosti paralelizace 4
Obsah:
• Úvod do OpenGL• OpenGL ES on embedded devices• Reprezentace objektů ve vertex arrays• Vertex a fragment shadery• Texturování• Framebuffer objekty• Doporučená literatura
IVS / Urychlování výpočtů, možnosti paralelizace 5
OpenGL
• Knihovna „Open Graphics Library“ od SGI• Dnes udržuje Khronos Group• Kreslení pomocí
– Immediate mode (glVertex3f())– Display lists (glCallLists())– Arrays (glDrawArrays())
• Fixed-function pipeline• Binding pro mnoho jazyků
– “C“/C ++– Java (JOGL)– Python (PyGL)– Další ...
IVS / Urychlování výpočtů, možnosti paralelizace 6
OpenGL (ES 1.0) fixed-function pipeline
IVS / Urychlování výpočtů, možnosti paralelizace 7
OpenGL programmable pipeline
vertex shadertesselation shadergeometry shader
fragment shadertransform feedback
IVS / Urychlování výpočtů, možnosti paralelizace 8
OpenGL ES 2.0 pipeline
vertex shadertesselation shadergeometry shader
fragment shadertransform feedback
IVS / Urychlování výpočtů, možnosti paralelizace 9
OpenGL ES on embedded devices
• Různé platformy– NVIDIA Tegra (ULP GeForce)– ARM
• Android-based devices– “C“/C ++– Java
• Apple iPhone– Objective C– Java
• Ubuntu, Win CE– “C“/C ++
IVS / Urychlování výpočtů, možnosti paralelizace 10
OpenGL ES bez zařízení
• Motivace– Vývojářské nástroje, možnost ladění– Snadné použití– Není potřeba mít cílové mobilní zařízení (zejména velké týmy)
• Emulace je možná na OpenGL 2.0 hardware• See (and use):
http://www.stud .fit .vutbr.cz/~xpolok 00/proj_glesemu.htm• Android emulator (pomalý)
IVS / Urychlování výpočtů, možnosti paralelizace 11
Inicializace OpenGL ES
• Windows CE– WGL + nativní okna– EGL
• Ubuntu– GLX + Xserver– EGL
• Android– android.opengl.GLSurfaceView (wrapper EGL)
IVS / Urychlování výpočtů, možnosti paralelizace 12
Inicializace OpenGL ES - Android
public class MyApp extends Activity {
GLSurfaceView mGLView;
GLSurfaceView.Renderer mRenderer = new MyRendererMyRendererMyRendererMyRenderer(this);
protected void onCreateonCreateonCreateonCreate(Bundle _instance) {
super.onCreateonCreateonCreateonCreate(_instance);
setContentViewsetContentViewsetContentViewsetContentView(R.layout.main);
setTitlesetTitlesetTitlesetTitle("OpenGL ES Hello World");
mGLView = (GLSurfaceView)findViewByIdfindViewByIdfindViewByIdfindViewById(R.id.glsv);
mGLView.setEGLContextClientVersionsetEGLContextClientVersionsetEGLContextClientVersionsetEGLContextClientVersion(2);
mGLView.setRenderersetRenderersetRenderersetRenderer(mRenderer);
}
protected void onPauseonPauseonPauseonPause()
{ super.onPauseonPauseonPauseonPause(); mGLView.onPauseonPauseonPauseonPause(); }
protected void onResumeonResumeonResumeonResume()
{ super.onResumeonResumeonResumeonResume(); mGLView.onResumeonResumeonResumeonResume(); } }
IVS / Urychlování výpočtů, možnosti paralelizace 13
Inicializace OpenGL ES - Android
public class MyRenderer implements GLSurfaceView.Renderer {
private int mWidth = 640, mHeight = 480;
private MyApp mContext;
public MyRendererMyRendererMyRendererMyRenderer(MyApp context)
{ supersupersupersuper(); mContext = context; }
public void onDrawFrameonDrawFrameonDrawFrameonDrawFrame(GL10 unused) {
GLES20.glViewportglViewportglViewportglViewport(0, 0, mWidth, mHeight);
GLES20.glClearColorglClearColorglClearColorglClearColor(0.0f, 0.0f, 1.0f, 1.0f);
GLES20.glClearglClearglClearglClear(GLES20.GL_COLOR_BUFFER_BIT);
// GLES20.glDoSomethingRatherInterestingglDoSomethingRatherInterestingglDoSomethingRatherInterestingglDoSomethingRatherInteresting(12345);
}
public void onSurfaceChangedonSurfaceChangedonSurfaceChangedonSurfaceChanged(GL10 gl, int w, int h)
{ mWidth = w; mHeight = h; }
public void onSurfaceCreatedonSurfaceCreatedonSurfaceCreatedonSurfaceCreated(GL10 gl, EGLConfig cfg)
{ /* perform init here */ }
}
IVS / Urychlování výpočtů, možnosti paralelizace 14
Inicializace OpenGL ES - Android
res.layout.main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent">
<androidandroidandroidandroid.openglopenglopenglopengl.GLSurfaceViewGLSurfaceViewGLSurfaceViewGLSurfaceViewandroid:layout_height="match_parent"android:layout_width="match_parent"android:id="@+id/glsvglsvglsvglsv"/>
</LinearLayout>
IVS / Urychlování výpočtů, možnosti paralelizace 15
Inicializace OpenGL ES - Android
IVS / Urychlování výpočtů, možnosti paralelizace 16
Kreslení v OpenGL ES
• Nemůžeme použít immediate mode (glVertex*())• Musíme použít
– Vertex attributes– Vertex arrays– Vertex shader– Fragment shader
IVS / Urychlování výpočtů, možnosti paralelizace 17
Vertex attributes
• OpenGL už nemá pevně danou sémantiku vrcholových dat– Dříve byla pozice, normála, barva, sekundární barva + texcoords
• Místo toho se používají očíslované atributy
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(uint attrib_number, // 0
uint num_dimensions, // 3
GLenum data_type, // GL_FLOAT
bool is_normalized, // false
uint stride, // 3 * sizeof(float)
const void *data) // {1, 2, 3}
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(uint attrib_number) // 0
• V Javě je místo “const void*“ java.nio.Buffer
IVS / Urychlování výpočtů, možnosti paralelizace 18
Vertex arrays
• Data vrcholů musí být někde uložená• Na lepších GPU použijeme Vertex Buffer Object (VBO)
– Ten však mobilní zařízení často nemají (sdílená RAM)
• Nebo použijeme jednoduchý buffer– V “C“/C++ prostě float*– V Javě java.nio.FloatBuffer (nebo jiný typ)
final float[] data = {1, 2, 3};
FloatBuffer buff =ByteBuffer.allocateDirectallocateDirectallocateDirectallocateDirect(data.length * 4).orderorderorderorder(ByteOrder.nativeOrdernativeOrdernativeOrdernativeOrder()).asFloatBufferasFloatBufferasFloatBufferasFloatBuffer();
buff.putputputput(data); buff.positionpositionpositionposition(0);
GLES20.glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3, GLES20.GL_FLOAT,false, 3 * 4, buff);
GLES20.glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0);
IVS / Urychlování výpočtů, možnosti paralelizace 19
Vertex arrays
• Když máme připravená data ve vertex bufferu, můžeme je poslat k vykreslení
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GLenum mode, // GL_TRIANGLES
uint first, // 0
uint count) // 3
• Když chceme kreslit složitější objekty kde se vrcholy opakují, přidáme druhý buffer s indexy (forma komprese)a voláme:
glDrawElementsglDrawElementsglDrawElementsglDrawElements(GLenum mode, // GL_TRIANGLESuint count, // 3
GLenum data_type, // GL_UNSIGNED_INT
const void *indices) // indexy
IVS / Urychlování výpočtů, možnosti paralelizace 20
Vertex arrays
• Vykreslení trojúhelníku
float buff[] = {0, .9f, 0,
.9f, -.9f, 0, -.9f, -.9f, 0};
// pozice vrcholů ve 3D
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff);
// pointer na data vertex atributu 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0);
// povolíme pole atributů 0
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GL_TRIANGLES, 0, 3);
// kreslíme tři vrcholy jako trojúhelník, začínáme nultým
x
y1
-1
0
(0, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 21
Vertex arrays
• Vykreslení čtverce
float buff[] = {
+.9f, +.9f, 0,
+.9f, -.9f, 0,
-.9f, -.9f, 0,
-.9f, +.9f, 0};
// pozice vrcholů ve 3D
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GL_QUADS, 0, 4);
// kreslíme 4 vrcholy jako čtverec, začínáme nultým
x
y1
-1
0
(0.9, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
(-0.9, 0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 22
Vertex arrays
• Vykreslení čtverce
float buff[] = {
+.9f, +.9f, 0,
+.9f, -.9f, 0,
-.9f, -.9f, 0,
-.9f, +.9f, 0};
// pozice vrcholů ve 3D
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GL_QUADS, 0, 4);
// kreslíme 4 vrcholy jako čtverec, začínáme nultým
x
y1
-1
0
(0.9, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
(-0.9, 0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 23
Vertex arrays
• Bohužel už nemáme GL_QUADS, GL_QUAD_STRIP a GL_POLYGON
• Máme GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_STRIP a GL_TRIANGLE_FAN
0
1
2
3
4
5
0
12
3
4
5
IVS / Urychlování výpočtů, možnosti paralelizace 24
Vertex arrays
• Vykreslení čtverce
float buff[] = {
-.9f, +.9f, 0,
+.9f, +.9f, 0,
+.9f, -.9f, 0,
+.9f, -.9f, 0,
-.9f, -.9f, 0,
-.9f, +.9f, 0};
// pozice vrcholů ve 3D
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GL_TRIANGLES, 0, 6);
// kreslíme 6 vrcholů jako trojúhelníky, začínáme nultým
x
y1
-1
0
(0.9, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
(-0.9, 0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 25
Vertex arrays
• Vykreslení čtverce
float buff[] = {
+.9f, +.9f, 0,
+.9f, -.9f, 0,
-.9f, -.9f, 0,
-.9f, +.9f, 0};
// pozice vrcholů ve 3D
int indices[] = {3, 0, 1, 1, 2, 3};
// permutace vrcholů, tvořící dva trojúhelníky
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glDrawElementsglDrawElementsglDrawElementsglDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
// kreslíme 6 vrcholů které vybíráme ze 4 pomocí pole indices
x
y1
-1
0
(0.9, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
(-0.9, 0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 26
Vertex arrays
• Vykreslení čtverce
float buff[] = {
-.9f, -.9f, 0,
-.9f, +.9f, 0,
+.9f, -.9f, 0,
+.9f, +.9f, 0};
// pozice vrcholů ve 3D
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 3 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glDrawArraysglDrawArraysglDrawArraysglDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// kreslíme 4 vrcholy jako tristrip, začínáme nultým
x
y1
-1
0
(0.9, 0.9)
(-0.9, -0.9)
(0.9, -0.9)
(-0.9, 0.9)
IVS / Urychlování výpočtů, možnosti paralelizace 27
Vertex arrays
• Vykreslení krychle
const float p_box_vertices[] = {
-1, -1, -1, +1, -1, -1,
+1, -1, +1, -1, -1, +1,
-1, +1, -1, +1, +1, -1,
+1, +1, +1, -1, +1, +1};
const unsigned int p_box_indices[] = {
0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5};
10
23
4
5
6 5
1 0
7 6
3
4
00 1
23
4 5
67
IVS / Urychlování výpočtů, možnosti paralelizace 28
Vertex arrays
• Vykreslení krychle
const float p_box_vertices[] = {
-1, -1, -1, +1, -1, -1,
+1, -1, +1, -1, -1, +1,
-1, +1, -1, +1, +1, -1,
+1, +1, +1, -1, +1, +1};
const unsigned int p_box_indices[] = {
0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5};
10
23
4
5
6 5
1 0
7 6
3
4
00 1
23
4 5
67
IVS / Urychlování výpočtů, možnosti paralelizace 29
Vertex Buffer Objekty (VBO)
• Paměť na GPU pro data vrcholů a indexů• Napřed je nutné buffery naplnit (box z předchozí strany)
int n_vertex_buffer, n_index_buffer;
glGenBuffersglGenBuffersglGenBuffersglGenBuffers(1, &n_vertex_buffer);
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer);
glBufferDataglBufferDataglBufferDataglBufferData(GL_ARRAY_BUFFER, sizeof(p_box_vertices), p_box_vertices, GL_STATIC_DRAW);
glGenBuffersglGenBuffersglGenBuffersglGenBuffers(1, &n_index_buffer);
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, n_index_buffer);
glBufferDataglBufferDataglBufferDataglBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(p_box_indices), p_box_indices, GL_STATIC_DRAW);
IVS / Urychlování výpočtů, možnosti paralelizace 30
Vertex Buffer Objekty (VBO)
• Pro nastavení vertex attributů je potřeba buffer nabindovat• Adresu dat v bufferu nevíme, použijeme NULL (+ offset,
pokud je třeba)• Použít pro různé vertex atributy data z více bufferů je
dovolené, někdy i žádoucí
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer);
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0);
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * sizeof(float), NULL); // NULL ukazuje na začátek VBO
// set vertex coordinate attribute
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, n_index_buffer);
glDrawElementsglDrawElementsglDrawElementsglDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_INT, NULL);
// NULL ukazuje na začátek VBO s indexy (element array)
IVS / Urychlování výpočtů, možnosti paralelizace 31
Vertex Array Objekty (VAO)
• VAO je objekt, který si „pamatuje“ nastavení vertex atributů• Nastavení vyrobíme takto:
int n_vao;
glGenVertexArraysglGenVertexArraysglGenVertexArraysglGenVertexArrays(1, &n_vao);
glBindVertexArrayglBindVertexArrayglBindVertexArrayglBindVertexArray(n_vao);
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ARRAY_BUFFER, n_vertex_buffer);
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0);
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3, GL_FLOAT, false, 3 * 4, NULL);
glBindBufferglBindBufferglBindBufferglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, n_index_buffer);
glBindVertexArrayglBindVertexArrayglBindVertexArrayglBindVertexArray(0); // zamezíme náhodnému poškození
• A v okamžiku potřeby si ho už jen vyvoláme:
glBindVertexArrayglBindVertexArrayglBindVertexArrayglBindVertexArray(n_vao);
glDrawElementsglDrawElementsglDrawElementsglDrawElements(GL_TRIANGLE_STRIP, 14, GL_UNSIGNED_INT, NULL);
IVS / Urychlování výpočtů, možnosti paralelizace 32
Vertex shader
• Krátký program, který říká jak se mají interpretovat vertexatributy
• Každá instance jeden vertex dostane a jeden taky „vyplivne“
precision highp float; // specifikace přesnosti
attribute vec3 v_pos; // atributy - vstup z dat vrcholu
varying vec3 v_color; // výstup - barva vrcholu
uniform mat4 t_modelview_projection;
// parametr shaderu - transformační matice
void mainmainmainmain() {
gl_Position = t_modelview_projection * vec4vec4vec4vec4(v_pos, 1.0);
// musíme zapsat pozici
v_color = v_pos * .5 + .5;
// vymyslíme barvu vrcholu pro fragment shader
}
IVS / Urychlování výpočtů, možnosti paralelizace 33
Fragment shader
• Krátký program, který říká jak vypočítat z interpolovaných souřadnic barvu
• Každá instance dostane interpolované atributy pro jeden pixel a na jejich základě může spočítat barvu nebo hloubku, případně pixel zahodit (discard )
precision highp float; // specifikace přesnosti
varying vec3 v_color; // vstup z vertex shaderu
void mainmainmainmain() {
gl_FragColor = vec4vec4vec4vec4(v_color, 1.0); // zapíše výstupní barvu
}
IVS / Urychlování výpočtů, možnosti paralelizace 34
Práce se shadery
• Na začátku vygenerujeme shader objekty, nahrajeme do nich zdrojový kód shaderů (jako text) a zkompilujeme
int p_shader[2]; // vertex a fragment
char *p_src[2] = {ReadFileReadFileReadFileReadFile(“vs.txt“), ReadFileReadFileReadFileReadFile(“fs.txt“)};
for(int i = 0, n_temp; i < 2; ++ i) {
p_shader[i] = glCreateShaderglCreateShaderglCreateShaderglCreateShader((i == 0)?GL_VERTEX_SHADER : GL_FRAGMENT_SHADER);
glShaderSourceglShaderSourceglShaderSourceglShaderSource(p_shader[i], 1, &p_src[i], NULL);
glCompileShaderglCompileShaderglCompileShaderglCompileShader(p_shader[i]);
glGetShaderivglGetShaderivglGetShaderivglGetShaderiv(p_shader[i], GL_COMPILE_STATUS, &n_temp);
if(n_temp != GL_TRUE)
failfailfailfail(); // chyba při kompilaci (glGetShaderInfoLogglGetShaderInfoLogglGetShaderInfoLogglGetShaderInfoLog())
freefreefreefree(p_src[i]); // !!
}
IVS / Urychlování výpočtů, možnosti paralelizace 35
Práce se shadery
• Vyrobíme program object a shadery k němu připojíme• Nastavíme čísla vertex atributů (propojení s proměnnými VS)• Slinkujeme program• Najdeme čísla parametrů shaderu (uniform )
int n_program_object = glCreateProgramglCreateProgramglCreateProgramglCreateProgram(), n_temp;
for(int i = 0, n_temp; i < 2; ++ i) glAttachShaderglAttachShaderglAttachShaderglAttachShader(n_program_object, p_shader[i]);
glBindAttribLocationglBindAttribLocationglBindAttribLocationglBindAttribLocation(n_program_object, 0, “v_pos“);
glLinkProgramglLinkProgramglLinkProgramglLinkProgram(n_program_object);
glGetProgramivglGetProgramivglGetProgramivglGetProgramiv(n_program_object, GL_LINK_STATUS, &n_temp);
if(n_temp != GL_TRUE)
failfailfailfail(); // chyba při linkování glGetProgramInfoLogglGetProgramInfoLogglGetProgramInfoLogglGetProgramInfoLog()
int n_mvp_uni = glGetUniformLocationglGetUniformLocationglGetUniformLocationglGetUniformLocation((((n_program_object, “t_modelview_projection“);
IVS / Urychlování výpočtů, možnosti paralelizace 36
Práce se shadery
• Při použití nastavíme program jako aktivní• Nastavíme hodnoty různých parametrů (uniform )
Matrix4f t_projection, t_modelview;
t_projection.PerspectivePerspectivePerspectivePerspective(90, 4.0f / 3, .01f, 1000);
t_modelview.IdentityIdentityIdentityIdentity();
t_modelview.TranslateTranslateTranslateTranslate(0, 0, -2);
t_modelview.RotateXRotateXRotateXRotateX(30 * M_PI / 180);
t_modelview.RotateYRotateYRotateYRotateY(10 * M_PI / 180);
Matrix4f t_mvp = t_projection * t_camera_matrix;
float *p_matrix = &t_mvp[0][0];
// OpenGL už nemá operace s maticemi, musíme “počítat sami“
glUseProgramglUseProgramglUseProgramglUseProgram(n_program_object);
glUniformMatrix4fvglUniformMatrix4fvglUniformMatrix4fvglUniformMatrix4fv(n_mvp_uni, 1, GL_FALSE, p_matrix);
// aktivujeme program a nastavíme matici
IVS / Urychlování výpočtů, možnosti paralelizace 37
Výsledek
IVS / Urychlování výpočtů, možnosti paralelizace 38
Textury
• Textury jsou dvourozměrné rastrové obrázky, jež lze v shaderu číst
• K texturám přistupujeme pomocí sampleru, je třeba nastavit číslo texturovací jednotky, ve které je textura nastavená
• OpenGL ES umí i 3D textury (GL_OES_texture_3D)
int n_texture;
glGenTexturesglGenTexturesglGenTexturesglGenTextures(1, &n_texture);
glBindTextureglBindTextureglBindTextureglBindTexture(GL_TEXTURE_2D, n_texture);
glTexParameteriglTexParameteriglTexParameteriglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // zapneme mipmapy (trilineární)
glTexParameteriglTexParameteriglTexParameteriglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // zapneme bilineární filtr
glTexImage2DglTexImage2DglTexImage2DglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 256, 0, GL_RGB, GL_UNSIGNED_BYTE, p_bitmap); // specifikujeme obraz
glGenerateMipmapglGenerateMipmapglGenerateMipmapglGenerateMipmap(GL_TEXTURE_2D); // spočítáme mipmapy
IVS / Urychlování výpočtů, možnosti paralelizace 39
Textury
• Pro texturování „tradičním“ způsobem je potřeba mít souřadnice textur (další vertex atribut)
• V shaderu ale můžeme souřadnice textury i nějak spočítat
float buff[] = {-.9f, -.9f, 0, 0, 0,
-.9f, +.9f, 0, 0, 1,
+.9f, -.9f, 0, 1, 0,
+.9f, +.9f, 0, 1, 1};
// 3D pozice vrcholů + 2D souřadnice textury (5 souřadnic)
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(0, 3,GL_FLOAT, false, 5 * 4, buff); // pointer na atribut 0
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(0); // povolíme pole atributů 0
glVertexAttribPointerglVertexAttribPointerglVertexAttribPointerglVertexAttribPointer(1, 2,GL_FLOAT, false, 5 * 4, buff + 3); // pointer na atribut 1
glEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArrayglEnableVertexAttribArray(1); // povolíme pole atributů 1
IVS / Urychlování výpočtů, možnosti paralelizace 40
Textury
• Vertex shader
precision highp float; // specifikace přesnosti
attribute vec3 v_pos;
attribute vec2 v_tex; // atributy - vstup z dat vrcholu
varying vec3 v_texcoord; // výstup - souřadnice textury
uniform mat4 t_modelview_projection;
// parametr shaderu - transformační matice
void mainmainmainmain() {
gl_Position = t_modelview_projection * vec4vec4vec4vec4(v_pos, 1.0);
// musíme zapsat pozici
v_texcoord = v_tex;
// souřadnici textury jen kopírujeme
}
IVS / Urychlování výpočtů, možnosti paralelizace 41
Textury
• Fragment shader
precision highp float; // specifikace přesnosti
varying vec2 v_texcoord; // vstup z vertex shaderu
uniform sampler2D n_sampler; // sampler pro čtení textury§
void mainmainmainmain() {
gl_FragColor = texture2Dtexture2Dtexture2Dtexture2D(n_sampler, v_texcoord);
// přečte texturu a zapíše ji na výstup
}
int n_sam_uni = glGetUniformLocationglGetUniformLocationglGetUniformLocationglGetUniformLocation(n_program_object, “n_sampler“); // najdi n_sampler ...
glUniform1iglUniform1iglUniform1iglUniform1i(n_sam_uni, 0);
// textura je v texturovací jednotce 0
IVS / Urychlování výpočtů, možnosti paralelizace 42
Výsledek
IVS / Urychlování výpočtů, možnosti paralelizace 43
Framebuffer objekty (FBO)
• Umožňují kreslení do textury– Různé efekty, Voda, Zrcadla– Stínové mapy
• Framebuffer objekt je „kontejner“ pro framebuffery– Renderbuffer objekt (kus paměťi pro uložení rastru)– Textura (při kreslení do textury)
• V OpenGL ES poměrně omezený– Jen jeden attachment pro color, musí být obsazený– Nejsou k dispozici formáty pro depth textury
• DokumentaceglGenFramebuffersglGenFramebuffersglGenFramebuffersglGenFramebuffers(), glGenRenderbuffersglGenRenderbuffersglGenRenderbuffersglGenRenderbuffers()
glBindFramebufferglBindFramebufferglBindFramebufferglBindFramebuffer(), glBindRenderbufferglBindRenderbufferglBindRenderbufferglBindRenderbuffer()
glRenderbufferStorageglRenderbufferStorageglRenderbufferStorageglRenderbufferStorage()
glFramebufferRenderbufferglFramebufferRenderbufferglFramebufferRenderbufferglFramebufferRenderbuffer(), glFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2D()
IVS / Urychlování výpočtů, možnosti paralelizace 44
Framebuffer objekty (FBO)int n_fb, n_rb, n_tex;
glGenFramebuffersglGenFramebuffersglGenFramebuffersglGenFramebuffers(1, &n_fb); glGenRenderbuffersglGenRenderbuffersglGenRenderbuffersglGenRenderbuffers(1, &n_rb);
glBindFramebufferglBindFramebufferglBindFramebufferglBindFramebuffer(GL_FRAMEBUFFER, n_fb);
glBindRenderbufferglBindRenderbufferglBindRenderbufferglBindRenderbuffer(GL_RENDERBUFFER, n_rb);
glRenderbufferStorageglRenderbufferStorageglRenderbufferStorageglRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT16, 256, 256); // renderbuffer pro depth
glFramebufferRenderbufferglFramebufferRenderbufferglFramebufferRenderbufferglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, n_rb); // připojí rb
glFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, n_tex, 0); // připojí texturu
int n_status = glCheckFramebufferStatusglCheckFramebufferStatusglCheckFramebufferStatusglCheckFramebufferStatus(GL_FRAMEBUFFER);
if(n_status != GL_FRAMEBUFFER_COMPLETE)
failfailfailfail(); // zpravidla chyba programátora
glViewportglViewportglViewportglViewport(0, 0, 256, 256); // potom je třeba vrátit původní
// kreslení do textury
glFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2DglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, 0, 0); // uvolnění textury pro kreslení
IVS / Urychlování výpočtů, možnosti paralelizace 45
Literatura
• NVIDIA OpenGL SDK• www.fit .vutbr.cz/~ipolok /gles /• www.fit .vutbr.cz/~ipolok /gl /• NeHe
The End
Questions?