INFORMATICA GRAFICA!

Documenti analoghi
INFORMATICA GRAFICA. 9 Giugno Shaders OpenGL Shading Language. Michele Antolini

Computer Graphics. Computer Graphics. Alcuni argomenti che non abbiamo trattato (o abbiamo trattato poco) Modelling: Rendering:

Corso di Tecniche Avanzate per la Grafica

Corso di GraficaComputazionale

Dati due punti sul piano calcolare la loro distanza

Utilizza i tipi di dati comuni a tutto il framework.net Accesso nativo ai tipi.net (C# è nato con.net) Concetti fondamentali:

Aggiungiamo attributi (per vertice!)

Il linguaggio C. Notate che...

Videogame e rendering 3D. Enrico Colombini (Erix) µhackademy 1 Marzo 2019

Introduzione al Real Time Shading

Introduzione a Java. Riferimenti

Capitolo 6 - Array. Copyright by Deitel & Associates, Inc. and Pearson Education Inc. All Rights Reserved.

Strategie di programmazione

Le Funzioni in C. Fondamenti di Informatica Anno Accademico 2010/2011. Corso di Laurea in Ingegneria Civile Politecnico di Bari Sede di Foggia

Elementi lessicali. Lezione 4. La parole chiave. Elementi lessicali. Elementi lessicali e espressioni logiche. Linguaggi di Programmazione I

Funzioni in C. Funzioni. Strategie di programmazione. Funzioni in C. Come riusare il codice? (2/3) Come riusare il codice? (1/3)

Laboratorio di Informatica I

Introduzione al linguaggio C Primi programmi

Le basi del linguaggio Java

Introduzione al Many/Multi-core Computing

Informatica 1 Tipi e dichiarazioni in C++ C++ - Tipi e dichiarazioni 1

Breve Manuale di Riferimento sulla Sintassi Linguaggi C++ e FORTRAN

Introduzione alla programmazione in linguaggio C

Variabili e Funzioni. Informatica 1 / 19

Il linguaggio C. Notate che...

Linguaggio C - sezione dichiarativa: costanti e variabili

Grafica Real-Time, Hardware Grafico e Linguaggi di Shading. Alessandro Martinelli

Computer Graphics. Digital representation of 3D objects. 3D Rendering. Scena 3D rendering image. Marco Tarini - univ insubria AA 2016/2017

Linguaggio C. Tipi predefiniti e operatori. Università degli Studi di Brescia. Docente: Massimiliano Giacomin

Introduzione al linguaggio C Funzioni

Parte Input e output in linguaggio i C. 3. Programmazione strutturata 1 (if, switch, comunque segnalare dei warning

ERRORI DI PROGRAMMAZIONE INDICE

ä t s r r ModelViewProjectionMatrix void main(void) { gl_position = gl_modelviewprojectionmatrix * gl_vertex; }

INFORMATICA GRAFICA. 28 Aprile Trasformazioni - Illuminazione. Michele Antolini

C++ funzioni Alberto Ferrari. Alberto Ferrari Programmazione di applicazioni SW

Algoritmi, Strutture Dati e Programmi. UD 2.b: Programmazione in Pascal

Funzioni, Stack e Visibilità delle Variabili in C

Corso di Fondamenti di Informatica Il sistema dei tipi in C++

Conoscere l uso delle collezioni in Java. Conoscere il concetto di Generics (programmazione

Introduzione al linguaggio C Puntatori

Tipi e Valori. Moreno Marzolla Dipartimento di Informatica Scienza e Ingegneria (DISI) Università di Bologna

Unità Didattica 1 Linguaggio C. Fondamenti. Struttura di un programma.

Concetti Base Encapsulation ed Ereditarietà Programmare con l Ereditarietà. Java: Ereditarietà. Damiano Macedonio

#include <stdio.h> /* l esecuzione comincia dalla funzione main */ int main()

1

Assembly. Linguaggio di programmazione corrispondente al linguaggio macchina P.H. Cap. 2.1, 2.2 e App. A. Linguaggio assembly (App.

Stringhe in C. Nicu Sebe. Informatica Nicu Sebe 1 / 14

OCA JAVA 7 SE PROGRAMMER I DOCENTE: DOTT. FAUSTO DELL ANNO

Linguaggi di Programmazione I Lezione 10

C: panoramica. Violetta Lonati

Fondamenti di Programmazione

Il corpo di tutte le funzioni deve essere contenuto tra parentesi graffe

Octave. Luca Abeni. Informatica Luca Abeni 1 / 21

Il C nel C++: Funzioni

Funzioni (1) Il C nel C++: Funzioni. Funzione (2) Vantaggi delle Funzioni. Localizzazione della funzionalità correggibilità manutenibilità

Introduzione al linguaggio C

Lezione 6 Introduzione al C++ Mauro Piccolo

Struttura di un programma C++

INFORMATICA GRAFICA!

Fondamenti di Grafica Tridimensionale

Il linguaggio C. Il preprocessore...

Esercizi Programmazione I

Corso di Linguaggi di Programmazione

L oggetto creato. Creazione di Oggetti. Rectangle: il concetto 10. Costruzione. Lo spazio di memoria del linguaggio Java. Rectangle: l oggetto

Stringhe in C. Luca Abeni. Informatica Luca Abeni 1 / 10

Strutture dati e loro organizzazione. Gabriella Trucco

IL LINGUAGGIO JAVA. Input, Tipi Elementari e Istruzione Condizionale. Primo esempio di un programma Java

Capitolo 5 - Funzioni

C funzioni à scope di variabili

Question 1: introduction to computer programming

IL LINGUAGGIO JAVA. Input, Tipi Elementari e Istruzione Condizionale. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica

Precisazione sui tipi in ANSi C

24 aprile Qualche minuto di laboratorio

High Dynamic Range Rendering in OpenGL

Qualsiasi programma in C++ segue lo schema: Variabili

Struttura di un. Struttura dei programmi C

Capitolo 2 GOCCE DI JAVA. Domande a risposte multiple

BASI LINGUAGGIO. Programmazione Web 1

Assegnazione di una variabile

Primi programmi in C

Il primo programma C++

Linguaggio C: Array Valeria Cardellini

INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Struttura di un programma Java

1 PANORAMICA SUL LINGUAGGIO C

Capitolo 5. Array e collezioni. c 2005 Pearson Education Italia Capitolo 5-1 / 61

Fondamenti di Informatica e Laboratorio T-AB Prova Pratica - 16 Giugno 2009 Compito A

IL LINGUAGGIO JAVA Input, Tipi Elementari e Istruzione Condizionale

BASI LINGUAGGIO. Programmazione Web 1

Linguaggi di Programmazione

Tipi di dato. Il concetto di tipo di dato viene introdotto per raggiungere due obiettivi:

Programmazione Procedurale in Linguaggio C++

Esempio. Le istruzioni corrispondono a quelle di sopra, ma sono scritte in modo simbolico. E indipendente dalla machina

Linguaggio C: Espressioni

Un esecutore di un linguaggio simbolico e costituito dalla coppia Compilatore, processore (o Interprete, processore)

A.A. 2006/2007 Laurea di Ingegneria Informatica. Fondamenti di C++ Horstmann Capitolo 3: Oggetti Revisione Prof. M. Angelaccio

Transcript:

Knowledge Aided Engineering Manufacturing and Related Technologies INFORMATICA GRAFICA 11 giugno Shaders OpenGL Shading Language Michele Antolini michele.antolini@mail.polimi.it

Shaders Ombreggiatura Uno shader permette di definire come un materiale reagisce alla luce Necessario per ottenere effetti fotorealistici Si possono fare anche altre cose (es. bump mapping, effetti particellari, animazioni)

Shaders http://www.realtime-technology.com

Shaders Le textures non bastano E necessario un controllo maggiore sulle caratteristiche della scena I primi shaders erano programmati direttamente sulla scheda video (es. flat, smooth shaders) Prima di OpenGL 2.0, alcune schede grafiche erano programmabili in linguaggio assembler, il cui codice binario doveva essere copiato sulla scheda Con OpenGL 2.0 è stato definito un linguaggio di programmazione per shaders

Shaders Le schede grafiche diventano una logica programmabile Il consorzio OpenGL ARB (Architecture Review Board) detta le specifiche per il linguaggio di alto livello (C-like) con cui programmare le schede Il compilatore è integrato nei driver OpenGL (se compatibile 2.0) di ogni scheda, quindi ottimizzato a seconda dell hardware sottostante

Shaders Gli shaders seguono il paradigma di programmazione definito stream processing La GPU permette centinaia, migliaia di operazioni contemporanee su dati multipli: Single Instruction Multiple Data (SIMD) Uno shader è un vero e proprio programma che sfrutta le capacità di calcolo parallelo della GPU

Shaders Categorie di shaders Vertex shaders Fragment shaders Geometry shaders (OpenGL 3.2)

Vertex shaders Eseguiti per ogni vertice Es. rettangolo: vertex shader eseguito 4 volte, una per ogni vertice generato per disegnarlo Usi: trasformazioni di vertici normalizzazione di vettori normali generazione di texture coordinates illuminazione applicazione di attributi (es. il colore del materiale)

Fragment shaders Eseguiti per ogni pixel dell oggetto rasterizzato Es. rettangolo: fragment shader eseguito per ogni pixel visibile dell area del rettangolo Usi: operazioni su attributi interpolati (varying) accesso a textures applicazione di textures effetto nebbia calcolo e applicazione colore pixel bump mapping

Geometry shaders Eseguiti per ogni vertice Permettono di creare nuove primitive (vertici) a partire da quelli esistenti Utilizzo più comune è la tassellazione di curve o superfici

GLSL Il consorzio OpenGL ARB ha definito un linguaggio standard di alto livello per la programmazione di shaders Sono stati tenuti in considerazione molti requisiti: Buona integrazione con specifiche OpenGL Possibilità di sfruttamento di hardware futuro Indipendenza dall hardware sottostante Semplicità e longevità Compatibilità con calcolo parallelo massivo

Shaders execution Application Shader source code OpenGL API Shader source code OpenGL Driver Compiler Shader Object compiled code Linker rogram Object executable code Graphics hard are Provided by application developer rovided by graphics hardware vendor R. Rost, OpenGL Shading Language 2 nd Edition, Addison-Wesley

Shaders execution Il punto di partenza è quindi il sorgente dello shader Avviene una compilazione a run-time nel linguaggio assembly della scheda grafica Il compilatore prende come argomenti degli array di stringhe, è quindi possibile la manipolazione per il riutilizzo di frammenti di codice

GLSL Language Definition Il GLSL (OpenGL Shading Language) è stato creato intenzionalmente ispirandosi al C Un programma possiede tipicamente due shaders: vertex e fragment E possibile utilizzare tre tipi di variabili globali all interno di uno shader uniform: può essere modificata una volta per ogni chiamata allo shader attribute: varia solitamente per ogni vertice (es. colore) varying: serve a far comunicare vertex e fragment shader Esiste anche una serie di variabili built-in, aventi prefisso gl_

Variabili uniform: le variabili uniform vengono utilizzate per definire proprietà che cambiano al più ogni frame attribute: gli attribute si usano per definire proprietà che possono cambiare per ogni vertice Usiamo già attributi predefiniti come glnormal, glcolor, gltexcoord varying: le variabili di tipo varying servono a definire proprietà il cui valore verrà automaticamente interpolato durante l esecuzione del fragment shader (es. colore di un pixel dato il colore dei vertici adiacenti

GLSL Simple Example Semplice esempio di vertex e fragment shader che permettono l assegnazione di una temperatura ad ogni vertice e visualizzarla sotto forma di colore

GLSL Simple Example Vertex Shader // Global variables // uniform qualified variables are changed at most once per primitive uniform float CoolestTemp; uniform float TempRange; // attribute qualified variables are typically changed per vertex attribute float VertexTemp; // out qualified variables communicate from the vertex shader to // the fragment shader varying float Temperature; void main() { // compute a temperature to be interpolated per fragment, // in the range [0.0, 1.0] Temperature = (VertexTemp - CoolestTemp) / TempRange; gl_position = gl_modelviewprojectionmatrix * gl_vertex; }

GLSL Simple Example Vertex Shader Le variabili uniform CoolestTemp e TempRange definiscono parametri di tipo generale per lo shader L attribute VertexTemp viene assegnato per ogni vertice specificato La variabile varying Temperature viene automaticamente interpolata tra i valori dei vertici adiacenti quando verrà eseguito il fragment shader Notare l uso di tre variabili built-in: gl_position, gl_modelviewprojectionmatrix e gl_vertex

GLSL Simple Example Fragment Shader // Global variables // vec3 declares a vector of three floating-point numbers uniform vec3 CoolestColor; uniform vec3 HottestColor; // Temperature contains the now interpolated per-fragment // value of temperature set by the vertex shader varying float Temperature; void main() { // get a color between coolest and hottest colors, using // the mix() built-in function vec3 color = mix(coolestcolor, HottestColor, Temperature); } // make a vector of 4 floating-point numbers by appending an // alpha of 1.0, and set this fragment s color gl_fragcolor = vec4(color, 1.0);

GLSL Simple Example Fragment Shader Le variabili uniform sono diverse dal vertex shader. Si possono infatti impostare più variabili uniform nell applicazione, ed utilizzarne solo alcune all interno degli shader La variabile varying Temperature ha già un valore interpolato (0, 1) in base alla distanza dai vertici adiacenti Il colore del pixel viene calcolato con una semplice formula (built-in) di interpolazione tra due vettori di 3 elementi (la funzione mix) L esecuzione dei fragment shader è parallela

GLSL Data Types I tipi di dati utilizzabili per il GLSL sono raggruppati in: scalari vettori matrici samplers struct array

GLSL Data Types Scalari float: singola precisione, virgola mobile int: numero intero bool: flag booleano non supportati operatori sui bit come shift (<<, >>) o and bit a bit (&) gli interi hanno precisione di 16bit più il segno, quindi [-65535, 65535]

GLSL Data Types Vettori vec2, vec3, vec4: vettore di 2,3 o 4 float ivec2, ivec3, ivec3: vettore di 2,3 o 4 int bvec2, bvec3, bvec4: vettore di 2,3 o 4 bool

GLSL Data Types Vettori Le componenti di un vettore si possono richiamare con i suffissi:.x,.y,.z,.w: il vettore viene trattato come posizione o direzione.r,.g,.b,.a: il vettore viene trattato come un colore.s,.t,.p,.q: il vettore viene trattato come coordinate texture Oppure tramite l indice tra [] ( es. p[0] )

GLSL Data Types Matrici mat2, mat3, mat4: matrici 2x2, 3x3, 4x4 di float Le matrici vengono indicizzate per colonna, riga m[0] restituisce un vec* contenente gli elementi della colonna 0 della matrice m m[0][1] indica l elemento 1 della colonna 0 di m I prodotti con scalari, vettori matrici vengono trattati secondo le regole dell algebra (convenzione: le matrici premoltiplicano i vettori)

GLSL Data Types Samplers sampler1d, sampler2d, sampler3d: texture mono, bi o tridimensionale samplercube: texture cube-map sampler1dshadow, sampler2dshadow: depth texture mono o bidimensionale per shadow mapping I sampler possono essere solo variabili di tipo uniform

GLSL Data Types Samplers <vertex shader> uniform sampler2d my_texture;... void main( void ) { vec3 texcolor = texture2d( my_texture, gl_multitexcoord0.st )... }

GLSL Data Types Samplers (vertex shader) uniform sampler2d my_texture; varying vec2 my_texcoord0; void main( void ) { } //ricava il colore della texture 0 alle coordinate del vertice corrente vec3 texcolor = texture2d( my_texture, gl_multitexcoord0.st ) //manda al fragment shader le coordinate texture del vertice (verranno automaticamente interpolate dato che si tratta di una variabile varying my_texcoord0 = gl_multitexcoord0; gl_position = gl_modelviewprojectionmatrix*gl_vertex;

GLSL Data Types Samplers (fragment shader) uniform sampler2d my_texture; varying vec2 my_texcoord0; void main( void ) { } //ricava il colore del pixel corrente in base alle coordinate texture interpolate gl_fragcolor = texture2d(my_texture, my_texcoord0);

GLSL Data Types Struct E possibile definire struct come in C: struct light { } vec3 position; vec3 color; Non solo ammessi tipi union, enum, class

GLSL Data Types Array E possibile creare array di qualunque tipo vec4 points[10] Se gli array non sono parametri di una funzione, possono essere dichiarati senza dimensione. vec4 points[] Possono essere ridichiarati con la dimensione specificata, altrimenti viene calcolata la dimensione in base all indice più alto utilizzato

GLSL Inizializzazione/Costruttori vec4 v = vec4(1.0, 2.0, 3.0, 4.0); vec4 v2; v2 = vec4(1.0, 2.0, 3.0, 4.0); vec3 color = vec3(0.2, 0.5, 0.8); vec4 color4 = vec4(color, 1.0);

GLSL Inizializzazione/Costruttori struct light { vec4 position; struct tlightcolor { vec3 color; float intensity; } lightcolor; } light1 = light(v, tlightcolor(color, 0.9)); vec4 p = light1.position; float f = light1.lightcolor.intensity; float a[4] = float[4](1.0, 1.0, 0.0, 1.0 );

GLSL Inizializzazione/Costruttori mat2 Matrix0 = mat2( 1.0, 2.0, 3.0, 4.0 ); risulta: vec3 v = vec3(0.6); equivalente a " 1.0 3.0% $ ' # 2.0 4.0& vec3 v = vec3(0.6, 0.6, 0.6); mat2 m = mat2(1.0); //matrice identità 2x2

GLSL Type Matching Type Conversion In GLSL non c è il casting automatico dei tipi, ma ogni variabile deve essere utilizzata seguendo le intestazioni formali delle funzioni I passaggi da un tipo all altro devono essere esplicite float f = 2.3; bool b = bool(f); float f = float(3); // integer 3 to floating-point 3.0 float g = float(b); // Boolean b to floating point vec4 v = vec4(2); // set all components of v to 2.0

GLSL - Swizzling Utilizzando l operatore. è possible riarrangiare i componenti di una struttura elencandone i nomi Questa procedura si chiama swizzling vec4 v4; v4.rgba; // is a vec4 and the same as just using v4 v4.rgb; // is a vec3 v4.b; // is a float v4.xy; // is a vec2 v4.xgba; // is illegal - the component names do not come from the same set

GLSL - Swizzling vec4 pos = vec4(1.0, 2.0, 3.0, 4.0); vec4 swiz = pos.wzyx; // swiz = (4.0, 3.0, 2.0, 1.0) vec4 dup = pos.xxyy; // dup = (1.0, 1.0, 2.0, 2.0) vec4 pos = vec4(1.0, 2.0, 3.0, 4.0); pos.xw = vec2(5.0, 6.0); // pos = (5.0, 2.0, 3.0, 6.0) pos.wx = vec2(7.0, 8.0); // pos = (8.0, 2.0, 3.0, 7.0) pos.xx = vec2(3.0, 4.0); // illegal - 'x' used twice

GLGL Operazioni su componenti Vettore/Scalare: vec3 v, u; float f; v = u + f; Equivalente a: v.x = u.x + f; v.y = u.y + f; v.z = u.z + f;

GLGL Operazioni su componenti Vettore/Vettore: vec3 v, u, w; w = v + u; Equivalente a: w.x = v.x + u.x; w.y = v.y + u.y; w.z = v.z + u.z;

GLGL Operazioni su componenti Tutte le operazioni aritmetiche agiscono elemento per elemento, tranne il prodotto vettore/matrice, matrice/vettore e matrice/matrice (eseguito secondo le regole dell algebra lineare) vec4 v, u; mat4 m; v * u; // Prodotto componente per componente v * m; // Prodotto vettore riga con matrice m * v; // Prodotto matrice con vettore colonna m * m; // Prodotto matrice con matrice

GLSL Uso nell applicazione Per installare ed utilizzare uno shader è necessario: 1. Creare uno o più shader vuoti con glcreateshader 2. Fornire il codice sorgente (sotto forma di array di string) con glshadersource 3. Compilare gli shader con glcompileshader 4. Creare un oggetto program con glcreateprogram 5. Connettere gli shader al program con glattachshader 6. Link-are il program con gllinkprogram 7. Impostare il programma nello stato corrente con gluseprogram

GLSL Application Code #include <GLEW/glew.h> //includere GL Extensions Wrapper void setshaders() { char *vs,*fs; v = glcreateshader(gl_vertex_shader); f = glcreateshader(gl_fragment_shader); vs = textfileread( myshader.vert"); fs = textfileread( myshader.frag"); const char * vv = vs; const char * ff = fs; glshadersource(v, 1, &vv, NULL); glshadersource(f, 1, &ff, NULL); free(vs);free(fs); glcompileshader(v); glcompileshader(f); p = glcreateprogram(); glattachshader(p,v); glattachshader(p,f); } gllinkprogram(p); gluseprogram(p); // gluseprogram(0) per disattivare uno shader

GLSL Impostazione parametri Per impostare parametri uniform o attribute deve essere prima richiesta la location (un identificatore) in base al nome del parametro (formato stringa) Parametri uniform: Glint loc1 = glgetuniformlocation(program, CoolestTemp"); gluniform1f(loc1,mytemp); esistono le varianti gluniform 2f, 3f, 4f, v

GLSL Impostazione parametri Parametri attribute: Specificati tra glbegin() e glend() Glint loc2 = glgetattriblocation(program, "height"); glbegin(gl_triangle_strip); glvertexattrib1f(loc2,2.0); glvertex2f(-1,1);... glend(); esistono le varianti glvertexattrib 2f, 3f, 4f, v

GLSL - Particles Gli shaders possono essere utilizzati anche per produrre animazioni Primo tipo: modifica ad ogni frame delle caratteristiche della superficie dell oggetto su cui è applicato lo shader (utilizzando il fragment shader) Secondo tipo: modifica ad ogni frame (in funzione del tempo) della posizione di un particolare vertice (vertex shader) Quest ultima tecnica permette di sfruttare la potenza di calcolo parallelo della GPU per ricalcolare la posizione di una serie di punti

GLSL Toon Shader Example

GLSL Toon Shader Example Vertex shader: varying vec3 Normal; void main(void) { //passo al fragment shader il vettore normale Normal = normalize(gl_normalmatrix * gl_normal); gl_position = gl_modelviewprojectionmatrix * gl_vertex; }

GLSL Toon Shader Example Fragment shader: uniform vec3 DiffuseColor; //default (0.0, 0.25, 1.0) uniform vec3 PhongColor; //default (0.75, 0.75, 1.0) uniform float Edge; //default 0.5 uniform float Phong; //default 0.98 varying vec3 Normal; void main (void) { vec3 color = DiffuseColor; float f = dot(vec3(0,0,1),normal); if (abs(f) < Edge) color = vec3(0); if (f > Phong) color = PhongColor; gl_fragcolor = vec4(color, 1); }

GLSL Effetti particellari

GLSL Effetti particellari Vertex Shader uniform float time; //il tempo viene incrementato per ogni frame varying vec4 Color; const float radius = 0.3; void main(void) { vec4 vertex = gl_vertex; //coordinate non trasformate float t1 = mod(time, 5.0); vertex.x = radius * gl_color.y * t1 * sin(gl_color.x * 6.28); vertex.z = radius * gl_color.y * t1 * cos(gl_color.x * 6.28); } float h = gl_color.y * 1.25; float t2 = mod(t1, h*2.0); vertex.y = -(t2-h)*(t2-h)+h*h; vertex.y -= 1.0; gl_position = gl_modelviewprojectionmatrix * vertex; Color.r = 1.0; Color.g = 1.0 - gl_color.y; Color.b = 0.0; Color.a = 1.0 - t1 / 5.0;

GLSL Effetti particellari Fragment Shader varying vec4 Color; void main (void) { gl_fragcolor = Color; }

GLSL - Particles Animazioni: ridisegno ciclico della scena Due metodi per chiamare la glutpostredisplay(): al termine della funzione Display() all interno della gluttimerfunc impostando un framerate specifico Si aggiorna una variabile uniform per far ricalcolare agli shaders il nuovo frame

GLSL Utility function char *textfileread(char *fn) { FILE *fp; char *content = NULL; int count=0; if (fn = NULL) { fp = fopen(fn,"rt"); if (fp = NULL) { fseek(fp, 0, SEEK_END); count = ftell(fp); rewind(fp); } } } return content; if (count > 0) { content = (char *)malloc(sizeof(char) * (count+1)); count = fread(content,sizeof(char),count,fp); content[count] = '\0'; } fclose(fp);

GLSL Utility function int printoglerror() { // // Returns 1 if an OpenGL error occurred, 0 otherwise. // GLenum glerr; int retcode = 0; } glerr = glgeterror(); while (glerr = GL_NO_ERROR) { printf("glerror: %s\n", gluerrorstring(glerr)); fflush(stdout); retcode = 1; glerr = glgeterror(); } return retcode;

GLSL Tutorials - Libri Lighthouse 3D http://www.lighthouse3d.com/opengl/glsl/index.php?intro 3D Shaders (R. Rost, OpenGL Shading Language Orange Book) http://www.3dshaders.com/home/