v4k-git-backup/workbench/plugins/shader_editor.c

171 lines
4.5 KiB
C

#include "pluginapi.h"
enum { WIDTH = 1024, HEIGHT = 1024 };
enum { UI_WIDTH = 512, UI_HEIGHT = 512 };
enum { VS, FS, FX, SHADERTOY };
typedef struct {
char kind;
bool reload;
// preview
handle fb, flipFB;
texture_t tex, flipTex;
texture_t texDepth;
union {
struct {
shadertoy_t shadertoy;
bool flip_y;
bool allow_mouse;
};
struct {
int model;
int fx_slot;
};
};
} shader_asset_t;
array(shader_asset_t) shaders = 0;
__declspec(dllexport) char *plug_ext() {
return "fx,glsl,vs,fs";
}
static inline
void reload_shader(asset_t *f, shader_asset_t *s) {
if (s->kind == SHADERTOY) {
s->shadertoy = shadertoy(f->name, (s->flip_y?SHADERTOY_FLIP_Y:0)|(s->allow_mouse?0:SHADERTOY_IGNORE_MOUSE)|SHADERTOY_IGNORE_FBO);
s->shadertoy.dims.x = WIDTH;
s->shadertoy.dims.y = HEIGHT;
}
else if (s->kind == FX) {
s->fx_slot = fx_load_from_mem(f->name, vfs_read(f->name));
}
s->reload = 0;
}
__declspec(dllexport) int plug_init(asset_t *f) {
shader_asset_t a = {0};
a.reload = 1;
if (strstri(f->name, "shadertoys")) {
a.kind = SHADERTOY;
}
// else if (strbegi(file_name(f->name), "vs_") || strendi(f->name, ".vs")) {
// a.kind = VS;
// }
// else if (strbegi(file_name(f->name), "fs_") || strendi(f->name, ".fs")) {
// a.kind = FS;
// }
else if (strbegi(file_name(f->name), "fx") && strendi(f->name, ".fs")) {
a.kind = FX;
} else {
PRINTF("unsupported shader: %s\n", f->name);
return 1;
}
a.tex = texture_create(WIDTH, HEIGHT, 4, NULL, TEXTURE_RGBA);
a.flipTex = texture_create(WIDTH, HEIGHT, 4, NULL, TEXTURE_RGBA);
a.texDepth = texture_create(WIDTH, HEIGHT, 1, NULL, TEXTURE_DEPTH|TEXTURE_FLOAT);
a.fb = fbo(a.tex.id, a.texDepth.id, 0);
a.flipFB = fbo(a.flipTex.id, 0, 0);
f->slot = array_count(shaders);
array_push(shaders, a);
return 0;
}
__declspec(dllexport) int plug_tick(asset_t *f) {
shader_asset_t *s = (shaders+f->slot);
if (s->reload) {
reload_shader(f, s);
ui_dims(f->name, UI_WIDTH, UI_HEIGHT*1.45);
}
fx_enable_all(0);
// vec2 win_dims = ui_get_dims();
// ui_dims(f->name, win_dims.x, win_dims.x*1.45);
fbo_bind(s->fb);
glViewport(0,0,WIDTH,HEIGHT);
glClearDepth(1);
glClearColor(0.0f,0.0f,0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
if (s->kind == SHADERTOY) {
shadertoy_render(&s->shadertoy, window_delta());
}
else if (s->kind == FX) {
fx_enable(s->fx_slot, 1);
// fx_begin();
fx_begin_res(WIDTH, HEIGHT);
enum { CUBE, SPHERE, SUZANNE, SHADERBALL, MAX_MODELS };
static camera_t cam;
static skybox_t sky;
static model_t models[MAX_MODELS];
do_once {
cam = camera();
sky = skybox(0,0);
camera_fps(&cam, 0,45);
models[CUBE] = model("meshes/cube.obj", MODEL_NO_ANIMATIONS);
// model_set_texture(models[CUBE], texture_checker());
rotation44(models[CUBE].pivot, -90, 1,0,0);
models[SPHERE] = model("meshes/sphere.obj", MODEL_NO_ANIMATIONS);
rotation44(models[SPHERE].pivot, -90, 1,0,0);
models[SUZANNE] = model("meshes/suzanne.obj", MODEL_NO_ANIMATIONS);
rotation44(models[SUZANNE].pivot, -90, 1,0,0);
models[SHADERBALL] = model("meshes/shaderBall.glb", MODEL_NO_ANIMATIONS);
mat44 sca; scale44(sca, 1,1,1);
mat44 rot; rotation44(rot, -90, 1,0,0);
multiply44x2(models[SHADERBALL].pivot, sca, rot);
}
bool active = (ui_active() || ui_hover()) && input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
// camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
camera_orbit(&cam, mouse.x,mouse.y, input_diff(MOUSE_W));
perspective44(cam.proj, cam.fov, UI_WIDTH/(float)UI_HEIGHT, 0.1f, 100.f);
skybox_render(&sky, cam.proj, cam.view);
ddraw_grid(0);
ddraw_flush();
model_render(models[s->model], cam.proj, cam.view, models[s->model].pivot, 0);
fx_end();
// fbo_bind(s->fb);
// fullscreen_quad_rgb(s->tex, 1.0);
// fbo_unbind();
}
fbo_bind(s->flipFB);
fullscreen_quad_rgb(s->tex, 1.0);
fbo_unbind();
ui_image(0, s->flipTex.id, UI_WIDTH, UI_HEIGHT);
if (s->kind == SHADERTOY) {
if (ui_bool("Flip Y", &s->flip_y)) {
s->reload = 1;
}
if (ui_bool("Allow mouse", &s->allow_mouse)) {
s->reload = 1;
}
}
else if (s->kind == FX) {
static char* model_selections[] = {"Cube", "Sphere", "Suzanne", "Shader ball"};
ui_list("Model", model_selections, 4, &s->model);
}
return 0;
}
__declspec(dllexport) int plug_quit(asset_t *f) {
shader_asset_t *s = (shaders+f->slot);
fbo_destroy(s->fb);
fbo_destroy(s->flipFB);
return 0;
}