summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2016-02-01 14:03:21 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2016-02-01 14:03:21 +0100
commit9d3cdc7f5ee96c3b2a9342e44b62102f5b05be3b (patch)
tree25493bd35211830753cfaa52283d5e040f782111
parent213e7046d1ceca7591dc6d66e68a227421a508c5 (diff)
downloadglslview-9d3cdc7f5ee96c3b2a9342e44b62102f5b05be3b.tar
glslview-9d3cdc7f5ee96c3b2a9342e44b62102f5b05be3b.zip
Add glslwrite tool and some examples
-rw-r--r--.gitignore1
-rw-r--r--Makefile5
-rw-r--r--examples/polygon.frag54
-rw-r--r--examples/snail.frag41
-rw-r--r--examples/square-in-circle.frag66
-rw-r--r--examples/square-in-square.frag74
-rw-r--r--examples/square-ring.frag41
-rw-r--r--examples/square-ring2.frag47
-rw-r--r--examples/squares.frag42
-rw-r--r--examples/supersnail.frag37
-rw-r--r--examples/torus.frag41
-rw-r--r--glslview.c10
-rw-r--r--glslwrite.c204
13 files changed, 658 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index 3acbfea..5d3e9a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
glslview
+glslwrite
diff --git a/Makefile b/Makefile
index aa6d2b1..0023a99 100644
--- a/Makefile
+++ b/Makefile
@@ -1,2 +1,7 @@
+all : glslview glslwrite
+
glslview : glslview.c
gcc -o glslview glslview.c -lSDL2 -lGL -lGLEW -Wall
+
+glslwrite : glslwrite.c
+ gcc -o glslwrite glslwrite.c -lSDL2 -lpng -lGL -lGLEW -Wall
diff --git a/examples/polygon.frag b/examples/polygon.frag
new file mode 100644
index 0000000..20d5cdc
--- /dev/null
+++ b/examples/polygon.frag
@@ -0,0 +1,54 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float poly(float n, vec2 m, float r, float rt, vec2 p) {
+ vec2 diff = (m - p) * rot(rt);
+ float d = length(diff);
+ float alpha = PI / n;
+ float gamma = mod(abs(atan(diff.x, diff.y)), alpha*2);
+
+ if (gamma > alpha)
+ gamma -= 2*alpha;
+
+ float r2 = r * cos(alpha) / cos(gamma);
+
+ return clamp((r2 - d)*sharpness, 0.0, 1.0);
+}
+
+float poly_d(float n, vec2 m, float r, float rt, vec2 p) {
+ return poly(n, m, r, rt, p) - poly(n, m, r - 1/sharpness, rt, p);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ float c;
+
+ c = poly_d(5 - 3*cos(time/1000), vec2(0, 0), 0.5, PI * time/1000, p);
+ scene = abs(scene - c);
+
+ c = poly_d(5 - 3*cos(time/1000), vec2(0, 0), 0.5, -PI * time/1000, p);
+ scene = abs(scene - c);
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/snail.frag b/examples/snail.frag
new file mode 100644
index 0000000..491c53a
--- /dev/null
+++ b/examples/snail.frag
@@ -0,0 +1,41 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float circle(vec2 m, float r, vec2 p) {
+ vec2 diff = m - p;
+ float d = sqrt(dot(diff, diff));
+
+ return clamp((r - d)*sharpness, 0.0, 1.0);
+}
+
+float circle_d(vec2 m, float r, vec2 p) {
+ return circle(m, r, p) - circle(m, r - 1/sharpness, p);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ for (int i = 1; i <= 50; i++) {
+ float c = circle_d(vec2(0.5, 0) * rot(time/500/i), 0.1 + 0.005*i, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/square-in-circle.frag b/examples/square-in-circle.frag
new file mode 100644
index 0000000..ad6c615
--- /dev/null
+++ b/examples/square-in-circle.frag
@@ -0,0 +1,66 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float circle(vec2 m, float r, vec2 p) {
+ vec2 diff = m - p;
+ float d = sqrt(dot(diff, diff));
+
+ return clamp((r - d)*sharpness, 0.0, 1.0);
+}
+
+float circle_d(vec2 m, float r, vec2 p) {
+ return circle(m, r, p) - circle(m, r - 1/sharpness, p);
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ int n = 20;
+ float b = 1;
+ float alpha = 0;
+ for (int i = 0; i < n; i++) {
+ float c;
+
+ c = circle_d(vec2(0, 0), b, p);
+ scene = abs(scene - c);
+
+ float delta = mod(time/5000, PI/2);
+ alpha = mod(alpha + delta, PI/2);
+ b /= sqrt(2);
+
+ c = square(vec2(0, 0), b, alpha, p);
+ scene = abs(scene - c);
+
+ c = square(vec2(0, 0), b, -alpha, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/square-in-square.frag b/examples/square-in-square.frag
new file mode 100644
index 0000000..cc00388
--- /dev/null
+++ b/examples/square-in-square.frag
@@ -0,0 +1,74 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float circle(vec2 m, float r, vec2 p) {
+ vec2 diff = m - p;
+ float d = sqrt(dot(diff, diff));
+
+ return clamp((r - d)*sharpness, 0.0, 1.0);
+}
+
+float circle_d(vec2 m, float r, vec2 p) {
+ return circle(m, r, p) - circle(m, r - 1/sharpness, p);
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+float square_d(vec2 m, float a, float r, vec2 p) {
+ return square(m, a, r, p) - square(m, a - 1/sharpness, r, p);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ int n = 20;
+ float b = 1;
+ float alpha = 0;
+ for (int i = 0; i < n; i++) {
+ float delta = mod(time/5000, PI/2);
+ alpha = mod(alpha + delta, PI/2);
+ b /= (sin(delta) + cos(delta));
+
+ float c = square(vec2(0, 0), b, alpha, p);
+ scene = abs(scene - c);
+ }
+
+
+ b = 1;
+ alpha = 0;
+ for (int i = 0; i < n; i++) {
+ float delta = mod(-time/5000, PI/2);
+ alpha = mod(alpha + delta, PI/2);
+ b /= (sin(delta) + cos(delta));
+
+ float c = square(vec2(0, 0), b, alpha, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/square-ring.frag b/examples/square-ring.frag
new file mode 100644
index 0000000..1ef1c2c
--- /dev/null
+++ b/examples/square-ring.frag
@@ -0,0 +1,41 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ int n = 10;
+ for (int i = 1; i <= n; i++) {
+ float c = square(vec2(0, 0), 0.5, PI/2*i/n - time/500, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/square-ring2.frag b/examples/square-ring2.frag
new file mode 100644
index 0000000..e90b633
--- /dev/null
+++ b/examples/square-ring2.frag
@@ -0,0 +1,47 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ int n = 5;
+ for (int i = 1; i <= n; i++) {
+ float c = square(vec2(0, 0), 0.5, PI/2*i/n - time/3000, p);
+ scene = abs(scene - c);
+ }
+
+ n = 5;
+ for (int i = 1; i <= n; i++) {
+ float c = square(vec2(0, 0), 0.5, PI/2*i/n + time/3000, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/squares.frag b/examples/squares.frag
new file mode 100644
index 0000000..fd5dc94
--- /dev/null
+++ b/examples/squares.frag
@@ -0,0 +1,42 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 500;
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float a = atan(p.x, p.y);
+
+ float x = mod(p.x, 0.1);
+ float y = mod(p.y, 0.1);
+
+ float scene = 0;
+
+ for (int i = 1; i <= 50; i++) {
+ float c = square(vec2(0.5, 0) * rot(time/500/i), 0.1 + 0.005*i, time/500/i + time/(100*i), p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/supersnail.frag b/examples/supersnail.frag
new file mode 100644
index 0000000..154652a
--- /dev/null
+++ b/examples/supersnail.frag
@@ -0,0 +1,37 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float circle(vec2 m, float r, vec2 p) {
+ vec2 diff = m - p;
+ float d = sqrt(dot(diff, diff));
+
+ return clamp((r - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ for (int i = 1; i <= 100; i++) {
+ float c = circle(vec2(0.5, 0) * rot(time/200/i), 0.1 + 0.002*i, p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/examples/torus.frag b/examples/torus.frag
new file mode 100644
index 0000000..9758e1d
--- /dev/null
+++ b/examples/torus.frag
@@ -0,0 +1,41 @@
+#version 330
+
+out vec4 fragColor;
+
+uniform vec2 res;
+uniform float time;
+
+const float sharpness = 300;
+
+const float PI = 3.14159265358979323846;
+
+
+mat2 rot(float a) {
+ return mat2(
+ cos(a), -sin(a),
+ sin(a), cos(a)
+ );
+}
+
+float square(vec2 m, float a, float r, vec2 p) {
+ vec2 diff = abs((m - p) * rot(r));
+ float d = max(diff.x, diff.y);
+
+ return clamp((a - d)*sharpness, 0.0, 1.0);
+}
+
+void main(void) {
+ vec2 m = res/2;
+ float s = min(m.x, m.y);
+ vec2 p = (gl_FragCoord.xy - m) / s;
+
+ float scene = 0;
+
+ int n = 48;
+ for (int i = 1; i <= n; i++) {
+ float c = square(vec2(0.5, 0) * rot(PI/2*(time/8000 + 4.0*i/n)) * vec2(1, 0.5), 0.1, PI/2*(24.0*i/n - time/800), p);
+ scene = abs(scene - c);
+ }
+
+ fragColor = vec4(vec3(1, 1, 1) * scene, 1);
+}
diff --git a/glslview.c b/glslview.c
index 843319f..c78bd7d 100644
--- a/glslview.c
+++ b/glslview.c
@@ -13,7 +13,7 @@ static GLint time;
static GLint res;
-char * readfile(const char *filename) {
+static char * readfile(const char *filename) {
FILE *f = fopen(filename, "r");
if (!f)
return NULL;
@@ -39,7 +39,7 @@ char * readfile(const char *filename) {
return buffer;
}
-void printShaderInfoLog(GLuint obj) {
+static void printShaderInfoLog(GLuint obj) {
GLint length = 0;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
@@ -52,7 +52,7 @@ void printShaderInfoLog(GLuint obj) {
}
}
-void printProgramInfoLog(GLuint obj) {
+static void printProgramInfoLog(GLuint obj) {
GLint length = 0;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
@@ -65,7 +65,7 @@ void printProgramInfoLog(GLuint obj) {
}
}
-void init(char *filename) {
+static void init(char *filename) {
glewInit();
glDisable(GL_DEPTH_TEST);
@@ -96,7 +96,7 @@ void init(char *filename) {
}
-void render(SDL_Window *window) {
+static void render(SDL_Window *window) {
int width, height;
SDL_GetWindowSize(window, &width, &height);
diff --git a/glslwrite.c b/glslwrite.c
new file mode 100644
index 0000000..ebe81d4
--- /dev/null
+++ b/glslwrite.c
@@ -0,0 +1,204 @@
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <png.h>
+
+#include <GL/glew.h>
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_opengl.h>
+
+
+
+static unsigned frame_time = 0;
+
+
+static GLint time_loc;
+static GLint res_loc;
+
+
+static char * readfile(const char *filename) {
+ FILE *f = fopen(filename, "r");
+ if (!f)
+ return NULL;
+
+ size_t size = 1024;
+ char *buffer = malloc(size+1);
+ size_t count = 0, r;
+
+ do {
+ if (count == size) {
+ size *= 2;
+ buffer = realloc(buffer, size+1);
+ }
+
+ r = fread(buffer+count, 1, size-count, f);
+ count += r;
+ } while (r);
+
+ fclose(f);
+
+ buffer[count] = 0;
+
+ return buffer;
+}
+
+static void printShaderInfoLog(GLuint obj) {
+ GLint length = 0;
+
+ glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length);
+
+ if(length > 0) {
+ char log[length];
+
+ glGetShaderInfoLog(obj, sizeof(log), NULL, log);
+ fprintf(stderr, "%s\n", log);
+ }
+}
+
+static void printProgramInfoLog(GLuint obj) {
+ GLint length = 0;
+
+ glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length);
+
+ if(length > 0) {
+ char log[length];
+
+ glGetProgramInfoLog(obj, sizeof(log), NULL, log);
+ fprintf(stderr, "%s\n", log);
+ }
+}
+
+static void init(char *filename) {
+ glewInit();
+
+ glDisable(GL_DEPTH_TEST);
+
+ char *shader = readfile(filename);
+ if (!shader) {
+ fprintf(stderr, "Error: unable to read '%s'\n", filename);
+ exit(1);
+ }
+
+ GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);
+ glShaderSource(frag, 1, (const GLchar **)&shader, NULL);
+ glCompileShader(frag);
+ printShaderInfoLog(frag);
+
+ GLuint program = glCreateProgram();
+ glAttachShader(program, frag);
+
+ glLinkProgram(program);
+ printProgramInfoLog(program);
+
+ glBindFragDataLocation(program, 0, "fragColor");
+ time_loc = glGetUniformLocation(program, "time");
+ res_loc = glGetUniformLocation(program, "res");
+
+ glUseProgram(program);
+}
+
+static void savePNG(uint8_t *pixels, int width, int height, const char *output_dir) {
+ char filename[strlen(output_dir) + 20];
+ snprintf(filename, sizeof(filename), "%s/%010u.png", output_dir, frame_time);
+
+ FILE *f = fopen(filename, "wb");
+ if (!f) {
+ fprintf(stderr, "unable to open PNG file\n");
+ exit(1);
+ }
+
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr) {
+ fprintf(stderr, "unable to open PNG file\n");
+ exit(1);
+ }
+
+ png_set_swap_alpha(png_ptr);
+
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ fprintf(stderr, "unable to create PNG info struct\n");
+ exit(1);
+ }
+
+ if (setjmp(png_jmpbuf(png_ptr))) {
+ fprintf(stderr, "unable to write PNG file\n");
+ exit(1);
+ }
+
+ png_init_io(png_ptr, f);
+
+ png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+
+ uint8_t *row_pointers[height];
+ for (size_t i = 0; i < height; i++)
+ row_pointers[i] = &pixels[4*i*width];
+
+ png_set_rows(png_ptr, info_ptr, row_pointers);
+ png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(f);
+}
+
+static void render(SDL_Window *window, const char *output_dir) {
+ int width, height;
+ SDL_GetWindowSize(window, &width, &height);
+
+ glViewport(0, 0, (GLsizei)width, (GLsizei)height);
+
+ glUniform1f(time_loc, frame_time);
+ glUniform2f(res_loc, width, height);
+
+ glBegin(GL_QUADS);
+ glVertex2f(-1, -1);
+ glVertex2f(1, -1);
+ glVertex2f(1, 1);
+ glVertex2f(-1, 1);
+ glEnd();
+
+ SDL_GL_SwapWindow(window);
+
+ uint8_t pixels[width*height*4];
+ glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, pixels);
+ savePNG(pixels, width, height, output_dir);
+
+ frame_time += 20;
+}
+
+
+int main(int argc, char *argv[]) {
+ bool running = true;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: glslwrite <shader> <output directory>\n");
+ exit(1);
+ }
+
+ SDL_Init(SDL_INIT_VIDEO);
+
+ SDL_Window *window = SDL_CreateWindow("glslwrite", 0, 0, 800, 800, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE);
+ SDL_GL_CreateContext(window);
+
+ init(argv[1]);
+
+ while (running) {
+ SDL_Event e;
+
+ while( SDL_PollEvent(&e)) {
+ if(e.type == SDL_QUIT) {
+ running = false;
+ break;
+ }
+ }
+
+ render(window, argv[2]);
+ //usleep(1);
+ }
+
+ return 0;
+}