Repository: kuravih/gllock Branch: master Commit: 8123a6566e4e Files: 19 Total size: 46.4 KB Directory structure: gitextract_5a6o3nxd/ ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── common.c ├── common.h ├── config.mk ├── gllock.c ├── install └── shaders/ ├── ascii.fragment.glsl ├── blur.fragment.glsl ├── bokeh.fragment.glsl ├── circle.fragment.glsl ├── crt.fragment.glsl ├── glitch.fragment.glsl ├── passthrough.vertex.glsl ├── radialbokeh.fragment.glsl ├── rain.fragment.glsl └── square.fragment.glsl ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.o ================================================ FILE: LICENSE ================================================ MIT/X Consortium License Copyright for portions of gllock are held by Anselm R Garbe , 2006-2012 as part of the project slock. All other copyright for gllock are held by Kuravi Hewawasam , 2019. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: Makefile ================================================ # gllock - simple screen locker # See LICENSE file for copyright and license details. include config.mk SRC = gllock.c common.c OBJ = ${SRC:.c=.o} all: options gllock options: @echo gllock build options: @echo "CFLAGS = ${CFLAGS}" @echo "LDFLAGS = ${LDFLAGS}" @echo "CC = ${CC}" .c.o: @echo CC $< @${CC} -c ${CFLAGS} $< ${OBJ}: config.mk gllock: ${OBJ} @echo CC -o $@ @${CC} -o $@ ${OBJ} ${LDFLAGS} clean: @echo cleaning @rm -f gllock ${OBJ} gllock-${VERSION}.tar.gz dist: clean @echo creating dist tarball @mkdir -p gllock-${VERSION} @cp -R LICENSE Makefile README config.mk ${SRC} gllock-${VERSION} @tar -cf gllock-${VERSION}.tar gllock-${VERSION} @gzip gllock-${VERSION}.tar @rm -rf gllock-${VERSION} install: all @echo installing executable file to ${DESTDIR}${PREFIX}/bin @mkdir -p ${DESTDIR}${PREFIX}/bin @cp -f gllock ${DESTDIR}${PREFIX}/bin @chmod 755 ${DESTDIR}${PREFIX}/bin/gllock @chmod u+s ${DESTDIR}${PREFIX}/bin/gllock @ln -sr shaders ${SHADER_LOCATION} uninstall: @echo removing executable file from ${DESTDIR}${PREFIX}/bin @rm -f ${DESTDIR}${PREFIX}/bin/gllock @echo removing shader link from ${SHADER_LOCATION} @rm -f ${SHADER_LOCATION}/shaders .PHONY: all options clean dist install uninstall ================================================ FILE: README.md ================================================ # gllock OpenGL extension to the simple screen locker [slock](http://github.com/anekos/slock) Inspired 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. **gllock** will obscure the screen using an opengl texture shader. ## few examples #### [circles](http://www.shadertoy.com/view/4dsXWs)

#### [squares](http://www.shadertoy.com/view/MtfXRN)

#### [ascii](http://www.shadertoy.com/view/lssGDj)

#### [crt](http://www.shadertoy.com/view/lt3yz7)

#### [glitch](http://www.shadertoy.com/view/MlVSD3)

