gKit2 light

- Main Page
- Related Pages
- Modules
- Classes
- Files

- File List
- File Members

tuto4GL_normals.cpp
Go to the documentation of this file.
1
7 #include "window.h"
8 #include "vec.h"
9 #include "mat.h"
10
11 #include "program.h"
12 #include "uniforms.h"
13
14 #include "orbiter.h"
15 #include "mesh.h"
16 #include "wavefront.h"
17
18 #include <stdio.h>
19
20 // shader program
21 GLuint program;
22
23 // vertex array object
24 GLuint vao;
25 GLuint vertex_buffer;
26 GLuint normal_buffer;
27 unsigned int vertex_count;
28
29 // camera
30 Orbiter camera;
31
32
33 int init( )
34 {
35 // compile un shader program
36 program= read_program("tutos/tuto4GL_normals.glsl");
37 program_print_errors(program);
38
39 // charge un objet
40 Mesh mesh= read_mesh("data/bigguy.obj");
41 vertex_count= mesh.vertex_count();
42
43 // camera
44 Point pmin, pmax;
45 mesh.bounds(pmin, pmax);
46
47 camera.lookat(pmin, pmax);
48
49 glGenBuffers(1, &vertex_buffer);
50 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
51
52 // dimensionne le buffer actif sur array_buffer, l'alloue et l'initialise avec les positions des sommets de l'objet
53 glBufferData(GL_ARRAY_BUFFER,
54 /* length */ mesh.vertex_buffer_size(),
55 /* data */ mesh.vertex_buffer(),
56 /* usage */ GL_STATIC_DRAW);
57 // GL_STATIC_DRAW decrit l'utilisation du contenu du buffer. dans ce cas, utilisation par draw, sans modifications
58
59 // on recommence avec les normales
60 glGenBuffers(1, &normal_buffer);
61 glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
62 glBufferData(GL_ARRAY_BUFFER, mesh.normal_buffer_size(), mesh.normal_buffer(), GL_STATIC_DRAW);
63
64 /* attention: c'est normal_buffer qui est selectionne maintenant sur array_buffer, plus vertex_buffer...
65 */
66
67 // creation d'un vertex array object
68 glGenVertexArrays(1, &vao);
69 glBindVertexArray(vao);
70
71 // recuperer l'identifiant de l'attribut : cf in vec3 position; dans le vertex shader
72 GLint attribute= glGetAttribLocation(program, "position");
73 if(attribute < 0)
74 return -1;
75
76 // re-selectionne vertex buffer pour configurer les positions
77 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
78 // format et organisation des donnees dans le vertex buffer selectionne sur array_buffer,
79 glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ 0);
80 glEnableVertexAttribArray(attribute);
81
82 // on recommence pour les normales
83 attribute= glGetAttribLocation(program, "normal");
84 if(attribute < 0)
85 return -1;
86
87 // re-selectionne normal_buffer pour configurer les normales
88 glBindBuffer(GL_ARRAY_BUFFER, normal_buffer);
89 glVertexAttribPointer(attribute, 3, GL_FLOAT, GL_FALSE, /* stride */ 0, /* offset */ 0); // in vec3 normal;
90 glEnableVertexAttribArray(attribute);
91
92 /* autre solution pour le meme resultat :
93
94 #include "buffer.h"
95
96 GLuint vao= make_vertex_format();
97
98 vertex_buffer= make_vertex_buffer(vao, glGetAttribLocation(program, "position"), 3, GL_FLOAT, mesh.vertex_buffer_size(), mesh.vertex_buffer());
99 normal_buffer= make_vertex_buffer(vao, glGetAttribLocation(program, "normal"), 3, GL_FLOAT, mesh.normal_buffer_size(), mesh.normal_buffer());
100 */
101
102
103 /* creer 2 buffers pour ranger les positions et les normales est arbitraire, on peut tres bien ne creer qu'un seul buffer,
104 par contre, la description du format / de l'organisation sera differente...
105 ce sont les parametres stride et offset de glVertexAttribPointer() qui permettent d'organiser les donnees librement,
106 ils permettent d'iterer sur les donnees, offset definit le premier element et stride permet de passer au suivant.
107
108 exemple 1: un seul buffer, toutes les positions, puis toutes les normales
109
110 PPPPPPPPNNNNNNNN
111
112 offset(position)= 0;
113 stride(position)= 0; // par definition stride(position) == sizeof(vec3)
114
115 offset(normal)= sizeof(vec3) * size(positions);
116 stride(normal)= 0; // ou sizeof(vec3)
117
118 exemple 2: un seul buffer, alterner les donnees, position + normale sommet 0, position + normale sommet 1, etc.
119
120 PNPNPNPNPNPNPN
121
122 offset(position)= 0;
123 stride(position)= sizeof(vec3) + sizeof(vec3); // la prochaine position se trouve apres la normale du sommet
124
125 offset(normal)= sizeof(vec3); // la premiere normale se trouve apres la premiere position
126 stride(normal)= sizeof(vec3) + sizeof(vec3);
127
128 exemple 3: et pour normale suivie de position ?
129
130 NPNPNPNPNPNPNPNP
131
132 */
133
134 // nettoyage
135 glBindVertexArray(0);
136 glBindBuffer(GL_ARRAY_BUFFER, 0);
137
138 // etat par defaut openGL
139 glClearColor(0.2f, 0.2f, 0.2f, 1);
140 glClearDepthf(1);
141
142 glDepthFunc(GL_LESS);
143 glEnable(GL_DEPTH_TEST);
144
145 glEnable(GL_CULL_FACE);
146 // glViewport(0, 0, window_width(), window_height()) // deja fait dans run( )
147 return 0;
148 }
149
150 int quit( )
151 {
152 release_program(program);
153 glDeleteBuffers(1, &vertex_buffer);
154 glDeleteVertexArrays(1, &vao);
155 return 0;
156 }
157
158 int draw( )
159 {
160 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
161
162 // todo recuperez les mouvements de la souris pour deplacer la camera, cf tutos/tuto6.cpp
163 // recupere les mouvements de la souris, utilise directement SDL2
164 int mx, my;
165 unsigned int mb= SDL_GetRelativeMouseState(&mx, &my);
166
167 // deplace la camera
168 if(mb & SDL_BUTTON(1)) // le bouton gauche est enfonce
169 // tourne autour de l'objet
170 camera.rotation(mx, my);
171
172 else if(mb & SDL_BUTTON(3)) // le bouton droit est enfonce
173 // approche / eloigne l'objet
174 camera.move(mx);
175
176 else if(mb & SDL_BUTTON(2)) // le bouton du milieu est enfonce
177 // deplace le point de rotation
178 camera.translation((float) mx / (float) window_width(), (float) my / (float) window_height());
179
180
181 /* configuration minimale du pipeline
182 vertex array
183 shader program
184 uniforms du shader program
185 */
186 glBindVertexArray(vao);
187
188 glUseProgram(program);
189
190 // recupere le point de vue et la projection de la camera
191 Transform model= Identity();
192 Transform view= camera.view();
193 Transform projection= camera.projection(window_width(), window_height(), 45);
194
195 // compose les matrices pour passer du repere local de l'objet au repere projectif
196 Transform mvp= projection * view * model;
197 Transform mv= view * model;
198
199 GLuint location;
200 location= glGetUniformLocation(program, "mvpMatrix");
201 glUniformMatrix4fv(location, 1, GL_TRUE, mvp.buffer());
202
203 // les normales ne subissent pas tout a fait la meme transformation que les sommets
204 program_uniform(program, "mvMatrix", mv.normal());
205
206 program_uniform(program, "color", vec3(1, 0.5, 0.));
207
208 glDrawArrays(GL_TRIANGLES, 0, vertex_count);
209
210 // nettoyage
211 glUseProgram(0);
212 glBindVertexArray(0);
213 return 1;
214 }
215
216
217 int main( int argc, char **argv )
218 {
219 // etape 1 : creer la fenetre
220 Window window= create_window(1024, 640);
221 if(window == NULL)
222 return 1; // erreur lors de la creation de la fenetre ou de l'init de sdl2
223
224 // etape 2 : creer un contexte opengl pour pouvoir dessiner
225 Context context= create_context(window);
226 if(context == NULL)
227 return 1; // erreur lors de la creation du contexte opengl
228
229 // etape 3 : creation des objets
230 if(init() < 0)
231 {
232 printf("[error] init failed.\n");
233 return 1;
234 }
235
236 // etape 4 : affichage de l'application, tant que la fenetre n'est pas fermee. ou que draw() ne renvoie pas 0
237 run(window, draw);
238
239 // etape 5 : nettoyage
240 quit();
241 release_context(context);
242 release_window(window);
243 return 0;
244 }
create_context
Context create_context(Window window, const int major, const int minor)
cree et configure un contexte opengl
Definition: window.cpp:252
Mesh::normal_buffer
const float * normal_buffer() const
renvoie l'adresse de la normale du premier sommet. par convention, la normale est un vec3...
Definition: mesh.h:200
Orbiter
representation de la camera, type orbiter, placee sur une sphere autour du centre de l'objet...
Definition: orbiter.h:16
window.h
Mesh::vertex_buffer
const float * vertex_buffer() const
renvoie l'adresse de la position du premier sommet. permet de construire les vertex buffers openGL...
Definition: mesh.h:195
uniforms.h
Mesh::bounds
void bounds(Point &pmin, Point &pmax)
renvoie min et max les coordonnees des extremites des positions des sommets de l'objet (boite engloba...
Definition: mesh.cpp:153
vec3
vecteur generique, utilitaire.
Definition: vec.h:104
Transform::normal
Transform normal() const
renvoie la transformation a appliquer aux normales d'un objet transforme par la matrice m...
Definition: mat.cpp:97
mesh.h
Mesh::normal_buffer_size
std::size_t normal_buffer_size() const
renvoie la longueur (en octets) du normal buffer.
Definition: mesh.h:202
Mesh
representation d'un objet / maillage.
Definition: mesh.h:88
Orbiter::move
void move(const float z)
rapproche / eloigne la camera du centre.
Definition: orbiter.cpp:33
Identity
Transform Identity()
construit la transformation identite.
Definition: mat.cpp:103
Mesh::vertex_buffer_size
std::size_t vertex_buffer_size() const
renvoie la longueur (en octets) du vertex buffer.
Definition: mesh.h:197
program.h
program_uniform
void program_uniform(const GLuint program, const char *uniform, const unsigned int v)
affecte une valeur a un uniform du shader program. uint.
Definition: uniforms.cpp:68
draw
void draw(Mesh &m, const Transform &model, const Transform &view, const Transform &projection, const GLuint texture)
applique une texture a la surface de l'objet. ne fonctionne que si les coordonnees de textures sont f...
Definition: draw.cpp:6
Orbiter::view
Transform view() const
renvoie la transformation vue.
Definition: orbiter.cpp:40
window_width
int window_width()
renvoie la largeur de la fenetre de l'application.
Definition: window.cpp:14
mat.h
Orbiter::projection
Transform projection(const float width, const float height, const float fov) const
renvoie la projection reglee pour une image d'aspect width / height, et une ouverture de fov degres...
Definition: orbiter.cpp:47
program_print_errors
int program_print_errors(const GLuint program)
affiche les erreurs de compilation.
Definition: program.cpp:330
Orbiter::lookat
void lookat(const Point &center, const float size)
observe le point center a une distance size.
Definition: orbiter.cpp:7
create_window
Window create_window(const int w, const int h)
creation d'une fenetre pour l'application.
Definition: window.cpp:186
read_program
GLuint read_program(const char *filename, const char *definitions)
Definition: program.cpp:150
Transform::buffer
const float * buffer() const
renvoie l'adresse de la premiere valeur de la matrice.
Definition: mat.h:44
Orbiter::translation
void translation(const float x, const float y)
deplace le centre / le point observe.
Definition: orbiter.cpp:27
printf
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
Definition: text.cpp:140
wavefront.h
Orbiter::rotation
void rotation(const float x, const float y)
change le point de vue / la direction d'observation.
Definition: orbiter.cpp:21
window_height
int window_height()
renvoie la hauteur de la fenetre de l'application.
Definition: window.cpp:18
Transform
representation d'une transformation, une matrice 4x4, organisee par ligne / row major.
Definition: mat.h:20
release_program
int release_program(const GLuint program)
detruit les shaders et le program.
Definition: program.cpp:157
release_context
void release_context(Context context)
detruit le contexte openGL.
Definition: window.cpp:306
Point
representation d'un point 3d.
Definition: vec.h:19
Mesh::vertex_count
int vertex_count() const
renvoie le nombre de sommets.
Definition: mesh.h:190
orbiter.h
release_window
void release_window(Window window)
destruction de la fenetre.
Definition: window.cpp:222
run
int run(Window window, int(*draw)(void))
fonction principale. gestion des evenements et appel de la fonction draw de l'application.
vec.h
read_mesh
Mesh read_mesh(const char *filename)
charge un fichier wavefront .obj et renvoie un mesh compose de triangles non indexes. utiliser glDrawArrays pour l'afficher. a detruire avec Mesh::release( ).
Definition: wavefront.cpp:8