"Fossies" - the Fresh Open Source Software Archive 
Member "SDL2-2.28.5/test/testshader.c" (2 Nov 2023, 16939 Bytes) of package /linux/misc/SDL2-2.28.5.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the last
Fossies "Diffs" side-by-side code changes report for "testshader.c":
2.26.5_vs_2.27.1.
1 /*
2 Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
3
4 This software is provided 'as-is', without any express or implied
5 warranty. In no event will the authors be held liable for any damages
6 arising from the use of this software.
7
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
10 freely.
11 */
12 /* This is a simple example of using GLSL shaders with SDL */
13
14 #include "SDL.h"
15
16 #ifdef HAVE_OPENGL
17
18 #include "SDL_opengl.h"
19
20 static SDL_bool shaders_supported;
21 static int current_shader = 0;
22
23 enum
24 {
25 SHADER_COLOR,
26 SHADER_TEXTURE,
27 SHADER_TEXCOORDS,
28 NUM_SHADERS
29 };
30
31 typedef struct
32 {
33 GLhandleARB program;
34 GLhandleARB vert_shader;
35 GLhandleARB frag_shader;
36 const char *vert_source;
37 const char *frag_source;
38 } ShaderData;
39
40 static ShaderData shaders[NUM_SHADERS] = {
41
42 /* SHADER_COLOR */
43 { 0, 0, 0,
44 /* vertex shader */
45 "varying vec4 v_color;\n"
46 "\n"
47 "void main()\n"
48 "{\n"
49 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
50 " v_color = gl_Color;\n"
51 "}",
52 /* fragment shader */
53 "varying vec4 v_color;\n"
54 "\n"
55 "void main()\n"
56 "{\n"
57 " gl_FragColor = v_color;\n"
58 "}" },
59
60 /* SHADER_TEXTURE */
61 { 0, 0, 0,
62 /* vertex shader */
63 "varying vec4 v_color;\n"
64 "varying vec2 v_texCoord;\n"
65 "\n"
66 "void main()\n"
67 "{\n"
68 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
69 " v_color = gl_Color;\n"
70 " v_texCoord = vec2(gl_MultiTexCoord0);\n"
71 "}",
72 /* fragment shader */
73 "varying vec4 v_color;\n"
74 "varying vec2 v_texCoord;\n"
75 "uniform sampler2D tex0;\n"
76 "\n"
77 "void main()\n"
78 "{\n"
79 " gl_FragColor = texture2D(tex0, v_texCoord) * v_color;\n"
80 "}" },
81
82 /* SHADER_TEXCOORDS */
83 { 0, 0, 0,
84 /* vertex shader */
85 "varying vec2 v_texCoord;\n"
86 "\n"
87 "void main()\n"
88 "{\n"
89 " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
90 " v_texCoord = vec2(gl_MultiTexCoord0);\n"
91 "}",
92 /* fragment shader */
93 "varying vec2 v_texCoord;\n"
94 "\n"
95 "void main()\n"
96 "{\n"
97 " vec4 color;\n"
98 " vec2 delta;\n"
99 " float dist;\n"
100 "\n"
101 " delta = vec2(0.5, 0.5) - v_texCoord;\n"
102 " dist = dot(delta, delta);\n"
103 "\n"
104 " color.r = v_texCoord.x;\n"
105 " color.g = v_texCoord.x * v_texCoord.y;\n"
106 " color.b = v_texCoord.y;\n"
107 " color.a = 1.0 - (dist * 4.0);\n"
108 " gl_FragColor = color;\n"
109 "}" },
110 };
111
112 static PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
113 static PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
114 static PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
115 static PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
116 static PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
117 static PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
118 static PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
119 static PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
120 static PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
121 static PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
122 static PFNGLUNIFORM1IARBPROC glUniform1iARB;
123 static PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
124
125 static SDL_bool CompileShader(GLhandleARB shader, const char *source)
126 {
127 GLint status = 0;
128
129 glShaderSourceARB(shader, 1, &source, NULL);
130 glCompileShaderARB(shader);
131 glGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &status);
132 if (status == 0) {
133 GLint length = 0;
134 char *info;
135
136 glGetObjectParameterivARB(shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
137 info = (char *)SDL_malloc((size_t)length + 1);
138 if (info == NULL) {
139 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
140 } else {
141 glGetInfoLogARB(shader, length, NULL, info);
142 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to compile shader:\n%s\n%s", source, info);
143 SDL_free(info);
144 }
145 return SDL_FALSE;
146 } else {
147 return SDL_TRUE;
148 }
149 }
150
151 static SDL_bool LinkProgram(ShaderData *data)
152 {
153 GLint status = 0;
154
155 glAttachObjectARB(data->program, data->vert_shader);
156 glAttachObjectARB(data->program, data->frag_shader);
157 glLinkProgramARB(data->program);
158
159 glGetObjectParameterivARB(data->program, GL_OBJECT_LINK_STATUS_ARB, &status);
160 if (status == 0) {
161 GLint length = 0;
162 char *info;
163
164 glGetObjectParameterivARB(data->program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
165 info = (char *)SDL_malloc((size_t)length + 1);
166 if (info == NULL) {
167 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!");
168 } else {
169 glGetInfoLogARB(data->program, length, NULL, info);
170 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to link program:\n%s", info);
171 SDL_free(info);
172 }
173 return SDL_FALSE;
174 } else {
175 return SDL_TRUE;
176 }
177 }
178
179 static SDL_bool CompileShaderProgram(ShaderData *data)
180 {
181 const int num_tmus_bound = 4;
182 int i;
183 GLint location;
184
185 glGetError();
186
187 /* Create one program object to rule them all */
188 data->program = glCreateProgramObjectARB();
189
190 /* Create the vertex shader */
191 data->vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
192 if (!CompileShader(data->vert_shader, data->vert_source)) {
193 return SDL_FALSE;
194 }
195
196 /* Create the fragment shader */
197 data->frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
198 if (!CompileShader(data->frag_shader, data->frag_source)) {
199 return SDL_FALSE;
200 }
201
202 /* ... and in the darkness bind them */
203 if (!LinkProgram(data)) {
204 return SDL_FALSE;
205 }
206
207 /* Set up some uniform variables */
208 glUseProgramObjectARB(data->program);
209 for (i = 0; i < num_tmus_bound; ++i) {
210 char tex_name[5];
211 (void)SDL_snprintf(tex_name, SDL_arraysize(tex_name), "tex%d", i);
212 location = glGetUniformLocationARB(data->program, tex_name);
213 if (location >= 0) {
214 glUniform1iARB(location, i);
215 }
216 }
217 glUseProgramObjectARB(0);
218
219 return (glGetError() == GL_NO_ERROR) ? SDL_TRUE : SDL_FALSE;
220 }
221
222 static void DestroyShaderProgram(ShaderData *data)
223 {
224 if (shaders_supported) {
225 glDeleteObjectARB(data->vert_shader);
226 glDeleteObjectARB(data->frag_shader);
227 glDeleteObjectARB(data->program);
228 }
229 }
230
231 static SDL_bool InitShaders()
232 {
233 int i;
234
235 /* Check for shader support */
236 shaders_supported = SDL_FALSE;
237 if (SDL_GL_ExtensionSupported("GL_ARB_shader_objects") &&
238 SDL_GL_ExtensionSupported("GL_ARB_shading_language_100") &&
239 SDL_GL_ExtensionSupported("GL_ARB_vertex_shader") &&
240 SDL_GL_ExtensionSupported("GL_ARB_fragment_shader")) {
241 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)SDL_GL_GetProcAddress("glAttachObjectARB");
242 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)SDL_GL_GetProcAddress("glCompileShaderARB");
243 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glCreateProgramObjectARB");
244 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)SDL_GL_GetProcAddress("glCreateShaderObjectARB");
245 glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)SDL_GL_GetProcAddress("glDeleteObjectARB");
246 glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)SDL_GL_GetProcAddress("glGetInfoLogARB");
247 glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)SDL_GL_GetProcAddress("glGetObjectParameterivARB");
248 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)SDL_GL_GetProcAddress("glGetUniformLocationARB");
249 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)SDL_GL_GetProcAddress("glLinkProgramARB");
250 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)SDL_GL_GetProcAddress("glShaderSourceARB");
251 glUniform1iARB = (PFNGLUNIFORM1IARBPROC)SDL_GL_GetProcAddress("glUniform1iARB");
252 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)SDL_GL_GetProcAddress("glUseProgramObjectARB");
253 if (glAttachObjectARB &&
254 glCompileShaderARB &&
255 glCreateProgramObjectARB &&
256 glCreateShaderObjectARB &&
257 glDeleteObjectARB &&
258 glGetInfoLogARB &&
259 glGetObjectParameterivARB &&
260 glGetUniformLocationARB &&
261 glLinkProgramARB &&
262 glShaderSourceARB &&
263 glUniform1iARB &&
264 glUseProgramObjectARB) {
265 shaders_supported = SDL_TRUE;
266 }
267 }
268
269 if (!shaders_supported) {
270 return SDL_FALSE;
271 }
272
273 /* Compile all the shaders */
274 for (i = 0; i < NUM_SHADERS; ++i) {
275 if (!CompileShaderProgram(&shaders[i])) {
276 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to compile shader!\n");
277 return SDL_FALSE;
278 }
279 }
280
281 /* We're done! */
282 return SDL_TRUE;
283 }
284
285 static void QuitShaders()
286 {
287 int i;
288
289 for (i = 0; i < NUM_SHADERS; ++i) {
290 DestroyShaderProgram(&shaders[i]);
291 }
292 }
293
294 /* Quick utility function for texture creation */
295 static int
296 power_of_two(int input)
297 {
298 int value = 1;
299
300 while (value < input) {
301 value <<= 1;
302 }
303 return value;
304 }
305
306 GLuint
307 SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
308 {
309 GLuint texture;
310 int w, h;
311 SDL_Surface *image;
312 SDL_Rect area;
313 SDL_BlendMode saved_mode;
314
315 /* Use the surface width and height expanded to powers of 2 */
316 w = power_of_two(surface->w);
317 h = power_of_two(surface->h);
318 texcoord[0] = 0.0f; /* Min X */
319 texcoord[1] = 0.0f; /* Min Y */
320 texcoord[2] = (GLfloat)surface->w / w; /* Max X */
321 texcoord[3] = (GLfloat)surface->h / h; /* Max Y */
322
323 image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
324 #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
325 0x000000FF,
326 0x0000FF00, 0x00FF0000, 0xFF000000
327 #else
328 0xFF000000,
329 0x00FF0000, 0x0000FF00, 0x000000FF
330 #endif
331 );
332 if (image == NULL) {
333 return 0;
334 }
335
336 /* Save the alpha blending attributes */
337 SDL_GetSurfaceBlendMode(surface, &saved_mode);
338 SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
339
340 /* Copy the surface into the GL texture image */
341 area.x = 0;
342 area.y = 0;
343 area.w = surface->w;
344 area.h = surface->h;
345 SDL_BlitSurface(surface, &area, image, &area);
346
347 /* Restore the alpha blending attributes */
348 SDL_SetSurfaceBlendMode(surface, saved_mode);
349
350 /* Create an OpenGL texture for the image */
351 glGenTextures(1, &texture);
352 glBindTexture(GL_TEXTURE_2D, texture);
353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
355 glTexImage2D(GL_TEXTURE_2D,
356 0,
357 GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
358 SDL_FreeSurface(image); /* No longer needed */
359
360 return texture;
361 }
362
363 /* A general OpenGL initialization function. Sets all of the initial parameters. */
364 void InitGL(int Width, int Height) /* We call this right after our OpenGL window is created. */
365 {
366 GLdouble aspect;
367
368 glViewport(0, 0, Width, Height);
369 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); /* This Will Clear The Background Color To Black */
370 glClearDepth(1.0); /* Enables Clearing Of The Depth Buffer */
371 glDepthFunc(GL_LESS); /* The Type Of Depth Test To Do */
372 glEnable(GL_DEPTH_TEST); /* Enables Depth Testing */
373 glShadeModel(GL_SMOOTH); /* Enables Smooth Color Shading */
374
375 glMatrixMode(GL_PROJECTION);
376 glLoadIdentity(); /* Reset The Projection Matrix */
377
378 aspect = (GLdouble)Width / Height;
379 glOrtho(-3.0, 3.0, -3.0 / aspect, 3.0 / aspect, 0.0, 1.0);
380
381 glMatrixMode(GL_MODELVIEW);
382 }
383
384 /* The main drawing function. */
385 void DrawGLScene(SDL_Window *window, GLuint texture, GLfloat *texcoord)
386 {
387 /* Texture coordinate lookup, to make it simple */
388 enum
389 {
390 MINX,
391 MINY,
392 MAXX,
393 MAXY
394 };
395
396 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /* Clear The Screen And The Depth Buffer */
397 glLoadIdentity(); /* Reset The View */
398
399 glTranslatef(-1.5f, 0.0f, 0.0f); /* Move Left 1.5 Units */
400
401 /* draw a triangle (in smooth coloring mode) */
402 glBegin(GL_POLYGON); /* start drawing a polygon */
403 glColor3f(1.0f, 0.0f, 0.0f); /* Set The Color To Red */
404 glVertex3f(0.0f, 1.0f, 0.0f); /* Top */
405 glColor3f(0.0f, 1.0f, 0.0f); /* Set The Color To Green */
406 glVertex3f(1.0f, -1.0f, 0.0f); /* Bottom Right */
407 glColor3f(0.0f, 0.0f, 1.0f); /* Set The Color To Blue */
408 glVertex3f(-1.0f, -1.0f, 0.0f); /* Bottom Left */
409 glEnd(); /* we're done with the polygon (smooth color interpolation) */
410
411 glTranslatef(3.0f, 0.0f, 0.0f); /* Move Right 3 Units */
412
413 /* Enable blending */
414 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
415 glEnable(GL_BLEND);
416 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
417
418 /* draw a textured square (quadrilateral) */
419 glEnable(GL_TEXTURE_2D);
420 glBindTexture(GL_TEXTURE_2D, texture);
421 glColor3f(1.0f, 1.0f, 1.0f);
422 if (shaders_supported) {
423 glUseProgramObjectARB(shaders[current_shader].program);
424 }
425
426 glBegin(GL_QUADS); /* start drawing a polygon (4 sided) */
427 glTexCoord2f(texcoord[MINX], texcoord[MINY]);
428 glVertex3f(-1.0f, 1.0f, 0.0f); /* Top Left */
429 glTexCoord2f(texcoord[MAXX], texcoord[MINY]);
430 glVertex3f(1.0f, 1.0f, 0.0f); /* Top Right */
431 glTexCoord2f(texcoord[MAXX], texcoord[MAXY]);
432 glVertex3f(1.0f, -1.0f, 0.0f); /* Bottom Right */
433 glTexCoord2f(texcoord[MINX], texcoord[MAXY]);
434 glVertex3f(-1.0f, -1.0f, 0.0f); /* Bottom Left */
435 glEnd(); /* done with the polygon */
436
437 if (shaders_supported) {
438 glUseProgramObjectARB(0);
439 }
440 glDisable(GL_TEXTURE_2D);
441
442 /* swap buffers to display, since we're double buffered. */
443 SDL_GL_SwapWindow(window);
444 }
445
446 int main(int argc, char **argv)
447 {
448 int done;
449 SDL_Window *window;
450 SDL_Surface *surface;
451 GLuint texture;
452 GLfloat texcoords[4];
453
454 /* Enable standard application logging */
455 SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
456
457 /* Initialize SDL for video output */
458 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
459 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to initialize SDL: %s\n", SDL_GetError());
460 exit(1);
461 }
462
463 /* Create a 640x480 OpenGL screen */
464 window = SDL_CreateWindow("Shader Demo", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, SDL_WINDOW_OPENGL);
465 if (window == NULL) {
466 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL window: %s\n", SDL_GetError());
467 SDL_Quit();
468 exit(2);
469 }
470
471 if (!SDL_GL_CreateContext(window)) {
472 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to create OpenGL context: %s\n", SDL_GetError());
473 SDL_Quit();
474 exit(2);
475 }
476
477 surface = SDL_LoadBMP("icon.bmp");
478 if (surface == NULL) {
479 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unable to load icon.bmp: %s\n", SDL_GetError());
480 SDL_Quit();
481 exit(3);
482 }
483 texture = SDL_GL_LoadTexture(surface, texcoords);
484 SDL_FreeSurface(surface);
485
486 /* Loop, drawing and checking events */
487 InitGL(640, 480);
488 if (InitShaders()) {
489 SDL_Log("Shaders supported, press SPACE to cycle them.\n");
490 } else {
491 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shaders not supported!\n");
492 }
493 done = 0;
494 while (!done) {
495 DrawGLScene(window, texture, texcoords);
496
497 /* This could go in a separate function */
498 {
499 SDL_Event event;
500 while (SDL_PollEvent(&event)) {
501 if (event.type == SDL_QUIT) {
502 done = 1;
503 }
504 if (event.type == SDL_KEYDOWN) {
505 if (event.key.keysym.sym == SDLK_SPACE) {
506 current_shader = (current_shader + 1) % NUM_SHADERS;
507 }
508 if (event.key.keysym.sym == SDLK_ESCAPE) {
509 done = 1;
510 }
511 }
512 }
513 }
514 }
515 QuitShaders();
516 SDL_Quit();
517 return 1;
518 }
519
520 #else /* HAVE_OPENGL */
521
522 int main(int argc, char *argv[])
523 {
524 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No OpenGL support on this system\n");
525 return 1;
526 }
527
528 #endif /* HAVE_OPENGL */
529
530 /* vi: set ts=4 sw=4 expandtab: */