## Requirements In order to build gllock you need the following packages: - _x11proto-core-dev_ for `#include ` - _libx11-dev_ for `#include ` - _libglew-dev_ for `#include ` The other requirement will be fulfilled automatically when installing the above. ## Installation Edit `config.mk` to match your local setup (**gllock** is installed into the `/usr/local` namespace by default). - `SHADER_LOCATION` - location of the shader files (default `~/.gllock/` which is a symlink to the shader folder of the repository) - `FRGMNT_SHADER` - the shader file to use (default circle.fragment.glsl) The following command builds and installs **gllock**: > sudo make clean install ## Running gllock Simply invoke the 'gllock' command. To get out of it, enter your password. However the typical setup involves using gllock with **xautolock**. For example in order to run **gllock** after N minutes of inactivity the following command may be used. > sudo xautolock -time N -locker "gllock" & ### Note when using a particular fragment shader you may want to figure out the supported glsl version for your system using > glxinfo | grep 'version' as 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. Most opengl texture shaders from [Shadertoy](www.shadertoy.com) may be adapted to gllock with minimal modifications. You may use the following substitutions as a starting point. * use `uniform vec2 screenSize` for `uniform vec3 iResolution` : viewport resolution *pixels*. (i.e. `iResolution.xy` -> `screenSize`). * use `uniform float time` for `uniform float iTime` : shader playback time *seconds*. (i.e. `iTime` -> `time`); * use `uniform sampler2D imageData` for `uniform samplerXX iChannel0..3` : input texture channel. (i.e. `iChannel0` -> `imageData`); * 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)`); `fragCoord` -> `gl_FragCoord` implicit input `fragColor` -> `gl_FragColor` implicit output ================================================ FILE: common.c ================================================ #include "common.h" #include #include #include #include #include #include #include #define DEBUG 0 #define MAX_N_TOKENS 65536 #define DELIMITERS " \t\r\n\a" float elapsed_time_s(struct timespec start_time) { struct timespec tick; clock_gettime(CLOCK_MONOTONIC_RAW, &tick); if (tick.tv_nsec < start_time.tv_nsec) return (tick.tv_sec - 1.0f - start_time.tv_sec) + (1000000000.0f + tick.tv_nsec - start_time.tv_nsec)/1000000000.0f; else return (tick.tv_sec - start_time.tv_sec) + (tick.tv_nsec - start_time.tv_nsec)/1000000000.0f; } static GLuint load_shaders_str(const char* vertex_shader_source, const char* fragment_shader_source) { // Create the shaders GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); GLint Result = GL_FALSE; int InfoLogLength; #if DEBUG printf("Compiling vertex shader\n"); printf("------------------------- vertex shader -------------------------\n%s\n-----------------------------------------------------------------\n\n",vertex_shader_source); #endif glShaderSource(VertexShaderID, 1, &vertex_shader_source , NULL); glCompileShader(VertexShaderID); // Check Vertex Shader glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if(InfoLogLength>0) { char* VertexShaderErrorMessage; VertexShaderErrorMessage = (char*) malloc(InfoLogLength+1); glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); printf("%s\n", &VertexShaderErrorMessage[0]); free(VertexShaderErrorMessage); } #if DEBUG printf("Compiling fragment shader\n"); printf("------------------------ fragment shader ------------------------\n%s\n-----------------------------------------------------------------\n\n",fragment_shader_source); #endif glShaderSource(FragmentShaderID, 1, &fragment_shader_source , NULL); glCompileShader(FragmentShaderID); // Check Fragment Shader glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); if(InfoLogLength>0) { char* FragmentShaderErrorMessage; FragmentShaderErrorMessage = (char*) malloc(InfoLogLength+1); glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); printf("%s\n", &FragmentShaderErrorMessage[0]); free(FragmentShaderErrorMessage); } // Link the program #if DEBUG printf("Linking program\n"); #endif GLuint ProgramID = glCreateProgram(); glAttachShader(ProgramID, VertexShaderID); glAttachShader(ProgramID, FragmentShaderID); glLinkProgram(ProgramID); // Check the program glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); if(InfoLogLength>0) { char* ProgramErrorMessage; ProgramErrorMessage = (char*) malloc(InfoLogLength+1); glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); printf("%s\n", &ProgramErrorMessage[0]); free(ProgramErrorMessage); } glDeleteShader(VertexShaderID); glDeleteShader(FragmentShaderID); return ProgramID; } static char* read_file(const char* filename) { char* buffer; long length = 0; size_t result = 0; FILE* fp = fopen(filename, "r"); if(fp) { fseek(fp, 0, SEEK_END); length = ftell(fp); rewind(fp); buffer = (char*)malloc(length); if(buffer) { result = fread(buffer, 1, length, fp); } fclose(fp); } else { #if DEBUG printf("file %s not loading\n",filename); #endif exit(0); } if (result != length) { #if DEBUG printf("Reading error %s\n",filename); #endif exit(3); } return buffer; } static int split_line (char* line, char*** p_tokens) { char* temp_tokens[MAX_N_TOKENS]; int i = 0, j = 0; char *token; int n_tokens = 0; token = strtok(line, DELIMITERS); while (token != NULL) { temp_tokens[i] = token; // printf("token : %s\n", temp_tokens[i]); i++; token = strtok(NULL, DELIMITERS); } n_tokens = i; // printf("----------\n"); *p_tokens = (char**) malloc(n_tokens * sizeof(char*)); for(j=0; j < n_tokens; j++) { // printf("token : %s\n", temp_tokens[j]); (*p_tokens)[j] = temp_tokens[j]; } return n_tokens; } static void shaders_defs(char* fragment_shader_source, struct shader_data* data) { data->rate = 0.0f; char** tokens; int n_tokens; n_tokens = split_line (fragment_shader_source, &tokens); size_t i; for(i=0; i < n_tokens; i++) { if((strcmp(tokens[i],"#define")==0) && (strcmp(tokens[i+1],"RATE")==0)) { data->rate = atof(tokens[i+2]); } } #if DEBUG printf("shader data: rate = %f", data->rate); #endif return; } static GLuint load_shaders_file(const char* vertex_shader_file, const char* fragment_shader_file, struct shader_data* data) { char *vertex_shader_str, *fragment_shader_str; GLuint ProgramID; vertex_shader_str = read_file(vertex_shader_file); #if DEBUG printf("------------------------- vertex shader -------------------------\nfile: %s\n-----------------------------------------------------------------\n\n",vertex_shader_file); #endif fragment_shader_str = read_file(fragment_shader_file); #if DEBUG printf("------------------------ fragment shader ------------------------\nfile: %s\n-----------------------------------------------------------------\n\n",fragment_shader_file); #endif ProgramID = load_shaders_str(vertex_shader_str, fragment_shader_str); shaders_defs(fragment_shader_str, data); free(vertex_shader_str); free(fragment_shader_str); return ProgramID; } Window fullscreen_win(Display* xdisplay, Window root) { GLint attrib[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; XVisualInfo* xvisual_info; xvisual_info = glXChooseVisual(xdisplay, 0, attrib); if(xvisual_info == NULL) { printf("no appropriate visual found\n"); exit(0); } XWindowAttributes xwindow_attrib; XGetWindowAttributes(xdisplay, root, &xwindow_attrib); XSetWindowAttributes set_xwindow_attrib; set_xwindow_attrib.colormap = XCreateColormap(xdisplay, root, xvisual_info->visual, AllocNone); set_xwindow_attrib.event_mask = ExposureMask | KeyPressMask; set_xwindow_attrib.override_redirect = 1; 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 ); } static XImage* screen_capture(Display* xdisplay, Window root) { XWindowAttributes xwindow_attrib; XGetWindowAttributes(xdisplay, root, &xwindow_attrib); return XGetImage(xdisplay, root, 0, 0, xwindow_attrib.width, xwindow_attrib.height, AllPlanes, ZPixmap); } #define MAJOR_VERSION 3 #define MINOR_VERSION 3 typedef GLXContext (*glXCreateContextAttribsARBProc) (Display*, GLXFBConfig, GLXContext, Bool, const int*); void create_gl_context(Display* xdisplay, Window win) { // Create_the_modern_OpenGL_context // -------------------------------- static int xvisual_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DOUBLEBUFFER, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; int num_fbc; GLXFBConfig* xfbc; xfbc = glXChooseFBConfig(xdisplay, DefaultScreen(xdisplay), xvisual_attribs, &num_fbc); if (!xfbc) { printf("glXChooseFBConfig() failed\n"); exit(1); } XVisualInfo* xvisual_info; // Create old OpenGL context to get correct function pointer for glXCreateContextAttribsARB() xvisual_info = glXGetVisualFromFBConfig(xdisplay, xfbc[0]); GLXContext xcontext_old; xcontext_old = glXCreateContext(xdisplay, xvisual_info, 0, GL_TRUE); glXCreateContextAttribsARBProc glXCreateContextAttribsARB; glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); /* Destroy old context */ glXMakeCurrent(xdisplay, 0, 0); glXDestroyContext(xdisplay, xcontext_old); if (!glXCreateContextAttribsARB) { printf("glXCreateContextAttribsARB() not found\n"); exit(1); } // Set desired minimum OpenGL version static int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, MAJOR_VERSION, GLX_CONTEXT_MINOR_VERSION_ARB, MINOR_VERSION, None }; // Create modern OpenGL context GLXContext xcontext; xcontext = glXCreateContextAttribsARB(xdisplay, xfbc[0], NULL, 1, context_attribs); if (!xcontext) { printf("Failed to create OpenGL context. Exiting.\n"); exit(1); } XMapRaised(xdisplay, win); glXMakeCurrent(xdisplay, win, xcontext); int major, minor; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); printf("OpenGL context created.\nVersion %d.%d\nVendor %s\nRenderer %s\n", major, minor, glGetString(GL_VENDOR), glGetString(GL_RENDERER)); glewExperimental = GL_TRUE; // Needed for core profile if (glewInit() != GLEW_OK) { fprintf(stderr, "Failed to initialize GLEW\n"); exit(0); } XWindowAttributes xwindow_attrib; XGetWindowAttributes(xdisplay, win, &xwindow_attrib); glViewport(0, 0, xwindow_attrib.width, xwindow_attrib.height); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); } GLuint setup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file) { GLuint VertexArrayID; glGenVertexArrays(1, &VertexArrayID); glBindVertexArray(VertexArrayID); GLuint programID; programID = load_shaders_file(vertex_shader_file, fragment_shader_file, data); // Create and compile our GLSL program from the shaders glUseProgram(programID); GLuint imageDataID = glGetUniformLocation(programID, "imageData"); glUniform1i(imageDataID, 0); glActiveTexture(GL_TEXTURE0); GLuint screenSizeID = glGetUniformLocation(programID, "screenSize"); XWindowAttributes xwindow_attrib; XGetWindowAttributes(xdisplay, win, &xwindow_attrib); glUniform2f(screenSizeID, xwindow_attrib.width, xwindow_attrib.height); static const GLfloat g_vertex_buffer_data[] = { -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, -1.0f, 0.0f }; GLuint vertexbuffer; glGenBuffers(1, &vertexbuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); XImage* ximage; ximage = screen_capture(xdisplay, root); if(ximage == NULL) { printf("\n\tximage could not be created.\n\n"); exit(0); } GLuint texture_id; glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, xwindow_attrib.width, xwindow_attrib.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(ximage->data[0]))); XDestroyImage(ximage); data->timeID = glGetUniformLocation(programID, "time"); data->endID = glGetUniformLocation(programID, "end"); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT ); // Clear the screen return programID; } void animate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data) { float time_s=0, end_s=0; struct timespec start_time; clock_gettime(CLOCK_MONOTONIC_RAW, &start_time); glUniform1f(data->endID, end_s); while (1) { time_s=elapsed_time_s(start_time); glUniform1f(data->timeID, time_s); glXSwapBuffers(xdisplay, win); glEnableVertexAttribArray(0); glDrawArrays(GL_TRIANGLES, 0, 6); glDisableVertexAttribArray(0); if ( (end_s>0) && ((time_s-end_s)*data->rate>=1.0) ) { // unlock fade out break; } // if ( (end_s==0) && (!*condition) ) { // TODO: unlock attempt fade out and in // glUniform1f(data->endID, end_s); // continue; // } if ( (end_s==0) && (!*condition) ) { // lock fade in and hold end_s = time_s; glUniform1f(data->endID, end_s); continue; } #if DEBUG printf("time_s : %f\n", time_s); #endif } printf("Attempts : %ld\n", *attempts); } ================================================ FILE: common.h ================================================ #ifndef _COMMON_h #define _COMMON_h #include #include #include struct shader_data { float rate; GLuint timeID; GLuint endID; GLuint rateID; }; Window fullscreen_win(Display*, Window); void create_gl_context(Display*, Window); GLuint setup_shaders(Display* xdisplay, Window root, Window win, struct shader_data* data, const char* vertex_shader_file, const char* fragment_shader_file); void animate(Display* xdisplay, Window win, Bool* condition, long* attempts, struct shader_data* data); #endif /* _COMMON_h */ ================================================ FILE: config.mk ================================================ # gllock version VERSION = 0.1-alpha # Customize below to fit your system # paths SHADER_LOCATION = $(HOME)/.gllock # shader # FRGMNT_SHADER = ascii.fragment.glsl # FRGMNT_SHADER = blur.fragment.glsl # FRGMNT_SHADER = bokeh.fragment.glsl FRGMNT_SHADER = circle.fragment.glsl # FRGMNT_SHADER = crt.fragment.glsl # FRGMNT_SHADER = glitch.fragment.glsl # FRGMNT_SHADER = radialbokeh.fragment.glsl # FRGMNT_SHADER = rain.fragment.glsl # FRGMNT_SHADER = square.fragment.glsl PREFIX = /usr/local X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib # includes and libs INCS = -I. -I/usr/include -I${X11INC} LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lGL -lGLEW -lpthread # flags CPPFLAGS = -DVERSION=\"${VERSION}\" -DHAVE_SHADOW_H -DSHADER_LOCATION=\"${SHADER_LOCATION}\" -DFRGMNT_SHADER=\"${FRGMNT_SHADER}\" CFLAGS = -pedantic -Wall -Os ${INCS} ${CPPFLAGS} LDFLAGS = -s ${LIBS} # On *BSD remove -DHAVE_SHADOW_H from CPPFLAGS and add -DHAVE_BSD_AUTH # On OpenBSD and Darwin remove -lcrypt from LIBS # compiler and linker CC = cc # Install mode. On BSD systems MODE=2755 and GROUP=auth # On others MODE=4755 and GROUP=root #MODE=2755 #GROUP=auth ================================================ FILE: gllock.c ================================================ /* See LICENSE file for license details. */ #define _XOPEN_SOURCE 500 #if HAVE_SHADOW_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include #include #include #include #include #include #include #if HAVE_BSD_AUTH #include #include #endif Display* xdisplay; typedef struct { int screen; Window root, win; pthread_t tid; Bool hold; long attempts; } lock_t; static lock_t* locks; static int nscreens; static Bool running = True; static void die(const char *errstr, ...) { va_list ap; va_start(ap, errstr); vfprintf(stderr, errstr, ap); va_end(ap); exit(EXIT_FAILURE); } #ifndef HAVE_BSD_AUTH static const char* getpw(void) { /* only run as root */ const char *rval; struct passwd *pw; pw = getpwuid(getuid()); if(!pw) die("gllock: cannot retrieve password entry (make sure to suid or sgid gllock)"); endpwent(); rval = pw->pw_passwd; #if HAVE_SHADOW_H if (strlen(rval)>=1) { /* kludge, assumes pw placeholder entry has len >= 1 */ struct spwd *sp; sp = getspnam(getenv("USER")); if(!sp) die("gllock: cannot retrieve shadow entry (make sure to suid or sgid gllock)\n"); endspent(); rval = sp->sp_pwdp; } #endif /* drop privileges */ if((setgid(pw->pw_gid)<0)||(setuid(pw->pw_uid)<0)) die("gllock: cannot drop privileges"); return rval; } #endif static void #ifdef HAVE_BSD_AUTH readpw(void) #else readpw(const char* pws) #endif { char buf[32], passwd[256]; int num, screen; unsigned int len, llen; KeySym ksym; XEvent ev; len = llen = 0; running = True; /* As "gllock" stands for "Simple X display locker". * The DPMS settings had been removed and you can set it with "xset" or some other utility. * This way the user can easily set a customized DPMS timeout. */ while(running && !XNextEvent(xdisplay, &ev)) { if(ev.type == KeyPress) { buf[0] = 0; num = XLookupString(&ev.xkey, buf, sizeof buf, &ksym, 0); if(IsKeypadKey(ksym)) { if(ksym == XK_KP_Enter) ksym = XK_Return; else if(ksym >= XK_KP_0 && ksym <= XK_KP_9) ksym = (ksym - XK_KP_0) + XK_0; } if(IsFunctionKey(ksym) || IsKeypadKey(ksym) || IsMiscFunctionKey(ksym) || IsPFKey(ksym) || IsPrivateKeypadKey(ksym)) continue; switch(ksym) { case XK_Return: passwd[len] = 0; #ifdef HAVE_BSD_AUTH running = !auth_userokay(getlogin(), NULL, "auth-xlock", passwd); #else running = strcmp(crypt(passwd, pws), pws); #endif if(running != False) // Wrong password { XBell(xdisplay, 100); for(screen = 0; screen < nscreens; screen++) { locks[screen].attempts++; } } len = 0; break; case XK_Escape: len = 0; break; case XK_BackSpace: if(len) --len; break; default: if(num && !iscntrl((int) buf[0]) && (len + num < sizeof passwd)) { memcpy(passwd + len, buf, num); len += num; } break; } if(llen == 0 && len != 0) { for(screen = 0; screen < nscreens; screen++) { // characters on the buffer } } else if(llen != 0 && len == 0) { for(screen = 0; screen < nscreens; screen++) { // Wrong password } } llen = len; } else for(screen = 0; screen < nscreens; screen++) XRaiseWindow(xdisplay, locks[screen].win); } } static void unlockscreen(lock_t* lock) { if(xdisplay == NULL || lock == NULL) return; lock->hold = False; pthread_join(lock->tid, NULL); XUngrabPointer(xdisplay, CurrentTime); XDestroyWindow(xdisplay, lock->win); } void* animation_runner(void* arg) { lock_t* lock = (lock_t*) arg; XLockDisplay(xdisplay); create_gl_context(xdisplay, lock->win); struct shader_data data; setup_shaders(xdisplay, lock->root, lock->win, &data, SHADER_LOCATION"/passthrough.vertex.glsl", SHADER_LOCATION"/"FRGMNT_SHADER); XUnlockDisplay(xdisplay); animate(xdisplay, lock->win, &(lock->hold), &(lock->attempts), &data); return NULL; } int lockscreen(lock_t* lock) { unsigned int len; Cursor invisible = 0; lock->hold = True; lock->attempts = 0; XLockDisplay(xdisplay); lock->win = fullscreen_win(xdisplay, lock->root); XUnlockDisplay(xdisplay); pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&(lock->tid), NULL, animation_runner, lock); for(len = 1000; len; len--) { if(XGrabPointer(xdisplay, lock->root, False, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, GrabModeAsync, GrabModeAsync, None, invisible, CurrentTime) == GrabSuccess) break; usleep(1000); } if(running && (len > 0)) { for(len = 1000; len; len--) { if(XGrabKeyboard(xdisplay, lock->root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) break; usleep(1000); } } running &= (len > 0); if(!running) { unlockscreen(lock); lock = NULL; } else { XSelectInput(xdisplay, lock->root, SubstructureNotifyMask); XSync(xdisplay, False); } return 1; } static void usage(void) { fprintf(stderr, "usage: gllock [-v]\n"); exit(EXIT_FAILURE); } int main(int argc, char **argv) { #ifndef HAVE_BSD_AUTH const char* password; #endif int screen; { int result; while((result = getopt(argc,argv,"vo:")) != -1) { switch(result) { case 'v': die("gllock-%s, © 2019 Kuravi H\n", VERSION); case '?': usage(); break; } } if((argc - optind) > 0) usage(); } if(!getpwuid(getuid())) die("gllock: no passwd entry for you"); #ifndef HAVE_BSD_AUTH password = getpw(); #endif XInitThreads(); if(!(xdisplay = XOpenDisplay(0))) die("gllock: cannot open display"); /* Get the number of screens in display "xdisplay" and blank them all. */ nscreens = ScreenCount(xdisplay); locks = malloc(nscreens*sizeof(lock_t)); for(screen = 0; screen < nscreens; screen++) { locks[screen].screen = screen; locks[screen].root = RootWindow(xdisplay, locks[screen].screen); } if(locks == NULL) die("gllock: malloc: %s", strerror(errno)); /* lock */ int nlocks = 0; for(screen = 0; screen < nscreens; screen++) { if( lockscreen(&(locks[screen])) ) nlocks++; } XSync(xdisplay, False); /* Did we actually manage to lock something? */ if(nlocks == 0) { // nothing to protect free(locks); XCloseDisplay(xdisplay); return 1; } /* Everything is now blank. Now wait for the correct password. */ #ifdef HAVE_BSD_AUTH readpw(); #else readpw(password); #endif /* Password ok, unlock everything and quit. */ for(screen = 0; screen < nscreens; screen++) unlockscreen(&(locks[screen])); free(locks); XCloseDisplay(xdisplay); return 0; } ================================================ FILE: install ================================================ #!/bin/sh DEST=~/bin/gllock make sudo chown root: gllock sudo chmod u+s gllock mv gllock $DEST ================================================ FILE: shaders/ascii.fragment.glsl ================================================ // http://www.shadertoy.com/view/lssGDj #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 1.0 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 0.0f #define MAX_SIZE 16.0f float character(int n, vec2 p) { p = floor(p*vec2(4.0, -4.0) + 2.5); if (clamp(p.x, 0.0, 4.0) == p.x) { if (clamp(p.y, 0.0, 4.0) == p.y) { int a = int(round(p.x) + 5.0 * round(p.y)); if (((n >> a) & 1) == 1) return 1.0; } } return 0.0; } void main(void) { float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE vec2 pix = vec2(1,-1)*gl_FragCoord.xy; vec3 col = texture(imageData, floor(pix/radius)*radius/screenSize.xy).rgb; float gray = 0.3 * col.r + 0.59 * col.g + 0.11 * col.b; int n = 4096; // . if (gray > 0.2) n = 65600; // : if (gray > 0.3) n = 332772; // * if (gray > 0.4) n = 15255086; // o if (gray > 0.5) n = 23385164; // & if (gray > 0.6) n = 15252014; // 8 if (gray > 0.7) n = 13199452; // @ if (gray > 0.8) n = 11512810; // # vec2 p = mod(2*pix/radius, 2.0) - vec2(1.0); col = col*character(n, p); gl_FragColor = vec4(col, 1.0); } // ================================================ FILE: shaders/blur.fragment.glsl ================================================ //https://www.shadertoy.com/view/XdfGDH #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.75 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 0.0f #define MAX_SIZE 7.0f //odd value required float normpdf(in float x, in float sigma) { return 0.39894*exp(-0.5*x*x/(sigma*sigma))/sigma; } void main(void) { vec3 c = texture(imageData, vec2(1,-1)*gl_FragCoord.xy/screenSize).rgb; //declare stuff const int mSize = int(MAX_SIZE+4); const int kSize = (mSize-1)/2; float kernel[mSize]; vec3 final_colour = vec3(0.0); float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE //create the 1-D kernel float Z = 0.0; for (int j = 0; j <= kSize; ++j) { kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), radius); } //get the normalization factor (as the gaussian has been clamped) for (int j = 0; j < mSize; ++j) { Z += kernel[j]; } //read out the texels for (int i=-kSize; i <= kSize; ++i) { for (int j=-kSize; j <= kSize; ++j) { final_colour += kernel[kSize+j]*kernel[kSize+i]*texture(imageData, vec2(1,-1)*(gl_FragCoord.xy+vec2(float(i),float(j))) / screenSize).rgb; } } gl_FragColor = vec4(final_colour/(Z*Z), 1.0); } ================================================ FILE: shaders/bokeh.fragment.glsl ================================================ // https://www.shadertoy.com/view/XsfSRr #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.75 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 0.0f #define MAX_SIZE 2.0f vec2 pixel; float factor; float radius; vec4 tex(vec2 uv) { return pow(texture(imageData, uv), vec4(2.2)); } vec4 accumCol = vec4(0.0); vec4 accumW = vec4(0.0); const float mas = 3.0; void add(vec2 uv, float i, float j) { vec2 offset = pixel * vec2(i, j); vec4 col = tex(uv + offset * radius); vec4 bokeh = vec4(1.0) + pow(col, vec4(4.0)) * vec4(factor); accumCol += col * bokeh; accumW += bokeh; } vec4 blur(vec2 uv) { for (float j = -7.0 + mas; j <= 7.0 - mas; j += 1.0) for (float i = -7.0 + mas; i <=7.0 - mas; i += 1.0) add(uv, i, j); for (float i = -5.0 + mas; i <=5.0 - mas; i+=1.0) { add(uv, i, -8.0 + mas); add(uv, i, 8.0 - mas); } for (float j = -5.0 + mas; j <=5.0 - mas; j+=1.0) { add(uv, -8.0 + mas, j); add(uv, 8.0 - mas, j); } for (float i = -3.0 +mas; i <=3.0 - mas; i+=1.0) { add(uv, i, -9.0 + mas); add(uv, i, 9.0 - mas); } for (float j = -3.0 + mas; j <=3.0 - mas; j+=1.0) { add(uv, -9.0 + mas, j); add(uv, 9.0 - mas, j); } return accumCol/accumW; } void main(void) { pixel = 1.0/screenSize; float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE factor = radius*16.0; vec2 uv = gl_FragCoord.xy / screenSize; gl_FragColor = pow(blur(vec2(0.0, 1.0) + uv * vec2(1.0, -1.0)),1.0/vec4(2.2)); } ================================================ FILE: shaders/circle.fragment.glsl ================================================ // http://www.shadertoy.com/view/4dsXWs #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 1.0 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 2.0f #define MAX_SIZE 18.0f // Compute the relative distance to the circle, where < 0.0 is outside the feathered border, and > 1.0 is inside the feathered border. float ComputeCircle(vec2 pos, vec2 center, float radius, float feather) { // Determine the distance to the center of the circle. float dist = length(center - pos); // Use the distance and the specified feather factor to determine where the distance lies relative to the circle border. float start = radius - feather; float end = radius + feather; return smoothstep(start, end, dist); } // The main function, which is executed once per pixel. void main(void) { float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); float diameter = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE float radius = diameter / 2.0; vec2 center = vec2(0.0); // Compute the relative distance to the circle, using mod() to repeat the circle across the display. // A feather value (in pixels) is used to reduce aliasing artifacts when the circles are small. // The position is adjusted so that a circle is in the center of the display. vec2 screenPos = gl_FragCoord.xy - (screenSize / 2.0) - vec2(radius); vec2 pos = mod(screenPos, vec2(diameter)) - vec2(radius); float d = ComputeCircle(pos, center, radius, 0.5); // Compute "pixelated" (stepped) texture coordinates using the floor() function. // The position is adjusted to match the circles, i.e. so a pixelated block is at the center of the display. vec2 count = screenSize / diameter; vec2 shift = vec2(0.5) - fract(count / 2.0); vec2 uv = floor(count * gl_FragCoord.xy / screenSize + shift) / count; // Sample the texture, using an offset to the center of the pixelated block. // 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. uv += vec2(0.5) / count; uv = clamp(uv, 0.0, 1.0); uv.y = 1.0 - uv.y; vec3 texColor = texture(imageData, uv, -32.0).rgb; // Calculate the color based on the circle shape, mixing between that color and a background color. // NOTE: Set the mix factor to 0.0 to see the pixelating effect directly, without the circles. vec3 bg = vec3(0.0, 0.0, 0.0); vec3 col = mix(texColor, bg, d); // Set the final fragment color. gl_FragColor = vec4(col, 1.0); } // ================================================ FILE: shaders/crt.fragment.glsl ================================================ // http://www.shadertoy.com/view/lt3yz7 #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.75 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- float rand(float seed){ return fract(sin(dot(vec2(seed) ,vec2(12.9898,78.233))) * 43758.5453); } vec2 displace(vec2 co, float seed, float seed2) { vec2 shift = vec2(0); if (rand(seed) > 0.5) { shift += 0.1 * vec2(2. * (0.5 - rand(seed2))); } if (rand(seed2) > 0.6) { if (co.y > 0.5) { shift.x *= rand(seed2 * seed); } } return shift; } vec4 interlace(vec2 co, vec4 col) { float shaderTime = time*RATE; if (int(co.y) % 3 == 0) { return col * ((sin(shaderTime * 4.) * 0.1) + 0.75) + (rand(shaderTime) * 0.05); } return col; } void main(void) { float shaderTime = time*RATE; // Normalized pixel coordinates (from 0 to 1) vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize; vec2 rDisplace = vec2(0); vec2 gDisplace = vec2(0); vec2 bDisplace = vec2(0); if (rand(shaderTime) > 0.95) { rDisplace = displace(uv, shaderTime * 2., 2. + shaderTime); gDisplace = displace(uv, shaderTime * 3., 3. + shaderTime); bDisplace = displace(uv, shaderTime * 5., 5. + shaderTime); } rDisplace.x += 0.005 * (0.5 - rand(shaderTime * 37. * uv.y)); gDisplace.x += 0.007 * (0.5 - rand(shaderTime * 41. * uv.y)); bDisplace.x += 0.0011 * (0.5 - rand(shaderTime * 53. * uv.y)); rDisplace.y += 0.001 * (0.5 - rand(shaderTime * 37. * uv.x)); gDisplace.y += 0.001 * (0.5 - rand(shaderTime * 41. * uv.x)); bDisplace.y += 0.001 * (0.5 - rand(shaderTime * 53. * uv.x)); // Output to screen float rcolor = texture(imageData, uv.xy + rDisplace).r; float gcolor = texture(imageData, uv.xy + gDisplace).g; float bcolor = texture(imageData, uv.xy + bDisplace).b; gl_FragColor = interlace(gl_FragCoord.xy, vec4(rcolor, gcolor, bcolor, 1)); } // ================================================ FILE: shaders/glitch.fragment.glsl ================================================ // http://www.shadertoy.com/view/MlVSD3 #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.75 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- float rand(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453) * 2.0 - 1.0; } float offset(float blocks, vec2 uv) { float shaderTime = time*RATE; return rand(vec2(shaderTime, floor(uv.y * blocks))); } void main(void) { vec2 uv = vec2(1,-1)*gl_FragCoord.xy / screenSize; gl_FragColor = texture(imageData, uv); gl_FragColor.r = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).r; gl_FragColor.g = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03 * 0.16666666, 0.0)).g; gl_FragColor.b = texture(imageData, uv + vec2(offset(64.0, uv) * 0.03, 0.0)).b; } // ================================================ FILE: shaders/passthrough.vertex.glsl ================================================ #version 330 core // Input vertex data, different for all executions of this shader. layout(location = 0) in vec3 vertexPosition_modelspace; void main(void){ gl_Position = vec4(vertexPosition_modelspace,1); } ================================================ FILE: shaders/radialbokeh.fragment.glsl ================================================ //https://www.shadertoy.com/view/XtjGWm // Bokeh disc. // by David Hoskins. // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.75 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 0.0f #define MAX_SIZE 0.5f #define PI 3.141596 // This is (3.-sqrt(5.0))*PI radians, which doesn't precompiled for some reason. // The compiler is a dunce I tells-ya!! #define GOLDEN_ANGLE 2.39996323 #define NUMBER 150.0 #define ITERATIONS (GOLDEN_ANGLE * NUMBER) //------------------------------------------------------------------------------------------- // This creates the 2D offset for the next point. // (r-1.0) is the equivalent to sqrt(0, 1, 2, 3...) vec2 Sample(in float theta, inout float r) { r += 1.0 / r; return (r-1.0) * vec2(cos(theta), sin(theta)); } //------------------------------------------------------------------------------------------- vec3 Bokeh(sampler2D tex, vec2 uv, float radius, float amount) { vec3 acc = vec3(0.0); vec3 div = vec3(0.0); vec2 pixel = vec2(screenSize.y/screenSize.x, 1.0) * radius * .006; float r = 1.0; for (float j = 0.0; j < ITERATIONS; j += GOLDEN_ANGLE) { vec3 col = texture(tex, uv + pixel * Sample(j, r), radius*1.5).xyz; vec3 bokeh = vec3(5.0) + pow(col, vec3(9.0)) * amount; acc += col * bokeh; div += bokeh; } return acc / div; } void main(void) { float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); float radius = mix(MIN_SIZE, MAX_SIZE, shaderTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE vec2 uv = gl_FragCoord.xy / screenSize; float a = 10.0; vec2 xy = vec2(uv.x,1.0-uv.y); float dis = distance(gl_FragCoord.xy, screenSize/2.0); gl_FragColor = vec4(Bokeh(imageData, xy, radius*dis*0.001, a), 1.0); } // ================================================ FILE: shaders/rain.fragment.glsl ================================================ // https://www.shadertoy.com/view/ltffzl #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 0.5 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_AMOUNT 0.0f #define MAX_AMOUNT 1.0f //odd value required // #define CHEAP_NORMALS // #define USE_POST_PROCESSING vec3 N13(float p) { // from DAVE HOSKINS vec3 p3 = fract(vec3(p) * vec3(.1031,.11369,.13787)); p3 += dot(p3, p3.yzx + 19.19); return fract(vec3((p3.x + p3.y)*p3.z, (p3.x+p3.z)*p3.y, (p3.y+p3.z)*p3.x)); } vec4 N14(float t) { return fract(sin(t*vec4(123., 1024., 1456., 264.))*vec4(6547., 345., 8799., 1564.)); } float N(float t) { return fract(sin(t*12345.564)*7658.76); } float Saw(float b, float t) { return smoothstep(0., b, t)*smoothstep(1., b, t); } vec2 DropLayer2(vec2 uv, float t) { vec2 UV = uv; uv.y += t*0.75; vec2 a = vec2(6., 1.); vec2 grid = a*2.; vec2 id = floor(uv*grid); float colShift = N(id.x); uv.y += colShift; id = floor(uv*grid); vec3 n = N13(id.x*35.2+id.y*2376.1); vec2 st = fract(uv*grid)-vec2(.5, 0); float x = n.x-.5; float y = UV.y*20.; float wiggle = sin(y+sin(y)); x += wiggle*(.5-abs(x))*(n.z-.5); x *= .7; float ti = fract(t+n.z); y = (Saw(.85, ti)-.5)*.9+.5; vec2 p = vec2(x, y); float d = length((st-p)*a.yx); float mainDrop = smoothstep(.4, .0, d); float r = sqrt(smoothstep(1., y, st.y)); float cd = abs(st.x-x); float trail = smoothstep(.23*r, .15*r*r, cd); float trailFront = smoothstep(-.02, .02, st.y-y); trail *= trailFront*r*r; y = UV.y; float trail2 = smoothstep(.2*r, .0, cd); float droplets = max(0., (sin(y*(1.-y)*120.)-st.y))*trail2*trailFront*n.z; y = fract(y*10.)+(st.y-.5); float dd = length(st-vec2(x, y)); droplets = smoothstep(.3, 0., dd); float m = mainDrop+droplets*r*trailFront; //m += st.x>a.y*.45 || st.y>a.x*.165 ? 1.2 : 0.; return vec2(m, trail); } float StaticDrops(vec2 uv, float t) { uv *= 40.; vec2 id = floor(uv); uv = fract(uv)-.5; vec3 n = N13(id.x*107.45+id.y*3543.654); vec2 p = (n.xy-.5)*.7; float d = length(uv-p); float fade = Saw(.025, fract(t+n.z)); float c = smoothstep(.3, 0., d)*fract(n.z*10.)*fade; return c; } vec2 Drops(vec2 uv, float t, float l0, float l1, float l2) { float s = StaticDrops(uv, t)*l0; vec2 m1 = DropLayer2(uv, t)*l1; vec2 m2 = DropLayer2(uv*1.85, t)*l2; float c = s+m1.x+m2.x; c = smoothstep(.3, 1., c); return vec2(c, max(m1.y*l0, m2.y*l1)); } void main(void) { float shaderTime = time*RATE; vec2 uv = (gl_FragCoord.xy-.5*screenSize) / screenSize.y; vec2 UV = vec2(1,-1)*gl_FragCoord.xy/screenSize; float amountTime = smoothstep(0.0,1.0,(time-end)*RATE); amountTime = (end==0)?amountTime:(1.0-amountTime); float amount = mix(MIN_AMOUNT, MAX_AMOUNT, amountTime); //Returns the linear blend of MIN_SIZE and MAX_SIZE float rainAmount = amount*(0.3*sin(shaderTime*0.05)+0.7); float maxBlur = mix(3.0, 6.0, rainAmount); float minBlur = 2.0; UV = (UV-0.5)+0.5; float staticDrops = smoothstep(-.5, 1., rainAmount)*2.; float layer1 = smoothstep(.25, .75, rainAmount); float layer2 = smoothstep(.0, .5, rainAmount); vec2 c = Drops(uv, shaderTime, staticDrops, layer1, layer2); vec2 e = vec2(.001, 0.); float cx = Drops(uv+e, shaderTime, staticDrops, layer1, layer2).x; float cy = Drops(uv+e.yx, shaderTime, staticDrops, layer1, layer2).x; vec2 n = vec2(cx-c.x, cy-c.x); // expensive normals float focus = mix(maxBlur, minBlur, smoothstep(.1, .2, c.x)); vec3 col = textureLod(imageData, UV+n, focus).rgb; gl_FragColor = vec4(col, 1.); } // ================================================ FILE: shaders/square.fragment.glsl ================================================ // http://www.shadertoy.com/view/MtfXRN #version 330 core // ---- gllock required fields ----------------------------------------------------------------------------------------- #define RATE 1.0 uniform float time; uniform float end; uniform sampler2D imageData; uniform vec2 screenSize; // --------------------------------------------------------------------------------------------------------------------- #define MIN_SIZE 2.0f #define MAX_SIZE 18.0f #define USE_TILE_BORDER #define USE_ROUNDED_CORNERS void main(void) { const float textureSamplesCount = 10.0; const float textureEdgeOffset = 0.005; const float borderSize = 0.75; float shaderTime = smoothstep(0.0,1.0,(time-end)*RATE); shaderTime = (end==0)?shaderTime:(1.0-shaderTime); float tileSize = mix(MIN_SIZE, MAX_SIZE, shaderTime); tileSize += mod(tileSize, 2.0); vec2 tileNumber = floor(gl_FragCoord.xy / tileSize); vec4 accumulator = vec4(0.0); for (float y = 0.0; y < textureSamplesCount; ++y) { for (float x = 0.0; x < textureSamplesCount; ++x) { vec2 textureCoordinates = (tileNumber + vec2((x + 0.5)/textureSamplesCount, (y + 0.5)/textureSamplesCount)) * tileSize / screenSize; textureCoordinates.y = 1.0 - textureCoordinates.y; textureCoordinates = clamp(textureCoordinates, 0.0 + textureEdgeOffset, 1.0 - textureEdgeOffset); accumulator += texture(imageData, textureCoordinates); } } gl_FragColor = accumulator / vec4(textureSamplesCount * textureSamplesCount); #if defined(USE_TILE_BORDER) || defined(USE_ROUNDED_CORNERS) vec2 pixelNumber = floor(gl_FragCoord.xy - (tileNumber * tileSize)); pixelNumber = mod(pixelNumber + borderSize, tileSize); #if defined(USE_TILE_BORDER) float pixelBorder = step(min(pixelNumber.x, pixelNumber.y), borderSize) * step(borderSize * 2.0 + 1.0, tileSize); #else float pixelBorder = step(pixelNumber.x, borderSize) * step(pixelNumber.y, borderSize) * step(borderSize * 2.0 + 1.0, tileSize); #endif gl_FragColor *= pow(gl_FragColor, vec4(pixelBorder)); #endif } //