documentation was wrong
[sdlhildon] / sdlgles / test / simplegl.cc
1  /* Created by exoticorn ( http://talk.maemo.org/showthread.php?t=37356 )
2   * edited and commented by AndrĂ© Bergner [endboss]
3   * edited by Javier for SDL_gles
4   *
5   * libraries needed: libgles2-dev | libgles2-sgx-img-dev, libsdl-gles1.2-dev, libsdl1.2-dev
6   *
7   * compile with: g++ -O2 -o simplegl  `sdl-config --cflags --libs` -lSDL_gles -lGLESv2  simplegl.cc
8   */
9
10 #include  <iostream>
11 using namespace std;
12
13 #include <SDL.h>
14 #include <SDL_gles.h>
15
16 #include  <cmath>
17 #include  <sys/time.h>
18
19 #include  <GLES2/gl2.h>
20
21 static const char vertex_src[] = "                                        \
22     attribute vec4        position;       \
23     varying mediump vec2  pos;            \
24     uniform vec4          offset;         \
25                                           \
26     void main()                           \
27     {                                     \
28        gl_Position = position + offset;   \
29        pos = position.xy;                 \
30     }                                     \
31  ";
32
33
34 static const char fragment_src[] =
35         "                                                      \
36     varying mediump vec2    pos;                        \
37     uniform mediump float   phase;                      \
38                                                         \
39     void  main()                                        \
40     {                                                   \
41        gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *     \
42          cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)   \
43               + atan(pos.y,pos.x) - phase );            \
44     }                                                   \
45  ";
46
47 static void print_shader_info_log(GLuint shader // handle to the shader
48         )
49 {
50         GLint length, success;
51
52         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
53         if (length) {
54                 char *buffer = new char[length];
55                 glGetShaderInfoLog(shader, length, NULL, buffer);
56                 cout << "shader info: " << buffer << flush;
57                 delete[]buffer;
58         }
59
60         glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
61         if (success != GL_TRUE) {
62                 cerr << "failed to build shader" << endl;
63                 exit(1);
64         }
65 }
66
67 static GLuint load_shader(const char *shader_source, GLenum type)
68 {
69         GLuint shader = glCreateShader(type);
70
71         glShaderSource(shader, 1, &shader_source, NULL);
72         glCompileShader(shader);
73
74         print_shader_info_log(shader);
75
76         return shader;
77 }
78
79 static SDL_Surface *screen;
80 static SDL_GLES_Context *context;
81
82 GLfloat norm_x = 0.0, norm_y = 0.0,
83         offset_x = 0.0, offset_y = 0.0, p1_pos_x = 0.0, p1_pos_y = 0.0;
84
85 GLint phase_loc, offset_loc, position_loc;
86
87 bool update_pos = false;
88
89 const float vertexArray[] = {
90         0.0, 0.5, 0.0,
91         -0.5, 0.0, 0.0,
92         0.0, -0.5, 0.0,
93         0.5, 0.0, 0.0,
94         0.0, 0.5, 0.0
95 };
96
97
98 void render()
99 {
100         static float phase = 0;
101
102         //// draw
103         glClear(GL_COLOR_BUFFER_BIT);
104
105         glUniform1f(phase_loc, phase);  // write the value of phase to the shaders phase
106         phase = fmodf(phase + 0.5f, 2.f * 3.141f);      // and update the local variable
107
108         if (update_pos) {                       // if the position of the texture has changed due to user action
109                 GLfloat old_offset_x = offset_x;
110                 GLfloat old_offset_y = offset_y;
111
112                 offset_x = norm_x - p1_pos_x;
113                 offset_y = norm_y - p1_pos_y;
114
115                 p1_pos_x = norm_x;
116                 p1_pos_y = norm_y;
117
118                 offset_x += old_offset_x;
119                 offset_y += old_offset_y;
120
121                 update_pos = false;
122         }
123
124         glUniform4f(offset_loc, offset_x, offset_y, 0.0, 0.0);
125
126         glVertexAttribPointer(position_loc, 3, GL_FLOAT, false, 0,
127                                                   vertexArray);
128         glEnableVertexAttribArray(position_loc);
129         glDrawArrays(GL_TRIANGLE_STRIP, 0, 5);
130
131         SDL_GLES_SwapBuffers();
132 }
133
134
135 int main()
136 {
137         SDL_Init(SDL_INIT_VIDEO);
138         SDL_GLES_Init(SDL_GLES_VERSION_2_0);
139         screen = SDL_SetVideoMode(0, 0, 16, SDL_SWSURFACE | SDL_FULLSCREEN);
140         SDL_WM_SetCaption("SimpleGL", "SimpleGL");
141         SDL_ShowCursor(SDL_DISABLE);
142         context = SDL_GLES_CreateContext();
143         SDL_GLES_MakeCurrent(context);
144
145         glClearColor(0.08, 0.06, 0.07, 1.0);    // background color
146
147         GLuint vertexShader = load_shader(vertex_src, GL_VERTEX_SHADER);        // load vertex shader
148         GLuint fragmentShader = load_shader(fragment_src, GL_FRAGMENT_SHADER);  // load fragment shader
149
150         GLuint shaderProgram = glCreateProgram();       // create program object
151         glAttachShader(shaderProgram, vertexShader);    // and attach both...
152         glAttachShader(shaderProgram, fragmentShader);  // ... shaders to it
153
154         glLinkProgram(shaderProgram);   // link the program
155         glUseProgram(shaderProgram);    // and select it for usage
156
157         //// now get the locations (kind of handle) of the shaders variables
158         position_loc = glGetAttribLocation(shaderProgram, "position");
159         phase_loc = glGetUniformLocation(shaderProgram, "phase");
160         offset_loc = glGetUniformLocation(shaderProgram, "offset");
161         if (position_loc < 0 || phase_loc < 0 || offset_loc < 0) {
162                 cerr << "Unable to get uniform location" << endl;
163                 return 1;
164         }
165
166         const float window_width = screen->w, window_height = screen->h;
167
168         //// this is needed for time measuring  -->  frames per second
169         struct timezone tz;
170         timeval t1, t2;
171         gettimeofday(&t1, &tz);
172         int num_frames = 0;
173
174         bool quit = false;
175         while (!quit) {                         // the main loop
176                 SDL_Event e;
177                 GLfloat window_y, window_x;
178                 while (SDL_PollEvent(&e)) {     // check for events
179                         switch(e.type) {
180                         case SDL_MOUSEMOTION: // if mouse has moved
181                                 window_y = (window_height - e.motion.y) - window_height / 2.0;
182                                 norm_y = window_y / (window_height / 2.0);
183                                 window_x = e.motion.x - window_width / 2.0;
184                                 norm_x = window_x / (window_width / 2.0);
185                                 update_pos = true;
186                                 break;
187                         case SDL_KEYDOWN:
188                         case SDL_QUIT:
189                                 quit = true;
190                                 break;
191                         }
192                 }
193
194                 render();                               // now we finally put something on the screen
195
196                 if (++num_frames % 100 == 0) { // update framerate counter
197                         gettimeofday(&t2, &tz);
198                         float dt =
199                                 t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6;
200                         cout << "fps: " << num_frames / dt << endl;
201                         num_frames = 0;
202                         t1 = t2;
203                 }
204         }
205
206         ////  cleaning up...
207         SDL_GLES_Quit();
208         SDL_Quit();
209
210         return 0;
211 }
212