sdfps/sdfps.c

254 lines
7.6 KiB
C
Raw Normal View History

2022-03-21 17:58:17 +00:00
// sdfps.c
#include <SDL2/SDL.h>
#include <glad/glad.h>
2022-03-21 21:56:24 +00:00
#include <stdio.h>
2022-03-21 17:58:17 +00:00
#include "types.h"
GLuint create_shader(GLenum shader_type, const char *src) {
GLuint s = glCreateShader(shader_type);
glShaderSource(s, 1, &src, NULL);
glCompileShader(s);
GLint s_compiled;
glGetShaderiv(s, GL_COMPILE_STATUS, &s_compiled);
if (s_compiled != GL_TRUE) {
GLsizei log_length = 0;
GLchar msg[1024] = { 0 };
glGetShaderInfoLog(s, sizeof(msg), &log_length, msg);
puts(msg);
}
return s;
}
void init(Sdfps* s) { /* TODO: Error checks */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
/* these 2 are required on macos [https://www.glfw.org/faq.html#41---how-do-i-create-an-opengl-30-context] */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
s -> window = SDL_CreateWindow("sdfps",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
2022-04-05 14:49:46 +00:00
512 + 128, 512 + 128,
2022-03-21 17:58:17 +00:00
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
s -> context = SDL_GL_CreateContext(s -> window);
SDL_GL_MakeCurrent(s -> window, s -> context);
SDL_GL_SetSwapInterval(1);
if (!gladLoadGLES2Loader(SDL_GL_GetProcAddress)) printf("FUCK, gl loading failed\n");
puts(glGetString(GL_VERSION));
s -> vert_shader = create_shader(GL_VERTEX_SHADER,
"#version 330\n"
"in vec4 a_pos;\n"
"void main() {\n"
"gl_Position = a_pos;\n"
"}\n");
s -> frag_shader = create_shader(GL_FRAGMENT_SHADER,
"#version 330\n"
"precision highp float;\n"
2022-03-21 21:56:24 +00:00
2022-04-05 14:49:46 +00:00
/* ~ from shader toy ~
uniform float iTimeDelta; // render time (in seconds)
uniform int iFrame; // shader playback frame
uniform float iChannelTime[4]; // channel playback time (in seconds)
uniform vec3 iChannelResolution[4]; // channel resolution (in pixels)
uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click
uniform samplerXX iChannel0..3; // input channel. XX = 2D/Cube
uniform vec4 iDate; // (year, month, day, time in seconds)
uniform float iSampleRate; // sound sample rate (i.e., 44100)
*/
2022-03-21 21:56:24 +00:00
/* viewport resolution (in pixels), z = 1 */
"uniform vec3 iResolution;\n"
2022-03-21 22:01:49 +00:00
/* playback time in seconds */
"uniform float iTime;\n"
2022-03-21 21:56:24 +00:00
2022-03-21 17:58:17 +00:00
"out vec4 out_color;\n"
"void main() {\n"
2022-03-21 22:01:49 +00:00
"vec2 xy = gl_FragCoord.xy + vec2(sin(iTime), cos(iTime));\n"
2022-03-21 21:56:24 +00:00
"out_color = vec4(sin(xy.x), sin(xy.y), sin(xy.x) + sin(xy.y), 1);\n"
"if(xy.x > iResolution.x / 2.0) out_color = out_color.zxyw;\n"
2022-03-21 17:58:17 +00:00
"}\n");
s -> shader_program = glCreateProgram();
glAttachShader(s -> shader_program, s -> vert_shader);
glAttachShader(s -> shader_program, s -> frag_shader);
glLinkProgram(s -> shader_program);
GLint program_linked;
glGetProgramiv(s -> shader_program, GL_LINK_STATUS, &program_linked);
if (program_linked != GL_TRUE) {
GLsizei log_length = 0;
GLchar msg[1024];
glGetProgramInfoLog(s -> shader_program, sizeof(msg), &log_length, msg);
puts(msg);
}
}
void deinit(Sdfps *s) {
2022-03-21 21:56:24 +00:00
glDeleteProgram(s -> shader_program);
glDeleteShader(s -> vert_shader);
glDeleteShader(s -> frag_shader);
2022-03-21 17:58:17 +00:00
SDL_GL_DeleteContext(s -> context);
SDL_DestroyWindow(s -> window);
}
2022-03-21 21:56:24 +00:00
s32 create_framebuffer(s32 w, s32 h, GLuint *texture, GLuint *framebuffer) {
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, *texture);
2022-03-21 17:58:17 +00:00
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(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);
2022-03-21 21:56:24 +00:00
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, *framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture, 0);
2022-03-21 17:58:17 +00:00
GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
2022-03-21 21:56:24 +00:00
if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
2022-03-21 17:58:17 +00:00
puts("FRAME BUFFER FUCKED UP SOMEWHERE");
2022-03-21 21:56:24 +00:00
return 1;
}
return 0;
}
2022-03-21 17:58:17 +00:00
2022-03-21 21:56:24 +00:00
void render(Sdfps *s) {
// setup render texture
const s32 fb_w = 4, fb_h = 4;
GLuint render_tex, framebuf;
create_framebuffer(fb_w, fb_h, &render_tex, &framebuf);
glViewport(0, 0, fb_w, fb_h);
2022-03-21 17:58:17 +00:00
2022-03-21 21:56:24 +00:00
GLuint iResolution = glGetUniformLocation(s -> shader_program, "iResolution");
// TODO: error check?
glUniform3f(iResolution, (f32) fb_w, (f32) fb_h, 1.0f);
2022-03-21 22:01:49 +00:00
glUniform1f(glGetUniformLocation(s -> shader_program, "iTime"), 0.001f * (f32) SDL_GetTicks());
2022-03-21 17:58:17 +00:00
glClearColor(0.1f, 0.25f, 0.24f, 1);
glClear(GL_COLOR_BUFFER_BIT);
GLint pos_attr_loc = glGetAttribLocation(s -> shader_program, "a_pos");
GLuint vertex_buffer;
glGenBuffers(1, &vertex_buffer);
GLfloat data[] = {
-1, 1,
4, 1,
-1, -4,
};
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
GLuint vert_array;
glGenVertexArrays(1, &vert_array);
glBindVertexArray(vert_array);
glEnableVertexAttribArray(pos_attr_loc);
glVertexAttribPointer(
pos_attr_loc,
2, // components per iteration, 2 = vec2
GL_FLOAT, // data type of each component
GL_FALSE, // data should/shouldnt be normalized
0, // stride, e.g. space between components (in bytes)
0 // pointer/start, 0 is gur location of gur first position
);
glUseProgram(s -> shader_program);
glBindVertexArray(vert_array);
glDrawArrays(GL_TRIANGLES,
0, // first in array
3 // count
);
#if 1
2022-03-21 21:56:24 +00:00
/*
just here to check that it works, since it can be used as an easy way to
get data back out of a shader, there's probs a more proper way to do it
that we could change to later
UPDATE: looking at shader toy's source it seems it uses this function to
2022-04-05 14:49:46 +00:00
get output for sound shaders, so i'm going to guess that it'd be fine of
us to render gur sdf feedback into a lower segment of gur frame buffer
2022-03-21 21:56:24 +00:00
*/
2022-03-21 17:58:17 +00:00
f32 pixels[16 * 16 * 4] = { 0.0f };
glReadPixels(
10, // x pixel starting bottom left,
10, // y pixel
16, // width in pixels, 1 = reading a single pixel
16, // height
GL_RGBA, // format, can also be GL_RGBA_INTEGER
GL_FLOAT, // type
pixels // data
);
#endif
// show it
glBindFramebuffer(GL_FRAMEBUFFER, 0); // not technically needed
s32 win_w, win_h;
SDL_GL_GetDrawableSize(s -> window, &win_w, &win_h);
glViewport(0, 0, win_w, win_h); // not technically needed
// copy framebuf to window?
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuf);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, fb_w, fb_h, 0, 0, win_w, win_h, GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, GL_NEAREST);
// deletes
glDeleteBuffers(1, &vertex_buffer);
glDeleteVertexArrays(1, &vert_array);
glDeleteFramebuffers(1, &framebuf);
glDeleteTextures(1, &render_tex);
SDL_GL_SwapWindow(s -> window);
}
/*
* so entry point, return non zero to quit program
* return 0 to reload so
*/
int sdfps_main(int argc, char **argv, Sdfps **u_data) {
/* TODO: actually copy gur data over from gur kv store */
if (*u_data == NULL) {
*u_data = malloc(1024);
init(*u_data);
}
if (!gladLoadGLES2Loader(SDL_GL_GetProcAddress)) printf("FUCK, gl loading failed\n");
Sdfps *sdfps = *u_data;
while (1) {
SDL_Event e;
while (SDL_PollEvent(&e))
if (e.type == SDL_QUIT)
goto quit;
render(sdfps);
SDL_Delay(1);
if (!remove("reload-trigger")) {
// do some cleanup before reloading,
// pause your audio devices etc
//deinit(sdfps);
puts("removed reload-trigger, reloading...");
return 0;
}
}
quit:
// do what ever you got to before process dies
deinit(sdfps);
return 1;
}