[
  {
    "path": ".gitignore",
    "content": "\n*.o\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT/X Consortium License\n\nCopyright for portions of gllock are held by Anselm R Garbe <anselm@garbe.us>, 2006-2012 as part of the project slock.\nAll other copyright for gllock are held by Kuravi Hewawasam <kuravih@gmail.com>, 2019.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "Makefile",
    "content": "# gllock - simple screen locker\n# See LICENSE file for copyright and license details.\n\ninclude config.mk\n\nSRC = gllock.c common.c\nOBJ = ${SRC:.c=.o}\n\nall: options gllock\n\noptions:\n\t@echo gllock build options:\n\t@echo \"CFLAGS   = ${CFLAGS}\"\n\t@echo \"LDFLAGS  = ${LDFLAGS}\"\n\t@echo \"CC       = ${CC}\"\n\n.c.o:\n\t@echo CC $<\n\t@${CC} -c ${CFLAGS} $<\n\n${OBJ}: config.mk\n\ngllock: ${OBJ}\n\t@echo CC -o $@\n\t@${CC} -o $@ ${OBJ} ${LDFLAGS}\n\nclean:\n\t@echo cleaning\n\t@rm -f gllock ${OBJ} gllock-${VERSION}.tar.gz\n\ndist: clean\n\t@echo creating dist tarball\n\t@mkdir -p gllock-${VERSION}\n\t@cp -R LICENSE Makefile README config.mk ${SRC} gllock-${VERSION}\n\t@tar -cf gllock-${VERSION}.tar gllock-${VERSION}\n\t@gzip gllock-${VERSION}.tar\n\t@rm -rf gllock-${VERSION}\n\ninstall: all\n\t@echo installing executable file to ${DESTDIR}${PREFIX}/bin\n\t@mkdir -p ${DESTDIR}${PREFIX}/bin\n\t@cp -f gllock ${DESTDIR}${PREFIX}/bin\n\t@chmod 755 ${DESTDIR}${PREFIX}/bin/gllock\n\t@chmod u+s ${DESTDIR}${PREFIX}/bin/gllock\n\t@ln -sr shaders ${SHADER_LOCATION}\n\nuninstall:\n\t@echo removing executable file from ${DESTDIR}${PREFIX}/bin\n\t@rm -f ${DESTDIR}${PREFIX}/bin/gllock\n\t@echo removing shader link from ${SHADER_LOCATION}\n\t@rm -f ${SHADER_LOCATION}/shaders\n\n.PHONY: all options clean dist install uninstall\n"
  },
  {
    "path": "README.md",
    "content": "# gllock\nOpenGL extension to the simple screen locker [slock](http://github.com/anekos/slock)\n\nInspired by this [reddit post](https://www.reddit.com/r/unixporn/comments/3358vu/i3lock_unixpornworthy_lock_screen/) this lock screen was implemented using the simplest lock program I could find.\n**gllock** will obscure the screen using an opengl texture shader.\n\n## few examples\n\n#### [circles](http://www.shadertoy.com/view/4dsXWs)\n\n<p align=\"center\">\n  <img width=\"460\" height=\"300\" src=\"images/circle_shader.gif\"></img>\n</p>\n\n\n#### [squares](http://www.shadertoy.com/view/MtfXRN)\n\n<p align=\"center\">\n  <img width=\"460\" height=\"300\" src=\"images/square_shader.gif\"></img>\n</p>\n\n\n#### [ascii](http://www.shadertoy.com/view/lssGDj)\n\n<p align=\"center\">\n  <img width=\"460\" height=\"300\" src=\"images/ascii_shader.gif\"></img>\n</p>\n\n\n#### [crt](http://www.shadertoy.com/view/lt3yz7)\n\n<p align=\"center\">\n  <img width=\"460\" height=\"300\" src=\"images/crt_shader.gif\"></img>\n</p>\n\n\n#### [glitch](http://www.shadertoy.com/view/MlVSD3)\n\n<p align=\"center\">\n  <img width=\"460\" height=\"300\" src=\"images/glitch_shader.gif\"></img>\n</p>\n\n\n## Requirements\nIn order to build gllock you need the following packages:\n  - _x11proto-core-dev_ for `#include <X11/keysym.h>`\n  - _libx11-dev_ for `#include <X11/Xlib.h>`\n  - _libglew-dev_ for `#include <GL/glew.h>`\n\nThe other requirement will be fulfilled automatically when installing the above.\n\n## Installation\nEdit `config.mk` to match your local setup (**gllock** is installed into the `/usr/local` namespace by default).\n\n- `SHADER_LOCATION` - location of the shader files (default `~/.gllock/` which is a symlink to the shader folder of the repository)\n- `FRGMNT_SHADER` -  the shader file to use (default circle.fragment.glsl)\n\nThe following command builds and installs **gllock**:\n    \n    > sudo make clean install\n\n## Running gllock\nSimply invoke the 'gllock' command. To get out of it, enter your password.\nHowever the typical setup involves using gllock with **xautolock**.\nFor example in order to run **gllock** after N minutes of inactivity the following command may be used.\n\n    > sudo xautolock -time N -locker \"gllock\" &\n\n### Note\nwhen using a particular fragment shader you may want to figure out the supported glsl version for your system using \n\n    > glxinfo | grep 'version'\n\nas explained [here](https://askubuntu.com/questions/47062/what-is-terminal-command-that-can-show-opengl-version) and then make the necessary modifications to the shader files.\n\nMost opengl texture shaders from [Shadertoy](www.shadertoy.com) may be adapted to gllock with minimal modifications.\nYou may use the following substitutions as a starting point.\n\n* use `uniform vec2 screenSize` for `uniform vec3 iResolution` : viewport resolution *pixels*. (i.e. `iResolution.xy` -> `screenSize`).\n* use `uniform float time` for `uniform float iTime` : shader playback time *seconds*. (i.e. `iTime` -> `time`);\n* use `uniform sampler2D imageData` for `uniform samplerXX iChannel0..3` : input texture channel. (i.e. `iChannel0` -> `imageData`);\n\n* use `void main(void)` for `void mainImage( out vec4 fragColor, in vec2 fragCoord )` for the main function (i.e. `void mainImage(out vec4 fragColor, in vec2 fragCoord)` -> `void main(void)`);\n`fragCoord` -> `gl_FragCoord` implicit input\n`fragColor` -> `gl_FragColor` implicit output\n"
  },
  {
    "path": "common.c",
    "content": "#include \"common.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n#include <unistd.h>\n\n#include <string.h>\n\n#include <GL/glew.h>\n#include <GL/glx.h>\n\n#define DEBUG 0\n#define MAX_N_TOKENS 65536\n#define DELIMITERS \" \\t\\r\\n\\a\"\n\n\n\n\n\n\n\n\n\n\nfloat\nelapsed_time_s(struct timespec start_time)\n{\n  struct timespec tick;\n  clock_gettime(CLOCK_MONOTONIC_RAW, &tick);\n  if (tick.tv_nsec < start_time.tv_nsec)\n    return (tick.tv_sec - 1.0f - start_time.tv_sec) + (1000000000.0f + tick.tv_nsec - start_time.tv_nsec)/1000000000.0f;\n  else\n    return (tick.tv_sec - start_time.tv_sec) + (tick.tv_nsec - start_time.tv_nsec)/1000000000.0f;\n}\n\n\n\n\n\n\n\n\n\n\nstatic GLuint\nload_shaders_str(const char* vertex_shader_source, const char* fragment_shader_source)\n{\n\n  // Create the shaders\n  GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);\n  GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);\n\n  GLint Result = GL_FALSE;\n  int InfoLogLength;\n\n#if DEBUG\n  printf(\"Compiling vertex shader\\n\");\n  printf(\"------------------------- vertex shader -------------------------\\n%s\\n-----------------------------------------------------------------\\n\\n\",vertex_shader_source);\n#endif\n\n  glShaderSource(VertexShaderID, 1, &vertex_shader_source , NULL);\n  glCompileShader(VertexShaderID);\n\n  // Check Vertex Shader\n  glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);\n  glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n  if(InfoLogLength>0)\n  {\n    char* VertexShaderErrorMessage;\n    VertexShaderErrorMessage = (char*) malloc(InfoLogLength+1);\n    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);\n    printf(\"%s\\n\", &VertexShaderErrorMessage[0]);\n    free(VertexShaderErrorMessage);\n  }\n\n#if DEBUG\n  printf(\"Compiling fragment shader\\n\");\n  printf(\"------------------------ fragment shader ------------------------\\n%s\\n-----------------------------------------------------------------\\n\\n\",fragment_shader_source);\n#endif\n\n  glShaderSource(FragmentShaderID, 1, &fragment_shader_source , NULL);\n  glCompileShader(FragmentShaderID);\n\n  // Check Fragment Shader\n  glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);\n  glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n  if(InfoLogLength>0)\n  {\n    char* FragmentShaderErrorMessage;\n    FragmentShaderErrorMessage = (char*) malloc(InfoLogLength+1);\n    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);\n    printf(\"%s\\n\", &FragmentShaderErrorMessage[0]);\n    free(FragmentShaderErrorMessage);\n  }\n\n  // Link the program\n#if DEBUG\n  printf(\"Linking program\\n\");\n#endif\n  GLuint ProgramID = glCreateProgram();\n  glAttachShader(ProgramID, VertexShaderID);\n  glAttachShader(ProgramID, FragmentShaderID);\n\n  glLinkProgram(ProgramID);\n\n  // Check the program\n  glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);\n  glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n  if(InfoLogLength>0)\n  {\n    char* ProgramErrorMessage;\n    ProgramErrorMessage = (char*) malloc(InfoLogLength+1);\n    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);\n    printf(\"%s\\n\", &ProgramErrorMessage[0]);\n    free(ProgramErrorMessage);\n  }\n\n  glDeleteShader(VertexShaderID);\n  glDeleteShader(FragmentShaderID);\n\n  return ProgramID;\n}\n\n\n\n\n\n\n\n\n\n\nstatic char*\nread_file(const char* filename)\n{\n  char* buffer;\n  long length = 0;\n  size_t result = 0;\n  FILE* fp = fopen(filename, \"r\");\n  if(fp)\n  {\n    fseek(fp, 0, SEEK_END);\n    length = ftell(fp);\n    rewind(fp);\n    buffer = (char*)malloc(length);\n    if(buffer)\n    {\n      result = fread(buffer, 1, length, fp);\n    }\n    fclose(fp);\n  }\n  else\n  {\n#if DEBUG\n    printf(\"file %s not loading\\n\",filename);\n#endif\n    exit(0);\n  }\n  \n  if (result != length)\n  {\n#if DEBUG\n    printf(\"Reading error %s\\n\",filename);\n#endif\n    exit(3);\n  }\n  return buffer;\n}\n\n\n\n\n\n\n\n\n\n\nstatic int\nsplit_line (char* line, char*** p_tokens)\n{\n  char* temp_tokens[MAX_N_TOKENS];\n  int i = 0, j = 0;\n  char *token;\n  int n_tokens = 0;\n\n  token = strtok(line, DELIMITERS);\n  while (token != NULL)\n  {\n    temp_tokens[i] = token;\n    // printf(\"token : %s\\n\", temp_tokens[i]);\n    i++;\n    token = strtok(NULL, DELIMITERS);\n  }\n  n_tokens = i;\n\n  // printf(\"----------\\n\");\n  *p_tokens = (char**) malloc(n_tokens * sizeof(char*));\n  for(j=0; j < n_tokens; j++)\n  {\n    // printf(\"token : %s\\n\", temp_tokens[j]);\n    (*p_tokens)[j] = temp_tokens[j];\n  }\n  return n_tokens;\n}\n\n\n\n\n\n\n\n\n\n\nstatic void\nshaders_defs(char* fragment_shader_source, struct shader_data* data)\n{\n  data->rate = 0.0f;\n  char** tokens;\n  int n_tokens;\n  n_tokens = split_line (fragment_shader_source, &tokens);\n  size_t i;\n  for(i=0; i < n_tokens; i++)\n  {\n    if((strcmp(tokens[i],\"#define\")==0) && (strcmp(tokens[i+1],\"RATE\")==0))\n    {\n      data->rate = atof(tokens[i+2]);\n    }\n  }\n#if DEBUG\n  printf(\"shader data: rate = %f\", data->rate);\n#endif\n  return;\n}\n\n\n\n\n\n\n\n\n\n\nstatic GLuint\nload_shaders_file(const char* vertex_shader_file, const char* fragment_shader_file, struct shader_data* data)\n{\n  char *vertex_shader_str, *fragment_shader_str;\n  GLuint ProgramID;\n\n  vertex_shader_str = read_file(vertex_shader_file);\n#if DEBUG\n  printf(\"------------------------- vertex shader -------------------------\\nfile: %s\\n-----------------------------------------------------------------\\n\\n\",vertex_shader_file);\n#endif\n  fragment_shader_str = read_file(fragment_shader_file);\n#if DEBUG\n  printf(\"------------------------ fragment shader ------------------------\\nfile: %s\\n-----------------------------------------------------------------\\n\\n\",fragment_shader_file);\n#endif\n  ProgramID = load_shaders_str(vertex_shader_str, fragment_shader_str);\n  shaders_defs(fragment_shader_str, data);\n\n  free(vertex_shader_str);\n  free(fragment_shader_str);\n  return ProgramID;\n}\n\n\n\n\n\n\n\n\n\n\nWindow\nfullscreen_win(Display* xdisplay, Window root)\n{\n  GLint attrib[] =\n  {\n    GLX_RGBA,\n    GLX_DEPTH_SIZE, 24,\n    GLX_DOUBLEBUFFER,\n    None\n  };\n  XVisualInfo* xvisual_info;\n  xvisual_info = glXChooseVisual(xdisplay, 0, attrib);\n  if(xvisual_info == NULL)\n  {\n    printf(\"no appropriate visual found\\n\");\n    exit(0);\n  }\n\n  XWindowAttributes xwindow_attrib;\n  XGetWindowAttributes(xdisplay, root, &xwindow_attrib);\n\n  XSetWindowAttributes set_xwindow_attrib;\n  set_xwindow_attrib.colormap = XCreateColormap(xdisplay, root, xvisual_info->visual, AllocNone);\n  set_xwindow_attrib.event_mask = ExposureMask | KeyPressMask;\n  set_xwindow_attrib.override_redirect = 1;\n\n  return XCreateWindow(xdisplay, root, 0, 0, xwindow_attrib.width, xwindow_attrib.height, 0, xvisual_info->depth, InputOutput, xvisual_info->visual, CWBorderPixel|CWColormap|CWEventMask|CWOverrideRedirect, &set_xwindow_attrib );\n}\n\n\n\n\n\n\n\n\n\n\nstatic XImage*\nscreen_capture(Display* xdisplay, Window root)\n{\n  XWindowAttributes xwindow_attrib;\n  XGetWindowAttributes(xdisplay, root, &xwindow_attrib);\n  return XGetImage(xdisplay, root, 0, 0, xwindow_attrib.width, xwindow_attrib.height, AllPlanes, ZPixmap);\n}\n\n\n\n\n\n\n\n\n\n\n#define MAJOR_VERSION 3\n#define MINOR_VERSION 3\n\ntypedef GLXContext (*glXCreateContextAttribsARBProc) (Display*, GLXFBConfig, GLXContext, Bool, const int*);\n\nvoid\ncreate_gl_context(Display* xdisplay, Window win)\n{\n\n  // Create_the_modern_OpenGL_context\n  // --------------------------------\n  static int xvisual_attribs[] =\n  {\n    GLX_RENDER_TYPE, GLX_RGBA_BIT,\n    GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, \n    GLX_DOUBLEBUFFER, 1,\n    GLX_RED_SIZE, 1,\n    GLX_GREEN_SIZE, 1,\n    GLX_BLUE_SIZE, 1,\n    None\n  };\n  \n  int num_fbc;\n  GLXFBConfig* xfbc;\n  xfbc = glXChooseFBConfig(xdisplay, DefaultScreen(xdisplay), xvisual_attribs, &num_fbc);\n  if (!xfbc)\n  {\n    printf(\"glXChooseFBConfig() failed\\n\");\n    exit(1);\n  }\n  \n  XVisualInfo* xvisual_info;\n  // Create old OpenGL context to get correct function pointer for glXCreateContextAttribsARB()\n  xvisual_info = glXGetVisualFromFBConfig(xdisplay, xfbc[0]);\n  \n  GLXContext xcontext_old;\n  xcontext_old = glXCreateContext(xdisplay, xvisual_info, 0, GL_TRUE);\n\n  glXCreateContextAttribsARBProc glXCreateContextAttribsARB;\n  glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)\"glXCreateContextAttribsARB\");\n  /* Destroy old context */\n  glXMakeCurrent(xdisplay, 0, 0);\n  glXDestroyContext(xdisplay, xcontext_old);\n  if (!glXCreateContextAttribsARB)\n  {\n    printf(\"glXCreateContextAttribsARB() not found\\n\");\n    exit(1);\n  }\n\n  // Set desired minimum OpenGL version\n  static int context_attribs[] =\n  {\n    GLX_CONTEXT_MAJOR_VERSION_ARB, MAJOR_VERSION,\n    GLX_CONTEXT_MINOR_VERSION_ARB, MINOR_VERSION,\n    None\n  };\n  // Create modern OpenGL context\n  GLXContext xcontext;\n  xcontext = glXCreateContextAttribsARB(xdisplay, xfbc[0], NULL, 1, context_attribs);\n  if (!xcontext)\n  {\n    printf(\"Failed to create OpenGL context. Exiting.\\n\");\n    exit(1);\n  }\n\n  XMapRaised(xdisplay, win);\n  glXMakeCurrent(xdisplay, win, xcontext);\n\n  int major, minor;\n  glGetIntegerv(GL_MAJOR_VERSION, &major);\n  glGetIntegerv(GL_MINOR_VERSION, &minor);\n  printf(\"OpenGL context created.\\nVersion %d.%d\\nVendor %s\\nRenderer %s\\n\", major, minor, glGetString(GL_VENDOR), glGetString(GL_RENDERER));\n\n  glewExperimental = GL_TRUE; // Needed for core profile\n  if (glewInit() != GLEW_OK)\n  {\n    fprintf(stderr, \"Failed to initialize GLEW\\n\");\n    exit(0);\n  }\n\n  XWindowAttributes xwindow_attrib;\n  XGetWindowAttributes(xdisplay, win, &xwindow_attrib);\n  glViewport(0, 0, xwindow_attrib.width, xwindow_attrib.height);\n\n  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);\n\n}\n\n\n\n\n\n\n\n\n\n\nGLuint\nsetup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file)\n{\n\n  GLuint VertexArrayID;\n  glGenVertexArrays(1, &VertexArrayID);\n  glBindVertexArray(VertexArrayID);\n\n  GLuint programID;\n  programID = load_shaders_file(vertex_shader_file, fragment_shader_file, data); // Create and compile our GLSL program from the shaders\n  glUseProgram(programID);\n\n  GLuint imageDataID = glGetUniformLocation(programID, \"imageData\");\n  glUniform1i(imageDataID, 0);\n  glActiveTexture(GL_TEXTURE0);\n\n  GLuint screenSizeID = glGetUniformLocation(programID, \"screenSize\");\n  XWindowAttributes xwindow_attrib;\n  XGetWindowAttributes(xdisplay, win, &xwindow_attrib);\n  glUniform2f(screenSizeID, xwindow_attrib.width, xwindow_attrib.height);\n\n  static const GLfloat g_vertex_buffer_data[] =\n  {\n    -1.0f,  1.0f, 0.0f,\n     1.0f,  1.0f, 0.0f,\n    -1.0f, -1.0f, 0.0f,\n     1.0f,  1.0f, 0.0f,\n     1.0f, -1.0f, 0.0f,\n    -1.0f, -1.0f, 0.0f\n  };\n\n  GLuint vertexbuffer;\n  glGenBuffers(1, &vertexbuffer);\n  glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);\n  glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);\n  glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);\n\n  XImage* ximage;\n  ximage = screen_capture(xdisplay, root);\n  if(ximage == NULL)\n  {\n    printf(\"\\n\\tximage could not be created.\\n\\n\");\n    exit(0);\n  }\n\n  GLuint texture_id;\n  glGenTextures(1, &texture_id);\n  glBindTexture(GL_TEXTURE_2D, texture_id);\n  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n  // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, xwindow_attrib.width, xwindow_attrib.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(ximage->data[0])));\n  XDestroyImage(ximage);\n\n  data->timeID = glGetUniformLocation(programID, \"time\");\n  data->endID = glGetUniformLocation(programID, \"end\");\n\n  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);\n\n  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); // Clear the screen\n\n  return programID;\n\n}\n\n\n\n\n\n\n\n\n\n\nvoid\nanimate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data)\n{\n  float time_s=0, end_s=0;\n  struct timespec start_time;\n  clock_gettime(CLOCK_MONOTONIC_RAW, &start_time);\n\n  glUniform1f(data->endID, end_s);\n  while (1)\n  {\n    time_s=elapsed_time_s(start_time);\n    glUniform1f(data->timeID, time_s);\n    glXSwapBuffers(xdisplay, win);\n    glEnableVertexAttribArray(0);\n    glDrawArrays(GL_TRIANGLES, 0, 6);\n    glDisableVertexAttribArray(0);\n    if ( (end_s>0) && ((time_s-end_s)*data->rate>=1.0) ) { // unlock fade out\n      break;\n    }\n    // if ( (end_s==0) && (!*condition) ) { // TODO: unlock attempt fade out and in\n    //   glUniform1f(data->endID, end_s);\n    //   continue;\n    // }\n    if ( (end_s==0) && (!*condition) ) { // lock fade in and hold\n      end_s = time_s;\n      glUniform1f(data->endID, end_s);\n      continue;\n    }\n#if DEBUG\n    printf(\"time_s : %f\\n\", time_s);\n#endif\n  }\n\n  printf(\"Attempts : %ld\\n\", *attempts);\n}"
  },
  {
    "path": "common.h",
    "content": "#ifndef _COMMON_h\n#define _COMMON_h\n\n#include <GL/glew.h>\n#include <GL/glx.h>\n#include <GL/gl.h>\n\nstruct shader_data {\n  float rate;\n  GLuint timeID;\n  GLuint endID;\n  GLuint rateID;\n};\n\nWindow fullscreen_win(Display*, Window);\nvoid create_gl_context(Display*, Window);\nGLuint setup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file);\nvoid animate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data);\n\n#endif /* _COMMON_h */\n\n\n"
  },
  {
    "path": "config.mk",
    "content": "# gllock version\nVERSION = 0.1-alpha\n\n# Customize below to fit your system\n\n# paths\nSHADER_LOCATION = $(HOME)/.gllock\n\n# shader\n# FRGMNT_SHADER = ascii.fragment.glsl\n# FRGMNT_SHADER = blur.fragment.glsl\n# FRGMNT_SHADER = bokeh.fragment.glsl\nFRGMNT_SHADER = circle.fragment.glsl\n# FRGMNT_SHADER = crt.fragment.glsl\n# FRGMNT_SHADER = glitch.fragment.glsl\n# FRGMNT_SHADER = radialbokeh.fragment.glsl\n# FRGMNT_SHADER = rain.fragment.glsl\n# FRGMNT_SHADER = square.fragment.glsl\n\nPREFIX = /usr/local\n\nX11INC = /usr/X11R6/include\nX11LIB = /usr/X11R6/lib\n\n# includes and libs\nINCS = -I. -I/usr/include -I${X11INC}\nLIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lGL -lGLEW -lpthread\n\n# flags\nCPPFLAGS = -DVERSION=\\\"${VERSION}\\\" -DHAVE_SHADOW_H -DSHADER_LOCATION=\\\"${SHADER_LOCATION}\\\" -DFRGMNT_SHADER=\\\"${FRGMNT_SHADER}\\\"\nCFLAGS = -pedantic -Wall -Os ${INCS} ${CPPFLAGS}\nLDFLAGS = -s ${LIBS}\n\n# On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS and add -DHAVE_BSD_AUTH\n# On OpenBSD and Darwin remove -lcrypt from LIBS\n\n# compiler and linker\nCC = cc\n\n# Install mode. On BSD systems MODE=2755 and GROUP=auth\n# On others MODE=4755 and GROUP=root\n#MODE=2755\n#GROUP=auth\n"
  },
  {
    "path": "gllock.c",
    "content": "\n/* See LICENSE file for license details. */\n#define _XOPEN_SOURCE 500\n\n#if HAVE_SHADOW_H\n#include <shadow.h>\n#endif\n\n#include <ctype.h>\n#include <errno.h>\n#include <pwd.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <X11/keysym.h>\n#include <X11/Xlib.h>\n#include <X11/Xutil.h>\n#include <X11/Xatom.h>\n\n#include \"common.h\"\n\n#include <time.h>\n#include <pthread.h>\n\n#include <string.h>\n#include <stdbool.h>\n\n#include <crypt.h>\n\n#include <GL/glew.h>\n#include <GL/glx.h>\n\n#if HAVE_BSD_AUTH\n#include <login_cap.h>\n#include <bsd_auth.h>\n#endif\n\n\n\nDisplay* xdisplay;\n\ntypedef struct\n{\n  int screen;\n  Window root, win;\n  pthread_t tid;\n  Bool hold;\n  long attempts;\n} lock_t;\n\nstatic lock_t* locks;\nstatic int nscreens;\nstatic Bool running = True;\n\n\n\n\n\n\n\n\n\n\nstatic void\ndie(const char *errstr, ...)\n{\n  va_list ap;\n\n  va_start(ap, errstr);\n  vfprintf(stderr, errstr, ap);\n  va_end(ap);\n  exit(EXIT_FAILURE);\n}\n\n\n\n\n\n\n\n\n\n\n#ifndef HAVE_BSD_AUTH\nstatic const char*\ngetpw(void)\n{ /* only run as root */\n  const char *rval;\n  struct passwd *pw;\n\n  pw = getpwuid(getuid());\n  if(!pw)\n    die(\"gllock: cannot retrieve password entry (make sure to suid or sgid gllock)\");\n  endpwent();\n  rval =  pw->pw_passwd;\n\n#if HAVE_SHADOW_H\n  if (strlen(rval)>=1)\n  { /* kludge, assumes pw placeholder entry has len >= 1 */\n    struct spwd *sp;\n    sp = getspnam(getenv(\"USER\"));\n    if(!sp)\n      die(\"gllock: cannot retrieve shadow entry (make sure to suid or sgid gllock)\\n\");\n    endspent();\n    rval = sp->sp_pwdp;\n  }\n#endif\n\n  /* drop privileges */\n  if((setgid(pw->pw_gid)<0)||(setuid(pw->pw_uid)<0))\n    die(\"gllock: cannot drop privileges\");\n  return rval;\n}\n#endif\n\n\n\n\n\n\n\n\n\n\nstatic void\n#ifdef HAVE_BSD_AUTH\nreadpw(void)\n#else\nreadpw(const char* pws)\n#endif\n{\n  char buf[32], passwd[256];\n  int num, screen;\n  unsigned int len, llen;\n  KeySym ksym;\n  XEvent ev;\n\n  len = llen = 0;\n  running = True;\n\n  /* As \"gllock\" stands for \"Simple X display locker\".\n   * The DPMS settings had been removed and you can set it with \"xset\" or some other utility.\n   * This way the user can easily set a customized DPMS timeout. */\n  while(running && !XNextEvent(xdisplay, &ev))\n  {\n\n    if(ev.type == KeyPress)\n    {\n      buf[0] = 0;\n      num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0);\n\n      if(IsKeypadKey(ksym))\n      {\n        if(ksym == XK_KP_Enter)\n          ksym = XK_Return;\n        else if(ksym >= XK_KP_0 && ksym <= XK_KP_9)\n          ksym = (ksym - XK_KP_0) + XK_0;\n      }\n\n      if(IsFunctionKey(ksym) || IsKeypadKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsPrivateKeypadKey(ksym))\n        continue;\n\n      switch(ksym)\n      {\n      case XK_Return:\n        passwd[len] = 0;\n\n#ifdef HAVE_BSD_AUTH\n        running = !auth_userokay(getlogin(), NULL, \"auth-xlock\", passwd);\n#else\n        running = strcmp(crypt(passwd, pws), pws);\n#endif\n\n        if(running != False) // Wrong password\n        {\n          XBell(xdisplay, 100);\n          for(screen = 0; screen < nscreens; screen++)\n          {\n            locks[screen].attempts++;\n          }\n        }\n\n        len = 0;\n        break;\n\n      case XK_Escape:\n        len = 0;\n        break;\n\n      case XK_BackSpace:\n        if(len)\n          --len;\n        break;\n\n      default:\n        if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd))\n        {\n          memcpy(passwd + len, buf, num);\n          len += num;\n        }\n        break;\n\n      }\n\n      if(llen == 0 && len != 0)\n      {\n        for(screen = 0; screen < nscreens; screen++)\n        {\n          // characters on the buffer\n        }\n      }\n      else if(llen != 0 && len == 0)\n      {\n        for(screen = 0; screen < nscreens; screen++)\n        {\n          // Wrong password\n        }\n      }\n      llen = len;\n    }\n    else\n      for(screen = 0; screen < nscreens; screen++)\n        XRaiseWindow(xdisplay, locks[screen].win);\n\n  }\n}\n\n\n\n\n\n\n\n\n\n\nstatic void\nunlockscreen(lock_t* lock)\n{\n  if(xdisplay == NULL || lock == NULL)\n    return;\n\n  lock->hold = False;\n\n  pthread_join(lock->tid, NULL);\n\n  XUngrabPointer(xdisplay, CurrentTime);\n  XDestroyWindow(xdisplay, lock->win);\n}\n\n\n\n\n\n\n\n\n\n\nvoid*\nanimation_runner(void* arg)\n{\n  lock_t* lock = (lock_t*) arg;\n\n  XLockDisplay(xdisplay);\n\n  create_gl_context(xdisplay, lock->win);\n\n  struct shader_data data;\n  setup_shaders(xdisplay, lock->root, lock->win, &data, SHADER_LOCATION\"/passthrough.vertex.glsl\", SHADER_LOCATION\"/\"FRGMNT_SHADER);\n\n  XUnlockDisplay(xdisplay);\n\n  animate(xdisplay, lock->win, &(lock->hold), &(lock->attempts), &data);\n\n  return NULL;\n}\n\n\n\n\n\n\n\n\n\n\nint\nlockscreen(lock_t* lock) {\n  unsigned int len;\n  Cursor invisible = 0;\n\n  lock->hold = True;\n  lock->attempts = 0;\n\n  XLockDisplay(xdisplay);\n\n  lock->win = fullscreen_win(xdisplay, lock->root);\n\n  XUnlockDisplay(xdisplay);\n\n  pthread_attr_t attr;\n  pthread_attr_init(&attr);\n  pthread_create(&(lock->tid), NULL, animation_runner, lock);\n\n  for(len = 1000; len; len--)\n  {\n    if(XGrabPointer(xdisplay, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess)\n      break;\n    usleep(1000);\n  }\n  if(running && (len > 0))\n  {\n    for(len = 1000; len; len--)\n    {\n      if(XGrabKeyboard(xdisplay, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)\n        break;\n      usleep(1000);\n    }\n  }\n\n  running &= (len > 0);\n  if(!running)\n  {\n    unlockscreen(lock);\n    lock = NULL;\n  }\n  else\n  {\n    XSelectInput(xdisplay, lock->root, SubstructureNotifyMask);\n    XSync(xdisplay, False);\n  }\n\n  return 1;\n}\n\n\n\n\n\n\n\n\n\n\nstatic void\nusage(void)\n{\n  fprintf(stderr, \"usage: gllock [-v]\\n\");\n  exit(EXIT_FAILURE);\n}\n\n\n\n\n\n\n\n\n\n\nint\nmain(int argc, char **argv)\n{\n#ifndef HAVE_BSD_AUTH\n  const char* password;\n#endif\n  int screen;\n\n  {\n    int result;\n    while((result = getopt(argc,argv,\"vo:\")) != -1)\n    {\n      switch(result)\n      {\n        case 'v':\n          die(\"gllock-%s, © 2019 Kuravi H\\n\", VERSION);\n        case '?':\n          usage();\n          break;\n      }\n    }\n    if((argc - optind) > 0)\n      usage();\n  }\n\n\n  if(!getpwuid(getuid()))\n    die(\"gllock: no passwd entry for you\");\n\n\n#ifndef HAVE_BSD_AUTH\n  password = getpw();\n#endif\n\n  XInitThreads();\n\n  if(!(xdisplay = XOpenDisplay(0)))\n    die(\"gllock: cannot open display\");\n\n\n  /* Get the number of screens in display \"xdisplay\" and blank them all. */\n  nscreens = ScreenCount(xdisplay);\n  locks = malloc(nscreens*sizeof(lock_t));\n  for(screen = 0; screen < nscreens; screen++)\n  {\n    locks[screen].screen = screen;\n    locks[screen].root = RootWindow(xdisplay, locks[screen].screen);\n  }\n  if(locks == NULL)\n    die(\"gllock: malloc: %s\", strerror(errno));\n\n\n  /* lock */\n  int nlocks = 0;\n  for(screen = 0; screen < nscreens; screen++)\n  {\n    if( lockscreen(&(locks[screen])) )\n      nlocks++;\n  }\n  XSync(xdisplay, False);\n\n\n  /* Did we actually manage to lock something? */\n  if(nlocks == 0)\n  { // nothing to protect\n    free(locks);\n    XCloseDisplay(xdisplay);\n    return 1;\n  }\n\n  /* Everything is now blank. Now wait for the correct password. */\n#ifdef HAVE_BSD_AUTH\n  readpw();\n#else\n  readpw(password);\n#endif\n\n  /* Password ok, unlock everything and quit. */\n  for(screen = 0; screen < nscreens; screen++)\n    unlockscreen(&(locks[screen]));\n\n  free(locks);\n  XCloseDisplay(xdisplay);\n\n  return 0;\n}\n"
  },
  {
    "path": "install",
    "content": "#!/bin/sh\n\nDEST=~/bin/gllock\n\nmake\nsudo chown root: gllock\nsudo chmod u+s gllock\nmv gllock $DEST\n\n\n"
  },
  {
    "path": "shaders/ascii.fragment.glsl",
    "content": "// http://www.shadertoy.com/view/lssGDj\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 1.0\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 0.0f\n#define MAX_SIZE 16.0f\n\nfloat character(int n, vec2 p)\n{\n  p = floor(p*vec2(4.0, -4.0) + 2.5);\n    if (clamp(p.x, 0.0, 4.0) == p.x)\n  {\n        if (clamp(p.y, 0.0, 4.0) == p.y)\t\n    {\n          int a = int(round(p.x) + 5.0 * round(p.y));\n      if (((n >> a) & 1) == 1) return 1.0;\n    }\t\n    }\n  return 0.0;\n}\n\nvoid main(void) {\n\n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n\n  float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n\n  vec2 pix =  vec2(1,-1)*gl_FragCoord.xy;\n  vec3 col = texture(imageData, floor(pix/radius)*radius/screenSize.xy).rgb;\t\n  \n  float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b;\n  \n  int n =  4096;                // .\n  if (gray > 0.2) n = 65600;    // :\n  if (gray > 0.3) n = 332772;   // *\n  if (gray > 0.4) n = 15255086; // o \n  if (gray > 0.5) n = 23385164; // &\n  if (gray > 0.6) n = 15252014; // 8\n  if (gray > 0.7) n = 13199452; // @\n  if (gray > 0.8) n = 11512810; // #\n  \n  vec2 p = mod(2*pix/radius, 2.0) - vec2(1.0);\n    \n  col = col*character(n, p);\n  \n  gl_FragColor = vec4(col, 1.0);\n}\n//"
  },
  {
    "path": "shaders/blur.fragment.glsl",
    "content": "//https://www.shadertoy.com/view/XdfGDH\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.75\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 0.0f\n#define MAX_SIZE 7.0f //odd value required\n\nfloat normpdf(in float x, in float sigma) {\n  return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma;\n}\n\nvoid main(void) {\n\n  vec3 c = texture(imageData, vec2(1,-1)*gl_FragCoord.xy/screenSize).rgb;\n\n  //declare stuff\n  const int mSize = int(MAX_SIZE+4);\n  const int kSize = (mSize-1)/2;\n  float kernel[mSize];\n  vec3 final_colour = vec3(0.0);\n  \n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n\n  float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n\n  //create the 1-D kernel\n  float Z = 0.0;\n  for (int j = 0; j <= kSize; ++j) {\n    kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), radius);\n  }\n  \n  //get the normalization factor (as the gaussian has been clamped)\n  for (int j = 0; j < mSize; ++j) {\n    Z += kernel[j];\n  }\n  \n  //read out the texels\n  for (int i=-kSize; i <= kSize; ++i) {\n    for (int j=-kSize; j <= kSize; ++j) {\n      final_colour += kernel[kSize+j]*kernel[kSize+i]*texture(imageData, vec2(1,-1)*(gl_FragCoord.xy+vec2(float(i),float(j))) / screenSize).rgb;\n    }\n  }\n\n  gl_FragColor = vec4(final_colour/(Z*Z), 1.0);\n\n}"
  },
  {
    "path": "shaders/bokeh.fragment.glsl",
    "content": "// https://www.shadertoy.com/view/XsfSRr\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.75\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 0.0f\n#define MAX_SIZE 2.0f\n\nvec2 pixel;\n\nfloat factor;\nfloat radius;\n\nvec4 tex(vec2 uv) {\n  return pow(texture(imageData, uv), vec4(2.2));\n}\n\nvec4 accumCol = vec4(0.0);\nvec4 accumW = vec4(0.0);\n\nconst float mas = 3.0;\n\nvoid add(vec2 uv, float i, float j) {\n  vec2 offset = pixel * vec2(i, j);\n  vec4 col = tex(uv + offset * radius);\n  vec4 bokeh = vec4(1.0) + pow(col, vec4(4.0)) * vec4(factor);\n  accumCol += col * bokeh;\n  accumW += bokeh;\n  }\n\nvec4 blur(vec2 uv) {\n  for (float j = -7.0 + mas; j <= 7.0 - mas; j += 1.0)\n    for (float i = -7.0 + mas; i <=7.0 - mas; i += 1.0)\n      add(uv, i, j);\n    \n  for (float i = -5.0 + mas; i <=5.0 - mas; i+=1.0) {\n    add(uv, i, -8.0 + mas);\n    add(uv, i, 8.0 - mas);\n  }\n  for (float j = -5.0 + mas; j <=5.0 - mas; j+=1.0) {\n    add(uv, -8.0 + mas, j);\n    add(uv, 8.0 - mas, j);\n  }\n\n  for (float i = -3.0 +mas; i <=3.0 -  mas; i+=1.0) {\n    add(uv, i, -9.0 + mas);\n    add(uv, i, 9.0 - mas);\n  }\n  for (float j = -3.0 + mas; j <=3.0 - mas; j+=1.0) {\n    add(uv, -9.0 + mas, j);\n    add(uv, 9.0 - mas, j);\n  }\n\n  return accumCol/accumW;\n}\n\nvoid main(void) {\n\n  pixel = 1.0/screenSize;\n\n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n\n  radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n  factor = radius*16.0;  \n\n  vec2 uv = gl_FragCoord.xy / screenSize;\n  gl_FragColor = pow(blur(vec2(0.0, 1.0) + uv * vec2(1.0, -1.0)),1.0/vec4(2.2));\n}"
  },
  {
    "path": "shaders/circle.fragment.glsl",
    "content": "// http://www.shadertoy.com/view/4dsXWs\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 1.0\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 2.0f\n#define MAX_SIZE 18.0f\n\n// Compute the relative distance to the circle, where < 0.0 is outside the feathered border, and > 1.0 is inside the feathered border.\nfloat ComputeCircle(vec2 pos, vec2 center, float radius, float feather) {\n  // Determine the distance to the center of the circle.\n  float dist = length(center - pos);\n  \n  // Use the distance and the specified feather factor to determine where the distance lies relative to the circle border.\n  float start = radius - feather;\n  float end   = radius + feather;\n  return smoothstep(start, end, dist);\n}\n\n// The main function, which is executed once per pixel.\nvoid main(void) {\n\n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n\n  float diameter = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n\n  float radius = diameter / 2.0;\n  vec2  center = vec2(0.0);\n  \n  // Compute the relative distance to the circle, using mod() to repeat the circle across the display.\n  // A feather value (in pixels) is used to reduce aliasing artifacts when the circles are small.\n  // The position is adjusted so that a circle is in the center of the display.\n  vec2 screenPos = gl_FragCoord.xy - (screenSize / 2.0) - vec2(radius);\n  vec2 pos = mod(screenPos, vec2(diameter)) - vec2(radius);\n  float d = ComputeCircle(pos, center, radius, 0.5);\n  \n  // Compute \"pixelated\" (stepped) texture coordinates using the floor() function.\n  // The position is adjusted to match the circles, i.e. so a pixelated block is at the center of the display.\n  vec2 count = screenSize / diameter;\n  vec2 shift = vec2(0.5) - fract(count / 2.0);\n  vec2 uv = floor(count * gl_FragCoord.xy / screenSize + shift) / count;\n  \n  // Sample the texture, using an offset to the center of the pixelated block.\n  // NOTE: Use a large negative bias to effectively disable mipmapping, which would otherwise lead to sampling artifacts where the UVs change abruptly at the pixelated block boundaries.\n  uv += vec2(0.5) / count;\n  uv = clamp(uv, 0.0, 1.0);\n  uv.y = 1.0 - uv.y;\n  vec3 texColor = texture(imageData, uv, -32.0).rgb;  \n  \n  // Calculate the color based on the circle shape, mixing between that color and a background color.\n  // NOTE: Set the mix factor to 0.0 to see the pixelating effect directly, without the circles.\n  vec3 bg  = vec3(0.0, 0.0, 0.0);\n  vec3 col = mix(texColor, bg, d);\n    \n  // Set the final fragment color.\n  gl_FragColor = vec4(col, 1.0);\n}\n//"
  },
  {
    "path": "shaders/crt.fragment.glsl",
    "content": "// http://www.shadertoy.com/view/lt3yz7\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.75\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\nfloat rand(float seed){\n  return fract(sin(dot(vec2(seed) ,vec2(12.9898,78.233))) * 43758.5453);\n}\n\nvec2 displace(vec2 co, float seed, float seed2) {\n  vec2 shift = vec2(0);\n  if (rand(seed) > 0.5) {\n    shift += 0.1 * vec2(2. * (0.5 - rand(seed2)));\n  }\n  if (rand(seed2) > 0.6) {\n    if (co.y > 0.5) {\n      shift.x *= rand(seed2 * seed);\n    }\n  }\n  return shift;\n}\n\nvec4 interlace(vec2 co, vec4 col) {\n  float shaderTime = time*RATE;\n  if (int(co.y) % 3 == 0) {\n    return col * ((sin(shaderTime * 4.) * 0.1) + 0.75) + (rand(shaderTime) * 0.05);\n  }\n  return col;\n}\n\nvoid main(void) {\n\n  float shaderTime = time*RATE;\n\n  // Normalized pixel coordinates (from 0 to 1)\n  vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize;\n\n  vec2 rDisplace = vec2(0);\n  vec2 gDisplace = vec2(0);\n  vec2 bDisplace = vec2(0);\n  \n  if (rand(shaderTime) > 0.95) {\n    rDisplace = displace(uv, shaderTime * 2., 2. + shaderTime);\n    gDisplace = displace(uv, shaderTime * 3., 3. + shaderTime);\n    bDisplace = displace(uv, shaderTime * 5., 5. + shaderTime);\n  }\n  \n  rDisplace.x += 0.005 * (0.5 - rand(shaderTime * 37. * uv.y));\n  gDisplace.x += 0.007 * (0.5 - rand(shaderTime * 41. * uv.y));\n  bDisplace.x += 0.0011 * (0.5 - rand(shaderTime * 53. * uv.y));\n\n  rDisplace.y += 0.001 * (0.5 - rand(shaderTime * 37. * uv.x));\n  gDisplace.y += 0.001 * (0.5 - rand(shaderTime * 41. * uv.x));\n  bDisplace.y += 0.001 * (0.5 - rand(shaderTime * 53. * uv.x));\n  \n  // Output to screen\n  float rcolor = texture(imageData, uv.xy + rDisplace).r;\n  float gcolor = texture(imageData, uv.xy + gDisplace).g;\n  float bcolor = texture(imageData, uv.xy + bDisplace).b;\n\n  gl_FragColor = interlace(gl_FragCoord.xy, vec4(rcolor, gcolor, bcolor, 1));\n    \n}\n//"
  },
  {
    "path": "shaders/glitch.fragment.glsl",
    "content": "// http://www.shadertoy.com/view/MlVSD3\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.75\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\nfloat rand(vec2 co){\n  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) * 2.0 - 1.0;\n}\n\nfloat offset(float blocks, vec2 uv) {\n  float shaderTime = time*RATE;\n  return rand(vec2(shaderTime, floor(uv.y * blocks)));\n}\n\nvoid main(void) {\n  vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize;\n  gl_FragColor = texture(imageData, uv);\n  gl_FragColor.r = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).r;\n  gl_FragColor.g = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03 * 0.16666666, 0.0)).g;\n  gl_FragColor.b = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).b;\n}\n//"
  },
  {
    "path": "shaders/passthrough.vertex.glsl",
    "content": "#version 330 core\r\n\r\n// Input vertex data, different for all executions of this shader.\r\nlayout(location = 0) in vec3 vertexPosition_modelspace;\r\n\r\nvoid main(void){\r\n  gl_Position = vec4(vertexPosition_modelspace,1);\r\n}\r\n\r\n"
  },
  {
    "path": "shaders/radialbokeh.fragment.glsl",
    "content": "//https://www.shadertoy.com/view/XtjGWm\n// Bokeh disc.\n// by David Hoskins.\n// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.75\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 0.0f\n#define MAX_SIZE 0.5f\n\n#define PI 3.141596\n// This is (3.-sqrt(5.0))*PI radians, which doesn't precompiled for some reason.\n// The compiler is a dunce I tells-ya!!\n#define GOLDEN_ANGLE 2.39996323\n#define NUMBER 150.0\n#define ITERATIONS (GOLDEN_ANGLE * NUMBER)\n\n//-------------------------------------------------------------------------------------------\n// This creates the 2D offset for the next point.\n// (r-1.0) is the equivalent to sqrt(0, 1, 2, 3...)\nvec2 Sample(in float theta, inout float r) {\n  r += 1.0 / r;\n  return (r-1.0) * vec2(cos(theta), sin(theta));\n}\n\n//-------------------------------------------------------------------------------------------\nvec3 Bokeh(sampler2D tex, vec2 uv, float radius, float amount) {\n  vec3 acc = vec3(0.0);\n  vec3 div = vec3(0.0);\n  vec2 pixel = vec2(screenSize.y/screenSize.x, 1.0) * radius * .006;\n  float r = 1.0;\n  for (float j = 0.0; j < ITERATIONS; j += GOLDEN_ANGLE) {\n    vec3 col = texture(tex, uv + pixel * Sample(j, r), radius*1.5).xyz;\n    vec3 bokeh = vec3(5.0) + pow(col, vec3(9.0)) * amount;\n    acc += col * bokeh;\n    div += bokeh;\n  }\n  return acc / div;\n}\n\nvoid main(void) {\n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n\n  float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n\n  vec2 uv = gl_FragCoord.xy / screenSize;\n  float a = 10.0;\n  vec2 xy = vec2(uv.x,1.0-uv.y);\n  float dis = distance(gl_FragCoord.xy, screenSize/2.0);\n  gl_FragColor = vec4(Bokeh(imageData, xy, radius*dis*0.001, a), 1.0);\n}\n//"
  },
  {
    "path": "shaders/rain.fragment.glsl",
    "content": "// https://www.shadertoy.com/view/ltffzl\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 0.5\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_AMOUNT 0.0f\n#define MAX_AMOUNT 1.0f //odd value required\n\n// #define CHEAP_NORMALS\n// #define USE_POST_PROCESSING\n\nvec3 N13(float p) {\n  //  from DAVE HOSKINS\n  vec3 p3 = fract(vec3(p) * vec3(.1031,.11369,.13787));\n  p3 += dot(p3, p3.yzx + 19.19);\n  return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x));\n}\n\nvec4 N14(float t) {\n  return fract(sin(t*vec4(123., 1024., 1456., 264.))*vec4(6547., 345., 8799., 1564.));\n}\n\nfloat N(float t) {\n  return fract(sin(t*12345.564)*7658.76);\n}\n\nfloat Saw(float b, float t) {\n  return smoothstep(0., b, t)*smoothstep(1., b, t);\n}\n\nvec2 DropLayer2(vec2 uv, float t) {\n  vec2 UV = uv;\n  \n  uv.y += t*0.75;\n  vec2 a = vec2(6., 1.);\n  vec2 grid = a*2.;\n  vec2 id = floor(uv*grid);\n  \n  float colShift = N(id.x); \n  uv.y += colShift;\n  \n  id = floor(uv*grid);\n  vec3 n = N13(id.x*35.2+id.y*2376.1);\n  vec2 st = fract(uv*grid)-vec2(.5, 0);\n  \n  float x = n.x-.5;\n  \n  float y = UV.y*20.;\n  float wiggle = sin(y+sin(y));\n  x += wiggle*(.5-abs(x))*(n.z-.5);\n  x *= .7;\n  float ti = fract(t+n.z);\n  y = (Saw(.85, ti)-.5)*.9+.5;\n  vec2 p = vec2(x, y);\n  \n  float d = length((st-p)*a.yx);\n  \n  float mainDrop = smoothstep(.4, .0, d);\n  \n  float r = sqrt(smoothstep(1., y, st.y));\n  float cd = abs(st.x-x);\n  float trail = smoothstep(.23*r, .15*r*r, cd);\n  float trailFront = smoothstep(-.02, .02, st.y-y);\n  trail *= trailFront*r*r;\n  \n  y = UV.y;\n  float trail2 = smoothstep(.2*r, .0, cd);\n  float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z;\n  y = fract(y*10.)+(st.y-.5);\n  float dd = length(st-vec2(x, y));\n  droplets = smoothstep(.3, 0., dd);\n  float m = mainDrop+droplets*r*trailFront;\n\n  //m += st.x>a.y*.45 || st.y>a.x*.165 ? 1.2 : 0.;\n  return vec2(m, trail);\n}\n\nfloat StaticDrops(vec2 uv, float t) {\n  uv *= 40.;\n    \n  vec2 id = floor(uv);\n  uv = fract(uv)-.5;\n  vec3 n = N13(id.x*107.45+id.y*3543.654);\n  vec2 p = (n.xy-.5)*.7;\n  float d = length(uv-p);\n  \n  float fade = Saw(.025, fract(t+n.z));\n  float c = smoothstep(.3, 0., d)*fract(n.z*10.)*fade;\n  return c;\n}\n\nvec2 Drops(vec2 uv, float t, float l0, float l1, float l2) {\n  float s = StaticDrops(uv, t)*l0; \n  vec2 m1 = DropLayer2(uv, t)*l1;\n  vec2 m2 = DropLayer2(uv*1.85, t)*l2;\n\n  float c = s+m1.x+m2.x;\n  c = smoothstep(.3, 1., c);\n\n  return vec2(c, max(m1.y*l0, m2.y*l1));\n}\n\nvoid main(void) {\n\n  float shaderTime = time*RATE;\n\n  vec2 uv = (gl_FragCoord.xy-.5*screenSize) / screenSize.y;\n  vec2 UV = vec2(1,-1)*gl_FragCoord.xy/screenSize;\n  \n  float amountTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  amountTime = (end==0)?amountTime:(1.0-amountTime);\n\n  float amount = mix(MIN_AMOUNT, MAX_AMOUNT, amountTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE\n\n  float rainAmount = amount*(0.3*sin(shaderTime*0.05)+0.7);\n  \n  float maxBlur = mix(3.0, 6.0, rainAmount);\n  float minBlur = 2.0;\n    \n  UV = (UV-0.5)+0.5;\n  \n  float staticDrops = smoothstep(-.5, 1., rainAmount)*2.;\n  float layer1 = smoothstep(.25, .75, rainAmount);\n  float layer2 = smoothstep(.0, .5, rainAmount);\n  \n  vec2 c = Drops(uv, shaderTime, staticDrops, layer1, layer2);\n\n  vec2 e = vec2(.001, 0.);\n  float cx = Drops(uv+e, shaderTime, staticDrops, layer1, layer2).x;\n  float cy = Drops(uv+e.yx, shaderTime, staticDrops, layer1, layer2).x;\n  vec2 n = vec2(cx-c.x, cy-c.x); // expensive normals\n  \n  float focus = mix(maxBlur, minBlur, smoothstep(.1, .2, c.x));\n  vec3 col = textureLod(imageData, UV+n, focus).rgb;\n    \n  gl_FragColor = vec4(col, 1.);\n}\n//"
  },
  {
    "path": "shaders/square.fragment.glsl",
    "content": "// http://www.shadertoy.com/view/MtfXRN\n#version 330 core\n\n// ---- gllock required fields -----------------------------------------------------------------------------------------\n#define RATE 1.0\n\nuniform float time;\nuniform float end;\nuniform sampler2D imageData;\nuniform vec2 screenSize;\n// ---------------------------------------------------------------------------------------------------------------------\n\n#define MIN_SIZE 2.0f\n#define MAX_SIZE 18.0f\n\n#define USE_TILE_BORDER\n#define USE_ROUNDED_CORNERS\n\nvoid main(void) {\n\n  const float textureSamplesCount = 10.0;\n  const float textureEdgeOffset = 0.005;\n  const float borderSize = 0.75;\n\n  float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE);\n  shaderTime = (end==0)?shaderTime:(1.0-shaderTime);\n  \n  float tileSize =  mix(MIN_SIZE, MAX_SIZE, shaderTime);\n\n  tileSize += mod(tileSize, 2.0);\n  vec2 tileNumber = floor(gl_FragCoord.xy / tileSize);\n\n  vec4 accumulator = vec4(0.0);\n  for (float y = 0.0; y < textureSamplesCount; ++y) {\n    for (float x = 0.0; x < textureSamplesCount; ++x) {\n      vec2 textureCoordinates = (tileNumber + vec2((x + 0.5)/textureSamplesCount, (y + 0.5)/textureSamplesCount)) * tileSize / screenSize;\n      textureCoordinates.y = 1.0 - textureCoordinates.y;\n      textureCoordinates = clamp(textureCoordinates, 0.0 + textureEdgeOffset, 1.0 - textureEdgeOffset);\n      accumulator += texture(imageData, textureCoordinates);\n     }\n  }\n  \n  gl_FragColor = accumulator / vec4(textureSamplesCount * textureSamplesCount);\n\n#if defined(USE_TILE_BORDER) || defined(USE_ROUNDED_CORNERS)\n  vec2 pixelNumber = floor(gl_FragCoord.xy - (tileNumber * tileSize));\n  pixelNumber = mod(pixelNumber + borderSize, tileSize);\n  \n#if defined(USE_TILE_BORDER)\n  float pixelBorder = step(min(pixelNumber.x, pixelNumber.y), borderSize) * step(borderSize * 2.0 + 1.0, tileSize);\n#else\n  float pixelBorder = step(pixelNumber.x, borderSize) * step(pixelNumber.y, borderSize) * step(borderSize * 2.0 + 1.0, tileSize);\n#endif\n  gl_FragColor *= pow(gl_FragColor, vec4(pixelBorder));\n#endif\n}\n//"
  }
]