added vbo/varr points method
[glpixels] / glpixels.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <assert.h>
5 #define GL_GLEXT_PROTOTYPES     1
6 #include <GL/glut.h>
7
8 enum {
9         MODE_POINTS,
10         MODE_DRAWPIX,
11         MODE_TEXQUAD,
12         MODE_TEXTRI,
13
14         NUM_MODES
15 };
16
17 int init(void);
18 void display(void);
19 void idle(void);
20 void reshape(int x, int y);
21 void keyb(unsigned char key, int x, int y);
22
23 int win_width, win_height;
24 int max_xscroll, max_yscroll;
25
26 #define IMG_W   1024
27 #define IMG_H   1024
28 unsigned int img[IMG_W * IMG_H];
29 float *varr, *carr;
30 unsigned int vbo_pos, vbo_col;
31 int varr_sz, carr_sz;
32
33 int mode = MODE_POINTS;
34
35 int have_vbo = 1;       /* TODO */
36
37
38 int main(int argc, char **argv)
39 {
40         glutInit(&argc, argv);
41         glutInitWindowSize(800, 600);
42         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
43         glutCreateWindow("GL pixel drawing methods");
44
45         glutDisplayFunc(display);
46         glutReshapeFunc(reshape);
47         glutKeyboardFunc(keyb);
48         glutIdleFunc(idle);
49
50         if(init() == -1) {
51                 return 1;
52         }
53         glutMainLoop();
54         return 0;
55 }
56
57
58 int init(void)
59 {
60         int i, j, xor, r, g, b;
61         unsigned int *ptr;
62         unsigned int tex;
63         float *vptr;
64
65         ptr = img;
66         for(i=0; i<IMG_H; i++) {
67                 for(j=0; j<IMG_W; j++) {
68                         xor = i ^ j;
69                         r = (xor >> 1) & 0xff;
70                         g = xor & 0xff;
71                         b = (xor << 1) & 0xff;
72                         *ptr++ = r | (g << 8) | (b << 16);
73                 }
74         }
75
76         glPixelStorei(GL_UNPACK_ROW_LENGTH, IMG_W);
77
78         win_width = glutGet(GLUT_WINDOW_WIDTH);
79         win_height = glutGet(GLUT_WINDOW_HEIGHT);
80
81         glGenTextures(1, &tex);
82         glBindTexture(GL_TEXTURE_2D, tex);
83         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
84         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
85         glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, win_width, win_height, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
86
87         varr_sz = win_width * win_height * sizeof *varr * 2;
88         if(!(varr = malloc(varr_sz))) {
89                 fprintf(stderr, "failed to allocate vertex array\n");
90                 return -1;
91         }
92         carr_sz = win_width * win_height * sizeof *carr * 3;
93         if(!(carr = malloc(carr_sz))) {
94                 fprintf(stderr, "failed to allocate color array\n");
95                 return -1;
96         }
97
98         vptr = varr;
99         for(i=0; i<win_height; i++) {
100                 for(j=0; j<win_width; j++) {
101                         vptr[0] = j;
102                         vptr[1] = i;
103                         vptr += 2;
104                 }
105         }
106
107         if(have_vbo) {
108                 glGenBuffers(1, &vbo_pos);
109                 glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
110                 glBufferData(GL_ARRAY_BUFFER, varr_sz, varr, GL_STATIC_DRAW);
111
112                 glGenBuffers(1, &vbo_col);
113                 glBindBuffer(GL_ARRAY_BUFFER, vbo_col);
114                 glBufferData(GL_ARRAY_BUFFER, carr_sz, 0, GL_STREAM_DRAW);
115         }
116
117         return 0;
118 }
119
120 void display(void)
121 {
122         int i, j;
123         unsigned int tm = glutGet(GLUT_ELAPSED_TIME);
124         float t = tm / 256.0f;
125         int xoffs = (int)((sin(t) * 0.5f + 0.5f) * max_xscroll);
126         int yoffs = (int)((cos(t) * 0.5f + 0.5f) * max_yscroll);
127         unsigned int *start = img + yoffs * IMG_W + xoffs;
128         float *vptr = varr;
129
130         switch(mode) {
131         case MODE_POINTS:
132                 /* draw with points */
133                 vptr = carr;
134                 for(i=0; i<win_height; i++) {
135                         for(j=0; j<win_width; j++) {
136                                 int r = start[j] & 0xff;
137                                 int g = (start[j] >> 8) & 0xff;
138                                 int b = (start[j] >> 16) & 0xff;
139                                 vptr[0] = r / 255.0f;
140                                 vptr[1] = g / 255.0f;
141                                 vptr[2] = b / 255.0f;
142                                 vptr += 3;
143                         }
144                         start += IMG_W;
145                 }
146
147                 if(have_vbo) {
148                         glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
149                         glVertexPointer(2, GL_FLOAT, 0, 0);
150                         glBindBuffer(GL_ARRAY_BUFFER, vbo_col);
151                         glBufferSubData(GL_ARRAY_BUFFER, 0, carr_sz, carr);
152                         glColorPointer(3, GL_FLOAT, 0, 0);
153                         glBindBuffer(GL_ARRAY_BUFFER, 0);
154                 } else {
155                         glVertexPointer(2, GL_FLOAT, 0, varr);
156                         glColorPointer(3, GL_FLOAT, 0, carr);
157                 }
158
159                 glEnableClientState(GL_VERTEX_ARRAY);
160                 glEnableClientState(GL_COLOR_ARRAY);
161
162                 glDrawArrays(GL_POINTS, 0, win_width * win_height);
163
164                 glDisableClientState(GL_VERTEX_ARRAY);
165                 glDisableClientState(GL_COLOR_ARRAY);
166                 break;
167
168         case MODE_DRAWPIX:
169                 /* draw with glDrawPixels */
170                 glDrawPixels(win_width, win_height, GL_RGBA, GL_UNSIGNED_BYTE, start);
171                 break;
172
173         case MODE_TEXQUAD:
174                 /* draw with textured quad */
175                 break;
176
177         case MODE_TEXTRI:
178                 /* draw with textured triangle */
179                 break;
180         }
181
182         glutSwapBuffers();
183         assert(glGetError() == GL_NO_ERROR);
184 }
185
186 void idle(void)
187 {
188         glutPostRedisplay();
189 }
190
191 void reshape(int x, int y)
192 {
193         glViewport(0, 0, x, y);
194
195         glMatrixMode(GL_PROJECTION);
196         glLoadIdentity();
197         glOrtho(0, x, 0, y, -1, 1);
198
199         win_width = x;
200         win_height = y;
201         max_xscroll = IMG_W - win_width;
202         max_yscroll = IMG_H - win_height;
203         if(max_xscroll < 0) max_xscroll = 0;
204         if(max_yscroll < 0) max_yscroll = 0;
205 }
206
207 void keyb(unsigned char key, int x, int y)
208 {
209         switch(key) {
210         case 27:
211                 exit(0);
212
213         case ' ':
214                 mode = (mode + 1) % NUM_MODES;
215                 break;
216
217         default:
218                 break;
219         }
220 }