forked from goliath/shadermeh
Initial commit
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
commit
acaef93bd8
11 changed files with 1182 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
*.o
|
||||||
|
*~
|
||||||
|
shadermeh
|
12
Makefile
Normal file
12
Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
CFLAGS = -ansi -pedantic -Wall -Wextra -O2 -Ofast -D_DEFAULT_SOURCE
|
||||||
|
LDFLAGS = -lX11 -lGL -lGLEW -lm -lrt
|
||||||
|
|
||||||
|
shadermeh: shadermeh.o window.o shader.o
|
||||||
|
|
||||||
|
window.o: window.c shadermeh.h
|
||||||
|
shader.o: shader.c shadermeh.h
|
||||||
|
shadermeh.o: shadermeh.c shadermeh.h
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(RM) shadermeh *.o
|
181
shader.c
Normal file
181
shader.c
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
#include "shadermeh.h"
|
||||||
|
|
||||||
|
/* stub vertex shader */
|
||||||
|
static const char *vert_src =
|
||||||
|
"#version 140\n"
|
||||||
|
"\n"
|
||||||
|
"in vec4 V_POSITION;\n"
|
||||||
|
"in vec4 V_COLOR;\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = V_POSITION;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
/* stub fragment shader */
|
||||||
|
static const char *frag_src_pre =
|
||||||
|
"#version 330\n"
|
||||||
|
"\n"
|
||||||
|
"uniform vec3 iResolution;\n"
|
||||||
|
"uniform float iTime;\n"
|
||||||
|
"uniform float iTimeDelta;\n"
|
||||||
|
"uniform float iFrame;\n"
|
||||||
|
"uniform float iChannelTime[4];\n"
|
||||||
|
"uniform vec4 iMouse;\n"
|
||||||
|
"uniform vec4 iDate;\n"
|
||||||
|
"uniform float iSampleRate;\n"
|
||||||
|
"uniform vec3 iChannelResolution[4];\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static const char *frag_src_post =
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" mainImage(gl_FragColor, gl_FragCoord.xy);\n"
|
||||||
|
"}\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
static char* load_file(const char *path)
|
||||||
|
{
|
||||||
|
size_t size, pre_len, post_len;
|
||||||
|
char *buffer;
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if (!path)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* try to open the file */
|
||||||
|
f = fopen(path, "r");
|
||||||
|
if (!f) {
|
||||||
|
perror(path);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get file size */
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
pre_len = strlen(frag_src_pre);
|
||||||
|
post_len = strlen(frag_src_post);
|
||||||
|
|
||||||
|
/* try to allocate buffer for file contents */
|
||||||
|
buffer = calloc(1, pre_len + size + post_len + 1);
|
||||||
|
|
||||||
|
if (!buffer) {
|
||||||
|
fclose(f);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read file contents into buffer */
|
||||||
|
memcpy(buffer, frag_src_pre, pre_len);
|
||||||
|
fread(buffer + pre_len, 1, size, f);
|
||||||
|
memcpy(buffer + pre_len + size, frag_src_post, post_len);
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
fclose(f);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
GLuint shader_program_load(const char *fsrc)
|
||||||
|
{
|
||||||
|
GLuint vsh = 0, fsh = 0, prog = 0;
|
||||||
|
char *fs = NULL;
|
||||||
|
|
||||||
|
if (!fsrc)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fs = load_file(fsrc);
|
||||||
|
|
||||||
|
if (!fs)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
|
if (!vsh || !fsh)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
prog = glCreateProgram();
|
||||||
|
if (!prog)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
glShaderSource(vsh, 1, (const GLchar **)&vert_src, NULL);
|
||||||
|
glShaderSource(fsh, 1, (const GLchar **)&fs, NULL);
|
||||||
|
|
||||||
|
glCompileShader(vsh);
|
||||||
|
glCompileShader(fsh);
|
||||||
|
|
||||||
|
glAttachShader(prog, vsh);
|
||||||
|
glAttachShader(prog, fsh);
|
||||||
|
|
||||||
|
glLinkProgram(prog);
|
||||||
|
done:
|
||||||
|
if (vsh)
|
||||||
|
glDeleteShader(vsh);
|
||||||
|
if (fsh)
|
||||||
|
glDeleteShader(fsh);
|
||||||
|
free(fs);
|
||||||
|
return prog;
|
||||||
|
}
|
||||||
|
|
||||||
|
int shader_program_get_build_status(GLuint prog)
|
||||||
|
{
|
||||||
|
GLuint shaders[3];
|
||||||
|
GLsizei i, count;
|
||||||
|
GLint v;
|
||||||
|
|
||||||
|
glGetProgramiv(prog, GL_LINK_STATUS, &v);
|
||||||
|
if (!v)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
glGetAttachedShaders(prog, 3, &count, shaders);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &v);
|
||||||
|
if (!v)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader_program_print_info_log(GLuint prog)
|
||||||
|
{
|
||||||
|
GLsizei i, count, len;
|
||||||
|
char *buffer = NULL;
|
||||||
|
int buffersize = 0;
|
||||||
|
GLuint shaders[3];
|
||||||
|
GLint v;
|
||||||
|
|
||||||
|
glGetAttachedShaders(prog, 3, &count, shaders);
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &v);
|
||||||
|
|
||||||
|
if ((v + 1) > buffersize) {
|
||||||
|
buffer = realloc(buffer, v + 1);
|
||||||
|
buffersize = v + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetShaderInfoLog(shaders[i], buffersize,
|
||||||
|
&len, (GLchar *)buffer);
|
||||||
|
buffer[len] = '\0';
|
||||||
|
printf("-------------\n%s\n-------------\n", buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &v);
|
||||||
|
|
||||||
|
if ((v + 1) > buffersize) {
|
||||||
|
buffer = realloc(buffer, v + 1);
|
||||||
|
buffersize = v + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetProgramInfoLog(prog, buffersize, &len, (GLchar *)buffer);
|
||||||
|
buffer[len] = '\0';
|
||||||
|
printf("-------------\n%s\n-------------\n", buffer);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
179
shadermeh.c
Normal file
179
shadermeh.c
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#include "shadermeh.h"
|
||||||
|
|
||||||
|
static GLfloat vertex_buffer[] = {
|
||||||
|
-1.0f, -1.0f, 0.0f, /* lower left corner */
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
+1.0f, -1.0f, 0.0f, /* lower right corner */
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
-1.0f, 1.0f, 0.0f, /* uper left corner */
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
+1.0f, +1.0f, 0.0f, /* upper right corner */
|
||||||
|
1.0f, 1.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
static double diff_timespec(const struct timespec *time1,
|
||||||
|
const struct timespec *time0)
|
||||||
|
{
|
||||||
|
return (time1->tv_sec - time0->tv_sec)
|
||||||
|
+ (time1->tv_nsec - time0->tv_nsec) / 1000000000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct option long_opts[] = {
|
||||||
|
{ "width", required_argument, NULL, 'w' },
|
||||||
|
{ "height", required_argument, NULL, 'h' },
|
||||||
|
{ "shader", required_argument, NULL, 's' },
|
||||||
|
{ NULL, 0, NULL, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *short_opts = "w:h:s:";
|
||||||
|
|
||||||
|
static const char *usage_str =
|
||||||
|
"shadermeh OPTIONS...\n"
|
||||||
|
"\n"
|
||||||
|
"Possible options:\n"
|
||||||
|
"\n"
|
||||||
|
" --width, -w <pixels>\n"
|
||||||
|
" --height, -h <pixels>\n"
|
||||||
|
"\n"
|
||||||
|
" --shader, -s <shader file>\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
GLuint u_iResolution, u_iTime, u_iTimeDelta, u_iFrame;
|
||||||
|
struct timespec start, frame_start, frame_end;
|
||||||
|
unsigned int width, height, iFrame = 0;
|
||||||
|
const char *shader_file = NULL;
|
||||||
|
GLint major, minor, prog;
|
||||||
|
float iTime, iTimeDelta;
|
||||||
|
GLuint vao, vbo;
|
||||||
|
window *wnd;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/******************** parse options ************************/
|
||||||
|
width = 800;
|
||||||
|
height = 450;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
i = getopt_long(argc, argv, short_opts, long_opts, NULL);
|
||||||
|
if (i == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 'w':
|
||||||
|
width = strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
height = strtol(optarg, NULL, 10);
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
shader_file = optarg;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fputs(usage_str, stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shader_file) {
|
||||||
|
fputs(usage_str, stderr);
|
||||||
|
fputs("No shader file specified!\n", stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********** create window and make context current **********/
|
||||||
|
wnd = window_create(width, height, "shader meh...");
|
||||||
|
|
||||||
|
if (!wnd) {
|
||||||
|
fputs("failed to create window", stderr);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_make_current(wnd);
|
||||||
|
window_set_vsync(wnd, 1);
|
||||||
|
|
||||||
|
/******************** load entry points ********************/
|
||||||
|
glewExperimental = GL_TRUE;
|
||||||
|
|
||||||
|
if (glewInit() != GLEW_OK) {
|
||||||
|
fputs("glewInit() error", stderr);
|
||||||
|
window_destroy(wnd);
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetIntegerv(GL_MAJOR_VERSION, &major);
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, &minor);
|
||||||
|
printf("OpenGL version %d.%d\n", major, minor);
|
||||||
|
|
||||||
|
/******************** initialization ********************/
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
/* vertex buffer object & vertex array object */
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &vbo);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_buffer),
|
||||||
|
vertex_buffer, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, 0);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6,
|
||||||
|
(GLvoid *)(3 * sizeof(GLfloat)));
|
||||||
|
|
||||||
|
/* shader */
|
||||||
|
prog = shader_program_load(shader_file);
|
||||||
|
|
||||||
|
if (!shader_program_get_build_status(prog)) {
|
||||||
|
shader_program_print_info_log(prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(prog);
|
||||||
|
|
||||||
|
/* uniforms */
|
||||||
|
u_iResolution = glGetUniformLocation(prog, "iResolution");
|
||||||
|
u_iTime = glGetUniformLocation(prog, "iTime");
|
||||||
|
u_iTimeDelta = glGetUniformLocation(prog, "iTimeDelta");
|
||||||
|
u_iFrame = glGetUniformLocation(prog, "iFrame;");
|
||||||
|
|
||||||
|
glUniform3f(u_iResolution, width, height, 0.0f);
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_RAW, &start);
|
||||||
|
|
||||||
|
/******************** drawing loop ********************/
|
||||||
|
while (window_handle_events()) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_RAW, &frame_start);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
window_swap_buffers(wnd);
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_RAW, &frame_end);
|
||||||
|
|
||||||
|
iFrame += 1;
|
||||||
|
iTimeDelta = diff_timespec(&frame_end, &frame_start);
|
||||||
|
iTime = diff_timespec(&frame_end, &start);
|
||||||
|
|
||||||
|
glUniform1f(u_iTimeDelta, iTimeDelta);
|
||||||
|
glUniform1f(u_iTime, iTime);
|
||||||
|
glUniform1ui(u_iFrame, iFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************** cleanup ********************/
|
||||||
|
glUseProgram(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glDeleteBuffers(1, &vbo);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glDeleteVertexArrays(1, &vao);
|
||||||
|
glDeleteProgram(prog);
|
||||||
|
|
||||||
|
window_make_current(NULL);
|
||||||
|
window_destroy(wnd);
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
45
shadermeh.h
Normal file
45
shadermeh.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#ifndef SHADERMEH_H
|
||||||
|
#define SHADERMEH_H
|
||||||
|
|
||||||
|
#include <X11/X.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/Xutil.h>
|
||||||
|
#include <X11/Xresource.h>
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
#include <GL/glx.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Window wnd;
|
||||||
|
GLXContext gl;
|
||||||
|
} window;
|
||||||
|
|
||||||
|
window *window_create(unsigned int width, unsigned int height,
|
||||||
|
const char *caption);
|
||||||
|
|
||||||
|
void window_make_current(window *wnd);
|
||||||
|
|
||||||
|
void window_swap_buffers(window *wnd);
|
||||||
|
|
||||||
|
void window_set_vsync(window *wnd, int enable);
|
||||||
|
|
||||||
|
void window_destroy(window *wnd);
|
||||||
|
|
||||||
|
int window_handle_events(void);
|
||||||
|
|
||||||
|
|
||||||
|
GLuint shader_program_load(const char *fsh);
|
||||||
|
|
||||||
|
int shader_program_get_build_status(GLuint prog);
|
||||||
|
|
||||||
|
void shader_program_print_info_log(GLuint prog);
|
||||||
|
|
||||||
|
#endif /* SHADERMEH_H */
|
158
shaders/cyber.frag
Normal file
158
shaders/cyber.frag
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
|
||||||
|
float sun(vec2 uv, float battery)
|
||||||
|
{
|
||||||
|
float val = smoothstep(0.3, 0.29, length(uv));
|
||||||
|
float bloom = smoothstep(0.7, 0.0, length(uv));
|
||||||
|
float cut = 3.0 * sin((uv.y + iTime * 0.2 * (battery + 0.02)) * 100.0)
|
||||||
|
+ clamp(uv.y * 14.0 + 1.0, -6.0, 6.0);
|
||||||
|
cut = clamp(cut, 0.0, 1.0);
|
||||||
|
return clamp(val * cut, 0.0, 1.0) + bloom * 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
float grid(vec2 uv, float battery)
|
||||||
|
{
|
||||||
|
vec2 size = vec2(uv.y, uv.y * uv.y * 0.2) * 0.01;
|
||||||
|
uv += vec2(0.0, iTime * 4.0 * (battery + 0.05));
|
||||||
|
uv = abs(fract(uv) - 0.5);
|
||||||
|
vec2 lines = smoothstep(size, vec2(0.0), uv);
|
||||||
|
lines += smoothstep(size * 5.0, vec2(0.0), uv) * 0.4 * battery;
|
||||||
|
return clamp(lines.x + lines.y, 0.0, 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float dot2(in vec2 v ) { return dot(v,v); }
|
||||||
|
|
||||||
|
float sdTrapezoid( in vec2 p, in float r1, float r2, float he )
|
||||||
|
{
|
||||||
|
vec2 k1 = vec2(r2,he);
|
||||||
|
vec2 k2 = vec2(r2-r1,2.0*he);
|
||||||
|
p.x = abs(p.x);
|
||||||
|
vec2 ca = vec2(p.x-min(p.x,(p.y<0.0)?r1:r2), abs(p.y)-he);
|
||||||
|
vec2 cb = p - k1 + k2*clamp( dot(k1-p,k2)/dot2(k2), 0.0, 1.0 );
|
||||||
|
float s = (cb.x<0.0 && ca.y<0.0) ? -1.0 : 1.0;
|
||||||
|
return s*sqrt( min(dot2(ca),dot2(cb)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdLine( in vec2 p, in vec2 a, in vec2 b )
|
||||||
|
{
|
||||||
|
vec2 pa = p-a, ba = b-a;
|
||||||
|
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
|
||||||
|
return length( pa - ba*h );
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdBox( in vec2 p, in vec2 b )
|
||||||
|
{
|
||||||
|
vec2 d = abs(p)-b;
|
||||||
|
return length(max(d,vec2(0))) + min(max(d.x,d.y),0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float opSmoothUnion(float d1, float d2, float k){
|
||||||
|
float h = clamp(0.5 + 0.5 * (d2 - d1) /k,0.0,1.0);
|
||||||
|
return mix(d2, d1 , h) - k * h * ( 1.0 - h);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdCloud(in vec2 p, in vec2 a1, in vec2 b1, in vec2 a2, in vec2 b2, float w)
|
||||||
|
{
|
||||||
|
//float lineVal1 = smoothstep(w - 0.0001, w, sdLine(p, a1, b1));
|
||||||
|
float lineVal1 = sdLine(p, a1, b1);
|
||||||
|
float lineVal2 = sdLine(p, a2, b2);
|
||||||
|
vec2 ww = vec2(w*1.5, 0.0);
|
||||||
|
vec2 left = max(a1 + ww, a2 + ww);
|
||||||
|
vec2 right = min(b1 - ww, b2 - ww);
|
||||||
|
vec2 boxCenter = (left + right) * 0.5;
|
||||||
|
//float boxW = right.x - left.x;
|
||||||
|
float boxH = abs(a2.y - a1.y) * 0.5;
|
||||||
|
//float boxVal = sdBox(p - boxCenter, vec2(boxW, boxH)) + w;
|
||||||
|
float boxVal = sdBox(p - boxCenter, vec2(0.04, boxH)) + w;
|
||||||
|
|
||||||
|
float uniVal1 = opSmoothUnion(lineVal1, boxVal, 0.05);
|
||||||
|
float uniVal2 = opSmoothUnion(lineVal2, boxVal, 0.05);
|
||||||
|
|
||||||
|
return min(uniVal1, uniVal2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 uv = (2.0 * fragCoord.xy - iResolution.xy)/iResolution.y;
|
||||||
|
float battery = 1.0;
|
||||||
|
//if (iMouse.x > 1.0 && iMouse.y > 1.0) battery = iMouse.y / iResolution.y;
|
||||||
|
//else battery = 0.8;
|
||||||
|
|
||||||
|
//if (abs(uv.x) < (9.0 / 16.0))
|
||||||
|
{
|
||||||
|
// Grid
|
||||||
|
float fog = smoothstep(0.1, -0.02, abs(uv.y + 0.2));
|
||||||
|
vec3 col = vec3(0.0, 0.1, 0.2);
|
||||||
|
if (uv.y < -0.2)
|
||||||
|
{
|
||||||
|
uv.y = 3.0 / (abs(uv.y + 0.2) + 0.05);
|
||||||
|
uv.x *= uv.y * 1.0;
|
||||||
|
float gridVal = grid(uv, battery);
|
||||||
|
col = mix(col, vec3(1.0, 0.5, 1.0), gridVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float fujiD = min(uv.y * 4.5 - 0.5, 1.0);
|
||||||
|
uv.y -= battery * 1.1 - 0.51;
|
||||||
|
|
||||||
|
vec2 sunUV = uv;
|
||||||
|
vec2 fujiUV = uv;
|
||||||
|
|
||||||
|
// Sun
|
||||||
|
sunUV += vec2(0.75, 0.2);
|
||||||
|
//uv.y -= 1.1 - 0.51;
|
||||||
|
col = vec3(1.0, 0.2, 1.0);
|
||||||
|
float sunVal = sun(sunUV, battery);
|
||||||
|
|
||||||
|
col = mix(col, vec3(1.0, 0.4, 0.1), sunUV.y * 2.0 + 0.2);
|
||||||
|
col = mix(vec3(0.0, 0.0, 0.0), col, sunVal);
|
||||||
|
|
||||||
|
// fuji
|
||||||
|
float fujiVal = sdTrapezoid( uv + vec2(-0.75+sunUV.y * 0.0, 0.5), 1.75 + pow(uv.y * uv.y, 2.1), 0.2, 0.5);
|
||||||
|
float waveVal = uv.y + sin(uv.x * 20.0 + iTime * 2.0) * 0.05 + 0.2;
|
||||||
|
float wave_width = smoothstep(0.0,0.01,(waveVal));
|
||||||
|
|
||||||
|
// fuji color
|
||||||
|
col = mix( col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), fujiD), step(fujiVal, 0.0));
|
||||||
|
// fuji top snow
|
||||||
|
col = mix( col, vec3(1.0, 0.5, 1.0), wave_width * step(fujiVal, 0.0));
|
||||||
|
// fuji outline
|
||||||
|
col = mix( col, vec3(1.0, 0.5, 1.0), 1.0-smoothstep(0.0,0.01,abs(fujiVal)) );
|
||||||
|
//col = mix( col, vec3(1.0, 1.0, 1.0), 1.0-smoothstep(0.03,0.04,abs(fujiVal)) );
|
||||||
|
//col = vec3(1.0, 1.0, 1.0) *(1.0-smoothstep(0.03,0.04,abs(fujiVal)));
|
||||||
|
|
||||||
|
// horizon color
|
||||||
|
col += mix( col, mix(vec3(1.0, 0.12, 0.8), vec3(0.0, 0.0, 0.2), clamp(uv.y * 3.5 + 3.0, 0.0, 1.0)), step(0.0, fujiVal) );
|
||||||
|
|
||||||
|
// cloud
|
||||||
|
vec2 cloudUV = uv;
|
||||||
|
cloudUV.x = mod(cloudUV.x + iTime * 0.1, 4.0) - 2.0;
|
||||||
|
float cloudTime = iTime * 0.5;
|
||||||
|
float cloudY = -0.5;
|
||||||
|
float cloudVal1 = sdCloud(cloudUV,
|
||||||
|
vec2(0.1 + sin(cloudTime + 140.5)*0.1,cloudY),
|
||||||
|
vec2(1.05 + cos(cloudTime * 0.9 - 36.56) * 0.1, cloudY),
|
||||||
|
vec2(0.2 + cos(cloudTime * 0.867 + 387.165) * 0.1,0.25+cloudY),
|
||||||
|
vec2(0.5 + cos(cloudTime * 0.9675 - 15.162) * 0.09, 0.25+cloudY), 0.075);
|
||||||
|
cloudY = -0.6;
|
||||||
|
float cloudVal2 = sdCloud(cloudUV,
|
||||||
|
vec2(-0.9 + cos(cloudTime * 1.02 + 541.75) * 0.1,cloudY),
|
||||||
|
vec2(-0.5 + sin(cloudTime * 0.9 - 316.56) * 0.1, cloudY),
|
||||||
|
vec2(-1.5 + cos(cloudTime * 0.867 + 37.165) * 0.1,0.25+cloudY),
|
||||||
|
vec2(-0.6 + sin(cloudTime * 0.9675 + 665.162) * 0.09, 0.25+cloudY), 0.075);
|
||||||
|
|
||||||
|
float cloudVal = min(cloudVal1, cloudVal2);
|
||||||
|
|
||||||
|
//col = mix(col, vec3(1.0,1.0,0.0), smoothstep(0.0751, 0.075, cloudVal));
|
||||||
|
col = mix(col, vec3(0.0, 0.0, 0.2), 1.0 - smoothstep(0.075 - 0.0001, 0.075, cloudVal));
|
||||||
|
col += vec3(1.0, 1.0, 1.0)*(1.0 - smoothstep(0.0,0.01,abs(cloudVal - 0.075)));
|
||||||
|
}
|
||||||
|
|
||||||
|
col += fog * fog * fog;
|
||||||
|
col = mix(vec3(col.r, col.r, col.r) * 0.5, col, battery * 0.7);
|
||||||
|
|
||||||
|
fragColor = vec4(col,1.0);
|
||||||
|
}
|
||||||
|
//else fragColor = vec4(0.0);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
66
shaders/fractal.frag
Normal file
66
shaders/fractal.frag
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
vec3 palette(float d){
|
||||||
|
return mix(vec3(0.2,0.7,0.9),vec3(1.,0.,1.),d);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 rotate(vec2 p,float a){
|
||||||
|
float c = cos(a);
|
||||||
|
float s = sin(a);
|
||||||
|
return p*mat2(c,s,-s,c);
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(vec3 p){
|
||||||
|
for( int i = 0; i<8; ++i){
|
||||||
|
float t = iTime*0.2;
|
||||||
|
p.xz =rotate(p.xz,t);
|
||||||
|
p.xy =rotate(p.xy,t*1.89);
|
||||||
|
p.xz = abs(p.xz);
|
||||||
|
p.xz-=.5;
|
||||||
|
}
|
||||||
|
return dot(sign(p),p)/5.;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 rm (vec3 ro, vec3 rd){
|
||||||
|
float t = 0.;
|
||||||
|
vec3 col = vec3(0.);
|
||||||
|
float d;
|
||||||
|
for(float i =0.; i<64.; i++){
|
||||||
|
vec3 p = ro + rd*t;
|
||||||
|
d = map(p)*.5;
|
||||||
|
if(d<0.02){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(d>100.){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//col+=vec3(0.6,0.8,0.8)/(400.*(d));
|
||||||
|
col+=palette(length(p)*.1)/(400.*(d));
|
||||||
|
t+=d;
|
||||||
|
}
|
||||||
|
return vec4(col,1./(d*100.));
|
||||||
|
}
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 uv = (fragCoord-(iResolution.xy/2.))/iResolution.x;
|
||||||
|
vec3 ro = vec3(0.,0.,-50.);
|
||||||
|
ro.xz = rotate(ro.xz,iTime);
|
||||||
|
vec3 cf = normalize(-ro);
|
||||||
|
vec3 cs = normalize(cross(cf,vec3(0.,1.,0.)));
|
||||||
|
vec3 cu = normalize(cross(cf,cs));
|
||||||
|
|
||||||
|
vec3 uuv = ro+cf*3. + uv.x*cs + uv.y*cu;
|
||||||
|
|
||||||
|
vec3 rd = normalize(uuv-ro);
|
||||||
|
|
||||||
|
vec4 col = rm(ro,rd);
|
||||||
|
|
||||||
|
|
||||||
|
fragColor = col;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** SHADERDATA
|
||||||
|
{
|
||||||
|
"title": "fractal pyramid",
|
||||||
|
"description": "",
|
||||||
|
"model": "car"
|
||||||
|
}
|
||||||
|
*/
|
26
shaders/mandelbrot.frag
Normal file
26
shaders/mandelbrot.frag
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#define MAX_ITERATIONS 1024
|
||||||
|
|
||||||
|
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||||
|
{
|
||||||
|
float s = exp(-iTime / 2.0);
|
||||||
|
vec2 c = vec2(-0.770007,0.100001);
|
||||||
|
vec2 z = vec2(0.0);
|
||||||
|
vec2 del = (2.0 * fragCoord/iResolution.xy - 1.0) * s;
|
||||||
|
del.x /= (iResolution.y / iResolution.x);
|
||||||
|
vec2 eps = vec2(0.0);
|
||||||
|
|
||||||
|
int iterations = 0;
|
||||||
|
while (length(z + eps) < 2.0 && iterations < MAX_ITERATIONS) {
|
||||||
|
eps = 2.0*vec2(z.x*eps.x - z.y*eps.y, z.x*eps.y + z.y*eps.x) + vec2(eps.x*eps.x - eps.y*eps.y, 2.0*eps.x*eps.y) + del;
|
||||||
|
z = vec2(z.x*z.x - z.y*z.y, 2.0*z.x*z.y) + c;
|
||||||
|
if (length(eps) > 100.0) {
|
||||||
|
z += eps;
|
||||||
|
eps = vec2(0.0);
|
||||||
|
}
|
||||||
|
iterations += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Output to screen
|
||||||
|
fragColor = vec4(vec3(float(iterations) / float(MAX_ITERATIONS)), 1.0);
|
||||||
|
}
|
204
shaders/seascape.frag
Normal file
204
shaders/seascape.frag
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
/*
|
||||||
|
* "Seascape" by Alexander Alekseev aka TDM - 2014
|
||||||
|
* License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
* Contact: tdmaav@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int NUM_STEPS = 8;
|
||||||
|
const float PI = 3.141592;
|
||||||
|
const float EPSILON = 1e-3;
|
||||||
|
#define EPSILON_NRM (0.1 / iResolution.x)
|
||||||
|
#define AA
|
||||||
|
|
||||||
|
// sea
|
||||||
|
const int ITER_GEOMETRY = 3;
|
||||||
|
const int ITER_FRAGMENT = 5;
|
||||||
|
const float SEA_HEIGHT = 0.6;
|
||||||
|
const float SEA_CHOPPY = 4.0;
|
||||||
|
const float SEA_SPEED = 0.8;
|
||||||
|
const float SEA_FREQ = 0.16;
|
||||||
|
const vec3 SEA_BASE = vec3(0.0,0.09,0.18);
|
||||||
|
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6)*0.6;
|
||||||
|
#define SEA_TIME (1.0 + iTime * SEA_SPEED)
|
||||||
|
const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
|
||||||
|
|
||||||
|
// math
|
||||||
|
mat3 fromEuler(vec3 ang) {
|
||||||
|
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
|
||||||
|
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
|
||||||
|
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
|
||||||
|
mat3 m;
|
||||||
|
m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
|
||||||
|
m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
|
||||||
|
m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
float hash( vec2 p ) {
|
||||||
|
float h = dot(p,vec2(127.1,311.7));
|
||||||
|
return fract(sin(h)*43758.5453123);
|
||||||
|
}
|
||||||
|
float noise( in vec2 p ) {
|
||||||
|
vec2 i = floor( p );
|
||||||
|
vec2 f = fract( p );
|
||||||
|
vec2 u = f*f*(3.0-2.0*f);
|
||||||
|
return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
|
||||||
|
hash( i + vec2(1.0,0.0) ), u.x),
|
||||||
|
mix( hash( i + vec2(0.0,1.0) ),
|
||||||
|
hash( i + vec2(1.0,1.0) ), u.x), u.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lighting
|
||||||
|
float diffuse(vec3 n,vec3 l,float p) {
|
||||||
|
return pow(dot(n,l) * 0.4 + 0.6,p);
|
||||||
|
}
|
||||||
|
float specular(vec3 n,vec3 l,vec3 e,float s) {
|
||||||
|
float nrm = (s + 8.0) / (PI * 8.0);
|
||||||
|
return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sky
|
||||||
|
vec3 getSkyColor(vec3 e) {
|
||||||
|
e.y = (max(e.y,0.0)*0.8+0.2)*0.8;
|
||||||
|
return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sea
|
||||||
|
float sea_octave(vec2 uv, float choppy) {
|
||||||
|
uv += noise(uv);
|
||||||
|
vec2 wv = 1.0-abs(sin(uv));
|
||||||
|
vec2 swv = abs(cos(uv));
|
||||||
|
wv = mix(wv,swv,wv);
|
||||||
|
return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(vec3 p) {
|
||||||
|
float freq = SEA_FREQ;
|
||||||
|
float amp = SEA_HEIGHT;
|
||||||
|
float choppy = SEA_CHOPPY;
|
||||||
|
vec2 uv = p.xz; uv.x *= 0.75;
|
||||||
|
|
||||||
|
float d, h = 0.0;
|
||||||
|
for(int i = 0; i < ITER_GEOMETRY; i++) {
|
||||||
|
d = sea_octave((uv+SEA_TIME)*freq,choppy);
|
||||||
|
d += sea_octave((uv-SEA_TIME)*freq,choppy);
|
||||||
|
h += d * amp;
|
||||||
|
uv *= octave_m; freq *= 1.9; amp *= 0.22;
|
||||||
|
choppy = mix(choppy,1.0,0.2);
|
||||||
|
}
|
||||||
|
return p.y - h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float map_detailed(vec3 p) {
|
||||||
|
float freq = SEA_FREQ;
|
||||||
|
float amp = SEA_HEIGHT;
|
||||||
|
float choppy = SEA_CHOPPY;
|
||||||
|
vec2 uv = p.xz; uv.x *= 0.75;
|
||||||
|
|
||||||
|
float d, h = 0.0;
|
||||||
|
for(int i = 0; i < ITER_FRAGMENT; i++) {
|
||||||
|
d = sea_octave((uv+SEA_TIME)*freq,choppy);
|
||||||
|
d += sea_octave((uv-SEA_TIME)*freq,choppy);
|
||||||
|
h += d * amp;
|
||||||
|
uv *= octave_m; freq *= 1.9; amp *= 0.22;
|
||||||
|
choppy = mix(choppy,1.0,0.2);
|
||||||
|
}
|
||||||
|
return p.y - h;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
|
||||||
|
float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
|
||||||
|
fresnel = pow(fresnel,3.0) * 0.5;
|
||||||
|
|
||||||
|
vec3 reflected = getSkyColor(reflect(eye,n));
|
||||||
|
vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
|
||||||
|
|
||||||
|
vec3 color = mix(refracted,reflected,fresnel);
|
||||||
|
|
||||||
|
float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
|
||||||
|
color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
|
||||||
|
|
||||||
|
color += vec3(specular(n,l,eye,60.0));
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracing
|
||||||
|
vec3 getNormal(vec3 p, float eps) {
|
||||||
|
vec3 n;
|
||||||
|
n.y = map_detailed(p);
|
||||||
|
n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
|
||||||
|
n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
|
||||||
|
n.y = eps;
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
|
||||||
|
float tm = 0.0;
|
||||||
|
float tx = 1000.0;
|
||||||
|
float hx = map(ori + dir * tx);
|
||||||
|
if(hx > 0.0) {
|
||||||
|
p = ori + dir * tx;
|
||||||
|
return tx;
|
||||||
|
}
|
||||||
|
float hm = map(ori + dir * tm);
|
||||||
|
float tmid = 0.0;
|
||||||
|
for(int i = 0; i < NUM_STEPS; i++) {
|
||||||
|
tmid = mix(tm,tx, hm/(hm-hx));
|
||||||
|
p = ori + dir * tmid;
|
||||||
|
float hmid = map(p);
|
||||||
|
if(hmid < 0.0) {
|
||||||
|
tx = tmid;
|
||||||
|
hx = hmid;
|
||||||
|
} else {
|
||||||
|
tm = tmid;
|
||||||
|
hm = hmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmid;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getPixel(in vec2 coord, float time) {
|
||||||
|
vec2 uv = coord / iResolution.xy;
|
||||||
|
uv = uv * 2.0 - 1.0;
|
||||||
|
uv.x *= iResolution.x / iResolution.y;
|
||||||
|
|
||||||
|
// ray
|
||||||
|
vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time);
|
||||||
|
vec3 ori = vec3(0.0,3.5,time*5.0);
|
||||||
|
vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.14;
|
||||||
|
dir = normalize(dir) * fromEuler(ang);
|
||||||
|
|
||||||
|
// tracing
|
||||||
|
vec3 p;
|
||||||
|
heightMapTracing(ori,dir,p);
|
||||||
|
vec3 dist = p - ori;
|
||||||
|
vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
|
||||||
|
vec3 light = normalize(vec3(0.0,1.0,0.8));
|
||||||
|
|
||||||
|
// color
|
||||||
|
return mix(
|
||||||
|
getSkyColor(dir),
|
||||||
|
getSeaColor(p,n,light,dir,dist),
|
||||||
|
pow(smoothstep(0.0,-0.02,dir.y),0.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
// main
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
float time = iTime * 0.3 + iMouse.x*0.01;
|
||||||
|
|
||||||
|
#ifdef AA
|
||||||
|
vec3 color = vec3(0.0);
|
||||||
|
for(int i = -1; i <= 1; i++) {
|
||||||
|
for(int j = -1; j <= 1; j++) {
|
||||||
|
vec2 uv = fragCoord+vec2(i,j)/3.0;
|
||||||
|
color += getPixel(uv, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
color /= 9.0;
|
||||||
|
#else
|
||||||
|
vec3 color = getPixel(fragCoord, time);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// post
|
||||||
|
fragColor = vec4(pow(color,vec3(0.65)), 1.0);
|
||||||
|
}
|
71
shaders/tiling.frag
Normal file
71
shaders/tiling.frag
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
#define sqrt25 0.6324555320 //sqrt(2./5.)
|
||||||
|
#define sqrt35 0.7745966692 //sqrt(3./5.)
|
||||||
|
|
||||||
|
//edge distance of a Cube
|
||||||
|
float cubeDist(vec3 uvw) {
|
||||||
|
vec3 d = abs(uvw); //mirroring along axis
|
||||||
|
return min(d.x, min(d.y, d.z))*2.; //*2. for 0-1 range
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cube Tiling
|
||||||
|
vec4 cubeTile(vec3 uvw) {
|
||||||
|
vec3 grid = fract(uvw)-.5; // centered UVW coords
|
||||||
|
float edist = cubeDist(grid); // edge distance
|
||||||
|
//float cdist = dot(grid,grid); //squared center distance
|
||||||
|
//vec3 id = uvw-grid; // Cells IDs
|
||||||
|
|
||||||
|
return vec4(grid, edist);
|
||||||
|
}
|
||||||
|
|
||||||
|
// scaled with offset cube tiling
|
||||||
|
vec4 cubeCell(vec3 uvw, vec3 offset, float gridRes) {
|
||||||
|
vec4 cubeTiling = cubeTile(uvw*gridRes + offset);
|
||||||
|
vec3 tiledUV = (cubeTiling.xyz - offset)/gridRes; //cube pixaltion
|
||||||
|
|
||||||
|
return vec4(tiledUV,cubeTiling.w);
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotates a vetor from SirBelfer4 (https://www.shadertoy.com/view/ssc3z4)
|
||||||
|
vec3 rotate(vec3 v, vec3 a)
|
||||||
|
{
|
||||||
|
// https://math.stackexchange.com/questions/2975109/how-to-convert-euler-angles-to-quaternions-and-get-the-same-euler-angles-back-fr
|
||||||
|
vec4 q;
|
||||||
|
vec3 c = cos(a * 0.5), s = sin(a * 0.5);
|
||||||
|
q.x = s.x * c.y * c.z - c.x * s.y * s.z;
|
||||||
|
q.y = c.x * s.y * c.z + s.x * c.y * s.z;
|
||||||
|
q.z = c.x * c.y * s.z - s.x * s.y * c.z;
|
||||||
|
q.w = c.x * c.y * c.z + s.x * s.y * s.z;
|
||||||
|
|
||||||
|
// https://blog.molecular-matters.com/2013/05/24/a-faster-quaternion-vector-multiplication/
|
||||||
|
vec3 qt = 2.0 * cross(q.xyz, v);
|
||||||
|
return v + q.w * qt + cross(q.xyz, qt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// makes RdYlBu_r colormap with polynimal 6 https://www.shadertoy.com/view/Nd3fR2
|
||||||
|
vec3 RdYlBu_r(float t) {
|
||||||
|
const vec3 c0 = vec3(0.207621,0.196195,0.618832);
|
||||||
|
const vec3 c1 = vec3(-0.088125,3.196170,-0.353302);
|
||||||
|
const vec3 c2 = vec3(8.261232,-8.366855,14.368787);
|
||||||
|
const vec3 c3 = vec3(-2.922476,33.244294,-43.419173);
|
||||||
|
const vec3 c4 = vec3(-34.085327,-74.476041,37.159352);
|
||||||
|
const vec3 c5 = vec3(50.429790,67.145621,-1.750169);
|
||||||
|
const vec3 c6 = vec3(-21.188828,-20.935464,-6.501427);
|
||||||
|
return c0+t*(c1+t*(c2+t*(c3+t*(c4+t*(c5+t*c6)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 uv = fragCoord/iResolution.y; //square UV pattern
|
||||||
|
float time = (0.05*iTime); // used as z dimension
|
||||||
|
float gridRes = 2.5; //size of cubes
|
||||||
|
|
||||||
|
vec3 point = vec3(uv, time); //uvw cords
|
||||||
|
|
||||||
|
//cosmetic rotate for fun triangles otherwise it looks so square
|
||||||
|
point = rotate(point, (vec3(sqrt25,sqrt35,0.))); //vec3 must be normalized
|
||||||
|
|
||||||
|
vec4 a = cubeCell(point, vec3(0.), gridRes);
|
||||||
|
|
||||||
|
vec3 col = RdYlBu_r(a.w); // cosmetic Colormap
|
||||||
|
|
||||||
|
fragColor = vec4(col, 1.);
|
||||||
|
}
|
237
window.c
Normal file
237
window.c
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#include "shadermeh.h"
|
||||||
|
|
||||||
|
#ifndef GLX_ARB_create_context
|
||||||
|
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
|
||||||
|
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
|
||||||
|
#define GLX_CONTEXT_FLAGS_ARB 0x2094
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef GLX_ARB_create_context_profile
|
||||||
|
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
|
||||||
|
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||||
|
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef GLXContext (*CREATECONTEXTATTRIBSPROC)(Display *, GLXFBConfig,
|
||||||
|
GLXContext, Bool,
|
||||||
|
const int *);
|
||||||
|
|
||||||
|
typedef void (*SWAPINTERVALEXTPROC)(Display *, GLXDrawable, int);
|
||||||
|
|
||||||
|
static int glversions[][2] = { {4,5}, {4,4}, {4,3}, {4,2}, {4,1}, {4,0},
|
||||||
|
{3,3}, {3,2}, {3,1}, {3,0} };
|
||||||
|
|
||||||
|
static Display *dpy;
|
||||||
|
static int dpy_ref = 0;
|
||||||
|
static Atom atom_wm_delete;
|
||||||
|
static XContext xctx;
|
||||||
|
|
||||||
|
static int xlib_swallow_errors(Display *display, XErrorEvent *event)
|
||||||
|
{
|
||||||
|
(void)display; (void)event;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
|
||||||
|
window *window_create(unsigned int width, unsigned int height,
|
||||||
|
const char *caption)
|
||||||
|
{
|
||||||
|
CREATECONTEXTATTRIBSPROC CreateContextAttribs;
|
||||||
|
XSetWindowAttributes swa;
|
||||||
|
int fbcount, attr[20];
|
||||||
|
GLXFBConfig fbc, *fbl;
|
||||||
|
unsigned int i = 0;
|
||||||
|
XSizeHints hints;
|
||||||
|
XVisualInfo *vi;
|
||||||
|
window *this;
|
||||||
|
|
||||||
|
this = calloc(1, sizeof(*this));
|
||||||
|
if (!this)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (dpy) {
|
||||||
|
++dpy_ref;
|
||||||
|
} else {
|
||||||
|
dpy = XOpenDisplay(0);
|
||||||
|
dpy_ref = 1;
|
||||||
|
|
||||||
|
if (!dpy) {
|
||||||
|
free(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
XSetErrorHandler(xlib_swallow_errors);
|
||||||
|
atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
|
||||||
|
|
||||||
|
xctx = XUniqueContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
attr[ 0] = GLX_BUFFER_SIZE; attr[ 1] = 32;
|
||||||
|
attr[ 2] = GLX_RED_SIZE; attr[ 3] = 8;
|
||||||
|
attr[ 4] = GLX_GREEN_SIZE; attr[ 5] = 8;
|
||||||
|
attr[ 6] = GLX_BLUE_SIZE; attr[ 7] = 8;
|
||||||
|
attr[ 8] = GLX_ALPHA_SIZE; attr[ 9] = 8;
|
||||||
|
attr[10] = GLX_DEPTH_SIZE; attr[11] = 24;
|
||||||
|
attr[12] = GLX_STENCIL_SIZE; attr[13] = 8;
|
||||||
|
attr[14] = GLX_DOUBLEBUFFER; attr[15] = True;
|
||||||
|
attr[16] = None;
|
||||||
|
|
||||||
|
fbl = glXChooseFBConfig(dpy, DefaultScreen(dpy), attr, &fbcount);
|
||||||
|
|
||||||
|
if (!fbl || !fbcount) {
|
||||||
|
window_destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
fbc = fbl[0];
|
||||||
|
vi = glXGetVisualFromFBConfig(dpy, fbl[0]);
|
||||||
|
XFree(fbl);
|
||||||
|
|
||||||
|
if (!vi) {
|
||||||
|
window_destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
swa.colormap = XCreateColormap(dpy, RootWindow(dpy,vi->screen),
|
||||||
|
vi->visual, AllocNone);
|
||||||
|
|
||||||
|
if (!swa.colormap) {
|
||||||
|
XFree(vi);
|
||||||
|
window_destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
swa.border_pixel = 0;
|
||||||
|
|
||||||
|
this->wnd = XCreateWindow(dpy, RootWindow(dpy,vi->screen), 0, 0,
|
||||||
|
width, height, 0, vi->depth, InputOutput,
|
||||||
|
vi->visual, CWBorderPixel|CWColormap, &swa);
|
||||||
|
XFree(vi);
|
||||||
|
|
||||||
|
if (!this->wnd) {
|
||||||
|
window_destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateContextAttribs = (CREATECONTEXTATTRIBSPROC)
|
||||||
|
glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
|
||||||
|
|
||||||
|
if (CreateContextAttribs) {
|
||||||
|
attr[0] = GLX_CONTEXT_MAJOR_VERSION_ARB;
|
||||||
|
attr[1] = 0;
|
||||||
|
attr[2] = GLX_CONTEXT_MINOR_VERSION_ARB;
|
||||||
|
attr[3] = 0;
|
||||||
|
attr[4] = GLX_CONTEXT_PROFILE_MASK_ARB;
|
||||||
|
attr[5] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
attr[6] = GLX_CONTEXT_FLAGS_ARB;
|
||||||
|
attr[7] = GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
|
||||||
|
attr[8] = None;
|
||||||
|
|
||||||
|
for (i = 0; !this->gl && i < sizeof(glversions) /
|
||||||
|
sizeof(glversions[0]); ++i) {
|
||||||
|
attr[1] = glversions[i][0];
|
||||||
|
attr[3] = glversions[i][1];
|
||||||
|
|
||||||
|
this->gl = CreateContextAttribs(dpy, fbc, 0,
|
||||||
|
True, attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->gl) {
|
||||||
|
this->gl = glXCreateNewContext(dpy, fbc, GLX_RGBA_TYPE,
|
||||||
|
0, GL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->gl) {
|
||||||
|
window_destroy(this);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
hints.flags = PSize | PMinSize | PMaxSize;
|
||||||
|
hints.min_width = hints.max_width = hints.base_width = width;
|
||||||
|
hints.min_height = hints.max_height = hints.base_height = height;
|
||||||
|
|
||||||
|
XSetWMNormalHints(dpy, this->wnd, &hints);
|
||||||
|
|
||||||
|
XSelectInput(dpy, this->wnd, StructureNotifyMask |
|
||||||
|
KeyPressMask | KeyReleaseMask |
|
||||||
|
PointerMotionMask | PropertyChangeMask |
|
||||||
|
ButtonPressMask | ButtonReleaseMask);
|
||||||
|
XSetWMProtocols(dpy, this->wnd, &atom_wm_delete, 1);
|
||||||
|
XFlush(dpy);
|
||||||
|
|
||||||
|
XStoreName(dpy, this->wnd, caption);
|
||||||
|
XMapWindow(dpy, this->wnd);
|
||||||
|
XSaveContext(dpy, this->wnd, xctx, (XPointer)this);
|
||||||
|
XFlush(dpy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_make_current(window *this)
|
||||||
|
{
|
||||||
|
if (this) {
|
||||||
|
glXMakeContextCurrent(dpy, this->wnd, this->wnd, this->gl);
|
||||||
|
} else {
|
||||||
|
glXMakeContextCurrent(dpy, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_swap_buffers(window *this)
|
||||||
|
{
|
||||||
|
glXSwapBuffers(dpy, this->wnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_set_vsync(window *this, int enable)
|
||||||
|
{
|
||||||
|
SWAPINTERVALEXTPROC SwapIntervalEXT;
|
||||||
|
|
||||||
|
SwapIntervalEXT = (SWAPINTERVALEXTPROC)
|
||||||
|
glXGetProcAddress((const GLubyte *)"glXSwapIntervalEXT");
|
||||||
|
|
||||||
|
if (SwapIntervalEXT)
|
||||||
|
SwapIntervalEXT(dpy, this->wnd, enable ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window_destroy(window *this)
|
||||||
|
{
|
||||||
|
if (this->gl) {
|
||||||
|
glXMakeContextCurrent(dpy, 0, 0, 0);
|
||||||
|
glXDestroyContext(dpy, this->gl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->wnd) {
|
||||||
|
XDeleteContext(dpy, this->wnd, xctx);
|
||||||
|
XDestroyWindow(dpy, this->wnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((--dpy_ref) <= 0) {
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
dpy_ref = 0;
|
||||||
|
dpy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int window_handle_events(void)
|
||||||
|
{
|
||||||
|
window *this;
|
||||||
|
XEvent e;
|
||||||
|
|
||||||
|
if (XPending(dpy)) {
|
||||||
|
XNextEvent(dpy, &e);
|
||||||
|
XFindContext(dpy, e.xany.window, xctx, (XPointer *)&this);
|
||||||
|
|
||||||
|
switch (e.type) {
|
||||||
|
case ClientMessage:
|
||||||
|
if (e.xclient.data.l[0] == (long)atom_wm_delete) {
|
||||||
|
XUnmapWindow(dpy, e.xany.window);
|
||||||
|
--dpy_ref;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (dpy_ref > 0);
|
||||||
|
}
|
Loading…
Reference in a new issue