From 2ec699948c803575108efef175bbe85ca3a8ecf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Madar=C3=A1sz?= Date: Sun, 17 Sep 2023 22:56:51 +0200 Subject: [PATCH] workbench: initial impl wip render: supporting changes ui: new methods --- MAKE.bat | 16 +- demos/00-demo.c | 2 +- demos/01-sprite.c | 2 +- demos/02-ddraw.c | 2 +- demos/03-anims.c | 2 +- demos/05-scene.c | 2 +- demos/06-controller.c | 2 +- demos/99-cubemap.c | 2 +- demos/99-dung.c | 2 +- demos/99-pbr.c | 2 +- demos/99-sponza.c | 2 +- demos/99-sprite.c | 2 +- demos/art/meshes/cube.obj | 40 ---- demos/html5/demo_collide.c | 2 +- engine/art/meshes/cube.mtl | 12 ++ engine/art/meshes/cube.obj | 49 +++++ {demos => engine}/art/meshes/shaderBall.glb | Bin .../art/meshes/shaderBall.license | 0 {demos => engine}/art/meshes/sphere.obj | 0 {demos => engine}/art/meshes/suzanne.obj | 0 engine/bind/v4k.lua | 32 +++- engine/joint/v4k.h | 156 +++++++++++++--- engine/split/v4k_render.c | 110 +++++++++-- engine/split/v4k_render.h | 18 +- engine/split/v4k_renderdd.c | 4 +- engine/split/v4k_ui.c | 13 ++ engine/split/v4k_ui.h | 11 +- engine/v4k.c | 127 +++++++++++-- engine/v4k.h | 29 ++- hello.c | 2 +- tools/editor/editor.c | 2 +- workbench/pluginapi.h | 26 +++ workbench/plugins/shader_editor.c | 173 ++++++++++++++++++ workbench/plugins/shader_editor.o | Bin 0 -> 4012 bytes workbench/plugins/shader_editor.obj | Bin 0 -> 4843 bytes workbench/workbench.c | 127 +++++++++++++ 36 files changed, 836 insertions(+), 135 deletions(-) delete mode 100644 demos/art/meshes/cube.obj create mode 100644 engine/art/meshes/cube.mtl create mode 100644 engine/art/meshes/cube.obj rename {demos => engine}/art/meshes/shaderBall.glb (100%) rename {demos => engine}/art/meshes/shaderBall.license (100%) rename {demos => engine}/art/meshes/sphere.obj (100%) rename {demos => engine}/art/meshes/suzanne.obj (100%) create mode 100644 workbench/pluginapi.h create mode 100644 workbench/plugins/shader_editor.c create mode 100644 workbench/plugins/shader_editor.o create mode 100644 workbench/plugins/shader_editor.obj create mode 100644 workbench/workbench.c diff --git a/MAKE.bat b/MAKE.bat index 330c651..07d7953 100644 --- a/MAKE.bat +++ b/MAKE.bat @@ -396,7 +396,7 @@ set run=no if "%1"=="extras" set "extras=yes" && set "hello=no" && goto loop if "%1"=="noeditor" set "editor=no" && goto loop if "%1"=="hello" set "hello=yes" && goto loop - if "%1"=="editor" set "editor=yes" && set "hello=no"&& goto loop + if "%1"=="editor" set "editor=yes" && set "v4k=no" && set "hello=no"&& goto loop if "%1"=="run" set "run=yes" && goto loop if "%1"=="all" set "v4k=yes" && set "demos=yes" && set "extras=yes" && set "editor=yes" && set "hello=yes" && goto loop @@ -600,9 +600,17 @@ if "!vis!"=="yes" echo !cc! engine\v4k.c !export! !args! ^&^& if "!dll!"=="dll" rem editor if "!editor!"=="yes" ( set edit=-DCOOK_ON_DEMAND -DUI_LESSER_SPACING -DUI_ICONS_SMALL -if "!vis!"=="yes" echo !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! -!echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1 -!echo! editor2 && !cc! !o! editor2.exe tools\editor\editor2.c !edit! !args! || set rc=1 +rem if "!vis!"=="yes" echo !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! +rem !echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1 +rem !echo! editor2 && !cc! !o! editor2.exe tools\editor\editor2.c !edit! !args! || set rc=1 + +set "plugins=" +for %%f in ("workbench\plugins\*.c") do ( + echo plugin: %%~nf.c + set "plugins=!plugins! workbench\plugins\%%~nf.c" +) + +!echo! workbench && !cc! !o! workbench.exe workbench\workbench.c !plugins! -Iworkbench !edit! !args! || set rc=1 ) rem demos diff --git a/demos/00-demo.c b/demos/00-demo.c index 4605db4..23ca2fa 100644 --- a/demos/00-demo.c +++ b/demos/00-demo.c @@ -180,7 +180,7 @@ int main() { } // post-fxs end here - fx_end(); + fx_end(0); // font demo do_once font_scales(FONT_FACE1, 48, 24, 18, 12, 9, 6); diff --git a/demos/01-sprite.c b/demos/01-sprite.c index 121dcf4..d5c9b4d 100644 --- a/demos/01-sprite.c +++ b/demos/01-sprite.c @@ -124,7 +124,7 @@ int main() { ); // post-fxs end here - fx_end(); + fx_end(0); // ui if( ui_panel("Audio", 0)) { diff --git a/demos/02-ddraw.c b/demos/02-ddraw.c index 51c6064..cd616d2 100644 --- a/demos/02-ddraw.c +++ b/demos/02-ddraw.c @@ -88,7 +88,7 @@ int main() { collide_demo(); } - fx_end(); + fx_end(0); // ui if( ui_panel("App", 0) ) { diff --git a/demos/03-anims.c b/demos/03-anims.c index fdbbe08..7792360 100644 --- a/demos/03-anims.c +++ b/demos/03-anims.c @@ -86,7 +86,7 @@ int main() { } } - fx_end(); + fx_end(0); if( ui_panel("Animation", 0) ) { if( ui_bool("Show aabb", &do_showaabb) ); diff --git a/demos/05-scene.c b/demos/05-scene.c index ad1dc22..a7cb8ec 100644 --- a/demos/05-scene.c +++ b/demos/05-scene.c @@ -125,7 +125,7 @@ int main() { } // post-fxs end here - fx_end(); + fx_end(0); // queue ui if( ui_panel("Camera", 0)) { diff --git a/demos/06-controller.c b/demos/06-controller.c index 7fd439e..1f83d9a 100644 --- a/demos/06-controller.c +++ b/demos/06-controller.c @@ -69,7 +69,7 @@ int main() { model_render(witch, cam.proj, cam.view, witch.pivot, 0); // render end (postfx) - fx_end(); + fx_end(0); // input controllers diff --git a/demos/99-cubemap.c b/demos/99-cubemap.c index 2e4c5c4..73296fc 100644 --- a/demos/99-cubemap.c +++ b/demos/99-cubemap.c @@ -43,7 +43,7 @@ int main(int argc, char** argv) { initialized = 1; sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0); mdl = model(OBJ_MDLS[OBJ_MDL], 0); - // rotation44(mdl.pivot, 0, 1,0,0); // @fixme: -90,1,0,0 -> should we rotate SHMs as well? compensate rotation in shader? + rotation44(mdl.pivot, 0, 1,0,0); // @fixme: -90,1,0,0 -> should we rotate SHMs as well? compensate rotation in shader? } // fps camera diff --git a/demos/99-dung.c b/demos/99-dung.c index b07e7e8..bb9dc27 100644 --- a/demos/99-dung.c +++ b/demos/99-dung.c @@ -169,7 +169,7 @@ int main() { skybox_render(&sky, cam.proj, cam.view); draw_world(); - fx_end(); + fx_end(0); } return 0; diff --git a/demos/99-pbr.c b/demos/99-pbr.c index c43bf30..1436532 100644 --- a/demos/99-pbr.c +++ b/demos/99-pbr.c @@ -577,7 +577,7 @@ int main( int argc, const char *argv[] ) { glDepthFunc( GL_LESS ); } - fx_end(); + fx_end(0); // --------------------------------------------------------------------- // UI diff --git a/demos/99-sponza.c b/demos/99-sponza.c index f15765a..e1e41b4 100644 --- a/demos/99-sponza.c +++ b/demos/99-sponza.c @@ -70,6 +70,6 @@ int main() { model_render(sponza, cam.proj, cam.view, M, 0); // post-fxs end here - fx_end(); + fx_end(0); } } diff --git a/demos/99-sprite.c b/demos/99-sprite.c index b4aa285..7c8d922 100644 --- a/demos/99-sprite.c +++ b/demos/99-sprite.c @@ -191,7 +191,7 @@ int main(int argc, char **argv) { } // post-fxs end here - fx_end(); + fx_end(0); // draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way { diff --git a/demos/art/meshes/cube.obj b/demos/art/meshes/cube.obj deleted file mode 100644 index cc4b2ef..0000000 --- a/demos/art/meshes/cube.obj +++ /dev/null @@ -1,40 +0,0 @@ -# Blender v2.64 (sub 0) OBJ File: '' -# www.blender.org -mtllib data/cube.mtl -o Cube -v 1.000000 -1.000000 -1.000000 -v 1.000000 -1.000000 1.000000 -v -1.000000 -1.000000 1.000000 -v -1.000000 -1.000000 -1.000000 -v 1.000000 1.000000 -0.999999 -v 0.999999 1.000000 1.000001 -v -1.000000 1.000000 1.000000 -v -1.000000 1.000000 -1.000000 -vt 0.666667 0.500000 -vt 0.666667 1.000000 -vt 0.333333 1.000000 -vt 1.000000 0.500000 -vt 1.000000 1.000000 -vt 0.998981 0.000000 -vt 0.666667 0.001019 -vt 0.333333 0.500000 -vt 0.333333 0.001020 -vt 0.000000 1.000000 -vt 0.333333 0.000000 -vt 0.000000 0.500000 -vt 0.665647 0.000000 -vt 0.000000 0.001020 -usemtl Material -s off -f 1/1 2/2 3/3 -f 5/4 8/5 6/1 -f 1/6 5/4 2/7 -f 2/8 6/9 3/1 -f 3/8 7/3 8/10 -f 5/11 1/8 4/12 -f 4/8 1/1 3/3 -f 8/5 7/2 6/1 -f 5/4 6/1 2/7 -f 6/9 7/13 3/1 -f 4/12 3/8 8/10 -f 8/14 5/11 4/12 diff --git a/demos/html5/demo_collide.c b/demos/html5/demo_collide.c index 8f8d9ab..42204f7 100644 --- a/demos/html5/demo_collide.c +++ b/demos/html5/demo_collide.c @@ -584,7 +584,7 @@ void game_loop(void *userdata) { //fx_begin(); //ddraw_flush(); - //fx_end(); + //fx_end(0); if( ui_panel("Vis", 0) ) { ui_bool("Skybox render", &draw_skybox); diff --git a/engine/art/meshes/cube.mtl b/engine/art/meshes/cube.mtl new file mode 100644 index 0000000..27f6142 --- /dev/null +++ b/engine/art/meshes/cube.mtl @@ -0,0 +1,12 @@ +# Blender 3.6.2 MTL File: 'None' +# www.blender.org + +newmtl Material.001 +Ns 0.000000 +Ka 1.000000 1.000000 1.000000 +Kd 0.800000 0.800000 0.800000 +Ks 0.000000 0.000000 0.000000 +Ke 0.000000 0.000000 0.000000 +Ni 1.450000 +d 1.000000 +illum 1 diff --git a/engine/art/meshes/cube.obj b/engine/art/meshes/cube.obj new file mode 100644 index 0000000..a26672e --- /dev/null +++ b/engine/art/meshes/cube.obj @@ -0,0 +1,49 @@ +# Blender 3.6.2 +# www.blender.org +mtllib cube.mtl +o Cube +v 1.000000 -1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 -0.999999 +v 0.999999 1.000000 1.000001 +v -1.000000 1.000000 1.000000 +v -1.000000 1.000000 -1.000000 +vn -0.0000 -1.0000 -0.0000 +vn -0.0000 1.0000 -0.0000 +vn 1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 1.0000 +vn -1.0000 -0.0000 -0.0000 +vn -0.0000 -0.0000 -1.0000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +vt 1.000000 0.000001 +vt 0.000000 0.000000 +vt 0.999999 1.000000 +vt 0.000000 0.000000 +vt 1.000000 0.000001 +vt 0.000000 1.000000 +vt 1.000000 0.000000 +vt 0.999999 1.000000 +vt 0.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 0.000000 +vt 1.000000 1.000000 +vt 1.000000 1.000000 +vt 0.000000 1.000000 +s 0 +usemtl Material.001 +f 1/1/1 2/2/1 3/3/1 +f 5/4/2 8/5/2 6/6/2 +f 1/7/3 5/8/3 2/9/3 +f 2/10/4 6/11/4 3/12/4 +f 3/9/5 7/13/5 8/14/5 +f 5/15/6 1/10/6 4/12/6 +f 4/5/1 1/1/1 3/3/1 +f 8/5/2 7/3/2 6/6/2 +f 5/8/3 6/16/3 2/9/3 +f 6/11/4 7/17/4 3/12/4 +f 4/7/5 3/9/5 8/14/5 +f 8/17/6 5/15/6 4/12/6 diff --git a/demos/art/meshes/shaderBall.glb b/engine/art/meshes/shaderBall.glb similarity index 100% rename from demos/art/meshes/shaderBall.glb rename to engine/art/meshes/shaderBall.glb diff --git a/demos/art/meshes/shaderBall.license b/engine/art/meshes/shaderBall.license similarity index 100% rename from demos/art/meshes/shaderBall.license rename to engine/art/meshes/shaderBall.license diff --git a/demos/art/meshes/sphere.obj b/engine/art/meshes/sphere.obj similarity index 100% rename from demos/art/meshes/sphere.obj rename to engine/art/meshes/sphere.obj diff --git a/demos/art/meshes/suzanne.obj b/engine/art/meshes/suzanne.obj similarity index 100% rename from demos/art/meshes/suzanne.obj rename to engine/art/meshes/suzanne.obj diff --git a/engine/bind/v4k.lua b/engine/bind/v4k.lua index d2fb673..cfbb8ce 100644 --- a/engine/bind/v4k.lua +++ b/engine/bind/v4k.lua @@ -1185,6 +1185,7 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in:vec3* in_vertex3; //lcpp INF [0000] vec3: macro name but used as C declaration in:vec3* out_vertex3; //lcpp INF [0000] vec4: macro name but used as C declaration in:vec4 color; +//lcpp INF [0000] vec2i: macro name but used as C declaration in:vec2i dims; //lcpp INF [0000] vec3: macro name but used as C declaration in:vec3 pose; //lcpp INF [0000] vec3: macro name but used as C declaration in:API vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC vec3 pose(bool forward, float curframe, int minframe, int maxframe, bool loop, float *opt_retframe); @@ -1391,6 +1392,9 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in:API void object_scale(object_t *obj, vec3 sca); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void object_scale(object_t *obj, vec3 sca); //lcpp INF [0000] vec3: macro name but used as C declaration in: void object_scale(object_t *obj, vec3 sca); +//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 ui_get_dims(); +//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 ui_get_dims(); +//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 ui_get_dims(); //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 window_canvas(); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 window_canvas(); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 window_canvas(); @@ -2289,8 +2293,10 @@ float specular_shininess; } pbr_material_t; bool pbr_material(pbr_material_t *pbr, const char *material); void pbr_material_destroy(pbr_material_t *m); - void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); - void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); + void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); + void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); + void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); + void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); void sprite( texture_t texture, float position[3], float rotation , uint32_t color ); void sprite_rect( texture_t t, vec4 rect, float zindex, vec3 pos, float tilt_deg, unsigned tint_rgba); void sprite_sheet( texture_t texture, float sheet[3], float position[3], float rotation, float offset[2], float scale[2], int is_additive, uint32_t rgba, int resolution_independant); @@ -2463,6 +2469,11 @@ float value; vec4 color; } layer[MAX_CHANNELS_PER_MATERIAL]; } material_t; +enum { +SHADERTOY_FLIP_Y = 2, +SHADERTOY_IGNORE_FBO = 4, +SHADERTOY_IGNORE_MOUSE = 8, +}; typedef struct shadertoy_t { handle vao, program; int uniforms[32]; @@ -2471,7 +2482,8 @@ int frame; float clickx, clicky; uint64_t t; texture_t tx; -unsigned dims; +vec2i dims; +int flags; } shadertoy_t; shadertoy_t shadertoy( const char *shaderfile, unsigned flags ); shadertoy_t* shadertoy_render( shadertoy_t *s, float delta ); @@ -2566,7 +2578,8 @@ float *pixels; int fx_load(const char *file); int fx_load_from_mem(const char *nameid, const char *content); void fx_begin(); - void fx_end(); + void fx_begin_res(int w, int h); + void fx_end(handle fb); void fx_enable(int pass, int enabled); int fx_enabled(int pass); void fx_enable_all(int enabled); @@ -2800,6 +2813,7 @@ PANEL_OPEN = 1, int ui_double(const char *label, double *value); int ui_buffer(const char *label, char *buffer, int buflen); int ui_string(const char *label, char **string); + int ui_text_wrap(const char *label, char *text); int ui_color3(const char *label, float *color3); int ui_color3f(const char *label, float *color3); int ui_color4(const char *label, float *color4); @@ -2838,10 +2852,12 @@ PANEL_OPEN = 1, int ui_collapse_end(); int ui_panel_end(); int ui_window_end(); - int ui_show(const char *panel_or_window_title, int enabled); - int ui_visible(const char *panel_or_window_title); - int ui_enable(); - int ui_disable(); + int ui_show(const char *panel_or_window_title, int enabled); + int ui_dims(const char *panel_or_window_title, float width, float height); + int ui_visible(const char *panel_or_window_title); + int ui_enable(); + int ui_disable(); + vec2 ui_get_dims(); int ui_has_menubar(); int ui_menu(const char *items); int ui_menu_editbox(char *buf, int bufcap); diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 47fe034..e60cec5 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -16536,8 +16536,10 @@ API void pbr_material_destroy(pbr_material_t *m); // ----------------------------------------------------------------------------- // fullscreen quads -API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); -API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); +API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); +API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); // ----------------------------------------------------------------------------- // sprites @@ -16863,6 +16865,12 @@ typedef struct material_t { // ----------------------------------------------------------------------------- // shadertoys +enum { + SHADERTOY_FLIP_Y = 2, + SHADERTOY_IGNORE_FBO = 4, + SHADERTOY_IGNORE_MOUSE = 8, +}; + typedef struct shadertoy_t { handle vao, program; int uniforms[32]; @@ -16871,7 +16879,8 @@ typedef struct shadertoy_t { float clickx, clicky; uint64_t t; texture_t tx; - unsigned dims; + vec2i dims; + int flags; } shadertoy_t; API shadertoy_t shadertoy( const char *shaderfile, unsigned flags ); @@ -17006,7 +17015,8 @@ API void viewport_clip(vec2 from, vec2 to); API int fx_load(const char *file); API int fx_load_from_mem(const char *nameid, const char *content); API void fx_begin(); -API void fx_end(); +API void fx_begin_res(int w, int h); +API void fx_end(handle fb); API void fx_enable(int pass, int enabled); API int fx_enabled(int pass); API void fx_enable_all(int enabled); @@ -17391,6 +17401,7 @@ API int ui_float4(const char *label, float value[4]); API int ui_double(const char *label, double *value); API int ui_buffer(const char *label, char *buffer, int buflen); API int ui_string(const char *label, char **string); +API int ui_text_wrap(const char *label, char *text); API int ui_color3(const char *label, float *color3); //[0..255] API int ui_color3f(const char *label, float *color3); //[0..1] API int ui_color4(const char *label, float *color4); //[0..255] @@ -17430,10 +17441,12 @@ API int ui_collapse_end(); API int ui_panel_end(); API int ui_window_end(); -API int ui_show(const char *panel_or_window_title, int enabled); -API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? -API int ui_enable(); -API int ui_disable(); +API int ui_show(const char *panel_or_window_title, int enabled); +API int ui_dims(const char *panel_or_window_title, float width, float height); +API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? +API int ui_enable(); +API int ui_disable(); +API vec2 ui_get_dims(); API int ui_has_menubar(); API int ui_menu(const char *items); // semicolon-separated or comma-separated items @@ -340575,6 +340588,37 @@ void fullscreen_quad_rgb( texture_t texture, float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ) { + static int program = -1, vao = -1, u_inv_gamma = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_inv_gamma.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_inv_gamma = glGetUniformLocation(program, "u_inv_gamma"); + glGenVertexArrays( 1, (GLuint*)&vao ); + } + + GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + + glBindVertexArray( vao ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( texture_type, texture.id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( texture_type, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; if( program < 0 ) { @@ -340619,6 +340663,50 @@ void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { + static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_ycbr_gamma_saturation.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_gamma = glGetUniformLocation(program, "u_gamma"); + + uy = glGetUniformLocation(program, "u_texture_y"); + ucb = glGetUniformLocation(program, "u_texture_cb"); + ucr = glGetUniformLocation(program, "u_texture_cr"); + + glGenVertexArrays( 1, (GLuint*)&vao ); + } + +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_gamma, gamma ); + + glBindVertexArray( vao ); + + glUniform1i(uy, 0); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[0].id ); + + glUniform1i(ucb, 1); + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[1].id ); + + glUniform1i(ucr, 2); + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[2].id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( GL_TEXTURE_2D, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + // ---------------------------------------------------------------------------- // sprites @@ -342380,7 +342468,7 @@ void postfx_destroy(postfx *fx); bool postfx_load(postfx *fx, const char *name, const char *fragment); bool postfx_begin(postfx *fx, int width, int height); -bool postfx_end(postfx *fx); +bool postfx_end(postfx *fx, handle fb); bool postfx_enabled(postfx *fx, int pass_number); bool postfx_enable(postfx *fx, int pass_number, bool enabled); @@ -342535,6 +342623,10 @@ bool postfx_begin(postfx *fx, int width, int height) { width += !width; height += !height; + int last_fb; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); + fbo_bind(last_fb); + // resize if needed if( fx->diffuse[0].w != width || fx->diffuse[0].h != height ) { texture_destroy(&fx->diffuse[0]); @@ -342558,7 +342650,7 @@ bool postfx_begin(postfx *fx, int width, int height) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { - fbo_unbind(); + fbo_bind(last_fb); return false; } @@ -342575,14 +342667,14 @@ bool postfx_begin(postfx *fx, int width, int height) { return true; } -bool postfx_end(postfx *fx) { +bool postfx_end(postfx *fx, handle fb) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { return false; } - fbo_unbind(); + fbo_bind(fb); // disable depth test in 2d rendering bool is_depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); @@ -342636,7 +342728,7 @@ bool postfx_end(postfx *fx) { profile_incstat("Render.num_triangles", +2); glBindVertexArray(0); - if( bound ) fbo_unbind(); + if( bound ) fbo_bind(fb); else glUseProgram(0); } } @@ -342644,6 +342736,8 @@ bool postfx_end(postfx *fx) { if(is_depth_test_enabled); glEnable(GL_DEPTH_TEST); + fbo_bind(fb); + return true; } @@ -342665,8 +342759,11 @@ int fx_load(const char *filemask) { void fx_begin() { postfx_begin(&fx, window_width(), window_height()); } -void fx_end() { - postfx_end(&fx); +void fx_begin_res(int w, int h) { + postfx_begin(&fx, w, h); +} +void fx_end(handle fb) { + postfx_end(&fx,fb); } int fx_enabled(int pass) { return postfx_enabled(&fx, pass); @@ -342821,7 +342918,7 @@ enum shadertoy_uniforms { shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t s = {0}; - s.dims = flags; + s.flags = flags; char *file = vfs_read(shaderfile); if( !file ) return s; @@ -342829,7 +342926,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { glGenVertexArrays(1, &s.vao); char *fs = stringf("%s%s", vfs_read("header_shadertoy.glsl"), file); - s.program = shader(flags ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); + s.program = shader((flags&SHADERTOY_FLIP_Y) ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); FREE(fs); if( strstr(file, "noise3.jpg")) @@ -342861,7 +342958,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if( s->program && s->vao ) { - if( s->dims && !texture_rec_begin(&s->tx, s->dims, s->dims / 2) ) { + if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; } @@ -342876,8 +342973,8 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glUniform1f(s->uniforms[iGlobalTime], s->t / 1000.f ); glUniform1f(s->uniforms[iGlobalFrame], s->frame++); glUniform1f(s->uniforms[iGlobalDelta], delta / 1000.f ); - glUniform2f(s->uniforms[iResolution], window_width(), window_height()); - glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); + glUniform2f(s->uniforms[iResolution], s->dims.x ? s->dims.x : window_width(), s->dims.y ? s->dims.y : window_height()); + if (!(s->flags&SHADERTOY_IGNORE_MOUSE)) glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); glUniform1i(s->uniforms[iFrame], (int)window_frame()); glUniform1f(s->uniforms[iTime], time_ss()); @@ -342896,7 +342993,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glBindVertexArray(s->vao); glDrawArrays(GL_TRIANGLES, 0, 3); - if(s->dims) texture_rec_end(&s->tx); // texture_rec + if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } return s; } @@ -344031,7 +344128,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); @@ -344063,7 +344160,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); @@ -346860,6 +346957,12 @@ int ui_show(const char *panel_or_window_title, int enabled) { } return !!enabled; } +int ui_dims(const char *panel_or_window_title, float width, float height) { + nk_window_set_size(ui_ctx, panel_or_window_title, (struct nk_vec2){width, height}); +} +vec2 ui_get_dims() { + return (vec2){nk_window_get_width(ui_ctx), nk_window_get_height(ui_ctx)}; +} static char *ui_build_window_list() { char *build_windows_menu = 0; strcatf(&build_windows_menu, "%s;", ICON_MD_VIEW_QUILT); // "Windows"); @@ -348338,6 +348441,13 @@ int ui_buffer(const char *label, char *buffer, int buflen) { return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; } +int ui_text_wrap(const char *label, char *text) { + nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1)); + ui_label_(label, NK_TEXT_LEFT); + nk_text_wrap(ui_ctx, text, strlen(text)); + return 0; +} + int ui_string(const char *label, char **str) { char *bak = va("%s%c", *str ? *str : "", '\0'); int rc = ui_buffer(label, bak, strlen(bak)+2); diff --git a/engine/split/v4k_render.c b/engine/split/v4k_render.c index ca23af5..fef65b4 100644 --- a/engine/split/v4k_render.c +++ b/engine/split/v4k_render.c @@ -1060,6 +1060,37 @@ void fullscreen_quad_rgb( texture_t texture, float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ) { + static int program = -1, vao = -1, u_inv_gamma = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_inv_gamma.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_inv_gamma = glGetUniformLocation(program, "u_inv_gamma"); + glGenVertexArrays( 1, (GLuint*)&vao ); + } + + GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + + glBindVertexArray( vao ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( texture_type, texture.id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( texture_type, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; if( program < 0 ) { @@ -1104,6 +1135,50 @@ void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { + static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_ycbr_gamma_saturation.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_gamma = glGetUniformLocation(program, "u_gamma"); + + uy = glGetUniformLocation(program, "u_texture_y"); + ucb = glGetUniformLocation(program, "u_texture_cb"); + ucr = glGetUniformLocation(program, "u_texture_cr"); + + glGenVertexArrays( 1, (GLuint*)&vao ); + } + +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_gamma, gamma ); + + glBindVertexArray( vao ); + + glUniform1i(uy, 0); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[0].id ); + + glUniform1i(ucb, 1); + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[1].id ); + + glUniform1i(ucr, 2); + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[2].id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( GL_TEXTURE_2D, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + // ---------------------------------------------------------------------------- // sprites @@ -2865,7 +2940,7 @@ void postfx_destroy(postfx *fx); bool postfx_load(postfx *fx, const char *name, const char *fragment); bool postfx_begin(postfx *fx, int width, int height); -bool postfx_end(postfx *fx); +bool postfx_end(postfx *fx, handle fb); bool postfx_enabled(postfx *fx, int pass_number); bool postfx_enable(postfx *fx, int pass_number, bool enabled); @@ -3020,6 +3095,10 @@ bool postfx_begin(postfx *fx, int width, int height) { width += !width; height += !height; + int last_fb; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); + fbo_bind(last_fb); + // resize if needed if( fx->diffuse[0].w != width || fx->diffuse[0].h != height ) { texture_destroy(&fx->diffuse[0]); @@ -3043,7 +3122,7 @@ bool postfx_begin(postfx *fx, int width, int height) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { - fbo_unbind(); + fbo_bind(last_fb); return false; } @@ -3060,14 +3139,14 @@ bool postfx_begin(postfx *fx, int width, int height) { return true; } -bool postfx_end(postfx *fx) { +bool postfx_end(postfx *fx, handle fb) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { return false; } - fbo_unbind(); + fbo_bind(fb); // disable depth test in 2d rendering bool is_depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); @@ -3121,7 +3200,7 @@ bool postfx_end(postfx *fx) { profile_incstat("Render.num_triangles", +2); glBindVertexArray(0); - if( bound ) fbo_unbind(); + if( bound ) fbo_bind(fb); else glUseProgram(0); } } @@ -3129,6 +3208,8 @@ bool postfx_end(postfx *fx) { if(is_depth_test_enabled); glEnable(GL_DEPTH_TEST); + fbo_bind(fb); + return true; } @@ -3150,8 +3231,11 @@ int fx_load(const char *filemask) { void fx_begin() { postfx_begin(&fx, window_width(), window_height()); } -void fx_end() { - postfx_end(&fx); +void fx_begin_res(int w, int h) { + postfx_begin(&fx, w, h); +} +void fx_end(handle fb) { + postfx_end(&fx,fb); } int fx_enabled(int pass) { return postfx_enabled(&fx, pass); @@ -3306,7 +3390,7 @@ enum shadertoy_uniforms { shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t s = {0}; - s.dims = flags; + s.flags = flags; char *file = vfs_read(shaderfile); if( !file ) return s; @@ -3314,7 +3398,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { glGenVertexArrays(1, &s.vao); char *fs = stringf("%s%s", vfs_read("header_shadertoy.glsl"), file); - s.program = shader(flags ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); + s.program = shader((flags&SHADERTOY_FLIP_Y) ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); FREE(fs); if( strstr(file, "noise3.jpg")) @@ -3346,7 +3430,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if( s->program && s->vao ) { - if( s->dims && !texture_rec_begin(&s->tx, s->dims, s->dims / 2) ) { + if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; } @@ -3361,8 +3445,8 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glUniform1f(s->uniforms[iGlobalTime], s->t / 1000.f ); glUniform1f(s->uniforms[iGlobalFrame], s->frame++); glUniform1f(s->uniforms[iGlobalDelta], delta / 1000.f ); - glUniform2f(s->uniforms[iResolution], window_width(), window_height()); - glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); + glUniform2f(s->uniforms[iResolution], s->dims.x ? s->dims.x : window_width(), s->dims.y ? s->dims.y : window_height()); + if (!(s->flags&SHADERTOY_IGNORE_MOUSE)) glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); glUniform1i(s->uniforms[iFrame], (int)window_frame()); glUniform1f(s->uniforms[iTime], time_ss()); @@ -3381,7 +3465,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glBindVertexArray(s->vao); glDrawArrays(GL_TRIANGLES, 0, 3); - if(s->dims) texture_rec_end(&s->tx); // texture_rec + if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } return s; } diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index ce8ffbd..27afe9f 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -183,8 +183,10 @@ API void pbr_material_destroy(pbr_material_t *m); // ----------------------------------------------------------------------------- // fullscreen quads -API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); -API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); +API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); +API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); // ----------------------------------------------------------------------------- // sprites @@ -510,6 +512,12 @@ typedef struct material_t { // ----------------------------------------------------------------------------- // shadertoys +enum { + SHADERTOY_FLIP_Y = 2, + SHADERTOY_IGNORE_FBO = 4, + SHADERTOY_IGNORE_MOUSE = 8, +}; + typedef struct shadertoy_t { handle vao, program; int uniforms[32]; @@ -518,7 +526,8 @@ typedef struct shadertoy_t { float clickx, clicky; uint64_t t; texture_t tx; - unsigned dims; + vec2i dims; + int flags; } shadertoy_t; API shadertoy_t shadertoy( const char *shaderfile, unsigned flags ); @@ -653,7 +662,8 @@ API void viewport_clip(vec2 from, vec2 to); API int fx_load(const char *file); API int fx_load_from_mem(const char *nameid, const char *content); API void fx_begin(); -API void fx_end(); +API void fx_begin_res(int w, int h); +API void fx_end(handle fb); API void fx_enable(int pass, int enabled); API int fx_enabled(int pass); API void fx_enable_all(int enabled); diff --git a/engine/split/v4k_renderdd.c b/engine/split/v4k_renderdd.c index a0bb004..5187841 100644 --- a/engine/split/v4k_renderdd.c +++ b/engine/split/v4k_renderdd.c @@ -95,7 +95,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); @@ -127,7 +127,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); diff --git a/engine/split/v4k_ui.c b/engine/split/v4k_ui.c index 39f562f..8f1b2ac 100644 --- a/engine/split/v4k_ui.c +++ b/engine/split/v4k_ui.c @@ -434,6 +434,12 @@ int ui_show(const char *panel_or_window_title, int enabled) { } return !!enabled; } +int ui_dims(const char *panel_or_window_title, float width, float height) { + nk_window_set_size(ui_ctx, panel_or_window_title, (struct nk_vec2){width, height}); +} +vec2 ui_get_dims() { + return (vec2){nk_window_get_width(ui_ctx), nk_window_get_height(ui_ctx)}; +} static char *ui_build_window_list() { char *build_windows_menu = 0; strcatf(&build_windows_menu, "%s;", ICON_MD_VIEW_QUILT); // "Windows"); @@ -1912,6 +1918,13 @@ int ui_buffer(const char *label, char *buffer, int buflen) { return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; } +int ui_text_wrap(const char *label, char *text) { + nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1)); + ui_label_(label, NK_TEXT_LEFT); + nk_text_wrap(ui_ctx, text, strlen(text)); + return 0; +} + int ui_string(const char *label, char **str) { char *bak = va("%s%c", *str ? *str : "", '\0'); int rc = ui_buffer(label, bak, strlen(bak)+2); diff --git a/engine/split/v4k_ui.h b/engine/split/v4k_ui.h index baec815..9b10676 100644 --- a/engine/split/v4k_ui.h +++ b/engine/split/v4k_ui.h @@ -25,6 +25,7 @@ API int ui_float4(const char *label, float value[4]); API int ui_double(const char *label, double *value); API int ui_buffer(const char *label, char *buffer, int buflen); API int ui_string(const char *label, char **string); +API int ui_text_wrap(const char *label, char *text); API int ui_color3(const char *label, float *color3); //[0..255] API int ui_color3f(const char *label, float *color3); //[0..1] API int ui_color4(const char *label, float *color4); //[0..255] @@ -64,10 +65,12 @@ API int ui_collapse_end(); API int ui_panel_end(); API int ui_window_end(); -API int ui_show(const char *panel_or_window_title, int enabled); -API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? -API int ui_enable(); -API int ui_disable(); +API int ui_show(const char *panel_or_window_title, int enabled); +API int ui_dims(const char *panel_or_window_title, float width, float height); +API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? +API int ui_enable(); +API int ui_disable(); +API vec2 ui_get_dims(); API int ui_has_menubar(); API int ui_menu(const char *items); // semicolon-separated or comma-separated items diff --git a/engine/v4k.c b/engine/v4k.c index b711358..89843fe 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -11284,6 +11284,37 @@ void fullscreen_quad_rgb( texture_t texture, float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ) { + static int program = -1, vao = -1, u_inv_gamma = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_inv_gamma.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_inv_gamma = glGetUniformLocation(program, "u_inv_gamma"); + glGenVertexArrays( 1, (GLuint*)&vao ); + } + + GLenum texture_type = texture.flags & TEXTURE_ARRAY ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_inv_gamma, 1.0f / (gamma + !gamma) ); + + glBindVertexArray( vao ); + + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( texture_type, texture.id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( texture_type, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; if( program < 0 ) { @@ -11328,6 +11359,50 @@ void fullscreen_quad_ycbcr( texture_t textureYCbCr[3], float gamma ) { // glDisable( GL_BLEND ); } +void fullscreen_quad_ycbcr_flipped( texture_t textureYCbCr[3], float gamma ) { + static int program = -1, vao = -1, u_gamma = -1, uy = -1, ucb = -1, ucr = -1; + if( program < 0 ) { + const char* vs = vfs_read("shaders/vs_0_2_fullscreen_quad_B.glsl"); + const char* fs = vfs_read("shaders/fs_2_4_texel_ycbr_gamma_saturation.glsl"); + + program = shader(vs, fs, "", "fragcolor" ); + u_gamma = glGetUniformLocation(program, "u_gamma"); + + uy = glGetUniformLocation(program, "u_texture_y"); + ucb = glGetUniformLocation(program, "u_texture_cb"); + ucr = glGetUniformLocation(program, "u_texture_cr"); + + glGenVertexArrays( 1, (GLuint*)&vao ); + } + +// glEnable( GL_BLEND ); + glUseProgram( program ); + glUniform1f( u_gamma, gamma ); + + glBindVertexArray( vao ); + + glUniform1i(uy, 0); + glActiveTexture( GL_TEXTURE0 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[0].id ); + + glUniform1i(ucb, 1); + glActiveTexture( GL_TEXTURE1 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[1].id ); + + glUniform1i(ucr, 2); + glActiveTexture( GL_TEXTURE2 ); + glBindTexture( GL_TEXTURE_2D, textureYCbCr[2].id ); + + glDrawArrays( GL_TRIANGLES, 0, 6 ); + profile_incstat("Render.num_drawcalls", +1); + profile_incstat("Render.num_triangles", +2); + + glBindTexture( GL_TEXTURE_2D, 0 ); + glBindVertexArray( 0 ); + glUseProgram( 0 ); +// glDisable( GL_BLEND ); +} + // ---------------------------------------------------------------------------- // sprites @@ -13089,7 +13164,7 @@ void postfx_destroy(postfx *fx); bool postfx_load(postfx *fx, const char *name, const char *fragment); bool postfx_begin(postfx *fx, int width, int height); -bool postfx_end(postfx *fx); +bool postfx_end(postfx *fx, handle fb); bool postfx_enabled(postfx *fx, int pass_number); bool postfx_enable(postfx *fx, int pass_number, bool enabled); @@ -13244,6 +13319,10 @@ bool postfx_begin(postfx *fx, int width, int height) { width += !width; height += !height; + int last_fb; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &last_fb); + fbo_bind(last_fb); + // resize if needed if( fx->diffuse[0].w != width || fx->diffuse[0].h != height ) { texture_destroy(&fx->diffuse[0]); @@ -13267,7 +13346,7 @@ bool postfx_begin(postfx *fx, int width, int height) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { - fbo_unbind(); + fbo_bind(last_fb); return false; } @@ -13284,14 +13363,14 @@ bool postfx_begin(postfx *fx, int width, int height) { return true; } -bool postfx_end(postfx *fx) { +bool postfx_end(postfx *fx, handle fb) { uint64_t num_active_passes = popcnt64(fx->mask); bool active = fx->enabled && num_active_passes; if( !active ) { return false; } - fbo_unbind(); + fbo_bind(fb); // disable depth test in 2d rendering bool is_depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); @@ -13345,7 +13424,7 @@ bool postfx_end(postfx *fx) { profile_incstat("Render.num_triangles", +2); glBindVertexArray(0); - if( bound ) fbo_unbind(); + if( bound ) fbo_bind(fb); else glUseProgram(0); } } @@ -13353,6 +13432,8 @@ bool postfx_end(postfx *fx) { if(is_depth_test_enabled); glEnable(GL_DEPTH_TEST); + fbo_bind(fb); + return true; } @@ -13374,8 +13455,11 @@ int fx_load(const char *filemask) { void fx_begin() { postfx_begin(&fx, window_width(), window_height()); } -void fx_end() { - postfx_end(&fx); +void fx_begin_res(int w, int h) { + postfx_begin(&fx, w, h); +} +void fx_end(handle fb) { + postfx_end(&fx,fb); } int fx_enabled(int pass) { return postfx_enabled(&fx, pass); @@ -13530,7 +13614,7 @@ enum shadertoy_uniforms { shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t s = {0}; - s.dims = flags; + s.flags = flags; char *file = vfs_read(shaderfile); if( !file ) return s; @@ -13538,7 +13622,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { glGenVertexArrays(1, &s.vao); char *fs = stringf("%s%s", vfs_read("header_shadertoy.glsl"), file); - s.program = shader(flags ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); + s.program = shader((flags&SHADERTOY_FLIP_Y) ? vfs_read("shaders/vs_shadertoy_flip.glsl") : vfs_read("shaders/vs_shadertoy.glsl"), fs, "", "fragColor"); FREE(fs); if( strstr(file, "noise3.jpg")) @@ -13570,7 +13654,7 @@ shadertoy_t shadertoy( const char *shaderfile, unsigned flags ) { shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { if( s->program && s->vao ) { - if( s->dims && !texture_rec_begin(&s->tx, s->dims, s->dims / 2) ) { + if( s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO) && !texture_rec_begin(&s->tx, s->dims.x, s->dims.y) ) { return s; } @@ -13585,8 +13669,8 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glUniform1f(s->uniforms[iGlobalTime], s->t / 1000.f ); glUniform1f(s->uniforms[iGlobalFrame], s->frame++); glUniform1f(s->uniforms[iGlobalDelta], delta / 1000.f ); - glUniform2f(s->uniforms[iResolution], window_width(), window_height()); - glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); + glUniform2f(s->uniforms[iResolution], s->dims.x ? s->dims.x : window_width(), s->dims.y ? s->dims.y : window_height()); + if (!(s->flags&SHADERTOY_IGNORE_MOUSE)) glUniform4f(s->uniforms[iMouse], mx, my, s->clickx, s->clicky ); glUniform1i(s->uniforms[iFrame], (int)window_frame()); glUniform1f(s->uniforms[iTime], time_ss()); @@ -13605,7 +13689,7 @@ shadertoy_t* shadertoy_render(shadertoy_t *s, float delta) { glBindVertexArray(s->vao); glDrawArrays(GL_TRIANGLES, 0, 3); - if(s->dims) texture_rec_end(&s->tx); // texture_rec + if(s->dims.x && !(s->flags&SHADERTOY_IGNORE_FBO)) texture_rec_end(&s->tx); // texture_rec } return s; } @@ -14740,7 +14824,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); @@ -14772,7 +14856,7 @@ void ddraw_flush_projview(mat44 proj, mat44 view) { vec3 rgbf = {((rgb>>16)&255)/255.f,((rgb>>8)&255)/255.f,((rgb>>0)&255)/255.f}; glUniform3fv(dd_u_color, GL_TRUE, &rgbf.x); // config vertex data - glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, count * 3 * 4, list, GL_STREAM_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), 0); // feed vertex data glDrawArrays(mode, 0, count); @@ -17569,6 +17653,12 @@ int ui_show(const char *panel_or_window_title, int enabled) { } return !!enabled; } +int ui_dims(const char *panel_or_window_title, float width, float height) { + nk_window_set_size(ui_ctx, panel_or_window_title, (struct nk_vec2){width, height}); +} +vec2 ui_get_dims() { + return (vec2){nk_window_get_width(ui_ctx), nk_window_get_height(ui_ctx)}; +} static char *ui_build_window_list() { char *build_windows_menu = 0; strcatf(&build_windows_menu, "%s;", ICON_MD_VIEW_QUILT); // "Windows"); @@ -19047,6 +19137,13 @@ int ui_buffer(const char *label, char *buffer, int buflen) { return !!(active & NK_EDIT_COMMITED) ? nk_edit_unfocus(ui_ctx), 1 : 0; } +int ui_text_wrap(const char *label, char *text) { + nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1)); + ui_label_(label, NK_TEXT_LEFT); + nk_text_wrap(ui_ctx, text, strlen(text)); + return 0; +} + int ui_string(const char *label, char **str) { char *bak = va("%s%c", *str ? *str : "", '\0'); int rc = ui_buffer(label, bak, strlen(bak)+2); diff --git a/engine/v4k.h b/engine/v4k.h index f660207..dcce828 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -2619,8 +2619,10 @@ API void pbr_material_destroy(pbr_material_t *m); // ----------------------------------------------------------------------------- // fullscreen quads -API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); -API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_rgb( texture_t texture_rgb, float gamma ); +API void fullscreen_quad_rgb_flipped( texture_t texture, float gamma ); +API void fullscreen_quad_ycbcr( texture_t texture_YCbCr[3], float gamma ); +API void fullscreen_quad_ycbcr_flipped( texture_t texture_YCbCr[3], float gamma ); // ----------------------------------------------------------------------------- // sprites @@ -2946,6 +2948,12 @@ typedef struct material_t { // ----------------------------------------------------------------------------- // shadertoys +enum { + SHADERTOY_FLIP_Y = 2, + SHADERTOY_IGNORE_FBO = 4, + SHADERTOY_IGNORE_MOUSE = 8, +}; + typedef struct shadertoy_t { handle vao, program; int uniforms[32]; @@ -2954,7 +2962,8 @@ typedef struct shadertoy_t { float clickx, clicky; uint64_t t; texture_t tx; - unsigned dims; + vec2i dims; + int flags; } shadertoy_t; API shadertoy_t shadertoy( const char *shaderfile, unsigned flags ); @@ -3089,7 +3098,8 @@ API void viewport_clip(vec2 from, vec2 to); API int fx_load(const char *file); API int fx_load_from_mem(const char *nameid, const char *content); API void fx_begin(); -API void fx_end(); +API void fx_begin_res(int w, int h); +API void fx_end(handle fb); API void fx_enable(int pass, int enabled); API int fx_enabled(int pass); API void fx_enable_all(int enabled); @@ -3474,6 +3484,7 @@ API int ui_float4(const char *label, float value[4]); API int ui_double(const char *label, double *value); API int ui_buffer(const char *label, char *buffer, int buflen); API int ui_string(const char *label, char **string); +API int ui_text_wrap(const char *label, char *text); API int ui_color3(const char *label, float *color3); //[0..255] API int ui_color3f(const char *label, float *color3); //[0..1] API int ui_color4(const char *label, float *color4); //[0..255] @@ -3513,10 +3524,12 @@ API int ui_collapse_end(); API int ui_panel_end(); API int ui_window_end(); -API int ui_show(const char *panel_or_window_title, int enabled); -API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? -API int ui_enable(); -API int ui_disable(); +API int ui_show(const char *panel_or_window_title, int enabled); +API int ui_dims(const char *panel_or_window_title, float width, float height); +API int ui_visible(const char *panel_or_window_title); // @todo: include ui_collapse() items that are open as well? +API int ui_enable(); +API int ui_disable(); +API vec2 ui_get_dims(); API int ui_has_menubar(); API int ui_menu(const char *items); // semicolon-separated or comma-separated items diff --git a/hello.c b/hello.c index ad83a44..dbecf37 100644 --- a/hello.c +++ b/hello.c @@ -80,7 +80,7 @@ int main() { model_render(girl, cam.proj, cam.view, girl.pivot, 0); // post-fxs end here - fx_end(); + fx_end(0); gizmo(&pos, &rot, &sca); model_render_skeleton(girl, girl.pivot); diff --git a/tools/editor/editor.c b/tools/editor/editor.c index 2f7802f..734de76 100644 --- a/tools/editor/editor.c +++ b/tools/editor/editor.c @@ -1772,7 +1772,7 @@ int main() { editor_obj_call0(obj, fn_draw); } - fx_end(); + fx_end(0); // draw gizmos, aabbs, markers, etc for each_set_ptr(editor_selection, void*, o) { diff --git a/workbench/pluginapi.h b/workbench/pluginapi.h new file mode 100644 index 0000000..2055371 --- /dev/null +++ b/workbench/pluginapi.h @@ -0,0 +1,26 @@ +#pragma once + +struct asset_t; + +typedef int (*ed_proc)(struct asset_t *asset); + +typedef struct { + ed_proc init; + ed_proc tick; + ed_proc quit; + char* (*ext)(); +} editor_vtable_t; + +typedef struct { + char *name; + editor_vtable_t f; +} editor_t; + +typedef struct { + char *name; + editor_t *ed; + + int slot; //<< internal, used by plugin +} asset_t; + +#define PLUG_DECLARE(name) editor_vtable_t name##__procs = { name##_init, name##_tick, name##_quit, name##_ext }; diff --git a/workbench/plugins/shader_editor.c b/workbench/plugins/shader_editor.c new file mode 100644 index 0000000..32617e0 --- /dev/null +++ b/workbench/plugins/shader_editor.c @@ -0,0 +1,173 @@ +#include "v4k.h" +#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; + +char *shader_editor_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; +} + +int shader_editor_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; +} + +int shader_editor_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(s->fb); + + // 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; +} + +int shader_editor_quit(asset_t *f) { + shader_asset_t *s = (shaders+f->slot); + + fbo_destroy(s->fb); + fbo_destroy(s->flipFB); + return 0; +} + +PLUG_DECLARE(shader_editor); diff --git a/workbench/plugins/shader_editor.o b/workbench/plugins/shader_editor.o new file mode 100644 index 0000000000000000000000000000000000000000..3dee8c3b6b9b091d9bb27622460dd4588de157ef GIT binary patch literal 4012 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 literal 0 HcmV?d00001 diff --git a/workbench/workbench.c b/workbench/workbench.c new file mode 100644 index 0000000..4cb2218 --- /dev/null +++ b/workbench/workbench.c @@ -0,0 +1,127 @@ +#define COOK_ON_DEMAND 1 +#include "v4k.c" +#include "pluginapi.h" + +array(editor_t) editors = 0; +array(asset_t) assets = 0; + +#define PLUGINS\ + X(shader_editor) + +#define X(name) extern editor_vtable_t name##__procs; + PLUGINS +#undef X + +void load_editor(char *pname, editor_vtable_t f) { + char *name = STRDUP(pname); // @leak + + editor_t ed = {0}; + ed.f = f; + ed.name = file_base(STRDUP(name)); // @leak + PRINTF("loaded plugin: '%s'\n", ed.name); + array_push(editors, ed); +} + +void load_editors() { + #define X(name) load_editor(#name, name##__procs); + PLUGINS + #undef X +} + +map(char*, editor_t*) assocs; + +void register_extensions() { + map_init(assocs, less_str, hash_str); + + for (int i=0; if.init((struct asset_t*)array_back(assets))) { + FREE(asset.name); + array_pop(assets); + PRINTF("fallback exec %s\n", fname); + edit_asset(fname); + } +} + +int main() { + window_create(75.0, WINDOW_MSAA8); + window_fps_unlock(); + + camera_t cam = camera(); + camera_enable(&cam); + + load_editors(); + register_extensions(); + + #if 1 + load_asset("demos/art/shadertoys/!default.fs"); + load_asset("demos/art/fx/fxDithering.fs"); + + #endif + + while( window_swap() && !input(KEY_ESC) ) { + static int wb_enabled = 1; + if (ui_window("Workbench", &wb_enabled)) { + static const char *file; + static bool show_browser = 1; + if( ui_browse(&file, &show_browser) ) { + load_asset(file); + show_browser = 1; + } + ui_window_end(); + } + + for (int i=0; iname, &open)) { + f->ed->f.tick(f); + + ui_separator(); + if (ui_button("reload asset") || !open) { + f->ed->f.quit(f); + f->ed->f.init(f); + } + if (ui_button("edit asset") || !open) { + edit_asset(assets[i].name); + } + if (ui_button("close asset") || !open) { + f->ed->f.quit(f); + FREE(assets[i].name); + array_erase(assets, i); + --i; + } + ui_window_end(); + } + } + } + return 0; +}