#include #include #include #include #include static GLint prog = 0; void keyboard_handler (unsigned char key, int x, int y) { switch (key) { case '\x1b': /* Escape */ case 'q': case 'Q': glutLeaveMainLoop (); break; case 'f': /* fullscreen */ case 'F': glutFullScreenToggle (); break; default: break; } } void redisplay (int value) { glutPostRedisplay (); glutTimerFunc (value, redisplay, value); } void display (void) { int width, height, ticks; GLint uindex; struct timespec ts; glUseProgram (prog); width = glutGet (GLUT_WINDOW_WIDTH); height = glutGet (GLUT_WINDOW_HEIGHT); clock_gettime (CLOCK_MONOTONIC_RAW, &ts); ticks = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; uindex = glGetUniformLocation (prog, "iGlobalTime"); if (uindex >= 0) glUniform1f (uindex, ((float) ticks) / 1000.0); uindex = glGetUniformLocation (prog, "iResolution"); if (uindex >= 0) glUniform3f (uindex, width, height, 1.0); glClear (GL_COLOR_BUFFER_BIT); glRectf (-1.0, -1.0, 1.0, 1.0); glutSwapBuffers (); } GLint compile_shader (const GLenum shader_type, const GLchar *shader_source) { GLuint shader = glCreateShader (shader_type); GLint status = GL_FALSE; GLint loglen; GLchar *error_message; glShaderSource (shader, 1, &shader_source, NULL); glCompileShader (shader); glGetShaderiv (shader, GL_COMPILE_STATUS, &status); if (status == GL_TRUE) return shader; glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &loglen); error_message = calloc (loglen, sizeof (GLchar)); glGetShaderInfoLog (shader, loglen, NULL, error_message); fprintf (stderr, "shader failed to compile:\n %s\n", error_message); free (error_message); return -1; } GLint link_program (const GLchar *shader_source) { GLint frag, program; GLint status = GL_FALSE; GLint loglen, n_uniforms; GLchar *error_message; GLint i; GLchar name[80]; GLsizei namelen; frag = compile_shader (GL_FRAGMENT_SHADER, shader_source); if (frag < 0) return -1; program = glCreateProgram (); glAttachShader (program, frag); glLinkProgram (program); // glDeleteShader (frag); glGetProgramiv (program, GL_LINK_STATUS, &status); if (status != GL_TRUE) { glGetProgramiv (program, GL_INFO_LOG_LENGTH, &loglen); error_message = calloc (loglen, sizeof (GLchar)); glGetProgramInfoLog (program, loglen, NULL, error_message); fprintf (stderr, "program failed to link:\n %s\n", error_message); free (error_message); return -1; } /* diagnostics */ glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &n_uniforms); fprintf (stderr, "%d uniforms:\n", n_uniforms); for (i = 0; i < n_uniforms; i++) { glGetActiveUniformName (program, i, 79, &namelen, name); name[namelen] = '\0'; fprintf (stderr, " %2d: %s\n", i, name); } return program; } void init_glew (void) { GLenum status; status = glewInit (); if (status != GLEW_OK) { fprintf (stderr, "glewInit error: %s\n", glewGetErrorString (status)); exit (-1); } fprintf (stderr, "GL_VERSION : %s\nGL_VENDOR : %s\nGL_RENDERER : %s\n" "GLEW_VERSION : %s\nGLSL VERSION : %s\n\n", glGetString (GL_VERSION), glGetString (GL_VENDOR), glGetString (GL_RENDERER), glewGetString (GLEW_VERSION), glGetString (GL_SHADING_LANGUAGE_VERSION)); if (!GLEW_VERSION_2_1) { fprintf (stderr, "OpenGL 2.1 or better required for GLSL support."); exit (-1); } } int main (int argc, char *argv[]) { char *frag_code = "\ uniform vec3 iResolution;\ uniform float iGlobalTime;\ void main(void)\ {\ vec2 uv = gl_FragCoord.xy / iResolution.xy;\ float a = uv.x * uv.y + iGlobalTime / 3.0;\ gl_FragColor = vec4( sin(a*3.141*2.5), sin(a*3.141*2.0),sin(a*3.141*1.0),1.0);\ }\ "; glutInit (&argc, argv); glutInitWindowSize (800, 600); glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow ("Shadertoy"); init_glew (); prog = link_program (frag_code); if (prog < 0) { fprintf (stderr, "Failed to link shader program. Aborting\n"); exit (-1); } glutDisplayFunc (display); glutKeyboardFunc (keyboard_handler); redisplay (1000/60); glutMainLoop (); return 0; }