sync with fwk
parent
a4869085a4
commit
d029777c9d
10
MAKE.bat
10
MAKE.bat
|
@ -372,7 +372,7 @@ set other=
|
|||
set v4k=yes
|
||||
set hello=no
|
||||
set demos=no
|
||||
set extras=no
|
||||
set lab=no
|
||||
set editor=no
|
||||
set vis=no
|
||||
set proj=no
|
||||
|
@ -402,12 +402,12 @@ set run=no
|
|||
if "%1"=="nov4k" set "v4k=no" && goto loop
|
||||
if "%1"=="nodemos" set "demos=no" && goto loop
|
||||
if "%1"=="demos" set "demos=yes" && set "hello=no" && goto loop
|
||||
if "%1"=="extras" set "extras=yes" && set "hello=no" && goto loop
|
||||
if "%1"=="lab" set "lab=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 "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
|
||||
if "%1"=="all" set "v4k=yes" && set "demos=yes" && set "lab=yes" && set "editor=yes" && set "hello=yes" && goto loop
|
||||
|
||||
if "%1"=="tcc" set "cc=%1" && goto loop
|
||||
if "%1"=="cl" set "cc=%1" && goto loop
|
||||
|
@ -646,8 +646,8 @@ if "!demos!"=="yes" (
|
|||
!echo! 07-network && !cc! !o! 07-network.exe demos\07-network.c !import! !args! || set rc=1
|
||||
)
|
||||
|
||||
rem extras
|
||||
if "!extras!"=="yes" (
|
||||
rem lab
|
||||
if "!lab!"=="yes" (
|
||||
for %%f in ("demos\99-*") do (
|
||||
!echo! %%~nf && !cc! !o! %%~nf.exe demos\%%~nf.c !import! !args! || set rc=1
|
||||
)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
#include "v4k.h" // Minimal C sample
|
||||
|
||||
int main() {
|
||||
window_create(75.0, 0); // 75% size, no extra flags
|
||||
|
||||
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
||||
puts("hello V4K from C!");
|
||||
}
|
||||
}
|
|
@ -25,4 +25,7 @@ int main() {
|
|||
end;
|
||||
end;
|
||||
));
|
||||
|
||||
// script test (lua)
|
||||
script_run( "-- Bye.lua\nio.write(\"script test: Bye world!, from \", _VERSION, \"\\n\")" );
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
// - rlyeh, public domain.
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\00-ui.c` (windows)
|
||||
// `sh MAKE.bat demos/00-ui.c` (linux, osx)
|
||||
// `make demos\01-ui.c` (windows)
|
||||
// `sh MAKE.bat demos/01-ui.c` (linux, osx)
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
|
@ -19,7 +19,7 @@ int main() {
|
|||
window_fps_lock(app_target_fps);
|
||||
|
||||
// load video
|
||||
video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB );
|
||||
video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_LOOP );
|
||||
|
||||
// app loop
|
||||
while( window_swap() ) {
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
// 2d demo: window, audio, camera, font, tiled, render, fx, spritesheet, input, ui. @todo: spine
|
||||
// - rlyeh, public domain.
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\01-demo2d.c` (windows)
|
||||
// `sh MAKE.bat demos/01-demo2d.c` (linux, osx)
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
void demo_kids(vec3 offs) {
|
||||
// init
|
||||
static texture_t kids; do_once kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR );
|
||||
static vec3 pos[2] = {{490,362},{442,362}}, vel[2] = {0};
|
||||
static int row[2] = {0,3}, frame[2] = {0};
|
||||
static int inputs[2][4] = {{KEY_W,KEY_A,KEY_S,KEY_D},{KEY_UP,KEY_LEFT,KEY_DOWN,KEY_RIGHT}};
|
||||
|
||||
// move
|
||||
for( int i = 0; i < countof(pos); ++i ) {
|
||||
vel[i].x = input(inputs[i][3]) - input(inputs[i][1]);
|
||||
vel[i].y = input(inputs[i][2]) - input(inputs[i][0]);
|
||||
pos[i].x = fmod(pos[i].x + vel[i].x, window_width() + 128);
|
||||
pos[i].y = fmod(pos[i].y + vel[i].y, window_height() + 128);
|
||||
frame[i] += vel[i].x || vel[i].y;
|
||||
}
|
||||
|
||||
// render
|
||||
for( int i = 0; i < countof(pos); ++i ) {
|
||||
int col = frame[i] / 10, num_frame = row[i] * 4 + col % 4; // 4x4 tilesheet
|
||||
float position[3] = {pos[i].x,pos[i].y,pos[i].y}, offset[2]={0,0}, scale[2]={0.5,0.5};
|
||||
float spritesheet[3]={num_frame,4,4};
|
||||
sprite_sheet(kids,
|
||||
spritesheet, // num_frame in a 4x4 spritesheet
|
||||
position, 0, // position(x,y,depth:sort-by-Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
false, WHITE, false // is_additive, tint color, resolution-independent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void demo_hud() {
|
||||
// draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way
|
||||
static texture_t inputs; do_once inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR );
|
||||
float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation
|
||||
float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling
|
||||
float position[3] = {window_width() - tile_w, window_height() - tile_h, window_height() }; // position in screen-coordinates (x,y,z-index)
|
||||
sprite_sheet(inputs, spritesheet, position, 0/*deg*/, offset, scale, false, WHITE, 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
// window (80% sized, MSAA x4 flag)
|
||||
window_create(80.0, WINDOW_MSAA4);
|
||||
window_title(__FILE__);
|
||||
|
||||
// tiled map
|
||||
tiled_t tmx = tiled(vfs_read("castle.tmx"));
|
||||
// tmx.parallax = true;
|
||||
|
||||
// spine model
|
||||
//spine_t *spn = spine("goblins.json", "goblins.atlas", 0);
|
||||
|
||||
// camera 2d
|
||||
camera_t cam = camera();
|
||||
cam.position = vec3(window_width()/2, window_height()/2, 3); // at(CX,CY) zoom(x3)
|
||||
camera_enable(&cam);
|
||||
|
||||
// audio (both clips & streams)
|
||||
audio_t clip1 = audio_clip( "coin.wav" );
|
||||
audio_t clip2 = audio_clip( "pew.sfxr" );
|
||||
audio_t stream1 = audio_stream( "larry.mid" );
|
||||
audio_t stream2 = audio_stream( "waterworld-map.fur" );
|
||||
audio_t BGM = stream1;
|
||||
audio_play(BGM, 0);
|
||||
|
||||
// font config: faces (6 max) and colors (10 max)
|
||||
#define FONT_CJK FONT_FACE3
|
||||
#define FONT_YELLOW FONT_COLOR2
|
||||
#define FONT_LIME FONT_COLOR3
|
||||
font_face(FONT_CJK, "mplus-1p-medium.ttf", 48.f, FONT_JP|FONT_2048); // CJK|FONT_2048|FONT_OVERSAMPLE_Y);
|
||||
font_color(FONT_YELLOW, RGB4(255,255,0,255));
|
||||
font_color(FONT_LIME, RGB4(128,255,0,255));
|
||||
|
||||
// fx: load all post fx files in all subdirs. enable a few filters by default
|
||||
fx_load("fx**.fs");
|
||||
fx_enable(fx_find("fxCRT2.fs"), 1);
|
||||
fx_enable(fx_find("fxGrain.fs"), 1);
|
||||
fx_enable(fx_find("fxContrast.fs"), 1);
|
||||
fx_enable(fx_find("fxVignette.fs"), 1);
|
||||
|
||||
// demo loop
|
||||
while (window_swap() && !input_down(KEY_ESC)) {
|
||||
|
||||
// handle input
|
||||
if( input_down(KEY_F5) ) window_reload();
|
||||
if( input_down(KEY_F11) ) window_fullscreen( !window_has_fullscreen() );
|
||||
|
||||
// camera panning (x,y) & zooming (z)
|
||||
if( !ui_hover() && !ui_active() ) {
|
||||
if( input(MOUSE_L) ) cam.position.x += input_diff(MOUSE_X);
|
||||
if( input(MOUSE_L) ) cam.position.y += input_diff(MOUSE_Y);
|
||||
cam.position.z += input_diff(MOUSE_W) * 0.1;
|
||||
}
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
profile("Rendering") {
|
||||
vec3 center = add3(cam.position,vec3(-window_width()/1,-window_height()/2,0));
|
||||
// render tiled map
|
||||
tiled_render(tmx, center);
|
||||
//
|
||||
demo_kids(vec3(0,0,1));
|
||||
demo_hud();
|
||||
// render spine model
|
||||
// spine_animate(spn, !window_has_pause() * window_delta());
|
||||
// spine_render(spn, vec3(cam.position.x, cam.position.y, 1), true );
|
||||
// sprite_flush();
|
||||
}
|
||||
|
||||
// subtitle sample
|
||||
font_print(
|
||||
FONT_BOTTOM FONT_CENTER
|
||||
FONT_CJK FONT_H1
|
||||
FONT_YELLOW "私はガラスを食べられます。" FONT_LIME "それは私を傷つけません。\n"
|
||||
);
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// ui
|
||||
if( ui_panel("Audio", 0)) {
|
||||
static float bgm = 1, sfx = 1, master = 1;
|
||||
if( ui_slider2("BGM", &bgm, va("%.2f", bgm))) audio_volume_stream(bgm);
|
||||
if( ui_slider2("SFX", &sfx, va("%.2f", sfx))) audio_volume_clip(sfx);
|
||||
if( ui_slider2("Master", &master, va("%.2f", master))) audio_volume_master(master);
|
||||
if( ui_label2_toolbar("BGM: Track #1", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream1, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Track #2", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream2, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(clip1, 0);
|
||||
if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(clip2, 0);
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("Tiled", 0)) {
|
||||
ui_float("Zoom in", &cam.position.z);
|
||||
tiled_ui(&tmx);
|
||||
ui_panel_end();
|
||||
}
|
||||
/*if( ui_panel("Spine", 0)) {
|
||||
spine_ui(spn);
|
||||
ui_panel_end();
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
// this demo supersedes following old sources:
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-audio.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-font.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-spine.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-sprite.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-tiled.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-tilemap.c
|
|
@ -1,7 +1,7 @@
|
|||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
window_create(0.75, WINDOW_MSAA8);
|
||||
window_create(75.0, WINDOW_MSAA8);
|
||||
|
||||
// style: our aliases
|
||||
#define FONT_REGULAR FONT_FACE1
|
||||
|
@ -24,11 +24,11 @@ int main() {
|
|||
#define FONT_TINY FONT_H6
|
||||
|
||||
// style: atlas size, unicode ranges and font faces (up to 6 faces)
|
||||
font_face(FONT_REGULAR, "Carlito-Regular.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_ITALIC, "Carlito-Italic.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_BOLD, "Carlito-Bold.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_REGULAR, "B612""-Regular.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_ITALIC, "B612""-Italic.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_BOLD, "B612""-Bold.ttf", 48.f, FONT_EU|FONT_AR|FONT_RU|FONT_2048);
|
||||
font_face(FONT_JAPANESE, "mplus-1p-medium.ttf", 48.f, FONT_JP|FONT_2048); // CJK|FONT_2048|FONT_OVERSAMPLE_Y);
|
||||
font_face(FONT_MONOSPACE, "Inconsolata-Regular.ttf", 24.f, FONT_EU|FONT_512);
|
||||
font_face(FONT_MONOSPACE, "B612Mono""-Regular.ttf", 24.f, FONT_EU|FONT_512);
|
||||
|
||||
// style: colors (up to 10 colors)
|
||||
font_color(FONT_GRAY, RGB4(100,100,100,255));
|
|
@ -1,167 +1,218 @@
|
|||
// sprite demo: window, audio, camera, font, tiled, render, fx, spritesheet, input, ui. @todo: finish spine
|
||||
// - rlyeh, public domain.
|
||||
// sprite routines
|
||||
// - rlyeh,
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\01-sprite.c` (windows)
|
||||
// `sh MAKE.bat demos/01-sprite.c` (linux, osx)
|
||||
// credits: original lovely demo by rxi (MIT License).
|
||||
// see https://github.com/rxi/autobatch/tree/master/demo/cats
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
void demo_kids(vec3 offs) {
|
||||
texture_t kids, catImage, shadowImage, inputs;
|
||||
int NUM_SPRITES = 100, NUM_SPRITES_CHANGED = 1;
|
||||
|
||||
typedef struct Cat {
|
||||
int cat, flip;
|
||||
double x, y;
|
||||
double vx, vy;
|
||||
double animSpeed;
|
||||
double moveTimer;
|
||||
double elapsed;
|
||||
} Cat;
|
||||
|
||||
void demo_cats() {
|
||||
static array(Cat) cats = 0;
|
||||
|
||||
// init
|
||||
static texture_t kids; do_once kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR );
|
||||
static vec3 pos[2] = {{490,362},{442,362}}, vel[2] = {0};
|
||||
static int row[2] = {0,3}, frame[2] = {0};
|
||||
static int inputs[2][4] = {{KEY_W,KEY_A,KEY_S,KEY_D},{KEY_UP,KEY_LEFT,KEY_DOWN,KEY_RIGHT}};
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
array_resize(cats, NUM_SPRITES); int i = 0;
|
||||
for each_array_ptr(cats, Cat, c) {
|
||||
randset(i++);
|
||||
c->x = randf() * window_width();
|
||||
c->y = randf() * window_height();
|
||||
c->vx = c->vy = 0;
|
||||
c->cat = randi(0, 4);
|
||||
c->flip = randf() < 0.5;
|
||||
c->animSpeed = 0.8 + randf() * 0.3;
|
||||
c->moveTimer = 0;
|
||||
c->elapsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// move
|
||||
for( int i = 0; i < countof(pos); ++i ) {
|
||||
vel[i].x = input(inputs[i][3]) - input(inputs[i][1]);
|
||||
vel[i].y = input(inputs[i][2]) - input(inputs[i][0]);
|
||||
pos[i].x = fmod(pos[i].x + vel[i].x, window_width() + 128);
|
||||
pos[i].y = fmod(pos[i].y + vel[i].y, window_height() + 128);
|
||||
frame[i] += vel[i].x || vel[i].y;
|
||||
const float dt = 1/120.f;
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
enum { yscale = 1 };
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Add velocity to position //and wrap to screen
|
||||
c->x += yscale * c->vx * dt; // % ;
|
||||
c->y += yscale * c->vy * dt; // % (int)window_height();
|
||||
if( c->x < 0 ) c->x += appw; else if( c->x > appw ) c->x -= appw;
|
||||
if( c->y < 0 ) c->y += apph; else if( c->y > apph ) c->y -= apph;
|
||||
// Faster animation if walking
|
||||
int boost = c->vx == 0 && c->vy == 0 ? 1 : 3;
|
||||
// Update elapsed time
|
||||
c->elapsed += dt * boost;
|
||||
// Update move timer -- if we hit zero then change or zero velocity
|
||||
c->moveTimer -= dt * boost;
|
||||
if (c->moveTimer < 0) {
|
||||
if (randf() < .2) {
|
||||
c->vx = (randf() * 2 - 1) * 30 * 2;
|
||||
c->vy = (randf() * 2 - 1) * 15 * 2;
|
||||
c->flip = c->vx < 0;
|
||||
} else {
|
||||
c->vx = c->vy = 0;
|
||||
}
|
||||
c->moveTimer = 1 + randf() * 5;
|
||||
}
|
||||
}
|
||||
|
||||
// render
|
||||
for( int i = 0; i < countof(pos); ++i ) {
|
||||
int col = frame[i] / 10, num_frame = row[i] * 4 + col % 4; // 4x4 tilesheet
|
||||
float position[3] = {pos[i].x,pos[i].y,pos[i].y}, offset[2]={0,0}, scale[2]={0.5,0.5};
|
||||
float spritesheet[3]={num_frame,4,4};
|
||||
sprite_sheet(kids,
|
||||
spritesheet, // num_frame in a 4x4 spritesheet
|
||||
position, 0, // position(x,y,depth:sort-by-Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
false, WHITE, false // is_additive, tint color, resolution-independent
|
||||
uint32_t white = rgba(255,255,255,255);
|
||||
uint32_t alpha = rgba(255,255,255,255*0.6);
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Get current animation frame (8x4 tilesheet)
|
||||
double e = c->elapsed * c->animSpeed;
|
||||
double frame_num = c->cat * 8 + floor( ((int)(e * 8)) % 4 );
|
||||
frame_num = c->vx != 0 || c->vy != 0 ? frame_num + 4 : frame_num;
|
||||
// Get x scale based on flip flag
|
||||
int xscale = yscale * (c->flip ? -1 : 1);
|
||||
// Draw
|
||||
float angle = 0; //fmod(window_time()*360/5, 360);
|
||||
float scale[2] = { 2*xscale, 2*yscale };
|
||||
float position[3] = { c->x,c->y,c->y }, no_offset[2] = {0,0}, spritesheet[3] = { frame_num,8,4 };
|
||||
sprite_sheet(catImage,
|
||||
spritesheet, // frame_number in a 8x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
no_offset, scale, // offset(x,y), scale(x,y)
|
||||
0,white,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
float position_neg_sort[3] = { c->x,c->y,-c->y }, offset[2] = {-1,5}, no_spritesheet[3] = {0,0,0};
|
||||
sprite_sheet(shadowImage,
|
||||
no_spritesheet, // no frame_number (0x0 spritesheet)
|
||||
position_neg_sort, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0,alpha,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void demo_hud() {
|
||||
// draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way
|
||||
static texture_t inputs; do_once inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR );
|
||||
float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation
|
||||
float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling
|
||||
float position[3] = {window_width() - tile_w, window_height() - tile_h, window_height() }; // position in screen-coordinates (x,y,z-index)
|
||||
sprite_sheet(inputs, spritesheet, position, 0/*deg*/, offset, scale, false, WHITE, 1);
|
||||
void demo_kids() {
|
||||
static int angle; //++angle;
|
||||
static int *x, *y, *v;
|
||||
|
||||
// init
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
y = (int*)REALLOC(y, 0 );
|
||||
x = (int*)REALLOC(x, NUM_SPRITES * sizeof(int) );
|
||||
y = (int*)REALLOC(y, NUM_SPRITES * sizeof(int) );
|
||||
v = (int*)REALLOC(v, NUM_SPRITES * sizeof(int) );
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
randset(i);
|
||||
x[i] = randi(0, window_width());
|
||||
y[i] = randi(0, window_height());
|
||||
v[i] = randi(1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// config
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
// move & render
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
y[i] = (y[i] + v[i]) % (apph + 128);
|
||||
int col = ((x[i] / 10) % 4); // 4x4 tilesheet
|
||||
int row = ((y[i] / 10) % 4);
|
||||
int num_frame = col * 4 + row;
|
||||
float position[3] = {x[i],y[i],y[i]}, offset[2]={0,0}, scale[2]={1,1}, spritesheet[3]={num_frame,4,4};
|
||||
sprite_sheet(kids,
|
||||
spritesheet, // num_frame in a 4x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0, ~0u, 0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
// window (80% sized, MSAA x4 flag)
|
||||
window_create(80.0, WINDOW_MSAA4);
|
||||
window_title(__FILE__);
|
||||
int main(int argc, char **argv) {
|
||||
window_create(75.f, 0);
|
||||
window_title("V4K - Sprite");
|
||||
window_color( SILVER );
|
||||
|
||||
// tiled map
|
||||
tiled_t tmx = tiled(vfs_read("castle.tmx"));
|
||||
// tmx.parallax = true;
|
||||
// options
|
||||
int do_cats = 1;
|
||||
NUM_SPRITES = optioni("--num_sprites,-N", NUM_SPRITES);
|
||||
if(do_cats) NUM_SPRITES/=2; // cat-sprite+cat-shadow == 2 sprites
|
||||
|
||||
// spine model
|
||||
//spine_t *spn = spine("goblins.json", "goblins.atlas", 0);
|
||||
// load sprites and sheets
|
||||
kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR );
|
||||
catImage = texture( "cat.png", TEXTURE_LINEAR ); //
|
||||
shadowImage = texture( "cat-shadow.png", TEXTURE_LINEAR );
|
||||
inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR );
|
||||
|
||||
// camera 2d
|
||||
// load all fx files, including subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// init camera (x,y) (z = zoom)
|
||||
camera_t cam = camera();
|
||||
cam.position = vec3(window_width()/2, window_height()/2, 3); // at(CX,CY) zoom(x3)
|
||||
cam.position = vec3(window_width()/2,window_height()/2,1);
|
||||
camera_enable(&cam);
|
||||
|
||||
// audio (both clips & streams)
|
||||
audio_t clip1 = audio_clip( "coin.wav" );
|
||||
audio_t clip2 = audio_clip( "pew.sfxr" );
|
||||
audio_t stream1 = audio_stream( "larry.mid" );
|
||||
audio_t stream2 = audio_stream( "monkey1.mid" );
|
||||
audio_t BGM = stream1;
|
||||
audio_play(BGM, 0);
|
||||
|
||||
// font config: faces (6 max) and colors (10 max)
|
||||
#define FONT_CJK FONT_FACE3
|
||||
#define FONT_YELLOW FONT_COLOR2
|
||||
#define FONT_LIME FONT_COLOR3
|
||||
font_face(FONT_CJK, "mplus-1p-medium.ttf", 48.f, FONT_JP|FONT_2048); // CJK|FONT_2048|FONT_OVERSAMPLE_Y);
|
||||
font_color(FONT_YELLOW, RGB4(255,255,0,255));
|
||||
font_color(FONT_LIME, RGB4(128,255,0,255));
|
||||
|
||||
// fx: load all post fx files in all subdirs. enable a few filters by default
|
||||
fx_load("fx**.fs");
|
||||
fx_enable(fx_find("fxCRT2.fs"), 1);
|
||||
fx_enable(fx_find("fxGrain.fs"), 1);
|
||||
fx_enable(fx_find("fxContrast.fs"), 1);
|
||||
fx_enable(fx_find("fxVignette.fs"), 1);
|
||||
|
||||
// demo loop
|
||||
while (window_swap() && !input_down(KEY_ESC)) {
|
||||
|
||||
// handle input
|
||||
if( input_down(KEY_F5) ) window_reload();
|
||||
if( input_down(KEY_F11) ) window_fullscreen( !window_has_fullscreen() );
|
||||
while(window_swap()) {
|
||||
if( input(KEY_F5)) window_reload();
|
||||
if( input(KEY_F11)) window_fullscreen( window_has_fullscreen() ^ 1);
|
||||
if( input(KEY_ESC) ) break;
|
||||
|
||||
// camera panning (x,y) & zooming (z)
|
||||
if( !ui_hover() && !ui_active() ) {
|
||||
if( input(MOUSE_L) ) cam.position.x += input_diff(MOUSE_X);
|
||||
if( input(MOUSE_L) ) cam.position.y += input_diff(MOUSE_Y);
|
||||
cam.position.z += input_diff(MOUSE_W) * 0.1;
|
||||
if( input(MOUSE_L) ) cam.position.x -= input_diff(MOUSE_X);
|
||||
if( input(MOUSE_L) ) cam.position.y -= input_diff(MOUSE_Y);
|
||||
cam.position.z += input_diff(MOUSE_W) * 0.1; // cam.p.z += 0.001f; for tests
|
||||
}
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
profile("Rendering") {
|
||||
vec3 center = add3(cam.position,vec3(-window_width()/1,-window_height()/2,0));
|
||||
// render tiled map
|
||||
tiled_render(tmx, center);
|
||||
//
|
||||
demo_kids(vec3(0,0,1));
|
||||
demo_hud();
|
||||
// render spine model
|
||||
// spine_animate(spn, !window_has_pause() * window_delta());
|
||||
// spine_render(spn, vec3(cam.position.x, cam.position.y, 1), true );
|
||||
// sprite_flush();
|
||||
profile("Sprite batching") {
|
||||
if(do_cats) demo_cats(); else demo_kids();
|
||||
}
|
||||
|
||||
// subtitle sample
|
||||
font_print(
|
||||
FONT_BOTTOM FONT_CENTER
|
||||
FONT_CJK FONT_H1
|
||||
FONT_YELLOW "私はガラスを食べられます。" FONT_LIME "それは私を傷つけません。\n"
|
||||
);
|
||||
// flush retained renderer, so we ensure the fbos are up to date before fx_end()
|
||||
profile("Sprite flushing") {
|
||||
sprite_flush();
|
||||
}
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// ui
|
||||
if( ui_panel("Audio", 0)) {
|
||||
static float bgm = 1, sfx = 1, master = 1;
|
||||
if( ui_slider2("BGM", &bgm, va("%.2f", bgm))) audio_volume_stream(bgm);
|
||||
if( ui_slider2("SFX", &sfx, va("%.2f", sfx))) audio_volume_clip(sfx);
|
||||
if( ui_slider2("Master", &master, va("%.2f", master))) audio_volume_master(master);
|
||||
if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream1, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Monkey Island", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream2, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(clip1, 0);
|
||||
if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(clip2, 0);
|
||||
ui_panel_end();
|
||||
// draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way
|
||||
{
|
||||
vec3 old_pos = camera_get_active()->position;
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = vec3(window_width()/2,window_height()/2,1);
|
||||
|
||||
float zindex = window_height(); // large number, on top
|
||||
float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation
|
||||
float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling
|
||||
float position[3] = {window_width() - tile_w, window_height() - tile_h, zindex }; // position in screen-coordinates
|
||||
sprite_sheet(inputs, spritesheet, position, 0/*rotation*/, offset, scale, false/*is_additive*/, WHITE/*color*/, false/*resolution_independant*/);
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = old_pos;
|
||||
}
|
||||
if( ui_panel("Tiled", 0)) {
|
||||
ui_float("Zoom in", &cam.position.z);
|
||||
tiled_ui(&tmx);
|
||||
ui_panel_end();
|
||||
}
|
||||
/*if( ui_panel("Spine", 0)) {
|
||||
spine_ui(spn);
|
||||
ui_panel_end();
|
||||
}*/
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
}
|
||||
|
||||
if( ui_panel("Sprite", 0) ) {
|
||||
const char *labels[] = {"Kids","Cats"};
|
||||
if( ui_list("Sprite type", labels, countof(labels), &do_cats) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_int("Number of Sprites", &NUM_SPRITES) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_clampf("Zoom", &cam.position.z, 0.1, 10));
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this demo supersedes following old sources:
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-audio.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-font.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-spine.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-sprite.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-tiled.c
|
||||
// https://github.com/r-lyeh/V4K/blob/45e34d7890b2b8fe1f4994f4b76e496280d83cb6/demos/00-tilemap.c
|
||||
|
|
|
@ -51,44 +51,40 @@ int main() {
|
|||
}
|
||||
}
|
||||
|
||||
fx_begin();
|
||||
// draw skybox
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
|
||||
// draw skybox
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
// world
|
||||
ddraw_grid(0);
|
||||
|
||||
// world
|
||||
ddraw_grid(0);
|
||||
// boids
|
||||
static swarm_t sw;
|
||||
if( do_boids_demo ) profile("boids") {
|
||||
do_once sw = swarm();
|
||||
do_once array_push(sw.steering_targets, vec3(0,0,0));
|
||||
do_once for(int i = 0; i < 100; ++i)
|
||||
array_push(sw.boids, boid(scale3(rnd3(),10), rnd3())); // pos,vel
|
||||
|
||||
// boids
|
||||
static swarm_t sw;
|
||||
if( do_boids_demo ) profile("boids") {
|
||||
do_once sw = swarm();
|
||||
do_once array_push(sw.steering_targets, vec3(0,0,0));
|
||||
do_once for(int i = 0; i < 100; ++i)
|
||||
array_push(sw.boids, boid(scale3(rnd3(),10), rnd3())); // pos,vel
|
||||
// move
|
||||
sw.steering_targets[0] = cam.position;
|
||||
swarm_update(&sw, window_delta());
|
||||
|
||||
// move
|
||||
sw.steering_targets[0] = cam.position;
|
||||
swarm_update(&sw, window_delta());
|
||||
|
||||
// draw
|
||||
for (int j = 0, end = array_count(sw.boids); j < end; ++j) {
|
||||
vec3 dir = norm3(sub3(sw.boids[j].position, sw.boids[j].prev_position));
|
||||
ddraw_boid(sw.boids[j].position, dir);
|
||||
}
|
||||
// draw
|
||||
for (int j = 0, end = array_count(sw.boids); j < end; ++j) {
|
||||
vec3 dir = norm3(sub3(sw.boids[j].position, sw.boids[j].prev_position));
|
||||
ddraw_boid(sw.boids[j].position, dir);
|
||||
}
|
||||
}
|
||||
|
||||
// showcase many debugdraw shapes
|
||||
if( do_debugdraw_demo ) {
|
||||
ddraw_demo();
|
||||
}
|
||||
// showcase many debugdraw shapes
|
||||
if( do_debugdraw_demo ) {
|
||||
ddraw_demo();
|
||||
}
|
||||
|
||||
// showcase many colliding tests
|
||||
if( do_colliders_demo ) {
|
||||
collide_demo();
|
||||
}
|
||||
|
||||
fx_end();
|
||||
// showcase many colliding tests
|
||||
if( do_colliders_demo ) {
|
||||
collide_demo();
|
||||
}
|
||||
|
||||
// ui
|
||||
if( ui_panel("App", 0) ) {
|
||||
|
@ -106,15 +102,6 @@ int main() {
|
|||
if( ui_float3("Position", cam.position.v3) ) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ int main() {
|
|||
array_resize(M, 32*32);
|
||||
for(int z = 0, i = 0; z < 32; ++z) {
|
||||
for(int x = 0; x < 32; ++x, ++i) {
|
||||
vec3 p = vec3(-x*9,0,-z*9);
|
||||
vec3 r = vec3(0,-90,0); // kgirl: 0,0,0
|
||||
vec3 s = vec3(2,2,2);
|
||||
compose44(M[i], p, eulerq(r), s);
|
||||
vec3 pos = vec3(-x*3,0,-z*3);
|
||||
vec3 rot = vec3(0,-90,0); // kgirl: 0,0,0
|
||||
vec3 sca = vec3(1,1,1); // kgirl: 2,2,2
|
||||
compose44(M[i], pos, eulerq(rot), sca);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,15 +167,6 @@ int main() {
|
|||
shader_vec3("u_rimrange", rimrange);
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, b);
|
||||
ui_fx(i);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@ void DrawModel(mesh_t *m) {
|
|||
"fragcolor = vec4(v_normal, 1.0);\n" // diffuse
|
||||
"}";
|
||||
|
||||
static unsigned program; do_once program = shader(vs, fs, "att_position,att_normal", "fragcolor", "");
|
||||
static unsigned program; do_once program = shader(vs, fs, "att_position,att_normal", "fragcolor", NULL);
|
||||
shader_bind(program);
|
||||
shader_mat44("VP", VP);
|
||||
shader_mat44("M", M);
|
||||
|
|
|
@ -142,14 +142,6 @@ int main() {
|
|||
if(ui_bool("Two sided", &do_twosided)) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +156,7 @@ int main() {
|
|||
// create camera
|
||||
camera_t cam = camera();
|
||||
// load video, RGB texture, no audio
|
||||
video_t *v = video( "bjork-all-is-full-of-love.mp4", VIDEO_RGB | VIDEO_NO_AUDIO ); video_seek(v, 30);
|
||||
video_t *v = video( "pexels-pachon-in-motion-17486489.mp4", VIDEO_RGB | VIDEO_NO_AUDIO | VIDEO_LOOP ); video_seek(v, 30);
|
||||
// load texture
|
||||
texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB);
|
||||
texture_t t2 = texture("matcaps/material3", 0);
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
// - rlyeh, public domain.
|
||||
//
|
||||
// Compile with:
|
||||
// `make demos\04-controller.c` (windows)
|
||||
// `sh MAKE.bat demos/04-controller.c` (linux, osx)
|
||||
// `make demos\99-controller.c` (windows)
|
||||
// `sh MAKE.bat demos/99-controller.c` (linux, osx)
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
// 75% window, MSAAx2 flag
|
||||
window_create(75, WINDOW_MSAA8);
|
||||
window_create(75, WINDOW_MSAA2);
|
||||
|
||||
// fx: load all post fx files in all subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
@ -262,14 +262,6 @@ int main() {
|
|||
ui_label("Keys I/J/K/L + Z/X");
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, b);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
// material demo
|
||||
// - rlyeh, public domain
|
||||
//
|
||||
// @todo: object_print(obj, "");
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
// create the window
|
||||
window_create( 0.75f, WINDOW_MSAA8 );
|
||||
window_color( GRAY );
|
||||
|
||||
// create camera
|
||||
camera_t cam = camera();
|
||||
|
@ -41,22 +47,17 @@ int main() {
|
|||
|
||||
// create point light
|
||||
light_t* l = scene_spawn_light();
|
||||
light_type(l, LIGHT_SPOT);
|
||||
light_ambient(l, vec3(0.03,0.03,0.06));
|
||||
light_specular(l, scale3(vec3(1,1.0,0.2), 2.5f));
|
||||
light_power(l, 56.f);
|
||||
light_type(l, LIGHT_POINT);
|
||||
|
||||
while(window_swap() && !input(KEY_ESC)) {
|
||||
// draw environment
|
||||
viewport_color( RGB3(22,22,32) );
|
||||
ddraw_grid(0);
|
||||
|
||||
// update video
|
||||
video_decode( v );
|
||||
|
||||
// update light data
|
||||
// update light position
|
||||
light_teleport(l, cam.position);
|
||||
light_dir(l, cam.look);
|
||||
|
||||
// draw scene
|
||||
scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF);
|
|
@ -8,10 +8,8 @@ int main() {
|
|||
window_create(80, WINDOW_MSAA4 | WINDOW_SQUARE);
|
||||
|
||||
// audio (both streams & clips)
|
||||
audio_t stream1 = audio_stream( "wrath_of_the_djinn.xm" );
|
||||
audio_t stream2 = audio_stream( "larry.mid" );
|
||||
audio_t stream3 = audio_stream( "monkey1.mid" );
|
||||
audio_t stream4 = audio_stream( "waterworld-map.fur" );
|
||||
audio_t stream1 = audio_stream( "larry.mid" );
|
||||
audio_t stream2 = audio_stream( "waterworld-map.fur" );
|
||||
audio_t BGM = stream1;
|
||||
audio_play(BGM, 0);
|
||||
|
||||
|
@ -27,10 +25,8 @@ int main() {
|
|||
if( ui_slider2("BGM", &bgm, va("%.2f", bgm))) audio_volume_stream(bgm);
|
||||
if( ui_slider2("SFX", &sfx, va("%.2f", sfx))) audio_volume_clip(sfx);
|
||||
if( ui_slider2("Master", &master, va("%.2f", master))) audio_volume_master(master);
|
||||
if( ui_label2_toolbar("BGM: Wrath of the Djinn", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream1, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream2, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Monkey Island", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream3, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Waterworld Map", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream4, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream1, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Waterworld Map", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = stream2, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(SFX1, 0);
|
||||
if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(SFX2, 0);
|
||||
ui_window_end();
|
|
@ -5,8 +5,7 @@
|
|||
|
||||
int main() {
|
||||
// 75% window, msaa x2
|
||||
window_create( 35, WINDOW_MSAA2 );
|
||||
window_aspect_lock(910, 540);
|
||||
window_create( 75, WINDOW_MSAA2 );
|
||||
|
||||
// load video
|
||||
int is_rgb = flag("--rgb") ? 1 : 0;
|
|
@ -5,12 +5,7 @@ const char *SKY_DIRS[] = {
|
|||
"cubemaps/bridge3/",
|
||||
"cubemaps/colors/",
|
||||
"cubemaps/colors2/",
|
||||
"cubemaps/mountain/",
|
||||
"cubemaps/room/",
|
||||
"cubemaps/stardust/",
|
||||
"hdr/MonValley_G_DirtRoad_1k.hdr",
|
||||
"hdr/Factory_Catwalk_1k.hdr",
|
||||
"hdr/Shiodome_Stairs_1k.hdr",
|
||||
"hdr/Tokyo_BigSight_1k.hdr",
|
||||
};
|
||||
|
||||
int OBJ_MDL = 0;
|
|
@ -0,0 +1,38 @@
|
|||
// shadertoy viewer
|
||||
// - rlyeh, public domain
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
window_create(75, 0); // WINDOW_MSAA8);
|
||||
|
||||
array(char*) list = 0;
|
||||
for( const char **dir = file_list("demos/art/shadertoys/", "**.fs"); *dir; dir++ ) {
|
||||
array_push(list, STRDUP(file_name(*dir)));
|
||||
}
|
||||
|
||||
shadertoy_t sh = shadertoy(*list, 0); // 0:no flags
|
||||
|
||||
while(window_swap()) {
|
||||
// selector
|
||||
static int selected = 0;
|
||||
int prev = input_down(KEY_UP) || input_down(KEY_LEFT);
|
||||
int next = input_down(KEY_DOWN) || input_down(KEY_RIGHT);
|
||||
if( prev ) if( selected > 0 ) sh = shadertoy( list[--selected], 0 );
|
||||
if( next ) if( selected < array_count(list) - 1 ) sh = shadertoy( list[++selected], 0 );
|
||||
|
||||
// draw
|
||||
shadertoy_render(&sh, window_delta());
|
||||
|
||||
// UI
|
||||
if( ui_panel("Shadertoy", 1)) {
|
||||
for( int i = 0; i < array_count(list); ++i ) {
|
||||
bool in_use = i == selected;
|
||||
if( ui_bool(list[i], &in_use) ) {
|
||||
sh = shadertoy( list[selected = i], 0 );
|
||||
}
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
https://www.tastyfish.cz/lrs/bytebeat.html
|
||||
Outputting the variable i creates a periodical saw-shaped beat, multiplication/division decreases/increases the speed, addition/subtraction shifts the phase backward/forward.
|
||||
Squaring (and other powers) create a wah-wah effect.
|
||||
Crazier patterns can be achieved by using the variable in places of numerical constants, e.g. i << ((i / 512) % 8) (shifting by a value that depends on the variable).
|
||||
Modulo (%) increases the frequency and decreases volume (limits the wave peak).
|
||||
So called Sierpinski harmonies are often used melodic expressions of the form i*N & i >> M.
|
||||
Bitwise and (&) can add distortion (create steps in the wave).
|
||||
A macro structure of the song (silent/louds parts, verse/chorus, ...) can be achieved by combining multiple patterns with some low-frequency pattern, e.g. this alternates a slower and faster beat: int cond = (i & 0x8000) == 0;, cond * (i / 16) + !cond * (i / 32)
|
||||
Extra variables can add more complexity (e.g. precompute some variable a which will subsequently be used multiple times in the final formula).
|
||||
*/
|
||||
|
||||
int main(void) {
|
||||
for (int t = 0;; ++t) {
|
||||
putchar(
|
||||
t|(t<<((t/920)%16))|(t/3*t&(t<<13)*t)|(t%16386?123:t&203?148:3)&(t/920)
|
||||
// (t/8)>>(t>>9)*t/((t>>14&3)+4)
|
||||
// ((1-(((t+10)>>((t>>9)&((t>>14))))&(t>>4&-2)))*2)*(((t>>10)^((t+((t>>6)&127))>>10))&1)*32+128
|
||||
// t*((0xbadbea75>>((t>>12)&30)&3)*0.25*(0x5afe5>>((t>>16)&28)&3))
|
||||
// ((t>>4)*(13&(0x8898a989>>(t>>11&30)))&255)+((((t>>9|(t>>2)|t>>8)*10+4*((t>>2)&t>>15|t>>8))&255)>>1)
|
||||
// t*((t>>12|t>>8)&63&t>>4)
|
||||
// ((0x47 >> ((t >> 9) % 32)) & (t >> (t % 32))) | (0x57 >> ((t >> 7) % 32)) | (0x06 >> ((t >> ((((t * 11) >> 14) & 0x0e) % 32)) % 32))
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -27,7 +27,7 @@ int main() {
|
|||
ssbo_update(0, sizeof(data), &data);
|
||||
|
||||
compute_dispatch(TEX_WIDTH/10, TEX_WIDTH/10, 1);
|
||||
image_write_barrier();
|
||||
write_barrier_image();
|
||||
|
||||
fullscreen_quad_rgb(tex, 2.2);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
// framework demo
|
||||
// - rlyeh, public domain
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
// options
|
||||
bool do_about = 0;
|
||||
float do_scale = 0.10f;
|
||||
bool do_debugdraw = 0;
|
||||
float do_gamepad_deadzone = 0.15f;
|
||||
vec2 do_gamepad_polarity = vec2(+1,+1);
|
||||
vec2 do_gamepad_sensitivity = vec2(0.1f,0.1f);
|
||||
vec2 do_mouse_polarity = vec2(+1,-1);
|
||||
vec2 do_mouse_sensitivity = vec2(0.2f,0.2f);
|
||||
bool do_billboard_x = 0, do_billboard_y = 0, do_billboard_z = 0;
|
||||
|
||||
// window (80% sized, MSAA x4 flag)
|
||||
window_create(80, WINDOW_MSAA4);
|
||||
window_title(__FILE__);
|
||||
|
||||
// load all fx files, including subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// load skybox
|
||||
skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0); // --mie for rayleigh/mie scattering
|
||||
|
||||
// load static scene
|
||||
model_t sponza;
|
||||
int do_sponza = flag("--sponza");
|
||||
if( do_sponza ) {
|
||||
sponza = model("sponza.obj", 0); // MODEL_NO_TEXTURES);
|
||||
translation44(sponza.pivot, 0,-1,0);
|
||||
rotate44(sponza.pivot, -90,1,0,0);
|
||||
scale44(sponza.pivot, 10,10,10);
|
||||
}
|
||||
|
||||
model_t shaderball;
|
||||
int do_shaderball = flag("--shaderball");
|
||||
if( do_shaderball ) {
|
||||
shaderball = model("shaderball.glb", 0);
|
||||
translation44(shaderball.pivot, 0,0,-10);
|
||||
rotate44(shaderball.pivot, -90,1,0,0);
|
||||
scale44(shaderball.pivot, 0.02,0.02,0.02);
|
||||
}
|
||||
|
||||
// animated models loading
|
||||
int model_flags = flag("--matcaps") ? MODEL_MATCAPS : 0;
|
||||
model_t girl = model("kgirl/kgirls01.fbx", model_flags);
|
||||
model_t alien = model("alien/alien_helmet.fbx", model_flags); rotation44(alien.pivot, -90,1,0,0);
|
||||
model_t george = model("robots/george.fbx", model_flags);
|
||||
model_t leela = model("robots/leela.fbx", model_flags);
|
||||
model_t mike = model("robots/mike.fbx", model_flags);
|
||||
model_t stan = model("robots/stan.fbx", model_flags);
|
||||
model_t robots[4] = { george, leela, mike, stan };
|
||||
for( int i = 0; i < countof(robots); ++i ) {
|
||||
rotation44(robots[i].pivot, -90,1,0,0);
|
||||
}
|
||||
|
||||
if( flag("--matcaps") ) {
|
||||
// patch models to use matcaps
|
||||
model_set_texture(george, texture("matcaps/3B6E10_E3F2C3_88AC2E_99CE51-256px", 0)); // green
|
||||
model_set_texture(leela, texture("matcaps/39433A_65866E_86BF8B_BFF8D8-256px", 0));
|
||||
model_set_texture(mike, texture("matcaps/394641_B1A67E_75BEBE_7D7256-256px.png", 0));
|
||||
model_set_texture(stan, texture("matcaps/test_steel", 0));
|
||||
model_set_texture(girl, texture("matcaps/material3", 0));
|
||||
model_set_texture(alien, texture("matcaps/material3", 0));
|
||||
|
||||
if( flag("--shaderball") )
|
||||
model_set_texture(shaderball, texture("matcaps/normals", 0));
|
||||
}
|
||||
|
||||
// camera
|
||||
camera_t cam = camera();
|
||||
cam.speed = 0.2f;
|
||||
|
||||
// audio (both clips & streams)
|
||||
audio_t SFX1 = audio_clip( "coin.wav" );
|
||||
audio_t SFX2 = audio_clip( "pew.sfxr" );
|
||||
audio_t BGM1 = audio_stream( "waterworld-map.fur"); // wrath_of_the_djinn.xm" );
|
||||
audio_t BGM2 = audio_stream( "larry.mid" );
|
||||
audio_t BGM3 = audio_stream( "monkey1.mid" ), BGM = BGM1;
|
||||
audio_play(SFX1, 0);
|
||||
audio_play(BGM, 0);
|
||||
|
||||
// demo loop
|
||||
while (window_swap())
|
||||
{
|
||||
// input
|
||||
if( input_down(KEY_ESC) ) break;
|
||||
if( input_down(KEY_F5) ) window_reload();
|
||||
if( input_down(KEY_W) && input_held(KEY_LCTRL) ) break;
|
||||
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
|
||||
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
||||
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
|
||||
|
||||
// vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), do_gamepad_deadzone + 1e-3);
|
||||
// vec2 filtered_rpad = input_filter_deadzone(input2(GAMEPAD_RPAD), do_gamepad_deadzone + 1e-3);
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||
camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
window_cursor( !active );
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
// queue debug drawcalls
|
||||
profile("Debugdraw") {
|
||||
ddraw_grid(0);
|
||||
ddraw_color(YELLOW);
|
||||
ddraw_text(vec3(+1,+1,-1), 0.04f, va("(%f,%f,%f)", cam.position.x,cam.position.y,cam.position.z));
|
||||
if(do_debugdraw) ddraw_demo(); // showcase many debugdraw shapes
|
||||
ddraw_color(YELLOW);
|
||||
ddraw_flush();
|
||||
}
|
||||
|
||||
// draw skybox
|
||||
profile("Skybox") {
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
}
|
||||
|
||||
profile("Skeletal update") if(!window_has_pause()) {
|
||||
float delta = window_delta() * 30; // 30fps anim
|
||||
|
||||
// animate girl & alien
|
||||
girl.curframe = model_animate(girl, girl.curframe + delta);
|
||||
alien.curframe = model_animate(alien, alien.curframe + delta);
|
||||
|
||||
// animate robots
|
||||
for(int i = 0; i < countof(robots); ++i) {
|
||||
robots[i].curframe = model_animate(robots[i], robots[i].curframe + delta);
|
||||
}
|
||||
}
|
||||
|
||||
profile("Skeletal render") {
|
||||
static vec3 p = {-10,0,-10}, r = {0,0,0}, s = {2,2,2};
|
||||
gizmo(&p, &r, &s);
|
||||
mat44 M; rotationq44(M, eulerq(r)); scale44(M, s.x,s.y,s.z); relocate44(M, p.x,p.y,p.z);
|
||||
|
||||
model_render(girl, cam.proj, cam.view, M, 0);
|
||||
|
||||
aabb box = model_aabb(girl, M);
|
||||
ddraw_color(YELLOW);
|
||||
ddraw_aabb(box.min, box.max);
|
||||
}
|
||||
|
||||
profile("Skeletal render") {
|
||||
static vec3 p = {+10,0,-10}, r = {0,-90,0}, s = {1,1,1};
|
||||
//gizmo(&p, &r, &s);
|
||||
mat44 M; rotationq44(M, eulerq(r)); scale44(M, s.x,s.y,s.z); relocate44(M, p.x,p.y,p.z);
|
||||
|
||||
model_render(alien, cam.proj, cam.view, M, 0);
|
||||
|
||||
aabb box = model_aabb(alien, M); // @fixme: neg Y
|
||||
ddraw_color(YELLOW);
|
||||
//ddraw_aabb(box.min, box.max);
|
||||
}
|
||||
|
||||
profile("Skeletal render") for(int i = 0; i < countof(robots); ++i) {
|
||||
float scale = 0.50;
|
||||
mat44 M; copy44(M, robots[i].pivot); translate44(M, i*3,0,0); scale44(M, scale,scale,scale);
|
||||
model_render(robots[i], cam.proj, cam.view, M, 0);
|
||||
}
|
||||
|
||||
if(do_sponza) profile("Sponza") {
|
||||
float scale = 1.00;
|
||||
mat44 M; copy44(M, sponza.pivot); translate44(M, 0,0,0); scale44(M, scale,scale,scale);
|
||||
model_render(sponza, cam.proj, cam.view, M, 0);
|
||||
}
|
||||
|
||||
if(do_shaderball) profile("Shaderball") {
|
||||
float scale = 1.00;
|
||||
mat44 M; copy44(M, shaderball.pivot); translate44(M, 0,0,0); scale44(M, scale,scale,scale);
|
||||
model_render(shaderball, cam.proj, cam.view, M, 0);
|
||||
}
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// font demo
|
||||
do_once font_scales(FONT_FACE1, 48, 24, 18, 12, 9, 6);
|
||||
font_print(va(FONT_RIGHT FONT_BOTTOM FONT_H4 "%5.2f FPS", window_fps()));
|
||||
|
||||
// queue ui
|
||||
if( ui_panel("App", 0)) {
|
||||
if(ui_bool("Show debugdraw demo", &do_debugdraw)) {}
|
||||
if(ui_separator()) {}
|
||||
if(ui_slider("Gamepad deadzone", &do_gamepad_deadzone)) {}
|
||||
if(ui_float2("Gamepad polarity", do_gamepad_polarity.v2)) {}
|
||||
if(ui_float2("Gamepad sensitivity", do_gamepad_sensitivity.v2)) {}
|
||||
if(ui_separator()) {}
|
||||
if(ui_float2("Mouse polarity", do_mouse_polarity.v2)) {}
|
||||
if(ui_float2("Mouse sensitivity", do_mouse_sensitivity.v2)) {}
|
||||
if(ui_separator()) {}
|
||||
if(ui_button("About...")) { do_about = 1; audio_play(SFX1, 0); }
|
||||
if(ui_dialog("About", __FILE__ "\n" __DATE__ "\n" "Public Domain.", 0, &do_about)) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("Camera", 0)) {
|
||||
if( ui_float("Speed", &cam.speed) ) {}
|
||||
if( ui_float3("Position", cam.position.v3) ) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("Audio", 0)) {
|
||||
static float bgm = 1, sfx = 1, master = 1;
|
||||
if( ui_slider2("BGM", &bgm, va("%.2f", bgm))) audio_volume_stream(bgm);
|
||||
if( ui_slider2("SFX", &sfx, va("%.2f", sfx))) audio_volume_clip(sfx);
|
||||
if( ui_slider2("Master", &master, va("%.2f", master))) audio_volume_master(master);
|
||||
if( ui_label2_toolbar("BGM: Waterworld Map" /*Wrath of the Djinn"*/, ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM1, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Leisure Suit Larry", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM2, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("BGM: Monkey Island", ICON_MD_VOLUME_UP)) audio_stop(BGM), audio_play(BGM = BGM3, AUDIO_SINGLE_INSTANCE);
|
||||
if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(SFX1, 0);
|
||||
if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(SFX2, 0);
|
||||
ui_panel_end();
|
||||
}
|
||||
|
||||
input_demo(); // show some keyboard/mouse/gamepad UI tabs
|
||||
ui_demo(1); // show all UI widgets in a tab
|
||||
}
|
||||
|
||||
// data tests (json5)
|
||||
const char json5[] =
|
||||
" /* json5 */ // comment\n"
|
||||
" abc: 42.67, def: true, integer:0x100 \n"
|
||||
" huge: 2.2239333e5, \n"
|
||||
" hello: 'world /*comment in string*/ //again', \n"
|
||||
" children : { a: 1, b: 2, c: 3 },\n"
|
||||
" array: [+1,2,-3,4,5], \n"
|
||||
" invalids : [ nan, NaN, -nan, -NaN, inf, Infinity, -inf, -Infinity ],";
|
||||
if( json_push(json5) ) {
|
||||
assert( json_float("/abc") == 42.67 );
|
||||
assert( json_int("/def") == 1 );
|
||||
assert( json_int("/integer") == 0x100 );
|
||||
assert( json_float("/huge") > 2.22e5 );
|
||||
assert( strlen(json_string("/hello")) == 35 );
|
||||
assert( json_int("/children/a") == 1 );
|
||||
assert( json_int("/children.b") == 2 );
|
||||
assert( json_int("/children[c]") == 3 );
|
||||
assert( json_int("/array[%d]", 2) == -3 );
|
||||
assert( json_count("/invalids") == 8 );
|
||||
assert( isnan(json_float("/invalids[0]")) );
|
||||
assert( !json_find("/non_existing") );
|
||||
assert( PRINTF("json5 tests OK\n") );
|
||||
json_pop();
|
||||
}
|
||||
|
||||
// data tests (xml)
|
||||
const char *xml = vfs_read("test1.xml");
|
||||
if( xml_push(xml) ) {
|
||||
puts( xml );
|
||||
puts( xml_string("/person/firstName/$") );
|
||||
puts( xml_string("/person/lastName/$") );
|
||||
puts( xml_string("/person/address/@type") );
|
||||
xml_pop();
|
||||
}
|
||||
|
||||
// network test (https)
|
||||
array(char) webfile = download("https://www.google.com/");
|
||||
printf("Network test: %d bytes downloaded from google.com\n", array_count(webfile));
|
||||
|
||||
// script test (lua)
|
||||
script_run( "-- Bye.lua\nio.write(\"script test: Bye world!, from \", _VERSION, \"\\n\")" );
|
||||
}
|
176
demos/99-dung.c
176
demos/99-dung.c
|
@ -1,176 +0,0 @@
|
|||
#include "v4k.h"
|
||||
|
||||
#define WS 32
|
||||
|
||||
enum {
|
||||
WALL=2, DOOR=4
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int16_t id:8;
|
||||
int16_t flags:8;
|
||||
} cell_t;
|
||||
|
||||
#define cell_t(...) C_CAST(cell_t, __VA_ARGS__)
|
||||
|
||||
typedef struct {
|
||||
cell_t grid[WS*WS];
|
||||
mesh_t level;
|
||||
} world_t;
|
||||
|
||||
static world_t world;
|
||||
|
||||
void world_init() {
|
||||
int i, j;
|
||||
for (i = 0; i < WS; ++i) {
|
||||
for (j = 0; j < WS; ++j) {
|
||||
if (i == 0 || i == WS-1 || j == 0 || j == WS-1) {
|
||||
// Border cells
|
||||
world.grid[i*WS + j] = cell_t(0, WALL);
|
||||
} else {
|
||||
// Interior cells
|
||||
world.grid[i*WS + j] = cell_t(rand()%3, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
world.level = mesh();
|
||||
|
||||
|
||||
const int cube_vertices = 24;
|
||||
const int cube_triangles = 12;
|
||||
const int vertex_count = WS * WS * cube_vertices;
|
||||
const int index_count = WS * WS * cube_triangles * 3;
|
||||
|
||||
struct vert {
|
||||
vec3 pos;
|
||||
vec3 normal;
|
||||
};
|
||||
|
||||
struct vert verts[vertex_count];
|
||||
|
||||
unsigned index_data[index_count];
|
||||
|
||||
int vertex_index = 0;
|
||||
int index_index = 0;
|
||||
|
||||
static vec3 normals[6] = {
|
||||
{1, 0, 0}, {-1, 0, 0},
|
||||
{0, 1, 0}, {0, -1, 0},
|
||||
{0, 0, 1}, {0, 0, -1}
|
||||
};
|
||||
|
||||
for(int z = 0; z < WS; ++z) {
|
||||
for(int x = 0; x < WS; ++x) {
|
||||
if(world.grid[z*WS + x].id >= 0) {
|
||||
for(int face = 0; face < 6; ++face) {
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
|
||||
vertex_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// Create 12 triangles for the cube
|
||||
static unsigned indices[12][3] = {
|
||||
{0, 1, 2}, {2, 1, 3}, {4, 5, 6}, {6, 5, 7},
|
||||
{0, 4, 1}, {1, 4, 5}, {2, 6, 3}, {3, 6, 7},
|
||||
{0, 2, 4}, {4, 2, 6}, {1, 3, 5}, {5, 3, 7}
|
||||
};
|
||||
for(int i = 0; i < 12; ++i) {
|
||||
for(int j = 0; j < 3; ++j) {
|
||||
index_data[index_index++] = vertex_index - 24 + indices[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mesh_update(&world.level, "p3 n3", sizeof(struct vert), vertex_count, verts, index_count, index_data, 0);
|
||||
}
|
||||
|
||||
void draw_world() {
|
||||
static mat44 M; do_once id44(M);
|
||||
static mat44 VP; multiply44x2(VP, camera_get_active()->proj, camera_get_active()->view);
|
||||
|
||||
static const char *vs =
|
||||
"#version 130\n"
|
||||
"//" FILELINE "\n"
|
||||
"uniform mat4 M,VP;\n"
|
||||
"in vec3 att_position;\n"
|
||||
"in vec3 att_normal;\n"
|
||||
"out vec3 v_normal;\n"
|
||||
"void main() {\n"
|
||||
" v_normal = normalize(att_position);\n"
|
||||
" gl_Position = M * VP * vec4( att_position, 1.0 );\n"
|
||||
"}\n";
|
||||
static const char *fs =
|
||||
"#version 130\n"
|
||||
"//" FILELINE "\n"
|
||||
"in vec3 v_normal;\n"
|
||||
"out vec4 fragcolor;\n"
|
||||
"void main() {\n"
|
||||
"fragcolor = vec4(v_normal, 1.0);\n" // diffuse
|
||||
"}";
|
||||
|
||||
static unsigned program; do_once program = shader(vs, fs, "att_position,att_normal", "fragcolor", "");
|
||||
shader_bind(program);
|
||||
shader_mat44("VP", VP);
|
||||
shader_mat44("M", M);
|
||||
|
||||
mesh_render(&world.level);
|
||||
}
|
||||
|
||||
|
||||
int main() {
|
||||
window_create(80, WINDOW_MSAA8);
|
||||
window_title(__FILE__);
|
||||
|
||||
// init world
|
||||
world_init();
|
||||
|
||||
// load all fx files
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// load skybox
|
||||
skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0); // --mie for rayleigh/mie scattering
|
||||
|
||||
// camera
|
||||
camera_t cam = camera();
|
||||
cam.speed = 0.2f;
|
||||
|
||||
// audio (both clips & streams)
|
||||
// audio_t SFX1 = audio_clip( "coin.wav" );
|
||||
// audio_t SFX2 = audio_clip( "pew.sfxr" );
|
||||
// audio_t BGM1 = audio_stream( "waterworld-map.fur"); // wrath_of_the_djinn.xm" );
|
||||
// audio_t BGM2 = audio_stream( "larry.mid" );
|
||||
// audio_t BGM3 = audio_stream( "monkey1.mid" ), BGM = BGM1;
|
||||
// audio_play(SFX1, 0);
|
||||
// audio_play(BGM1, 0);
|
||||
|
||||
while (window_swap()) {
|
||||
// input
|
||||
if( input_down(KEY_ESC) ) break;
|
||||
if( input_down(KEY_F5) ) window_reload();
|
||||
if( input_down(KEY_W) && input_held(KEY_LCTRL) ) break;
|
||||
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
|
||||
if( input_down(KEY_X) ) window_screenshot(__FILE__ ".png");
|
||||
if( input_down(KEY_Z) ) window_record(__FILE__ ".mp4");
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||
vec3 wasdecq = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-(input(KEY_C)||input(KEY_Q)),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||
camera_move(&cam, wasdecq.x,wasdecq.y,wasdecq.z);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
window_cursor( !active );
|
||||
|
||||
fx_begin();
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
|
||||
draw_world();
|
||||
fx_end();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
// instanced models demo
|
||||
// - rlyeh, public domain.
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
window_create(75, WINDOW_MSAA2);
|
||||
window_title(__FILE__);
|
||||
|
||||
camera_t cam = camera();
|
||||
skybox_t sky = skybox("cubemaps/stardust", 0);
|
||||
model_t girl = model("kgirls01.fbx", 0);
|
||||
|
||||
while( window_swap() ) {
|
||||
if(input(KEY_F5)) window_reload();
|
||||
if(input(KEY_ESC)) break;
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
window_cursor( !active );
|
||||
|
||||
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||
camera_move(&cam, wasdec.x,wasdec.y,wasdec.z);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
|
||||
// ground rendering
|
||||
ddraw_ground(0);
|
||||
ddraw_flush();
|
||||
|
||||
// skeletal
|
||||
profile("Skeletal update") {
|
||||
float delta = window_has_pause() ? 0 : window_delta() * 30; // 30fps anim
|
||||
girl.curframe = model_animate(girl, girl.curframe + delta);
|
||||
}
|
||||
|
||||
profile("Skeletal render") {
|
||||
enum { ROW = 32, MAX_INSTANCES = ROW * ROW };
|
||||
static mat44 M[MAX_INSTANCES];
|
||||
|
||||
do_once {
|
||||
int i = 0;
|
||||
for(int z = 0; z < ROW; ++z) {
|
||||
for(int x = 0; x < ROW; ++x, ++i) {
|
||||
vec3 p = vec3(-x*3,0,-z*3);
|
||||
vec3 r = vec3(0,0,0);
|
||||
vec3 s = vec3(2,2,2);
|
||||
rotationq44(M[i], eulerq(r)); scale44(M[i], s.x,s.y,s.z); relocate44(M[i], p.x,p.y,p.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model_render_instanced(girl, cam.proj, cam.view, M, 0, MAX_INSTANCES);
|
||||
}
|
||||
|
||||
// skybox
|
||||
profile("Skybox") {
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,8 @@
|
|||
// pathfind demo
|
||||
// - rlyeh, public domain
|
||||
//
|
||||
// @todo: use 2d sprites instead, will shorten things
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
bool topdown_cam = 1;
|
||||
|
@ -5,7 +10,7 @@ bool topdown_cam = 1;
|
|||
void move_players();
|
||||
|
||||
int main() {
|
||||
window_create(75, 0); // WINDOW_MSAA4);
|
||||
window_create(85, 0); // WINDOW_MSAA4);
|
||||
window_title(__FILE__);
|
||||
window_fps_lock(60);
|
||||
|
||||
|
@ -49,6 +54,10 @@ void draw_scene() {
|
|||
float dd = randi(1,10);
|
||||
float hh = randi(3,10);
|
||||
aabb b = { vec3(ox,0,oz), vec3(ox+ww,hh,oz+dd) };
|
||||
|
||||
static aabb spawn_zone = { {-10,-10,-10},{10,10,10} };
|
||||
if( aabb_hit_aabb(b, spawn_zone) ) continue;
|
||||
|
||||
array_push(blockers, b);
|
||||
|
||||
for( int y = oz; y < (oz+dd); ++y )
|
||||
|
@ -248,7 +257,9 @@ void move_players() {
|
|||
|
||||
// ui
|
||||
if( ui_panel("Controls", 0) ) {
|
||||
ui_label2("Girl", ICON_MD_MOUSE " Set Waypoint");
|
||||
ui_label2("[F1]", ICON_MD_KEYBOARD " Debug traversal visualization");
|
||||
ui_label2("[Left mouse]", ICON_MD_MOUSE " Set Waypoint");
|
||||
ui_label2("[Right mouse]", ICON_MD_MOUSE " Toggle camera");
|
||||
ui_label2("Girl", ICON_MD_GAMEPAD " CURSOR keys");
|
||||
ui_label2("Alien", ICON_MD_GAMEPAD " W,A,S,D keys");
|
||||
ui_label2("Robot", ICON_MD_GAMEPAD " I,J,K,L keys");
|
||||
|
|
|
@ -648,16 +648,6 @@ int main( int argc, const char *argv[] ) {
|
|||
ui_panel_end();
|
||||
}
|
||||
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
|
||||
if( ui_panel("Help", 0)) {
|
||||
if( fps_mode ) {
|
||||
ui_label("TAB: switch to Orbit camera mode");
|
||||
|
|
|
@ -1,146 +0,0 @@
|
|||
#include "v4k.h"
|
||||
|
||||
typedef void* (*rpc_function)();
|
||||
|
||||
typedef struct rpc_call {
|
||||
char *method;
|
||||
rpc_function function;
|
||||
uint64_t function_hash;
|
||||
} rpc_call;
|
||||
|
||||
#define RPC_SIGNATURE_i_iii UINT64_C(0x78409099752fa48a) // printf("%llx\n, HASH_STR("int(int,int,int)"));
|
||||
#define RPC_SIGNATURE_i_ii UINT64_C(0x258290edf43985a5) // printf("%llx\n, HASH_STR("int(int,int)"));
|
||||
#define RPC_SIGNATURE_s_s UINT64_C(0x97deedd17d9afb12) // printf("%llx\n, HASH_STR("char*(char*)"));
|
||||
#define RPC_SIGNATURE_s_v UINT64_C(0x09c16a1242049b80) // printf("%llx\n, HASH_STR("char*(void)"));
|
||||
|
||||
static
|
||||
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
||||
if( signature && function ) {
|
||||
array(char*)tokens = strsplit(signature, "(,)");
|
||||
if( array_count(tokens) >= 1 ) {
|
||||
char *method = strrchr(tokens[0], ' ')+1;
|
||||
char *rettype = va("%.*s", (int)(method - tokens[0] - 1), tokens[0]);
|
||||
int num_args = array_count(tokens) - 1;
|
||||
char* hash_sig = va("%s(%s)", rettype, num_args ? (array_pop_front(tokens), strjoin(tokens, ",")) : "void");
|
||||
uint64_t hash = hash_str(hash_sig);
|
||||
method = va("%s%d", method, num_args );
|
||||
#if RPC_DEBUG
|
||||
printf("%p %p %s `%s` %s(", function, (void*)hash, rettype, hash_sig, method); for(int i = 0, end = array_count(tokens); i < end; ++i) printf("%s%s", tokens[i], i == (end-1)? "":", "); puts(");");
|
||||
#endif
|
||||
return (rpc_call) { strdup(method), function, hash }; // LEAK
|
||||
}
|
||||
}
|
||||
return (rpc_call) {0};
|
||||
}
|
||||
|
||||
static map(char*, rpc_call) rpc_calls = 0;
|
||||
|
||||
static
|
||||
void rpc_insert(const char *signature, void *function ) {
|
||||
rpc_call call = rpc_new_call(signature, function);
|
||||
if( call.method ) {
|
||||
if( !rpc_calls ) map_init(rpc_calls, less_str, hash_str);
|
||||
if( map_find(rpc_calls, call.method)) {
|
||||
map_erase(rpc_calls, call.method);
|
||||
}
|
||||
map_insert(rpc_calls, call.method, call);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[]) {
|
||||
#if RPC_DEBUG
|
||||
printf("id:%x method:%s args:", id, method );
|
||||
for( int i = 0; i < num_args; ++i ) printf("%s,", args[i]); puts("");
|
||||
#endif
|
||||
|
||||
method = va("%s%d", method, num_args);
|
||||
rpc_call *found = map_find(rpc_calls, (char*)method);
|
||||
if( found ) {
|
||||
switch(found->function_hash) {
|
||||
case RPC_SIGNATURE_i_iii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
||||
case RPC_SIGNATURE_i_ii: return va("%d %d", id, (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
||||
case RPC_SIGNATURE_s_s: return va("%d %s", id, (char*)found->function(args[0]) );
|
||||
case RPC_SIGNATURE_s_v: return va("%d %s", id, (char*)found->function() );
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return va("%d -1", id);
|
||||
}
|
||||
|
||||
static
|
||||
array(char*) rpc_parse_args( const char *cmdline, bool quote_whitespaces ) { // parse cmdline arguments. must array_free() after use
|
||||
// - supports quotes: "abc" "abc def" "abc \"def\"" "abc \"def\"""ghi" etc.
|
||||
// - #comments removed
|
||||
array(char*) args = 0; // LEAK
|
||||
for( int i = 0; cmdline[i]; ) {
|
||||
char buf[256] = {0}, *ptr = buf;
|
||||
while(cmdline[i] && isspace(cmdline[i])) ++i;
|
||||
bool quoted = cmdline[i] == '\"';
|
||||
if( quoted ) {
|
||||
while(cmdline[++i]) {
|
||||
char ch = cmdline[i];
|
||||
/**/ if (ch == '\\' && cmdline[i + 1] == '\"') *ptr++ = '\"', ++i;
|
||||
else if (ch == '\"' && cmdline[i + 1] == '\"') ++i;
|
||||
else if (ch == '\"' && (!cmdline[i + 1] || isspace(cmdline[i + 1]))) {
|
||||
++i; break;
|
||||
}
|
||||
else *ptr++ = ch;
|
||||
}
|
||||
} else {
|
||||
while(cmdline[i] && !isspace(cmdline[i])) *ptr++ = cmdline[i++];
|
||||
}
|
||||
if (buf[0] && buf[0] != '#') { // exclude empty args + comments
|
||||
if( quote_whitespaces && quoted )
|
||||
array_push(args, va("\"%s\"",buf));
|
||||
else
|
||||
array_push(args, va("%s",buf));
|
||||
}
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
static
|
||||
char* rpc(unsigned id, const char* cmdline) {
|
||||
array(char*) args = rpc_parse_args(cmdline, false);
|
||||
int num_args = array_count(args);
|
||||
char *ret = num_args ? rpc_full(id, args[0], num_args - 1, &args[1]) : rpc_full(id, "", 0, NULL);
|
||||
array_free(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void enet_quit(void) {
|
||||
do_once {
|
||||
// enet_deinitialize();
|
||||
}
|
||||
}
|
||||
static void enet_init() {
|
||||
do_once {
|
||||
if( enet_initialize() != 0 ) {
|
||||
PANIC("cannot initialize enet");
|
||||
}
|
||||
atexit( enet_quit );
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// demo
|
||||
|
||||
int rpc_add2(int num1, int num2) {
|
||||
return num1+num2;
|
||||
}
|
||||
int rpc_add3(int num1, int num2, int num3) {
|
||||
return num1+num2+num3;
|
||||
}
|
||||
char *rpc_echo(char *text) {
|
||||
return text;
|
||||
}
|
||||
|
||||
int main() {
|
||||
rpc_insert("int add(int,int)", rpc_add2);
|
||||
rpc_insert("int add(int,int,int)", rpc_add3);
|
||||
rpc_insert("char* echo(char*)", rpc_echo);
|
||||
puts(rpc(0,"add 1 2")); // -> 3
|
||||
puts(rpc(1,"add 100 3 -3")); // -> 100
|
||||
puts(rpc(2,"echo \"hello world\"")); // -> hello world
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
// shadertoy viewer
|
||||
// - rlyeh, public domain
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
int main() {
|
||||
window_create(75, 0); // WINDOW_MSAA8);
|
||||
window_title(__FILE__);
|
||||
|
||||
const char **list = file_list("demos/art/shadertoys/", "**.fs");
|
||||
if(!list[0]) exit(-1);
|
||||
array(char*) browser = 0;
|
||||
while(*list) array_push(browser, STRDUP(file_name(*list++)));
|
||||
int browser_count = array_count(browser);
|
||||
|
||||
shadertoy_t sh = {0};
|
||||
|
||||
while(window_swap() && !input(KEY_ESC)) {
|
||||
if( input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen() ^ 1 );
|
||||
// selector
|
||||
int next = input_down(KEY_UP) || input_down(KEY_LEFT);
|
||||
int prev = input_down(KEY_DOWN) || input_down(KEY_RIGHT);
|
||||
static int selector = 0;
|
||||
static int reload = 1;
|
||||
if( next ) if( selector > 0 ) --selector, reload = 1;
|
||||
if( prev ) if( selector < browser_count - 1 ) ++selector, reload = 1;
|
||||
if( reload ) {
|
||||
reload = 0;
|
||||
window_title(va("V4K - %s", browser[selector]));
|
||||
sh = shadertoy( browser[selector], 0 );
|
||||
}
|
||||
|
||||
// draw
|
||||
shadertoy_render(&sh, window_delta());
|
||||
|
||||
// UI
|
||||
if( ui_panel("Shadertoy", 0)) {
|
||||
if( ui_list("In use", (const char**)browser, browser_count, &selector) ) {
|
||||
reload = 1;
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ int main() {
|
|||
fx_load("fx**.fs");
|
||||
|
||||
// load skybox
|
||||
skybox_t sky = skybox(flag("--mie") ? 0 : "cubemaps/stardust", 0); // --mie for rayleigh/mie scattering
|
||||
skybox_t sky = skybox(flag("--mie") ? 0 : "hdr/Tokyo_BigSight_1k.hdr", 0); // --mie for rayleigh/mie scattering
|
||||
|
||||
// load static scene
|
||||
model_t sponza;
|
||||
|
@ -70,6 +70,6 @@ int main() {
|
|||
model_render(sponza, cam.proj, cam.view, M, 0);
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
fx_end(0);
|
||||
}
|
||||
}
|
||||
|
|
554
demos/99-spot.c
554
demos/99-spot.c
|
@ -1,554 +0,0 @@
|
|||
// [ref] http://fabiensanglard.net/shadowmappingVSM/index.php
|
||||
// [ref] http://www.opengl-tutorial.org/es/intermediate-tutorials/tutorial-16-shadow-mapping/
|
||||
// [ref] https://github.com/cforfang/opengl-shadowmapping
|
||||
// [ref] https://learnopengl.com/Advanced-Lighting/Shadows/Shadow-Mapping
|
||||
|
||||
// @todo: spotlight (cone light)
|
||||
// @todo: pointlight (cubemap light)
|
||||
// @todo: area light (rect or circle light)
|
||||
// @todo: directional light (sunlight)
|
||||
|
||||
// further reading (in order):
|
||||
// DPSM [3] Brabec, Annen: Shadow mapping for hemispherical and omnidirectional light sources (2002)
|
||||
// DPSM* [4] Osman, Bukowski: Practical implementation of dual paraboloid shadow maps (2006)
|
||||
// IPSM [5] Vanek, Herout: High-quality Shadows with Improved Paraboloid Mapping (2011)
|
||||
// LiSPSMs
|
||||
// CSMs
|
||||
|
||||
// status: CUBE(0)+BLUR(0): ok
|
||||
// status: CUBE(0)+BLUR(1): ok
|
||||
// status: CUBE(1)+BLUR(1): ok
|
||||
// status: CUBE(1)+BLUR(0): ok
|
||||
// status: CUBE(?)+BLUR(?): no {
|
||||
// 003.470s|!cannot find uniform 'shadowMap' in shader program 21 |shader_uniform|v4k_render.c:772
|
||||
// 001: 00007FF7AF6A3FDA callstack (C:\prj\thread\V4K\v4k_system.c:250)
|
||||
// 002: 00007FF7AF8E7CBC shader_uniform (C:\prj\thread\V4K\v4k_render.c:772)
|
||||
// 003: 00007FF7AF691C27 shader_int (C:\prj\thread\V4K\v4k_render.c:777)
|
||||
// 004: 00007FF7AF8F54EF color_begin (C:\prj\thread\V4K\spot.c:525)
|
||||
// 005: 00007FF7AF8F5BF7 main (C:\prj\thread\V4K\spot.c:607)
|
||||
// }
|
||||
|
||||
#ifndef VSMCUBE
|
||||
#define VSMCUBE 0
|
||||
#endif
|
||||
#ifndef VSMBLUR
|
||||
#define VSMBLUR 1
|
||||
#endif
|
||||
|
||||
#include "v4k.h"
|
||||
#include "split/v4k_shaders.c"
|
||||
|
||||
model_t sponza;
|
||||
|
||||
typedef struct Mesh
|
||||
{
|
||||
GLuint vao;
|
||||
GLuint vbo;
|
||||
} Mesh;
|
||||
|
||||
static float quadVertices[] = {
|
||||
// Front-face
|
||||
// Pos // Color //Tex // Norm
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top-left
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top-right
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // Bottom-right
|
||||
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // Bottom-right
|
||||
-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, //Bottom-left
|
||||
-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, // Top-left
|
||||
};
|
||||
|
||||
static Mesh create_mesh(float* verts, int size) {
|
||||
Mesh mesh;
|
||||
|
||||
// Create VAO
|
||||
glGenVertexArrays(1, &mesh.vao);
|
||||
glBindVertexArray(mesh.vao);
|
||||
|
||||
// Create VBO and copy the vertex data to it
|
||||
glGenBuffers(1, &mesh.vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, verts, GL_STATIC_DRAW);
|
||||
|
||||
// Enable attribs
|
||||
// Position
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), 0);
|
||||
// Color
|
||||
glEnableVertexAttribArray(3);
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
// Texcoords
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(6 * sizeof(float)));
|
||||
// Normal
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 11 * sizeof(float), (void*)(8 * sizeof(float)));
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Mesh create_quad() {
|
||||
return create_mesh(quadVertices, sizeof(quadVertices));
|
||||
}
|
||||
|
||||
struct shadow {
|
||||
// Resources
|
||||
GLuint shadowProgram, blurProgram;
|
||||
Mesh quadMesh;
|
||||
GLuint shadowMapFBO, shadowMapTex, shadowMapTexDepth;
|
||||
GLuint blurFBO, blurTex;
|
||||
// Options
|
||||
bool do_blur;
|
||||
bool do_debugshadow;
|
||||
float BLUR_SCALE; // Amount of blurring [0..100]
|
||||
GLuint SHADOWMAP_WIDTH; // 256,512,1024,2048
|
||||
// State
|
||||
int shadow_active;
|
||||
vec3 lightPos;
|
||||
vec3 lightAimPos;
|
||||
|
||||
// VSM cubemap
|
||||
GLuint cubeTex, cubeDepthTex, cubeFBOs[6];
|
||||
GLuint currentSideTex, currentSideDepthTex;
|
||||
GLuint toCurrentSideFBO;
|
||||
} shadow;
|
||||
|
||||
#define shadowProgram shadow.shadowProgram
|
||||
#define blurProgram shadow.blurProgram
|
||||
#define quadMesh shadow.quadMesh
|
||||
#define shadowMapFBO shadow.shadowMapFBO
|
||||
#define shadowMapTex shadow.shadowMapTex
|
||||
#define shadowMapTexDepth shadow.shadowMapTexDepth
|
||||
#define blurFBO shadow.blurFBO
|
||||
#define blurTex shadow.blurTex
|
||||
#define do_blur shadow.do_blur
|
||||
#define do_debugshadow shadow.do_debugshadow
|
||||
#define BLUR_SCALE shadow.BLUR_SCALE
|
||||
#define SHADOWMAP_WIDTH shadow.SHADOWMAP_WIDTH
|
||||
#define shadow_active shadow.shadow_active
|
||||
#define lightPos shadow.lightPos
|
||||
#define lightAimPos shadow.lightAimPos
|
||||
// vsm cubemap
|
||||
#define cubeTex shadow.cubeTex
|
||||
#define cubeDepthTex shadow.cubeDepthTex
|
||||
#define cubeFBOs shadow.cubeFBOs
|
||||
#define currentSideTex shadow.currentSideTex
|
||||
#define currentSideDepthTex shadow.currentSideDepthTex
|
||||
#define toCurrentSideFBO shadow.toCurrentSideFBO
|
||||
|
||||
|
||||
|
||||
static GLuint cubemap_create(GLsizei size, int flags) {
|
||||
GLenum texel = flags & TEXTURE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGB32F;
|
||||
GLenum pixel = flags & TEXTURE_DEPTH ? GL_DEPTH_COMPONENT : GL_RGB;
|
||||
GLenum storage = flags & TEXTURE_DEPTH ? GL_FLOAT : GL_UNSIGNED_BYTE; // swap?
|
||||
GLuint id;
|
||||
glGenTextures(1, &id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, texel, size, size, 0, pixel, storage, NULL);
|
||||
if( flags & TEXTURE_DEPTH ) {
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
}
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
return id;
|
||||
}
|
||||
static void framebuffer_cube_create(GLuint cube_fbo[6], GLuint cube_texture, GLuint cube_texture_depth) {
|
||||
glGenFramebuffers(6, cube_fbo);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, cube_fbo[i]);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cube_texture, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, cube_texture_depth, 0);
|
||||
GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (GL_FRAMEBUFFER_COMPLETE != result) {
|
||||
printf("ERROR: Framebuffer is not complete.\n");
|
||||
}
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
static void set_shadow_matrix_uniform(const GLuint program, int dir) {
|
||||
if(dir<0) return;
|
||||
mat44 P, V, PV;
|
||||
perspective44(P, 90.0f, 1.0f, 0.5f, 100.0f);
|
||||
|
||||
/**/ if(dir == 0) lookat44(V, lightPos, add3(lightPos, vec3(+1, 0, 0)), vec3(0, -1, 0)); // +X
|
||||
else if(dir == 1) lookat44(V, lightPos, add3(lightPos, vec3(-1, 0, 0)), vec3(0, -1, 0)); // -X
|
||||
else if(dir == 2) lookat44(V, lightPos, add3(lightPos, vec3( 0, +1, 0)), vec3(0, 0, +1)); // +Y
|
||||
else if(dir == 3) lookat44(V, lightPos, add3(lightPos, vec3( 0, -1, 0)), vec3(0, 0, -1)); // -Y
|
||||
else if(dir == 4) lookat44(V, lightPos, add3(lightPos, vec3( 0, 0, +1)), vec3(0, -1, 0)); // +Z
|
||||
else /*dir == 5*/ lookat44(V, lightPos, add3(lightPos, vec3( 0, 0, -1)), vec3(0, -1, 0)); // -Z
|
||||
multiply44x2(PV, P, V); // -Z
|
||||
|
||||
shader_bind(program); shader_mat44("cameraToShadowView", V);
|
||||
shader_bind(program); shader_mat44("cameraToShadowProjector", PV);
|
||||
}
|
||||
|
||||
void shadow_create(int RESOLUTION) {
|
||||
do_blur = 1;
|
||||
do_debugshadow = 0;
|
||||
BLUR_SCALE = 0.5; // Amount of blurring [0..1]
|
||||
SHADOWMAP_WIDTH = RESOLUTION; // 256,512,1024,2048
|
||||
lightPos = vec3(-2, 2.0, -2);
|
||||
lightAimPos = vec3(0.0, 0, -5.0);
|
||||
|
||||
// Create programs
|
||||
shadowProgram = shader(vs_shadow_vsm, fs_shadow_vsm, "position", "outColor", "");
|
||||
blurProgram = shader(vs_shadow_blur, fs_shadow_blur, "position,,texcoord", "outColor", "");
|
||||
|
||||
// ShadowMap-textures and FBO // @todo: GL_RG32F+GL_RG also GL_CLAMP to remove artifacts
|
||||
shadowMapTex = texture_create(SHADOWMAP_WIDTH, SHADOWMAP_WIDTH, 2, NULL, TEXTURE_FLOAT).id;
|
||||
shadowMapTexDepth = texture_create(SHADOWMAP_WIDTH, SHADOWMAP_WIDTH, 0, NULL, TEXTURE_DEPTH | TEXTURE_FLOAT).id;
|
||||
shadowMapFBO = fbo(shadowMapTex, shadowMapTexDepth, 0);
|
||||
|
||||
// Textures and FBO to perform blurring
|
||||
blurTex = texture_create(SHADOWMAP_WIDTH, SHADOWMAP_WIDTH, 2, NULL, TEXTURE_FLOAT).id;
|
||||
blurFBO = fbo(blurTex, 0, 0);
|
||||
|
||||
#if VSMCUBE
|
||||
// Create cubemap
|
||||
cubeTex = cubemap_create(SHADOWMAP_WIDTH, 0);
|
||||
cubeDepthTex = cubemap_create(SHADOWMAP_WIDTH, TEXTURE_DEPTH);
|
||||
framebuffer_cube_create(cubeFBOs, cubeTex, cubeDepthTex);
|
||||
// Temporary storage
|
||||
currentSideTex = texture_create(SHADOWMAP_WIDTH, SHADOWMAP_WIDTH, 2, NULL, TEXTURE_FLOAT /*| TEXTURE_EDGE*/ ).id;
|
||||
currentSideDepthTex = texture_create(SHADOWMAP_WIDTH, SHADOWMAP_WIDTH, 0, NULL, TEXTURE_DEPTH | TEXTURE_FLOAT).id;
|
||||
toCurrentSideFBO = fbo(currentSideTex, currentSideDepthTex, 0);
|
||||
#endif
|
||||
}
|
||||
void shadow_destroy() {
|
||||
glDeleteProgram(shadowProgram);
|
||||
glDeleteProgram(blurProgram);
|
||||
|
||||
glDeleteTextures(1, &blurTex);
|
||||
glDeleteFramebuffers(1, &blurFBO);
|
||||
|
||||
glDeleteTextures(1, &shadowMapTex);
|
||||
glDeleteTextures(1, &shadowMapTexDepth);
|
||||
glDeleteFramebuffers(1, &shadowMapFBO);
|
||||
}
|
||||
bool shadow_is_active() {
|
||||
return shadow_active;
|
||||
}
|
||||
void shadow_pv_matrix(mat44 PV) {
|
||||
mat44 P,V;
|
||||
// perspective44(P, 45.0f, 1.0f, 2.0f, 100.0f);
|
||||
perspective44(P, 45*2, window_width() / ((float)window_height()+!window_height()), 1.f, 100.f);
|
||||
|
||||
lookat44(V, lightPos, lightAimPos, vec3(0, 1, 0)); // Point toward object regardless of position
|
||||
multiply44x2(PV, P, V);
|
||||
}
|
||||
void shadow_position(vec3 p) {
|
||||
lightPos = p;
|
||||
}
|
||||
void shadow_target(vec3 p) {
|
||||
lightAimPos = p;
|
||||
}
|
||||
void shadow_begin() {
|
||||
shadow_active = 1;
|
||||
|
||||
// shadow_state() {
|
||||
glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS);
|
||||
glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CW);
|
||||
glBlendFunc(1, 0);
|
||||
#if VSMCUBE
|
||||
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
|
||||
#endif
|
||||
// }
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFBO);
|
||||
|
||||
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_WIDTH);
|
||||
//glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
mat44 PV; shadow_pv_matrix(PV);
|
||||
shader_bind(shadowProgram);shader_mat44("cameraToShadowProjector", PV);
|
||||
}
|
||||
static void draw_fullscreen_quad() {
|
||||
//delete_mesh(quadMesh);
|
||||
if(!quadMesh.vao) quadMesh = create_quad();
|
||||
|
||||
glBindVertexArray(quadMesh.vao);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
static void shadow_blur() {
|
||||
// remap 0(min)..1(max) -> 2(min)..epsilon(max)
|
||||
float blur_scale = 1.999 * (1 - BLUR_SCALE) + 0.001;
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Blur shadowMapTex (horizontally) to blurTex
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, blurFBO);
|
||||
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_WIDTH);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, shadowMapTex); //Input-texture
|
||||
shader_bind(blurProgram); shader_vec2("ScaleU", vec2(1.0 / (SHADOWMAP_WIDTH*blur_scale), 0));
|
||||
shader_int("textureSource",0);
|
||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
draw_fullscreen_quad();
|
||||
|
||||
// Blur blurTex vertically and write to shadowMapTex
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFBO);
|
||||
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_WIDTH);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, blurTex);
|
||||
shader_bind(blurProgram); shader_vec2("ScaleU", vec2(0, 1.0 / (SHADOWMAP_WIDTH*blur_scale)));
|
||||
shader_int("textureSource",0);
|
||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
draw_fullscreen_quad();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
void shadow_end() {
|
||||
// Reset
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
if(do_blur) shadow_blur();
|
||||
shadow_active = 0;
|
||||
|
||||
glViewport(0, 0, window_width(), window_height());
|
||||
}
|
||||
void shadow_ui() {
|
||||
// UI
|
||||
if( ui_panel("Shadow", 0) ) {
|
||||
if(ui_toggle("Debug", &do_debugshadow)) {}
|
||||
if(ui_toggle("Blur shadow", &do_blur)) {}
|
||||
if(ui_slider("Blur amount", &BLUR_SCALE)) {}
|
||||
ui_panel_end();
|
||||
}
|
||||
|
||||
if(do_debugshadow) {
|
||||
// Blur and draw to screen
|
||||
shader_bind(blurProgram); shader_vec2("ScaleU", vec2(0, 0)); // ... but make sure we don't actually blur
|
||||
glBindTexture(GL_TEXTURE_2D, shadowMapTex);
|
||||
draw_fullscreen_quad();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define USER_DRAWCALL(shader) do { \
|
||||
model_render(sponza, camera_get_active()->proj, camera_get_active()->view, sponza.pivot, shader); \
|
||||
} while(0)
|
||||
|
||||
|
||||
static void vsm_cube_draw()
|
||||
{
|
||||
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_WIDTH);
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
shader_bind(shadowProgram);
|
||||
|
||||
// For each side of cubemap
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
#if VSMBLUR
|
||||
// Draw to temp. storage
|
||||
shader_bind(shadowProgram);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, toCurrentSideFBO);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
set_shadow_matrix_uniform(shadowProgram, i);
|
||||
USER_DRAWCALL(shadowProgram);
|
||||
|
||||
// Blur horizontally to blurTex
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
shader_bind(blurProgram);
|
||||
shader_vec2("ScaleU", vec2(1.0 / SHADOWMAP_WIDTH, 0));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, blurFBO);
|
||||
glBindTexture(GL_TEXTURE_2D, currentSideTex);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
draw_fullscreen_quad();
|
||||
|
||||
// Blur vertically to actual cubemap
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, cubeFBOs[i]);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, blurTex);
|
||||
shader_bind(blurProgram);
|
||||
shader_vec2("ScaleU", vec2(0, 1.0 / SHADOWMAP_WIDTH));
|
||||
|
||||
draw_fullscreen_quad();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
#else
|
||||
// Draw directly to cubemap
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, cubeFBOs[i]);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
set_shadow_matrix_uniform(shadowProgram, i);
|
||||
USER_DRAWCALL(shadowProgram);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Reset state
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
#undef shadowProgram
|
||||
#undef blurProgram
|
||||
#undef quadMesh
|
||||
#undef shadowMapFBO
|
||||
#undef shadowMapTex
|
||||
#undef shadowMapTexDepth
|
||||
#undef blurFBO
|
||||
#undef blurTex
|
||||
#undef do_blur
|
||||
#undef do_debugshadow
|
||||
#undef BLUR_SCALE
|
||||
#undef SHADOWMAP_WIDTH
|
||||
#undef shadow_active
|
||||
#undef lightPos
|
||||
#undef lightAimPos
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Geometry (world coordinates)
|
||||
static bool do_animate = 1;
|
||||
|
||||
static void color_begin(const GLuint program) {
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
#if 1 // VSMCUBE
|
||||
glViewport(0, 0, window_width(), window_height());
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
#endif
|
||||
|
||||
// Upload uniforms
|
||||
shader_bind(program);
|
||||
shader_mat44("view", camera_get_active()->view);
|
||||
// shader_mat44("proj", camera_get_active()->proj);
|
||||
shader_vec3("lightPos", shadow.lightPos);
|
||||
|
||||
#if VSMCUBE
|
||||
set_shadow_matrix_uniform(program, -1);
|
||||
#else
|
||||
mat44 PV; shadow_pv_matrix(PV);
|
||||
shader_mat44("cameraToShadowProjector", PV);
|
||||
#endif
|
||||
|
||||
glActiveTexture(GL_TEXTURE0+1);
|
||||
#if VSMCUBE
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cubeTex);
|
||||
#else
|
||||
glBindTexture(GL_TEXTURE_2D, shadow.shadowMapTex); //Input-texture
|
||||
#endif
|
||||
shader_int("shadowMap",1);
|
||||
}
|
||||
static void color_end() {
|
||||
#if VSMCUBE
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
|
||||
#else
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
window_create(0.75f, 0);
|
||||
|
||||
camera_t cam = camera();
|
||||
|
||||
// init shadowing 384x384 // 512x512
|
||||
shadow_create(argc > 1 ? atoi(argv[1]) : 384);
|
||||
|
||||
sponza = model("sponza.obj", 0);
|
||||
translation44(sponza.pivot, 0,-1,0);
|
||||
rotate44(sponza.pivot, -90,1,0,0);
|
||||
scale44(sponza.pivot, 10,10,10);
|
||||
|
||||
model_t suzanne = model("suzanne.obj", 0);
|
||||
|
||||
// create geometry
|
||||
GLuint vsm_program = sponza.program;
|
||||
#if 1
|
||||
const char *tpl[] = {
|
||||
"{{include-shadowmap}}", fs_0_0_shadowmap_lit,
|
||||
};
|
||||
vsm_program = shader(strlerp(1,tpl,vs_323444143_16_332_model), strlerp(1,tpl,fs_32_4_model), "att_position,att_texcoord,att_normal,att_tangent,att_instanced_matrix,,,,att_indexes,att_weights,att_vertexindex,att_color,att_bitangent", "fragColor", "");
|
||||
#endif
|
||||
|
||||
while (window_swap())
|
||||
{
|
||||
// input
|
||||
if (input(KEY_ESC))
|
||||
break;
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() ? 0 : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
vec3 wasdec = scale3( vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), 0.2f);
|
||||
vec2 mouse = scale2( vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||
camera_move(&cam, wasdec.x,wasdec.y,wasdec.z);
|
||||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
window_cursor( !active );
|
||||
|
||||
#if 1
|
||||
// animate light
|
||||
if( do_animate ) {
|
||||
static vec3 lightPos;
|
||||
do_once {
|
||||
lightPos = cam.position;
|
||||
};
|
||||
vec3 offs = vec3(sin(window_time()) * 15, 0, cos(window_time()) * 15);
|
||||
shadow_position(add3(lightPos, offs));
|
||||
// shadow_target(vec3(0,0,0)); // good for pointlight
|
||||
shadow_target(add3(add3(lightPos, offs), vec3(0,0,-1)));
|
||||
}
|
||||
#else
|
||||
shadow_position(cam.position);
|
||||
shadow_target(add3(cam.position, cam.look));
|
||||
#endif
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// render
|
||||
|
||||
#if VSMCUBE
|
||||
shadow_begin();
|
||||
vsm_cube_draw();
|
||||
shadow_end();
|
||||
#else
|
||||
shadow_begin();
|
||||
model_render(sponza, camera_get_active()->proj, camera_get_active()->view, sponza.pivot, shadow.shadowProgram); //< typo!, but works!
|
||||
shadow_end();
|
||||
#endif
|
||||
|
||||
color_begin(vsm_program);
|
||||
model_render(sponza, camera_get_active()->proj, camera_get_active()->view, sponza.pivot, vsm_program); // does not work without program
|
||||
color_end();
|
||||
|
||||
|
||||
// // light bulb (suzanne)
|
||||
// {
|
||||
// mat44 M; scaling44(M, 10,10,10); relocate44(M, shadow.lightPos.x, shadow.lightPos.y, shadow.lightPos.z );
|
||||
// model_render(suzanne, camera_get_active()->proj, camera_get_active()->view, M, 0);
|
||||
// }
|
||||
|
||||
|
||||
// if( ui_panel("App", 0) ) {
|
||||
// if(ui_toggle("Animate light", &do_animate)) {}
|
||||
// ui_panel_end();
|
||||
// }
|
||||
|
||||
// shadow_ui();
|
||||
}
|
||||
}
|
|
@ -1,227 +0,0 @@
|
|||
// sprite routines
|
||||
// - rlyeh,
|
||||
//
|
||||
// credits: original lovely demo by rxi (MIT License).
|
||||
// see https://github.com/rxi/autobatch/tree/master/demo/cats
|
||||
|
||||
#include "v4k.h"
|
||||
|
||||
texture_t kids, catImage, shadowImage, inputs;
|
||||
int NUM_SPRITES = 100, NUM_SPRITES_CHANGED = 1;
|
||||
|
||||
typedef struct Cat {
|
||||
int cat, flip;
|
||||
double x, y;
|
||||
double vx, vy;
|
||||
double animSpeed;
|
||||
double moveTimer;
|
||||
double elapsed;
|
||||
} Cat;
|
||||
|
||||
void demo_cats() {
|
||||
static array(Cat) cats = 0;
|
||||
|
||||
// init
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
array_resize(cats, NUM_SPRITES); int i = 0;
|
||||
for each_array_ptr(cats, Cat, c) {
|
||||
randset(i++);
|
||||
c->x = randf() * window_width();
|
||||
c->y = randf() * window_height();
|
||||
c->vx = c->vy = 0;
|
||||
c->cat = randi(0, 4);
|
||||
c->flip = randf() < 0.5;
|
||||
c->animSpeed = 0.8 + randf() * 0.3;
|
||||
c->moveTimer = 0;
|
||||
c->elapsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// move
|
||||
const float dt = 1/120.f;
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
enum { yscale = 1 };
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Add velocity to position //and wrap to screen
|
||||
c->x += yscale * c->vx * dt; // % ;
|
||||
c->y += yscale * c->vy * dt; // % (int)window_height();
|
||||
if( c->x < 0 ) c->x += appw; else if( c->x > appw ) c->x -= appw;
|
||||
if( c->y < 0 ) c->y += apph; else if( c->y > apph ) c->y -= apph;
|
||||
// Faster animation if walking
|
||||
int boost = c->vx == 0 && c->vy == 0 ? 1 : 3;
|
||||
// Update elapsed time
|
||||
c->elapsed += dt * boost;
|
||||
// Update move timer -- if we hit zero then change or zero velocity
|
||||
c->moveTimer -= dt * boost;
|
||||
if (c->moveTimer < 0) {
|
||||
if (randf() < .2) {
|
||||
c->vx = (randf() * 2 - 1) * 30 * 2;
|
||||
c->vy = (randf() * 2 - 1) * 15 * 2;
|
||||
c->flip = c->vx < 0;
|
||||
} else {
|
||||
c->vx = c->vy = 0;
|
||||
}
|
||||
c->moveTimer = 1 + randf() * 5;
|
||||
}
|
||||
}
|
||||
|
||||
// render
|
||||
uint32_t white = rgba(255,255,255,255);
|
||||
uint32_t alpha = rgba(255,255,255,255*0.6);
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
Cat *c = &cats[i];
|
||||
// Get current animation frame (8x4 tilesheet)
|
||||
double e = c->elapsed * c->animSpeed;
|
||||
double frame_num = c->cat * 8 + floor( ((int)(e * 8)) % 4 );
|
||||
frame_num = c->vx != 0 || c->vy != 0 ? frame_num + 4 : frame_num;
|
||||
// Get x scale based on flip flag
|
||||
int xscale = yscale * (c->flip ? -1 : 1);
|
||||
// Draw
|
||||
float angle = 0; //fmod(window_time()*360/5, 360);
|
||||
float scale[2] = { 2*xscale, 2*yscale };
|
||||
float position[3] = { c->x,c->y,c->y }, no_offset[2] = {0,0}, spritesheet[3] = { frame_num,8,4 };
|
||||
sprite_sheet(catImage,
|
||||
spritesheet, // frame_number in a 8x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
no_offset, scale, // offset(x,y), scale(x,y)
|
||||
0,white,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
float position_neg_sort[3] = { c->x,c->y,-c->y }, offset[2] = {-1,5}, no_spritesheet[3] = {0,0,0};
|
||||
sprite_sheet(shadowImage,
|
||||
no_spritesheet, // no frame_number (0x0 spritesheet)
|
||||
position_neg_sort, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0,alpha,0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void demo_kids() {
|
||||
static int angle; //++angle;
|
||||
static int *x, *y, *v;
|
||||
|
||||
// init
|
||||
if( NUM_SPRITES_CHANGED ) {
|
||||
NUM_SPRITES_CHANGED = 0;
|
||||
|
||||
y = (int*)REALLOC(y, 0 );
|
||||
x = (int*)REALLOC(x, NUM_SPRITES * sizeof(int) );
|
||||
y = (int*)REALLOC(y, NUM_SPRITES * sizeof(int) );
|
||||
v = (int*)REALLOC(v, NUM_SPRITES * sizeof(int) );
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
randset(i);
|
||||
x[i] = randi(0, window_width());
|
||||
y[i] = randi(0, window_height());
|
||||
v[i] = randi(1, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// config
|
||||
const int appw = window_width(), apph = window_height();
|
||||
|
||||
// move & render
|
||||
for( int i = 0; i < NUM_SPRITES; ++i ) {
|
||||
y[i] = (y[i] + v[i]) % (apph + 128);
|
||||
int col = ((x[i] / 10) % 4); // 4x4 tilesheet
|
||||
int row = ((y[i] / 10) % 4);
|
||||
int num_frame = col * 4 + row;
|
||||
float position[3] = {x[i],y[i],y[i]}, offset[2]={0,0}, scale[2]={1,1}, spritesheet[3]={num_frame,4,4};
|
||||
sprite_sheet(kids,
|
||||
spritesheet, // num_frame in a 4x4 spritesheet
|
||||
position, angle, // position(x,y,depth: sort by Y), angle
|
||||
offset, scale, // offset(x,y), scale(x,y)
|
||||
0, ~0u, 0 // is_additive, tint color, resolution independant
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
window_create(75.f, 0);
|
||||
window_title("V4K - Sprite");
|
||||
window_color( SILVER );
|
||||
|
||||
// options
|
||||
int do_cats = 1;
|
||||
NUM_SPRITES = optioni("--num_sprites,-N", NUM_SPRITES);
|
||||
if(do_cats) NUM_SPRITES/=2; // cat-sprite+cat-shadow == 2 sprites
|
||||
|
||||
// load sprites and sheets
|
||||
kids = texture( "spriteSheetExample.png", TEXTURE_LINEAR );
|
||||
catImage = texture( "cat.png", TEXTURE_LINEAR ); //
|
||||
shadowImage = texture( "cat-shadow.png", TEXTURE_LINEAR );
|
||||
inputs = texture( "prompts_tilemap_34x24_16x16x1.png", TEXTURE_LINEAR );
|
||||
|
||||
// load all fx files, including subdirs
|
||||
fx_load("fx**.fs");
|
||||
|
||||
// init camera (x,y) (z = zoom)
|
||||
camera_t cam = camera();
|
||||
cam.position = vec3(window_width()/2,window_height()/2,1);
|
||||
camera_enable(&cam);
|
||||
|
||||
while(window_swap()) {
|
||||
if( input(KEY_F5)) window_reload();
|
||||
if( input(KEY_F11)) window_fullscreen( window_has_fullscreen() ^ 1);
|
||||
if( input(KEY_ESC) ) break;
|
||||
|
||||
// camera panning (x,y) & zooming (z)
|
||||
if( !ui_hover() && !ui_active() ) {
|
||||
if( input(MOUSE_L) ) cam.position.x -= input_diff(MOUSE_X);
|
||||
if( input(MOUSE_L) ) cam.position.y -= input_diff(MOUSE_Y);
|
||||
cam.position.z += input_diff(MOUSE_W) * 0.1; // cam.p.z += 0.001f; for tests
|
||||
}
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
profile("Sprite batching") {
|
||||
if(do_cats) demo_cats(); else demo_kids();
|
||||
}
|
||||
|
||||
// flush retained renderer, so we ensure the fbos are up to date before fx_end()
|
||||
profile("Sprite flushing") {
|
||||
sprite_flush();
|
||||
}
|
||||
|
||||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
// draw pixel-art hud, 16x16 ui element, scaled and positioned in resolution-independant way
|
||||
{
|
||||
vec3 old_pos = camera_get_active()->position;
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = vec3(window_width()/2,window_height()/2,1);
|
||||
|
||||
float zindex = window_height(); // large number, on top
|
||||
float spritesheet[3] = {17,34,24}, offset[2] = {0, - 2*absf(sin(window_time()*5))}; // sprite cell and animation
|
||||
float scale[2] = {3, 3}, tile_w = 16 * scale[0], tile_h = 16 * scale[1]; // scaling
|
||||
float position[3] = {window_width() - tile_w, window_height() - tile_h, zindex }; // position in screen-coordinates
|
||||
sprite_sheet(inputs, spritesheet, position, 0/*rotation*/, offset, scale, false/*is_additive*/, WHITE/*color*/, false/*resolution_independant*/);
|
||||
|
||||
sprite_flush();
|
||||
camera_get_active()->position = old_pos;
|
||||
}
|
||||
|
||||
if( ui_panel("Sprite", 0) ) {
|
||||
const char *labels[] = {"Kids","Cats"};
|
||||
if( ui_list("Sprite type", labels, countof(labels), &do_cats) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_int("Number of Sprites", &NUM_SPRITES) ) NUM_SPRITES_CHANGED = 1;
|
||||
if( ui_clampf("Zoom", &cam.position.z, 0.1, 10));
|
||||
ui_panel_end();
|
||||
}
|
||||
if( ui_panel("FX", 0) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,7 +76,7 @@ int main() {
|
|||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, TEX_WIDTH, TEX_WIDTH, 0, GL_RGBA, GL_FLOAT, img);
|
||||
shader_bind(comp);
|
||||
compute_dispatch(TEX_WIDTH/16, TEX_WIDTH/16, 1);
|
||||
image_write_barrier();
|
||||
write_barrier_image();
|
||||
} else {
|
||||
temp_calc(img);
|
||||
texture_update(&tex, TEX_WIDTH, TEX_WIDTH, 4, img, TEXTURE_LINEAR|TEXTURE_FLOAT);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
uniform float intensity = 0.003f; /// min:0.001 max:0.10 set:0.003
|
||||
uniform float angle = 0.0f; /// min:0 max:6.28 set:0
|
||||
uniform float separation; /// min:-0.10 max:0.10 set:0.003
|
||||
uniform float angle; /// min:0 max:6.28 set:0
|
||||
|
||||
void main() {
|
||||
vec2 uv = TEXCOORD.st;
|
||||
vec2 offset = intensity * vec2( cos(angle), sin(angle) );
|
||||
vec2 offset = separation * vec2( cos(angle), sin(angle) );
|
||||
vec4 color = texture( iChannel0, uv);
|
||||
color.r = texture( iChannel0, uv + offset ).x;
|
||||
color.b = texture( iChannel0, uv - offset ).z;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float intensity = 2.0; /// set:2.0
|
||||
uniform float intensity; /// set:2.0
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// [ref] https://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
|
||||
|
||||
uniform float intensity; /// set:4
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec4 base = texture(iChannel0, uv), color = vec4(0.0);
|
||||
vec2 offset = vec2(intensity,0) / iResolution;
|
||||
color += base * 0.30;
|
||||
color += texture(iChannel0, uv + offset) * 0.35;
|
||||
color += texture(iChannel0, uv - offset) * 0.35;
|
||||
|
||||
fragColor = vec4( color.rgb, base.a );
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
// [ref] https://rastergrid.com/blog/2010/09/efficient-gaussian-blur-with-linear-sampling/
|
||||
|
||||
uniform float intensity; /// set:4
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
vec4 base = texture(iChannel0, uv), color = vec4(0.0);
|
||||
vec2 offset = vec2(0,intensity) / iResolution;
|
||||
color += base * 0.30;
|
||||
color += texture(iChannel0, uv + offset) * 0.35;
|
||||
color += texture(iChannel0, uv - offset) * 0.35;
|
||||
|
||||
fragColor = vec4( color.rgb, base.a );
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// [ref] https://www.inf.ufrgs.br/~oliveira/pubs_files/CVD_Simulation/CVD_Simulation.html
|
||||
|
||||
uniform int colorblind_mode = 2; /// min:0 max:4 set:2 tip:"off, achromatopsia, protanomaly, deuteranomaly, tritanomaly"
|
||||
uniform int colorblind_mode; /// set:2 min:0 max:4 tip:"off, achromatopsia, protanomaly, deuteranomaly, tritanomaly"
|
||||
uniform mat3 colorblind_matrices[5] = mat3[5](
|
||||
mat3(1.000,0.000,0.000, 0.000,1.000,0.000, 0.000,0.000,1.000), // 0 no colorblind
|
||||
mat3(0.299,0.587,0.114, 0.299,0.587,0.114, 0.299,0.587,0.114), // 1 achromatopsia (luma)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
uniform float contrast = 1.5; /// set:1.5 tip:"bleach-to-gray < 1 > saturate"
|
||||
uniform float brightness = 0; /// set:0 max:2
|
||||
uniform float contrast; /// set:1.5 tip:"bleach-to-gray < 1 > saturate"
|
||||
uniform float brightness; /// set:0 max:2
|
||||
|
||||
void main() {
|
||||
vec4 pixelColor = texture(iChannel0, TEXCOORD.st);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float intensity = 0.004; /// set:0.004 max:0.03
|
||||
uniform float intensity; /// set:0.004 max:0.03
|
||||
|
||||
highp float rand(vec2 co) {
|
||||
highp float a = 12.9898;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/// tip:"Requires MSAA off for best results"
|
||||
|
||||
// FXAA fragment shader by Timothy Lottes (public domain)
|
||||
// http://timothylottes.blogspot.com/
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
/// tip:"Requires MSAA off for best results"
|
||||
|
||||
/*****************************************
|
||||
* FXAA 3.11 Implementation - effendiian
|
||||
* -------------------------------------
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float intensity = 16.0; /// set:16 max:32
|
||||
uniform float intensity; /// set:16 max:32
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
uniform float h = 1.0; /// set:1.0 tip:"hue color shift"
|
||||
uniform float s = 0.5; /// set:0.5 tip:"gray: <1, saturate: >1"
|
||||
uniform float v = 1.0; /// set:1.0 tip:"black: <1, white: >1"
|
||||
uniform float h; /// set:1.58 tip:"hue color shift"
|
||||
uniform float s; /// set:1.51 tip:"gray: <1, saturate: >1"
|
||||
uniform float v; /// set:1.05 tip:"black: <1, white: >1"
|
||||
|
||||
vec3 hsv2rgb(vec3 c) {
|
||||
return mix(vec3(1.),clamp((abs(fract(c.r+vec3(3.,2.,1.)/3.)*6.-3.)-1.),0.,1.),c.g)*c.b;
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
uniform float amount; /// min:0 set:0.10 max:0.5
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
||||
// letterbox
|
||||
if( abs(2.*fragCoord.y-iResolution.y) > iResolution.x * 0.42 ) {
|
||||
if( uv.y < amount || (1.0-uv.y) < amount ) {
|
||||
fragColor = vec4( 0., 0., 0., 1. );
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
fragColor = texture(iChannel0, uv);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
uniform int thickness = 2; /// set:2
|
||||
uniform vec4 border_color = vec4(1,1,0,1); /// set:1,1,0,1
|
||||
/// tip:"Ensure colorbuffer is alpha clear before calling this one."
|
||||
|
||||
uniform int thickness; /// set:2
|
||||
uniform vec4 border_color; /// set:1,1,0,1
|
||||
|
||||
void main() {
|
||||
vec4 texel = texture(iChannel0, uv);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
uniform float CellSize = 2.5; /// min:1 set:2.5 max:16
|
||||
//uniform float xCellSize = 2.5; /// min:1 set:2.5
|
||||
//uniform float yCellSize = 2.5; /// min:1 set:2.5
|
||||
uniform float CellSize; /// min:1 set:2.5 max:16
|
||||
//uniform float xCellSize; /// min:1 set:2.5
|
||||
//uniform float yCellSize; /// min:1 set:2.5
|
||||
|
||||
void main() {
|
||||
float xPixels = iWidth/CellSize, yPixels = iHeight/CellSize; // iWidth/xCellSize, iHeight/yCellSize;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float factor = 3.0; /// min:1 max:255 set:3
|
||||
uniform float factor; /// min:1 max:255 set:3
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// based on code by arkano22. See: http://www.gamedev.net/forums/topic/550699-ssao-no-halo-artifacts/
|
||||
// - rlyeh, public domain
|
||||
|
||||
uniform vec2 camerarange = vec2(1.0, 1024.0);
|
||||
uniform vec2 camerarange; /// set:1,1024
|
||||
|
||||
// uniform sampler2D som; // Depth texture (iChannel1)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
uniform float hardness = 0.1; /// set:0.1 max:2
|
||||
uniform float flickering = 0.01; /// set:0.01
|
||||
uniform float hardness; /// set:0.1 max:2
|
||||
uniform float flickering; /// set:0.01
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// note: valve edition from http://alex.vlachos.com/graphics/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
|
||||
// note: input in pixels (ie not normalized uv)
|
||||
|
||||
uniform float intensity = 250.0; /// min:245 max:255 set:250
|
||||
uniform float intensity; /// min:245 max:255 set:250
|
||||
|
||||
vec3 ScreenSpaceDither2(vec2 vScreenPos, float colorDepth) {
|
||||
// lestyn's RGB dither (7 asm instructions) from Portal 2 X360, slightly modified for VR
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
uniform float intensity = 1.0; /// set:1
|
||||
uniform float brightness; /// set:1
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
vec4 src = texture(iChannel0, uv);
|
||||
|
||||
vec3 color = vec3(
|
||||
dot(src.rgb, vec3(0.393 * intensity, 0.769 * intensity, 0.189 * intensity)),
|
||||
dot(src.rgb, vec3(0.349 * intensity, 0.686 * intensity, 0.168 * intensity)),
|
||||
dot(src.rgb, vec3(0.272 * intensity, 0.534 * intensity, 0.131 * intensity))
|
||||
dot(src.rgb, vec3(0.393 * brightness, 0.769 * brightness, 0.189 * brightness)),
|
||||
dot(src.rgb, vec3(0.349 * brightness, 0.686 * brightness, 0.168 * brightness)),
|
||||
dot(src.rgb, vec3(0.272 * brightness, 0.534 * brightness, 0.131 * brightness))
|
||||
);
|
||||
|
||||
fragColor = vec4(color, src.a);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float intensity = 0.25; /// set:0.25 max:2
|
||||
uniform float intensity; /// set:0.25 max:2
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ){
|
||||
vec2 uv = fragCoord / iResolution.xy;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// exposure tone mapping
|
||||
// https://learnopengl.com/Advanced-Lighting/HDR
|
||||
|
||||
uniform float exposure = 1.0; // min:0.1 max:5 set:1
|
||||
uniform float exposure; // min:0.1 max:5 set:1
|
||||
|
||||
out vec4 color;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float gamma = 2.2; /// set:2.2
|
||||
uniform float gamma; /// set:2.2
|
||||
out vec4 color;
|
||||
|
||||
void main(void) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
uniform float radius = 0.75; /// set:0.75
|
||||
uniform float radius; /// set:0.75
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
http://hdri.cgtechniques.com/~sponza/files/
|
||||
|
||||
Sponza modeled by Marko Dabrovic, with UVs and crack errors fixed by Kenzie Lamar at Vicarious Visions.
|
||||
Bump maps painted by Morgan McGuire.
|
|
@ -0,0 +1,21 @@
|
|||
/// tip:"Ensure colorbuffer is alpha clear before calling this one."
|
||||
|
||||
uniform int thickness; /// set:2
|
||||
uniform vec4 border_color; /// set:1,1,0,1
|
||||
|
||||
void main() {
|
||||
vec4 texel = texture(iChannel0, uv);
|
||||
float outline = 0.0;
|
||||
if( texel.a == 0.0 ) {
|
||||
for( int x = -thickness; x <= thickness; x++ ) {
|
||||
for( int y = -thickness;y <= thickness; y++ ) {
|
||||
float sample = texture(iChannel0, uv+vec2(float(x)/iWidth, float(y)/iHeight)).a;
|
||||
if( sample > 0.0 ) {
|
||||
outline = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FRAGCOLOR = vec4(border_color.rgb, outline * border_color.a); // mix(texel, border_color, outline * border_color.a);
|
||||
}
|
|
@ -2313,7 +2313,7 @@ enum { NETWORK_USERID = 7, NETWORK_COUNT , NETWORK_CAPACITY };
|
|||
extern void (*dtor[256])();
|
||||
void* obj_initialize( void **ptr, char *type_and_info );
|
||||
void *obj_tmpalloc;
|
||||
int profile_enable(bool on);
|
||||
int profiler_enable(bool on);
|
||||
struct profile_t { double stat; int32_t cost, avg; };
|
||||
typedef struct { map base; struct { pair p; char * key; struct profile_t val; } tmp, *ptr; struct profile_t* tmpval; int (*typed_cmp)(char *, char *); uint64_t (*typed_hash)(char *); } * profiler_t;
|
||||
extern profiler_t profiler;
|
||||
|
@ -2504,6 +2504,8 @@ int texture_width;
|
|||
void shader_destroy(unsigned shader);
|
||||
unsigned shader_properties(unsigned shader);
|
||||
char** shader_property(unsigned shader, unsigned property_no);
|
||||
void shader_apply_param(unsigned shader, unsigned param_no);
|
||||
void shader_apply_params(unsigned shader, const char *parameter_mask);
|
||||
int ui_shader(unsigned shader);
|
||||
int ui_shaders();
|
||||
enum BUFFER_MODE {
|
||||
|
@ -2515,8 +2517,8 @@ BUFFER_READ_WRITE
|
|||
void compute_dispatch(unsigned wx, unsigned wy, unsigned wz);
|
||||
void shader_image(texture_t t, unsigned unit, unsigned level, int layer, unsigned access);
|
||||
void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int layer, unsigned texel_type, unsigned access);
|
||||
void image_write_barrier();
|
||||
void write_barrier();
|
||||
void write_barrier_image();
|
||||
enum SSBO_USAGE {
|
||||
STATIC_DRAW,
|
||||
STATIC_READ,
|
||||
|
@ -2968,7 +2970,6 @@ 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);
|
||||
|
@ -2990,18 +2991,17 @@ PANEL_OPEN = 1,
|
|||
int ui_subimage(const char *label, handle id, unsigned iw, unsigned ih, unsigned sx, unsigned sy, unsigned sw, unsigned sh);
|
||||
int ui_colormap(const char *label, colormap_t *cm);
|
||||
int ui_separator();
|
||||
int ui_bits8(const char *label, uint8_t *bits);
|
||||
int ui_bits16(const char *label, uint16_t *bits);
|
||||
int ui_bitmask8(const char *label, uint8_t *bits);
|
||||
int ui_bitmask16(const char *label, uint16_t *bits);
|
||||
int ui_console();
|
||||
int ui_clampf(const char *label, float *value, float minf, float maxf);
|
||||
int ui_label(const char *label);
|
||||
int ui_label2(const char *label, const char *caption);
|
||||
int ui_label2_bool(const char *label, bool enabled);
|
||||
int ui_label2_float(const char *label, float value);
|
||||
int ui_label2_toolbar(const char *label, const char *icons);
|
||||
int ui_slider(const char *label, float *value);
|
||||
int ui_slider2(const char *label, float *value, const char *caption);
|
||||
int ui_const_bool(const char *label, const double value);
|
||||
int ui_const_float(const char *label, const double value);
|
||||
int ui_const_string(const char *label, const char *value);
|
||||
int ui_contextual_end();
|
||||
int ui_collapse_clicked();
|
||||
int ui_collapse_end();
|
||||
|
@ -3010,9 +3010,10 @@ PANEL_OPEN = 1,
|
|||
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 on);
|
||||
int ui_enabled();
|
||||
vec2 ui_get_dims();
|
||||
int ui_enable();
|
||||
int ui_enabled();
|
||||
int ui_disable();
|
||||
int ui_has_menubar();
|
||||
int ui_menu(const char *items);
|
||||
int ui_menu_editbox(char *buf, int bufcap);
|
||||
|
|
|
@ -14226,14 +14226,14 @@ extern "C" {
|
|||
// system headers
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // for linux
|
||||
#define _GNU_SOURCE ///- for linux
|
||||
#endif
|
||||
|
||||
#if is(cl) && is(win32) // for VC IDE
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _WIN32_WINNT 0x0600 // 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#define _CRT_SECURE_NO_WARNINGS ///-
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE ///-
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS ///-
|
||||
#define _WIN32_WINNT 0x0600 ///- 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#endif
|
||||
|
||||
#if is(cl)
|
||||
|
@ -16345,9 +16345,9 @@ static __thread void *obj_tmpalloc;
|
|||
# define profile(section) for(int macro(i) = 1; macro(i); macro(i) = 0)
|
||||
# define profile_incstat(name, accum) do {} while(0)
|
||||
# define profile_setstat(name, value) do {} while(0)
|
||||
# define profile_init() do {} while(0)
|
||||
# define profile_render() do {} while(0)
|
||||
# define profile_enable(x) 0
|
||||
# define profiler_init() do {} while(0)
|
||||
# define profiler_enable(x) 0
|
||||
# define ui_profiler() do {} while(0)
|
||||
#else
|
||||
# define profile(section) for( \
|
||||
struct profile_t *found = profiler_enabled ? \
|
||||
|
@ -16360,7 +16360,7 @@ static __thread void *obj_tmpalloc;
|
|||
# define profile_setstat(name, value) for( \
|
||||
struct profile_t *found = profiler_enabled ? map_find_or_add(profiler, name, (struct profile_t){0}) : NULL; \
|
||||
found; found->stat = value, found = NULL) ///+
|
||||
API int profile_enable(bool on);
|
||||
API int profiler_enable(bool on);
|
||||
|
||||
struct profile_t { double stat; int32_t cost, avg; }; ///-
|
||||
typedef map(char *, struct profile_t) profiler_t; ///-
|
||||
|
@ -16715,6 +16715,9 @@ API void shader_destroy(unsigned shader);
|
|||
API unsigned shader_properties(unsigned shader);
|
||||
API char** shader_property(unsigned shader, unsigned property_no);
|
||||
|
||||
API void shader_apply_param(unsigned shader, unsigned param_no);
|
||||
API void shader_apply_params(unsigned shader, const char *parameter_mask);
|
||||
|
||||
API int ui_shader(unsigned shader);
|
||||
API int ui_shaders();
|
||||
|
||||
|
@ -16759,12 +16762,12 @@ API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int
|
|||
|
||||
// gpu memory barriers
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void image_write_barrier();
|
||||
|
||||
/// Blocks main thread until all memory operations are done by the GPU.
|
||||
API void write_barrier();
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void write_barrier_image();
|
||||
|
||||
// ssbo
|
||||
/// `STATIC`, `DYNAMIC` AND `STREAM` specify the frequency at which we intend to access the data.
|
||||
/// `DRAW` favors CPU->GPU operations.
|
||||
|
@ -17485,7 +17488,6 @@ 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]
|
||||
|
@ -17507,18 +17509,17 @@ API int ui_image(const char *label, handle id, unsigned w, unsigned h); //(w,
|
|||
API int ui_subimage(const char *label, handle id, unsigned iw, unsigned ih, unsigned sx, unsigned sy, unsigned sw, unsigned sh);
|
||||
API int ui_colormap(const char *label, colormap_t *cm); // returns num member changed: 1 for color, 2 for texture map
|
||||
API int ui_separator();
|
||||
API int ui_bits8(const char *label, uint8_t *bits);
|
||||
API int ui_bits16(const char *label, uint16_t *bits);
|
||||
API int ui_bitmask8(const char *label, uint8_t *bits);
|
||||
API int ui_bitmask16(const char *label, uint16_t *bits);
|
||||
API int ui_console();
|
||||
API int ui_clampf(const char *label, float *value, float minf, float maxf);
|
||||
API int ui_label(const char *label);
|
||||
API int ui_label2(const char *label, const char *caption);
|
||||
API int ui_label2_bool(const char *label, bool enabled);
|
||||
API int ui_label2_float(const char *label, float value);
|
||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||
API int ui_slider(const char *label, float *value);
|
||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||
API int ui_const_bool(const char *label, const double value);
|
||||
API int ui_const_float(const char *label, const double value);
|
||||
API int ui_const_string(const char *label, const char *value);
|
||||
API int ui_contextual_end();
|
||||
API int ui_collapse_clicked();
|
||||
API int ui_collapse_end();
|
||||
|
@ -17528,10 +17529,12 @@ API int ui_window_end();
|
|||
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(int on);
|
||||
API int ui_enabled();
|
||||
API vec2 ui_get_dims();
|
||||
|
||||
API int ui_enable();
|
||||
API int ui_enabled();
|
||||
API int ui_disable();
|
||||
|
||||
API int ui_has_menubar();
|
||||
API int ui_menu(const char *items); // semicolon-separated or comma-separated items
|
||||
API int ui_menu_editbox(char *buf, int bufcap);
|
||||
|
@ -330739,6 +330742,9 @@ float audio_volume_master(float gain) {
|
|||
}
|
||||
|
||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// do nothing, gain used as-is
|
||||
} else {
|
||||
|
@ -333133,6 +333139,7 @@ int cook_jobs() {
|
|||
|
||||
void cook_config( const char *pathfile_to_cook_ini ) { // @todo: test run-from-"bin/" case on Linux.
|
||||
COOK_INI = pathfile_to_cook_ini;
|
||||
ASSERT( file_exist(COOK_INI) );
|
||||
}
|
||||
#line 0
|
||||
|
||||
|
@ -337536,32 +337543,37 @@ bool input_touch_active() {
|
|||
void input_demo() {
|
||||
if( ui_panel("Input",0) ) {
|
||||
ui_section("Keyboard");
|
||||
ui_const_bool("[Key 1]", input(KEY_1));
|
||||
ui_const_bool("[Key 2]", input(KEY_2));
|
||||
ui_const_bool("[Key 3]", input(KEY_3));
|
||||
ui_const_bool("[Key 4]", input(KEY_4));
|
||||
ui_const_bool("[Key 5]", input(KEY_5));
|
||||
ui_const_bool("[Key 6]", input(KEY_6));
|
||||
ui_const_bool("[Key 7]", input(KEY_7));
|
||||
|
||||
uint8_t keymap = 0;
|
||||
keymap |= (!!input(KEY_1)) << 7;
|
||||
keymap |= (!!input(KEY_2)) << 6;
|
||||
keymap |= (!!input(KEY_3)) << 5;
|
||||
keymap |= (!!input(KEY_4)) << 4;
|
||||
keymap |= (!!input(KEY_5)) << 3;
|
||||
keymap |= (!!input(KEY_6)) << 2;
|
||||
keymap |= (!!input(KEY_7)) << 1;
|
||||
keymap |= (!!input(KEY_8)) << 0;
|
||||
ui_bitmask8("[Keys 1..8]", &keymap);
|
||||
|
||||
ui_separator();
|
||||
ui_const_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_const_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_const_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_const_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_const_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_const_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_const_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_label2_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_label2_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_label2_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_label2_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_label2_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_label2_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_label2_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_separator();
|
||||
|
||||
ui_section("Mouse");
|
||||
ui_const_float("X", input(MOUSE_X));
|
||||
ui_const_float("Y", input(MOUSE_Y));
|
||||
ui_label2_float("X", input(MOUSE_X));
|
||||
ui_label2_float("Y", input(MOUSE_Y));
|
||||
ui_separator();
|
||||
ui_const_float("Wheel", input(MOUSE_W));
|
||||
ui_label2_float("Wheel", input(MOUSE_W));
|
||||
ui_separator();
|
||||
ui_const_bool("Left", input(MOUSE_L));
|
||||
ui_const_bool("Middle", input(MOUSE_M));
|
||||
ui_const_bool("Right", input(MOUSE_R));
|
||||
ui_label2_bool("Left", input(MOUSE_L));
|
||||
ui_label2_bool("Middle", input(MOUSE_M));
|
||||
ui_label2_bool("Right", input(MOUSE_R));
|
||||
ui_separator();
|
||||
for( int i = 0; i <= CURSOR_SW_AUTO; ++i ) if(ui_button(va("Cursor shape #%d", i))) window_cursor_shape(i);
|
||||
ui_separator();
|
||||
|
@ -337573,45 +337585,45 @@ void input_demo() {
|
|||
|
||||
input_use(gamepad_id);
|
||||
|
||||
ui_const_string("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_const_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
ui_label2("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_label2_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_bool("A", input(GAMEPAD_A) );
|
||||
ui_const_bool("B", input(GAMEPAD_B) );
|
||||
ui_const_bool("X", input(GAMEPAD_X) );
|
||||
ui_const_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_const_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_const_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_const_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_const_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_const_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_const_bool("Start", input(GAMEPAD_START) );
|
||||
ui_label2_bool("A", input(GAMEPAD_A) );
|
||||
ui_label2_bool("B", input(GAMEPAD_B) );
|
||||
ui_label2_bool("X", input(GAMEPAD_X) );
|
||||
ui_label2_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_label2_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_label2_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_label2_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_label2_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_label2_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_label2_bool("Start", input(GAMEPAD_START) );
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_const_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_const_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_const_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_const_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
ui_label2_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_label2_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_label2_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_label2_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_label2_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
|
||||
vec2 v = input_filter_deadzone( input2(GAMEPAD_LPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", v.x);
|
||||
ui_const_float("Filtered pad y", v.y);
|
||||
ui_label2_float("Filtered pad x", v.x);
|
||||
ui_label2_float("Filtered pad y", v.y);
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_const_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_const_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_const_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_const_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
ui_label2_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_label2_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_label2_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_label2_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_label2_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
|
||||
vec2 w = input_filter_deadzone( input2(GAMEPAD_RPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", w.x);
|
||||
ui_const_float("Filtered pad y", w.y);
|
||||
ui_label2_float("Filtered pad x", w.x);
|
||||
ui_label2_float("Filtered pad y", w.y);
|
||||
|
||||
input_use(0);
|
||||
|
||||
|
@ -339909,22 +339921,23 @@ unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char
|
|||
array(char*) props = 0;
|
||||
do_once map_init_int( shader_reflect );
|
||||
if(vs) for each_substring(vs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(fs) for each_substring(fs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(gs) for each_substring(gs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if( props ) {
|
||||
map_insert(shader_reflect, program, props);
|
||||
for( int i = 0; i < array_count(props); ++i ) shader_apply_param(program, i);
|
||||
}
|
||||
|
||||
return program;
|
||||
|
@ -339937,7 +339950,60 @@ unsigned shader_properties(unsigned shader) {
|
|||
|
||||
char** shader_property(unsigned shader, unsigned property) {
|
||||
array(char*) *found = map_find(shader_reflect, shader);
|
||||
return found ? &(*found)[property] : NULL;
|
||||
return found && property < array_count(*found) ? &(*found)[property] : NULL;
|
||||
}
|
||||
|
||||
void shader_apply_param(unsigned shader, unsigned param_no) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
if( param_no < num_properties ) {
|
||||
char *line = *shader_property(shader, param_no);
|
||||
|
||||
char type[32], name[32];
|
||||
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
if( strchr("ibfv", type[0]) ) {
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'b') glUniform1i(glGetUniformLocation(shader, name), !!setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shader_apply_params(unsigned shader, const char *parameter_mask) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
for( unsigned i = 0; i < num_properties; ++i ) {
|
||||
char *line = *shader_property(shader,i);
|
||||
|
||||
char name[32];
|
||||
if( sscanf(line, "%*s %*s %s", name) != 1 ) continue;
|
||||
if( !strmatch(name, parameter_mask) ) continue;
|
||||
shader_apply_param(shader, i);
|
||||
}
|
||||
}
|
||||
|
||||
int ui_shader(unsigned shader) {
|
||||
|
@ -339948,25 +340014,43 @@ int ui_shader(unsigned shader) {
|
|||
char **ptr = shader_property(shader,i);
|
||||
|
||||
const char *line = *ptr; // debug: ui_label(line);
|
||||
char uniform[32], type[32], name[32];
|
||||
if( sscanf(line, "%s %s %s", uniform, type, name) != 3) continue;
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
|
||||
char uniform[32], type[32], name[32], early_exit = '\0';
|
||||
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
|
||||
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
|
||||
va("%c%s " ICON_MD_HELP "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
// supports int,float,vec2/3/4,color3/4
|
||||
int touched = 0;
|
||||
if( type[0] == 'i' ) {
|
||||
if( type[0] == 'b' ) {
|
||||
bool v = !!setv.x;
|
||||
|
||||
if( (touched = ui_bool(label, &v)) != 0 ) {
|
||||
setv.x = v;
|
||||
}
|
||||
}
|
||||
else if( type[0] == 'i' ) {
|
||||
int v = setv.x;
|
||||
|
||||
if( (touched = ui_int(label, &v)) != 0 ) {
|
||||
|
@ -339974,9 +340058,11 @@ int ui_shader(unsigned shader) {
|
|||
}
|
||||
}
|
||||
else if( type[0] == 'f' ) {
|
||||
setv.x = (clampf(setv.x, minv.x, maxv.x) - minv.x) / (maxv.x - minv.x);
|
||||
setv.x = clampf(setv.x, minv.x, maxv.x);
|
||||
char *caption = va("%5.2f", setv.x);
|
||||
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
|
||||
|
||||
if( (touched = ui_slider2(label, &setv.x, va("%5.2f", setv.x))) != 0 ) {
|
||||
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
|
||||
setv.x = clampf(minv.x + setv.x * (maxv.x-minv.x), minv.x, maxv.x); // min..max range
|
||||
}
|
||||
}
|
||||
|
@ -340001,28 +340087,20 @@ int ui_shader(unsigned shader) {
|
|||
setv = clamp4(setv,minv,maxv);
|
||||
}
|
||||
}
|
||||
else if( tip ) ui_label( tip );
|
||||
|
||||
if( touched ) {
|
||||
// send to shader
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
|
||||
// upgrade value
|
||||
*ptr = FREE(*ptr);
|
||||
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
|
||||
|
||||
// apply
|
||||
shader_apply_param(shader, i);
|
||||
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(num_properties) ui_separator();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -340030,13 +340108,14 @@ int ui_shaders() {
|
|||
if( !map_count(shader_reflect) ) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("Shaders", 0) : ui_panel("Shaders", 0) ) ) {
|
||||
for each_map_ptr(shader_reflect, unsigned, k, array(char*), v) {
|
||||
ui_section(va("Shader %d",*k));
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
char *id = va("##SHD%d", *k);
|
||||
char *title = va("Shader %d", *k);
|
||||
for( int p = (open = ui_collapse(title, id)), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_label(va("Shader %d",*k));
|
||||
changed |= ui_shader(*k);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@ -340091,7 +340170,7 @@ void write_barrier(){
|
|||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
}
|
||||
|
||||
void image_write_barrier(){
|
||||
void write_barrier_image(){
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
}
|
||||
|
||||
|
@ -342949,9 +343028,9 @@ void postfx_clear(postfx *fx) {
|
|||
|
||||
int ui_postfx(postfx *fx, int pass) {
|
||||
int on = ui_enabled();
|
||||
ui_enable( postfx_enabled(fx,pass) );
|
||||
( postfx_enabled(fx,pass) ? ui_enable : ui_disable )();
|
||||
int rc = ui_shader(fx->pass[pass].program);
|
||||
ui_enable( on );
|
||||
( on ? ui_enable : ui_disable )();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -343132,16 +343211,12 @@ int ui_fxs() {
|
|||
if(!fx.num_loaded) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("FX", 0) : ui_panel("FX", 0) ) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -347179,8 +347254,8 @@ default_hue = 0.52;
|
|||
struct nk_color active = nk_hsv_f( 0.600, 0.00, 0.150); // bright b/w
|
||||
struct nk_color table[NK_COLOR_COUNT] = {0};
|
||||
table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 215);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 245);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 245);
|
||||
table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
|
||||
table[NK_COLOR_BUTTON] = main;
|
||||
table[NK_COLOR_BUTTON_HOVER] = hover;
|
||||
|
@ -347571,7 +347646,7 @@ int ui_active() {
|
|||
}
|
||||
|
||||
static
|
||||
int ui_enable_(int enabled) {
|
||||
int ui_set_enable_(int enabled) {
|
||||
static struct nk_style off, on;
|
||||
do_once {
|
||||
off = on = ui_ctx->style;
|
||||
|
@ -347809,8 +347884,11 @@ int ui_enable_(int enabled) {
|
|||
}
|
||||
|
||||
static int ui_is_enabled = 1;
|
||||
int ui_enable(int on) {
|
||||
return ui_is_enabled == on ? 0 : ui_enable_(ui_is_enabled = on);
|
||||
int ui_enable() {
|
||||
return ui_is_enabled == 1 ? 0 : ui_set_enable_(ui_is_enabled = 1);
|
||||
}
|
||||
int ui_disable() {
|
||||
return ui_is_enabled == 0 ? 0 : ui_set_enable_(ui_is_enabled = 0);
|
||||
}
|
||||
int ui_enabled() {
|
||||
return ui_is_enabled;
|
||||
|
@ -348592,6 +348670,20 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x
|
|||
|
||||
return ui_label_icon_clicked_R.x;
|
||||
}
|
||||
int ui_label2_bool(const char *text, bool value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_label2_float(const char *text, float value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_label2_wrap(const char *label, const char *str) { // @fixme: does not work (remove dynamic layout?)
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
nk_text_wrap(ui_ctx, str, strlen(str));
|
||||
return 0;
|
||||
}
|
||||
int ui_label2_toolbar(const char *label, const char *icons) {
|
||||
int mouse_click = ui_label2(label, va(">%s", icons));
|
||||
int choice = !mouse_click ? 0 : 1 + -mouse_click / (UI_ICON_FONTSIZE + UI_ICON_SPACING_X); // divided by px per ICON_MD_ glyph approximately
|
||||
|
@ -348706,18 +348798,6 @@ int ui_button(const char *s) {
|
|||
return ui_buttons(1, s);
|
||||
}
|
||||
|
||||
int ui_const_bool(const char *text, const double value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_const_float(const char *text, const double value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_const_string(const char *label, const char *text) {
|
||||
return ui_label2(label, text);
|
||||
}
|
||||
|
||||
int ui_toggle(const char *label, bool *value) {
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
|
@ -348981,13 +349061,6 @@ 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);
|
||||
|
@ -349111,8 +349184,8 @@ int ui_dialog(const char *title, const char *text, int choices, bool *show) { //
|
|||
return *show;
|
||||
}
|
||||
|
||||
#define ui_bits_template(X) \
|
||||
int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
||||
#define ui_bitmask_template(X) \
|
||||
int ui_bitmask##X(const char *label, uint##X##_t *enabled) { \
|
||||
/* @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive */ \
|
||||
nk_layout_row_dynamic(ui_ctx, 1, 1); \
|
||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx); \
|
||||
|
@ -349143,9 +349216,9 @@ int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
|||
return copy ^ *enabled; \
|
||||
}
|
||||
|
||||
ui_bits_template(8);
|
||||
ui_bits_template(16);
|
||||
//ui_bits_template(32);
|
||||
ui_bitmask_template(8);
|
||||
ui_bitmask_template(16);
|
||||
//ui_bitmask_template(32);
|
||||
|
||||
int ui_console() { // @fixme: buggy
|
||||
static char *cmd = 0;
|
||||
|
@ -349306,13 +349379,15 @@ int ui_demo(int do_windows) {
|
|||
if(choice == 2) ui_notify(va("My random toast (%d)", rand()), va("This is notification #%d", ++hits));
|
||||
if(choice == 3) disable_all ^= 1;
|
||||
|
||||
if( disable_all ) ui_enable(0);
|
||||
if( disable_all ) ui_disable();
|
||||
|
||||
if( ui_browse(&browsed_file, &show_browser) ) puts(browsed_file);
|
||||
|
||||
if( ui_section("Labels")) {}
|
||||
if( ui_label("my label")) {}
|
||||
if( ui_label("my label with tooltip@built on " __DATE__ " " __TIME__)) {}
|
||||
if( ui_label2_toolbar("my toolbar", ICON_MD_STAR ICON_MD_STAR_OUTLINE ICON_MD_BOOKMARK ICON_MD_BOOKMARK_BORDER) ) {}
|
||||
//if( ui_label2_wrap("my long label", "and some long long long long text wrapped")) {}
|
||||
|
||||
if( ui_section("Types")) {}
|
||||
if( ui_bool("my bool", &boolean) ) puts("bool changed");
|
||||
|
@ -349345,7 +349420,7 @@ int ui_demo(int do_windows) {
|
|||
}
|
||||
|
||||
if( ui_section("Others")) {}
|
||||
if( ui_bits8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_bitmask8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_toggle("my toggle", &toggle) ) printf("toggle %s\n", toggle ? "on":"off");
|
||||
if( ui_image("my image", texture_checker().id, 0, 0) ) { puts("image clicked"); }
|
||||
|
||||
|
@ -349355,7 +349430,7 @@ int ui_demo(int do_windows) {
|
|||
if( ui_buttons(3, "yes", "no", "maybe") ) { puts("button clicked"); }
|
||||
if( ui_dialog("my dialog", __FILE__ "\n" __DATE__ "\n" "Public Domain.", 2/*two buttons*/, &show_dialog) ) {}
|
||||
|
||||
if( disable_all ) ui_enable(1);
|
||||
if( disable_all ) ui_enable(); // restore enabled state
|
||||
|
||||
ui_panel_end();
|
||||
}
|
||||
|
@ -349447,30 +349522,14 @@ int ui_demo(int do_windows) {
|
|||
profiler_t profiler;
|
||||
int profiler_enabled = 1;
|
||||
|
||||
void (profile_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profile_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (profile_render)() {
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) return;
|
||||
// @transparent
|
||||
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
if( frames <= 0 ) return;
|
||||
}
|
||||
}
|
||||
|
||||
if( has_menu ? ui_window("Profiler", 0) : ui_panel("Profiler", 0) ) {
|
||||
void (profiler_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profiler_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (ui_profiler)() {
|
||||
// @todo: ui_plot()
|
||||
|
||||
double fps = window_fps();
|
||||
profile_setstat("Render.num_fps", fps);
|
||||
|
||||
if(1) { // @todo: ui_plot()
|
||||
// draw fps-meter: 300 samples, [0..70] range each, 70px height plot.
|
||||
nk_layout_row_dynamic(ui_ctx, 70, 1);
|
||||
|
||||
|
@ -349499,7 +349558,6 @@ void (profile_render)() {
|
|||
if( index >= 0 ) {
|
||||
nk_tooltipf(ui_ctx, "%.2f fps", (float)values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
for each_map_ptr_sorted(profiler, const char *, key, struct profile_t, val ) {
|
||||
if( isnan(val->stat) ) {
|
||||
|
@ -349510,9 +349568,6 @@ void (profile_render)() {
|
|||
ui_slider2(*key, &v, va("%.2f", val->stat));
|
||||
val->stat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -350109,7 +350164,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
#if is(ems)
|
||||
if( FLAGS_FULLSCREEN ) window_fullscreen(1);
|
||||
#else
|
||||
gladLoadGL(glfwGetProcAddress);
|
||||
int gl_version = gladLoadGL(glfwGetProcAddress);
|
||||
#endif
|
||||
|
||||
glDebugEnable();
|
||||
|
@ -350133,6 +350188,8 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
PRINTF("GPU driver: %s\n", glGetString(GL_VERSION));
|
||||
|
||||
#if !is(ems)
|
||||
PRINTF("GPU OpenGL: %d.%d\n", GLAD_VERSION_MAJOR(gl_version), GLAD_VERSION_MINOR(gl_version));
|
||||
|
||||
if( FLAGS_TRANSPARENT ) { // @transparent
|
||||
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
|
||||
if( scale >= 1 ) glfwMaximizeWindow(window);
|
||||
|
@ -350261,10 +350318,51 @@ int window_frame_begin() {
|
|||
|
||||
ui_create();
|
||||
|
||||
profile_render();
|
||||
bool may_render_stats = 1;
|
||||
|
||||
ui_shaders();
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
may_render_stats = (frames > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) may_render_stats = 0;
|
||||
// @transparent
|
||||
|
||||
// generate Debug panel contents
|
||||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug", 0) : ui_panel("Debug", 0) ) {
|
||||
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
|
||||
for( int p = (open = ui_collapse("FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_fxs();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_profiler();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_shaders();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // deprecated
|
||||
// run user-defined hooks
|
||||
|
@ -352277,22 +352375,20 @@ int main() {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void v4k_pre_init() {
|
||||
window_icon(va("%s.png", app_name()));
|
||||
ifdef(win32,window_icon(va("%s.ico", app_name())));
|
||||
const char *appname = app_name();
|
||||
window_icon(va("%s.png", appname));
|
||||
ifdef(win32,window_icon(va("%s.ico", appname)));
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for( i = 0; i <= 3; ++i) {
|
||||
/**/ if( i == 0 ) ddraw_init();// init this on thread#0 since it will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||
else if( i == 1 ) sprite_init();
|
||||
else if( i == 2 ) profile_init();
|
||||
else if( i == 2 ) profiler_init();
|
||||
else if( i == 3 ) storage_mount("save/"), storage_read(), touch_init(); // for ems
|
||||
}
|
||||
;
|
||||
|
||||
// window_swap();
|
||||
}
|
||||
|
|
|
@ -386,6 +386,9 @@ float audio_volume_master(float gain) {
|
|||
}
|
||||
|
||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// do nothing, gain used as-is
|
||||
} else {
|
||||
|
|
|
@ -211,14 +211,14 @@
|
|||
// system headers
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // for linux
|
||||
#define _GNU_SOURCE ///- for linux
|
||||
#endif
|
||||
|
||||
#if is(cl) && is(win32) // for VC IDE
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _WIN32_WINNT 0x0600 // 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#define _CRT_SECURE_NO_WARNINGS ///-
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE ///-
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS ///-
|
||||
#define _WIN32_WINNT 0x0600 ///- 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#endif
|
||||
|
||||
#if is(cl)
|
||||
|
|
|
@ -804,4 +804,5 @@ int cook_jobs() {
|
|||
|
||||
void cook_config( const char *pathfile_to_cook_ini ) { // @todo: test run-from-"bin/" case on Linux.
|
||||
COOK_INI = pathfile_to_cook_ini;
|
||||
ASSERT( file_exist(COOK_INI) );
|
||||
}
|
||||
|
|
|
@ -626,32 +626,37 @@ bool input_touch_active() {
|
|||
void input_demo() {
|
||||
if( ui_panel("Input",0) ) {
|
||||
ui_section("Keyboard");
|
||||
ui_const_bool("[Key 1]", input(KEY_1));
|
||||
ui_const_bool("[Key 2]", input(KEY_2));
|
||||
ui_const_bool("[Key 3]", input(KEY_3));
|
||||
ui_const_bool("[Key 4]", input(KEY_4));
|
||||
ui_const_bool("[Key 5]", input(KEY_5));
|
||||
ui_const_bool("[Key 6]", input(KEY_6));
|
||||
ui_const_bool("[Key 7]", input(KEY_7));
|
||||
|
||||
uint8_t keymap = 0;
|
||||
keymap |= (!!input(KEY_1)) << 7;
|
||||
keymap |= (!!input(KEY_2)) << 6;
|
||||
keymap |= (!!input(KEY_3)) << 5;
|
||||
keymap |= (!!input(KEY_4)) << 4;
|
||||
keymap |= (!!input(KEY_5)) << 3;
|
||||
keymap |= (!!input(KEY_6)) << 2;
|
||||
keymap |= (!!input(KEY_7)) << 1;
|
||||
keymap |= (!!input(KEY_8)) << 0;
|
||||
ui_bitmask8("[Keys 1..8]", &keymap);
|
||||
|
||||
ui_separator();
|
||||
ui_const_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_const_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_const_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_const_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_const_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_const_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_const_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_label2_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_label2_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_label2_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_label2_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_label2_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_label2_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_label2_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_separator();
|
||||
|
||||
ui_section("Mouse");
|
||||
ui_const_float("X", input(MOUSE_X));
|
||||
ui_const_float("Y", input(MOUSE_Y));
|
||||
ui_label2_float("X", input(MOUSE_X));
|
||||
ui_label2_float("Y", input(MOUSE_Y));
|
||||
ui_separator();
|
||||
ui_const_float("Wheel", input(MOUSE_W));
|
||||
ui_label2_float("Wheel", input(MOUSE_W));
|
||||
ui_separator();
|
||||
ui_const_bool("Left", input(MOUSE_L));
|
||||
ui_const_bool("Middle", input(MOUSE_M));
|
||||
ui_const_bool("Right", input(MOUSE_R));
|
||||
ui_label2_bool("Left", input(MOUSE_L));
|
||||
ui_label2_bool("Middle", input(MOUSE_M));
|
||||
ui_label2_bool("Right", input(MOUSE_R));
|
||||
ui_separator();
|
||||
for( int i = 0; i <= CURSOR_SW_AUTO; ++i ) if(ui_button(va("Cursor shape #%d", i))) window_cursor_shape(i);
|
||||
ui_separator();
|
||||
|
@ -663,45 +668,45 @@ void input_demo() {
|
|||
|
||||
input_use(gamepad_id);
|
||||
|
||||
ui_const_string("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_const_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
ui_label2("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_label2_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_bool("A", input(GAMEPAD_A) );
|
||||
ui_const_bool("B", input(GAMEPAD_B) );
|
||||
ui_const_bool("X", input(GAMEPAD_X) );
|
||||
ui_const_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_const_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_const_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_const_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_const_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_const_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_const_bool("Start", input(GAMEPAD_START) );
|
||||
ui_label2_bool("A", input(GAMEPAD_A) );
|
||||
ui_label2_bool("B", input(GAMEPAD_B) );
|
||||
ui_label2_bool("X", input(GAMEPAD_X) );
|
||||
ui_label2_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_label2_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_label2_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_label2_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_label2_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_label2_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_label2_bool("Start", input(GAMEPAD_START) );
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_const_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_const_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_const_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_const_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
ui_label2_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_label2_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_label2_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_label2_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_label2_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
|
||||
vec2 v = input_filter_deadzone( input2(GAMEPAD_LPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", v.x);
|
||||
ui_const_float("Filtered pad y", v.y);
|
||||
ui_label2_float("Filtered pad x", v.x);
|
||||
ui_label2_float("Filtered pad y", v.y);
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_const_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_const_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_const_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_const_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
ui_label2_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_label2_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_label2_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_label2_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_label2_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
|
||||
vec2 w = input_filter_deadzone( input2(GAMEPAD_RPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", w.x);
|
||||
ui_const_float("Filtered pad y", w.y);
|
||||
ui_label2_float("Filtered pad x", w.x);
|
||||
ui_label2_float("Filtered pad y", w.y);
|
||||
|
||||
input_use(0);
|
||||
|
||||
|
|
|
@ -1,22 +1,20 @@
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void v4k_pre_init() {
|
||||
window_icon(va("%s.png", app_name()));
|
||||
ifdef(win32,window_icon(va("%s.ico", app_name())));
|
||||
const char *appname = app_name();
|
||||
window_icon(va("%s.png", appname));
|
||||
ifdef(win32,window_icon(va("%s.ico", appname)));
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for( i = 0; i <= 3; ++i) {
|
||||
/**/ if( i == 0 ) ddraw_init();// init this on thread#0 since it will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||
else if( i == 1 ) sprite_init();
|
||||
else if( i == 2 ) profile_init();
|
||||
else if( i == 2 ) profiler_init();
|
||||
else if( i == 3 ) storage_mount("save/"), storage_read(), touch_init(); // for ems
|
||||
}
|
||||
;
|
||||
|
||||
// window_swap();
|
||||
}
|
||||
|
|
|
@ -2,30 +2,14 @@
|
|||
profiler_t profiler;
|
||||
int profiler_enabled = 1;
|
||||
|
||||
void (profile_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profile_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (profile_render)() {
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) return;
|
||||
// @transparent
|
||||
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
if( frames <= 0 ) return;
|
||||
}
|
||||
}
|
||||
|
||||
if( has_menu ? ui_window("Profiler", 0) : ui_panel("Profiler", 0) ) {
|
||||
void (profiler_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profiler_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (ui_profiler)() {
|
||||
// @todo: ui_plot()
|
||||
|
||||
double fps = window_fps();
|
||||
profile_setstat("Render.num_fps", fps);
|
||||
|
||||
if(1) { // @todo: ui_plot()
|
||||
// draw fps-meter: 300 samples, [0..70] range each, 70px height plot.
|
||||
nk_layout_row_dynamic(ui_ctx, 70, 1);
|
||||
|
||||
|
@ -54,7 +38,6 @@ void (profile_render)() {
|
|||
if( index >= 0 ) {
|
||||
nk_tooltipf(ui_ctx, "%.2f fps", (float)values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
for each_map_ptr_sorted(profiler, const char *, key, struct profile_t, val ) {
|
||||
if( isnan(val->stat) ) {
|
||||
|
@ -65,9 +48,6 @@ void (profile_render)() {
|
|||
ui_slider2(*key, &v, va("%.2f", val->stat));
|
||||
val->stat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
# define profile(section) for(int macro(i) = 1; macro(i); macro(i) = 0)
|
||||
# define profile_incstat(name, accum) do {} while(0)
|
||||
# define profile_setstat(name, value) do {} while(0)
|
||||
# define profile_init() do {} while(0)
|
||||
# define profile_render() do {} while(0)
|
||||
# define profile_enable(x) 0
|
||||
# define profiler_init() do {} while(0)
|
||||
# define profiler_enable(x) 0
|
||||
# define ui_profiler() do {} while(0)
|
||||
#else
|
||||
# define profile(section) for( \
|
||||
struct profile_t *found = profiler_enabled ? \
|
||||
|
@ -20,7 +20,7 @@
|
|||
# define profile_setstat(name, value) for( \
|
||||
struct profile_t *found = profiler_enabled ? map_find_or_add(profiler, name, (struct profile_t){0}) : NULL; \
|
||||
found; found->stat = value, found = NULL) ///+
|
||||
API int profile_enable(bool on);
|
||||
API int profiler_enable(bool on);
|
||||
|
||||
struct profile_t { double stat; int32_t cost, avg; }; ///-
|
||||
typedef map(char *, struct profile_t) profiler_t; ///-
|
||||
|
|
|
@ -194,22 +194,23 @@ unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char
|
|||
array(char*) props = 0;
|
||||
do_once map_init_int( shader_reflect );
|
||||
if(vs) for each_substring(vs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(fs) for each_substring(fs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(gs) for each_substring(gs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if( props ) {
|
||||
map_insert(shader_reflect, program, props);
|
||||
for( int i = 0; i < array_count(props); ++i ) shader_apply_param(program, i);
|
||||
}
|
||||
|
||||
return program;
|
||||
|
@ -222,7 +223,60 @@ unsigned shader_properties(unsigned shader) {
|
|||
|
||||
char** shader_property(unsigned shader, unsigned property) {
|
||||
array(char*) *found = map_find(shader_reflect, shader);
|
||||
return found ? &(*found)[property] : NULL;
|
||||
return found && property < array_count(*found) ? &(*found)[property] : NULL;
|
||||
}
|
||||
|
||||
void shader_apply_param(unsigned shader, unsigned param_no) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
if( param_no < num_properties ) {
|
||||
char *line = *shader_property(shader, param_no);
|
||||
|
||||
char type[32], name[32];
|
||||
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
if( strchr("ibfv", type[0]) ) {
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'b') glUniform1i(glGetUniformLocation(shader, name), !!setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shader_apply_params(unsigned shader, const char *parameter_mask) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
for( unsigned i = 0; i < num_properties; ++i ) {
|
||||
char *line = *shader_property(shader,i);
|
||||
|
||||
char name[32];
|
||||
if( sscanf(line, "%*s %*s %s", name) != 1 ) continue;
|
||||
if( !strmatch(name, parameter_mask) ) continue;
|
||||
shader_apply_param(shader, i);
|
||||
}
|
||||
}
|
||||
|
||||
int ui_shader(unsigned shader) {
|
||||
|
@ -233,25 +287,43 @@ int ui_shader(unsigned shader) {
|
|||
char **ptr = shader_property(shader,i);
|
||||
|
||||
const char *line = *ptr; // debug: ui_label(line);
|
||||
char uniform[32], type[32], name[32];
|
||||
if( sscanf(line, "%s %s %s", uniform, type, name) != 3) continue;
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
|
||||
char uniform[32], type[32], name[32], early_exit = '\0';
|
||||
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
|
||||
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
|
||||
va("%c%s " ICON_MD_HELP "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
// supports int,float,vec2/3/4,color3/4
|
||||
int touched = 0;
|
||||
if( type[0] == 'i' ) {
|
||||
if( type[0] == 'b' ) {
|
||||
bool v = !!setv.x;
|
||||
|
||||
if( (touched = ui_bool(label, &v)) != 0 ) {
|
||||
setv.x = v;
|
||||
}
|
||||
}
|
||||
else if( type[0] == 'i' ) {
|
||||
int v = setv.x;
|
||||
|
||||
if( (touched = ui_int(label, &v)) != 0 ) {
|
||||
|
@ -259,9 +331,11 @@ int ui_shader(unsigned shader) {
|
|||
}
|
||||
}
|
||||
else if( type[0] == 'f' ) {
|
||||
setv.x = (clampf(setv.x, minv.x, maxv.x) - minv.x) / (maxv.x - minv.x);
|
||||
setv.x = clampf(setv.x, minv.x, maxv.x);
|
||||
char *caption = va("%5.2f", setv.x);
|
||||
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
|
||||
|
||||
if( (touched = ui_slider2(label, &setv.x, va("%5.2f", setv.x))) != 0 ) {
|
||||
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
|
||||
setv.x = clampf(minv.x + setv.x * (maxv.x-minv.x), minv.x, maxv.x); // min..max range
|
||||
}
|
||||
}
|
||||
|
@ -286,28 +360,20 @@ int ui_shader(unsigned shader) {
|
|||
setv = clamp4(setv,minv,maxv);
|
||||
}
|
||||
}
|
||||
else if( tip ) ui_label( tip );
|
||||
|
||||
if( touched ) {
|
||||
// send to shader
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
|
||||
// upgrade value
|
||||
*ptr = FREE(*ptr);
|
||||
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
|
||||
|
||||
// apply
|
||||
shader_apply_param(shader, i);
|
||||
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(num_properties) ui_separator();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -315,13 +381,14 @@ int ui_shaders() {
|
|||
if( !map_count(shader_reflect) ) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("Shaders", 0) : ui_panel("Shaders", 0) ) ) {
|
||||
for each_map_ptr(shader_reflect, unsigned, k, array(char*), v) {
|
||||
ui_section(va("Shader %d",*k));
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
char *id = va("##SHD%d", *k);
|
||||
char *title = va("Shader %d", *k);
|
||||
for( int p = (open = ui_collapse(title, id)), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_label(va("Shader %d",*k));
|
||||
changed |= ui_shader(*k);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@ -376,7 +443,7 @@ void write_barrier(){
|
|||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
}
|
||||
|
||||
void image_write_barrier(){
|
||||
void write_barrier_image(){
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
}
|
||||
|
||||
|
@ -3234,9 +3301,9 @@ void postfx_clear(postfx *fx) {
|
|||
|
||||
int ui_postfx(postfx *fx, int pass) {
|
||||
int on = ui_enabled();
|
||||
ui_enable( postfx_enabled(fx,pass) );
|
||||
( postfx_enabled(fx,pass) ? ui_enable : ui_disable )();
|
||||
int rc = ui_shader(fx->pass[pass].program);
|
||||
ui_enable( on );
|
||||
( on ? ui_enable : ui_disable )();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -3417,16 +3484,12 @@ int ui_fxs() {
|
|||
if(!fx.num_loaded) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("FX", 0) : ui_panel("FX", 0) ) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
|
|
@ -343,6 +343,9 @@ API void shader_destroy(unsigned shader);
|
|||
API unsigned shader_properties(unsigned shader);
|
||||
API char** shader_property(unsigned shader, unsigned property_no);
|
||||
|
||||
API void shader_apply_param(unsigned shader, unsigned param_no);
|
||||
API void shader_apply_params(unsigned shader, const char *parameter_mask);
|
||||
|
||||
API int ui_shader(unsigned shader);
|
||||
API int ui_shaders();
|
||||
|
||||
|
@ -387,12 +390,12 @@ API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int
|
|||
|
||||
// gpu memory barriers
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void image_write_barrier();
|
||||
|
||||
/// Blocks main thread until all memory operations are done by the GPU.
|
||||
API void write_barrier();
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void write_barrier_image();
|
||||
|
||||
// ssbo
|
||||
/// `STATIC`, `DYNAMIC` AND `STREAM` specify the frequency at which we intend to access the data.
|
||||
/// `DRAW` favors CPU->GPU operations.
|
||||
|
|
|
@ -145,8 +145,8 @@ default_hue = 0.52;
|
|||
struct nk_color active = nk_hsv_f( 0.600, 0.00, 0.150); // bright b/w
|
||||
struct nk_color table[NK_COLOR_COUNT] = {0};
|
||||
table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 215);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 245);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 245);
|
||||
table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
|
||||
table[NK_COLOR_BUTTON] = main;
|
||||
table[NK_COLOR_BUTTON_HOVER] = hover;
|
||||
|
@ -537,7 +537,7 @@ int ui_active() {
|
|||
}
|
||||
|
||||
static
|
||||
int ui_enable_(int enabled) {
|
||||
int ui_set_enable_(int enabled) {
|
||||
static struct nk_style off, on;
|
||||
do_once {
|
||||
off = on = ui_ctx->style;
|
||||
|
@ -775,8 +775,11 @@ int ui_enable_(int enabled) {
|
|||
}
|
||||
|
||||
static int ui_is_enabled = 1;
|
||||
int ui_enable(int on) {
|
||||
return ui_is_enabled == on ? 0 : ui_enable_(ui_is_enabled = on);
|
||||
int ui_enable() {
|
||||
return ui_is_enabled == 1 ? 0 : ui_set_enable_(ui_is_enabled = 1);
|
||||
}
|
||||
int ui_disable() {
|
||||
return ui_is_enabled == 0 ? 0 : ui_set_enable_(ui_is_enabled = 0);
|
||||
}
|
||||
int ui_enabled() {
|
||||
return ui_is_enabled;
|
||||
|
@ -1558,6 +1561,20 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x
|
|||
|
||||
return ui_label_icon_clicked_R.x;
|
||||
}
|
||||
int ui_label2_bool(const char *text, bool value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_label2_float(const char *text, float value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_label2_wrap(const char *label, const char *str) { // @fixme: does not work (remove dynamic layout?)
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
nk_text_wrap(ui_ctx, str, strlen(str));
|
||||
return 0;
|
||||
}
|
||||
int ui_label2_toolbar(const char *label, const char *icons) {
|
||||
int mouse_click = ui_label2(label, va(">%s", icons));
|
||||
int choice = !mouse_click ? 0 : 1 + -mouse_click / (UI_ICON_FONTSIZE + UI_ICON_SPACING_X); // divided by px per ICON_MD_ glyph approximately
|
||||
|
@ -1672,18 +1689,6 @@ int ui_button(const char *s) {
|
|||
return ui_buttons(1, s);
|
||||
}
|
||||
|
||||
int ui_const_bool(const char *text, const double value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_const_float(const char *text, const double value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_const_string(const char *label, const char *text) {
|
||||
return ui_label2(label, text);
|
||||
}
|
||||
|
||||
int ui_toggle(const char *label, bool *value) {
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
|
@ -1947,13 +1952,6 @@ 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);
|
||||
|
@ -2077,8 +2075,8 @@ int ui_dialog(const char *title, const char *text, int choices, bool *show) { //
|
|||
return *show;
|
||||
}
|
||||
|
||||
#define ui_bits_template(X) \
|
||||
int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
||||
#define ui_bitmask_template(X) \
|
||||
int ui_bitmask##X(const char *label, uint##X##_t *enabled) { \
|
||||
/* @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive */ \
|
||||
nk_layout_row_dynamic(ui_ctx, 1, 1); \
|
||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx); \
|
||||
|
@ -2109,9 +2107,9 @@ int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
|||
return copy ^ *enabled; \
|
||||
}
|
||||
|
||||
ui_bits_template(8);
|
||||
ui_bits_template(16);
|
||||
//ui_bits_template(32);
|
||||
ui_bitmask_template(8);
|
||||
ui_bitmask_template(16);
|
||||
//ui_bitmask_template(32);
|
||||
|
||||
int ui_console() { // @fixme: buggy
|
||||
static char *cmd = 0;
|
||||
|
@ -2272,13 +2270,15 @@ int ui_demo(int do_windows) {
|
|||
if(choice == 2) ui_notify(va("My random toast (%d)", rand()), va("This is notification #%d", ++hits));
|
||||
if(choice == 3) disable_all ^= 1;
|
||||
|
||||
if( disable_all ) ui_enable(0);
|
||||
if( disable_all ) ui_disable();
|
||||
|
||||
if( ui_browse(&browsed_file, &show_browser) ) puts(browsed_file);
|
||||
|
||||
if( ui_section("Labels")) {}
|
||||
if( ui_label("my label")) {}
|
||||
if( ui_label("my label with tooltip@built on " __DATE__ " " __TIME__)) {}
|
||||
if( ui_label2_toolbar("my toolbar", ICON_MD_STAR ICON_MD_STAR_OUTLINE ICON_MD_BOOKMARK ICON_MD_BOOKMARK_BORDER) ) {}
|
||||
//if( ui_label2_wrap("my long label", "and some long long long long text wrapped")) {}
|
||||
|
||||
if( ui_section("Types")) {}
|
||||
if( ui_bool("my bool", &boolean) ) puts("bool changed");
|
||||
|
@ -2311,7 +2311,7 @@ int ui_demo(int do_windows) {
|
|||
}
|
||||
|
||||
if( ui_section("Others")) {}
|
||||
if( ui_bits8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_bitmask8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_toggle("my toggle", &toggle) ) printf("toggle %s\n", toggle ? "on":"off");
|
||||
if( ui_image("my image", texture_checker().id, 0, 0) ) { puts("image clicked"); }
|
||||
|
||||
|
@ -2321,7 +2321,7 @@ int ui_demo(int do_windows) {
|
|||
if( ui_buttons(3, "yes", "no", "maybe") ) { puts("button clicked"); }
|
||||
if( ui_dialog("my dialog", __FILE__ "\n" __DATE__ "\n" "Public Domain.", 2/*two buttons*/, &show_dialog) ) {}
|
||||
|
||||
if( disable_all ) ui_enable(1);
|
||||
if( disable_all ) ui_enable(); // restore enabled state
|
||||
|
||||
ui_panel_end();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ 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]
|
||||
|
@ -47,18 +46,17 @@ API int ui_image(const char *label, handle id, unsigned w, unsigned h); //(w,
|
|||
API int ui_subimage(const char *label, handle id, unsigned iw, unsigned ih, unsigned sx, unsigned sy, unsigned sw, unsigned sh);
|
||||
API int ui_colormap(const char *label, colormap_t *cm); // returns num member changed: 1 for color, 2 for texture map
|
||||
API int ui_separator();
|
||||
API int ui_bits8(const char *label, uint8_t *bits);
|
||||
API int ui_bits16(const char *label, uint16_t *bits);
|
||||
API int ui_bitmask8(const char *label, uint8_t *bits);
|
||||
API int ui_bitmask16(const char *label, uint16_t *bits);
|
||||
API int ui_console();
|
||||
API int ui_clampf(const char *label, float *value, float minf, float maxf);
|
||||
API int ui_label(const char *label);
|
||||
API int ui_label2(const char *label, const char *caption);
|
||||
API int ui_label2_bool(const char *label, bool enabled);
|
||||
API int ui_label2_float(const char *label, float value);
|
||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||
API int ui_slider(const char *label, float *value);
|
||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||
API int ui_const_bool(const char *label, const double value);
|
||||
API int ui_const_float(const char *label, const double value);
|
||||
API int ui_const_string(const char *label, const char *value);
|
||||
API int ui_contextual_end();
|
||||
API int ui_collapse_clicked();
|
||||
API int ui_collapse_end();
|
||||
|
@ -68,10 +66,12 @@ API int ui_window_end();
|
|||
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(int on);
|
||||
API int ui_enabled();
|
||||
API vec2 ui_get_dims();
|
||||
|
||||
API int ui_enable();
|
||||
API int ui_enabled();
|
||||
API int ui_disable();
|
||||
|
||||
API int ui_has_menubar();
|
||||
API int ui_menu(const char *items); // semicolon-separated or comma-separated items
|
||||
API int ui_menu_editbox(char *buf, int bufcap);
|
||||
|
|
|
@ -356,7 +356,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
#if is(ems)
|
||||
if( FLAGS_FULLSCREEN ) window_fullscreen(1);
|
||||
#else
|
||||
gladLoadGL(glfwGetProcAddress);
|
||||
int gl_version = gladLoadGL(glfwGetProcAddress);
|
||||
#endif
|
||||
|
||||
glDebugEnable();
|
||||
|
@ -380,6 +380,8 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
PRINTF("GPU driver: %s\n", glGetString(GL_VERSION));
|
||||
|
||||
#if !is(ems)
|
||||
PRINTF("GPU OpenGL: %d.%d\n", GLAD_VERSION_MAJOR(gl_version), GLAD_VERSION_MINOR(gl_version));
|
||||
|
||||
if( FLAGS_TRANSPARENT ) { // @transparent
|
||||
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
|
||||
if( scale >= 1 ) glfwMaximizeWindow(window);
|
||||
|
@ -508,10 +510,51 @@ int window_frame_begin() {
|
|||
|
||||
ui_create();
|
||||
|
||||
profile_render();
|
||||
bool may_render_stats = 1;
|
||||
|
||||
ui_shaders();
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
may_render_stats = (frames > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) may_render_stats = 0;
|
||||
// @transparent
|
||||
|
||||
// generate Debug panel contents
|
||||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug", 0) : ui_panel("Debug", 0) ) {
|
||||
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
|
||||
for( int p = (open = ui_collapse("FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_fxs();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_profiler();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_shaders();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // deprecated
|
||||
// run user-defined hooks
|
||||
|
|
403
engine/v4k.c
403
engine/v4k.c
|
@ -1346,6 +1346,9 @@ float audio_volume_master(float gain) {
|
|||
}
|
||||
|
||||
int audio_play_gain_pitch_pan( audio_t a, int flags, float gain, float pitch, float pan ) {
|
||||
static bool muted = 0; do_once muted = flag("--mute") || flag("--muted");
|
||||
if(muted) return 1;
|
||||
|
||||
if( flags & AUDIO_IGNORE_MIXER_GAIN ) {
|
||||
// do nothing, gain used as-is
|
||||
} else {
|
||||
|
@ -3740,6 +3743,7 @@ int cook_jobs() {
|
|||
|
||||
void cook_config( const char *pathfile_to_cook_ini ) { // @todo: test run-from-"bin/" case on Linux.
|
||||
COOK_INI = pathfile_to_cook_ini;
|
||||
ASSERT( file_exist(COOK_INI) );
|
||||
}
|
||||
#line 0
|
||||
|
||||
|
@ -8143,32 +8147,37 @@ bool input_touch_active() {
|
|||
void input_demo() {
|
||||
if( ui_panel("Input",0) ) {
|
||||
ui_section("Keyboard");
|
||||
ui_const_bool("[Key 1]", input(KEY_1));
|
||||
ui_const_bool("[Key 2]", input(KEY_2));
|
||||
ui_const_bool("[Key 3]", input(KEY_3));
|
||||
ui_const_bool("[Key 4]", input(KEY_4));
|
||||
ui_const_bool("[Key 5]", input(KEY_5));
|
||||
ui_const_bool("[Key 6]", input(KEY_6));
|
||||
ui_const_bool("[Key 7]", input(KEY_7));
|
||||
|
||||
uint8_t keymap = 0;
|
||||
keymap |= (!!input(KEY_1)) << 7;
|
||||
keymap |= (!!input(KEY_2)) << 6;
|
||||
keymap |= (!!input(KEY_3)) << 5;
|
||||
keymap |= (!!input(KEY_4)) << 4;
|
||||
keymap |= (!!input(KEY_5)) << 3;
|
||||
keymap |= (!!input(KEY_6)) << 2;
|
||||
keymap |= (!!input(KEY_7)) << 1;
|
||||
keymap |= (!!input(KEY_8)) << 0;
|
||||
ui_bitmask8("[Keys 1..8]", &keymap);
|
||||
|
||||
ui_separator();
|
||||
ui_const_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_const_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_const_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_const_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_const_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_const_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_const_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_label2_bool("[Key 1] Down event", input_down(KEY_1) );
|
||||
ui_label2_bool("[Key 2] Held event", input_held(KEY_2) );
|
||||
ui_label2_bool("[Key 3] Up event", input_up(KEY_3) );
|
||||
ui_label2_bool("[Key 4] Idle event", input_idle(KEY_4) );
|
||||
ui_label2_bool("[Key 5] Click event", input_click(KEY_5,500) );
|
||||
ui_label2_bool("[Key 6] Click2 event", input_click2(KEY_6,1000) );
|
||||
ui_label2_bool("[Key 7] Repeat event", input_repeat(KEY_7,750) );
|
||||
ui_separator();
|
||||
|
||||
ui_section("Mouse");
|
||||
ui_const_float("X", input(MOUSE_X));
|
||||
ui_const_float("Y", input(MOUSE_Y));
|
||||
ui_label2_float("X", input(MOUSE_X));
|
||||
ui_label2_float("Y", input(MOUSE_Y));
|
||||
ui_separator();
|
||||
ui_const_float("Wheel", input(MOUSE_W));
|
||||
ui_label2_float("Wheel", input(MOUSE_W));
|
||||
ui_separator();
|
||||
ui_const_bool("Left", input(MOUSE_L));
|
||||
ui_const_bool("Middle", input(MOUSE_M));
|
||||
ui_const_bool("Right", input(MOUSE_R));
|
||||
ui_label2_bool("Left", input(MOUSE_L));
|
||||
ui_label2_bool("Middle", input(MOUSE_M));
|
||||
ui_label2_bool("Right", input(MOUSE_R));
|
||||
ui_separator();
|
||||
for( int i = 0; i <= CURSOR_SW_AUTO; ++i ) if(ui_button(va("Cursor shape #%d", i))) window_cursor_shape(i);
|
||||
ui_separator();
|
||||
|
@ -8180,45 +8189,45 @@ void input_demo() {
|
|||
|
||||
input_use(gamepad_id);
|
||||
|
||||
ui_const_string("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_const_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
ui_label2("Name", input_frames(GAMEPAD_NAME,0));
|
||||
ui_label2_bool("Connected", input(GAMEPAD_CONNECTED));
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_bool("A", input(GAMEPAD_A) );
|
||||
ui_const_bool("B", input(GAMEPAD_B) );
|
||||
ui_const_bool("X", input(GAMEPAD_X) );
|
||||
ui_const_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_const_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_const_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_const_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_const_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_const_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_const_bool("Start", input(GAMEPAD_START) );
|
||||
ui_label2_bool("A", input(GAMEPAD_A) );
|
||||
ui_label2_bool("B", input(GAMEPAD_B) );
|
||||
ui_label2_bool("X", input(GAMEPAD_X) );
|
||||
ui_label2_bool("Y", input(GAMEPAD_Y) );
|
||||
ui_label2_bool("Up", input(GAMEPAD_UP) );
|
||||
ui_label2_bool("Down", input(GAMEPAD_DOWN) );
|
||||
ui_label2_bool("Left", input(GAMEPAD_LEFT) );
|
||||
ui_label2_bool("Right", input(GAMEPAD_RIGHT) );
|
||||
ui_label2_bool("Menu", input(GAMEPAD_MENU) );
|
||||
ui_label2_bool("Start", input(GAMEPAD_START) );
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_const_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_const_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_const_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_const_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
ui_label2_float("Left pad x", input(GAMEPAD_LPADX) );
|
||||
ui_label2_float("Left pad y", input(GAMEPAD_LPADY) );
|
||||
ui_label2_float("Left trigger", input(GAMEPAD_LT) );
|
||||
ui_label2_bool("Left bumper", input(GAMEPAD_LB) );
|
||||
ui_label2_bool("Left thumb", input(GAMEPAD_LTHUMB) );
|
||||
|
||||
vec2 v = input_filter_deadzone( input2(GAMEPAD_LPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", v.x);
|
||||
ui_const_float("Filtered pad y", v.y);
|
||||
ui_label2_float("Filtered pad x", v.x);
|
||||
ui_label2_float("Filtered pad y", v.y);
|
||||
|
||||
ui_separator();
|
||||
|
||||
ui_const_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_const_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_const_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_const_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_const_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
ui_label2_float("Right pad x", input(GAMEPAD_RPADX) );
|
||||
ui_label2_float("Right pad y", input(GAMEPAD_RPADY) );
|
||||
ui_label2_float("Right trigger", input(GAMEPAD_RT) );
|
||||
ui_label2_bool("Right bumper", input(GAMEPAD_RB) );
|
||||
ui_label2_bool("Right thumb", input(GAMEPAD_RTHUMB) );
|
||||
|
||||
vec2 w = input_filter_deadzone( input2(GAMEPAD_RPADX), 0.1f );
|
||||
ui_const_float("Filtered pad x", w.x);
|
||||
ui_const_float("Filtered pad y", w.y);
|
||||
ui_label2_float("Filtered pad x", w.x);
|
||||
ui_label2_float("Filtered pad y", w.y);
|
||||
|
||||
input_use(0);
|
||||
|
||||
|
@ -10516,22 +10525,23 @@ unsigned shader_geom(const char *gs, const char *vs, const char *fs, const char
|
|||
array(char*) props = 0;
|
||||
do_once map_init_int( shader_reflect );
|
||||
if(vs) for each_substring(vs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(fs) for each_substring(fs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if(gs) for each_substring(gs, "\r\n", line) {
|
||||
if( strstr(line, "/""//") && !strbeg(line,"//") ) {
|
||||
array_push(props, STRDUP(line));
|
||||
}
|
||||
const char *found = strstr(line, "/""//");
|
||||
if( found > line && line[0] == '/' && line[1] == '/' ) continue;
|
||||
if( found ) array_push(props, STRDUP(line));
|
||||
}
|
||||
if( props ) {
|
||||
map_insert(shader_reflect, program, props);
|
||||
for( int i = 0; i < array_count(props); ++i ) shader_apply_param(program, i);
|
||||
}
|
||||
|
||||
return program;
|
||||
|
@ -10544,7 +10554,60 @@ unsigned shader_properties(unsigned shader) {
|
|||
|
||||
char** shader_property(unsigned shader, unsigned property) {
|
||||
array(char*) *found = map_find(shader_reflect, shader);
|
||||
return found ? &(*found)[property] : NULL;
|
||||
return found && property < array_count(*found) ? &(*found)[property] : NULL;
|
||||
}
|
||||
|
||||
void shader_apply_param(unsigned shader, unsigned param_no) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
if( param_no < num_properties ) {
|
||||
char *line = *shader_property(shader, param_no);
|
||||
|
||||
char type[32], name[32];
|
||||
if( sscanf(line, "%*s %s %[^ =;/]", type, name) != 2 ) return;
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
if( strchr("ibfv", type[0]) ) {
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'b') glUniform1i(glGetUniformLocation(shader, name), !!setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shader_apply_params(unsigned shader, const char *parameter_mask) {
|
||||
unsigned num_properties = shader_properties(shader);
|
||||
for( unsigned i = 0; i < num_properties; ++i ) {
|
||||
char *line = *shader_property(shader,i);
|
||||
|
||||
char name[32];
|
||||
if( sscanf(line, "%*s %*s %s", name) != 1 ) continue;
|
||||
if( !strmatch(name, parameter_mask) ) continue;
|
||||
shader_apply_param(shader, i);
|
||||
}
|
||||
}
|
||||
|
||||
int ui_shader(unsigned shader) {
|
||||
|
@ -10555,25 +10618,43 @@ int ui_shader(unsigned shader) {
|
|||
char **ptr = shader_property(shader,i);
|
||||
|
||||
const char *line = *ptr; // debug: ui_label(line);
|
||||
char uniform[32], type[32], name[32];
|
||||
if( sscanf(line, "%s %s %s", uniform, type, name) != 3) continue;
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
|
||||
char uniform[32], type[32], name[32], early_exit = '\0';
|
||||
if( sscanf(line, "%s %s %[^ =;/]", uniform, type, name) != 3 ) continue; // @todo optimize: move to shader()
|
||||
if( strcmp(uniform, "uniform") && strcmp(uniform, "}uniform") ) { if(tip) ui_label(va(ICON_MD_INFO "%s", tip)); continue; } // @todo optimize: move to shader()
|
||||
|
||||
int is_color = !!strstri(name, "color"), top = is_color ? 1 : 10;
|
||||
vec4 minv = strstr(line, "min:") ? atof4(strstr(line, "min:") + 4) : vec4(0,0,0,0);
|
||||
vec4 setv = strstr(line, "set:") ? atof4(strstr(line, "set:") + 4) : vec4(0,0,0,0);
|
||||
vec4 maxv = strstr(line, "max:") ? atof4(strstr(line, "max:") + 4) : vec4(top,top,top,top);
|
||||
char* tip = strstr(line, "tip:"); tip = tip && tip[4] ? tip + 4 : 0;
|
||||
char *label = !tip ? va("%c%s", name[0] - 32 * !!(name[0] >= 'a'), name+1) :
|
||||
va("%c%s " ICON_MD_HELP "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
va("%c%s " ICON_MD_INFO "@%s", name[0] - 32 * !!(name[0] >= 'a'), name+1, tip);
|
||||
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x);
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y);
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z);
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w);
|
||||
if(minv.x > maxv.x) swapf(&minv.x, &maxv.x); // @optimize: move to shader()
|
||||
if(minv.y > maxv.y) swapf(&minv.y, &maxv.y); // @optimize: move to shader()
|
||||
if(minv.z > maxv.z) swapf(&minv.z, &maxv.z); // @optimize: move to shader()
|
||||
if(minv.w > maxv.w) swapf(&minv.w, &maxv.w); // @optimize: move to shader()
|
||||
|
||||
if( !strstr(line, "max:") ) {
|
||||
if(setv.x > maxv.x) maxv.x = setv.x;
|
||||
if(setv.y > maxv.y) maxv.y = setv.y;
|
||||
if(setv.z > maxv.z) maxv.z = setv.z;
|
||||
if(setv.w > maxv.w) maxv.w = setv.w;
|
||||
}
|
||||
|
||||
setv = clamp4(setv, minv, maxv);
|
||||
|
||||
// supports int,float,vec2/3/4,color3/4
|
||||
int touched = 0;
|
||||
if( type[0] == 'i' ) {
|
||||
if( type[0] == 'b' ) {
|
||||
bool v = !!setv.x;
|
||||
|
||||
if( (touched = ui_bool(label, &v)) != 0 ) {
|
||||
setv.x = v;
|
||||
}
|
||||
}
|
||||
else if( type[0] == 'i' ) {
|
||||
int v = setv.x;
|
||||
|
||||
if( (touched = ui_int(label, &v)) != 0 ) {
|
||||
|
@ -10581,9 +10662,11 @@ int ui_shader(unsigned shader) {
|
|||
}
|
||||
}
|
||||
else if( type[0] == 'f' ) {
|
||||
setv.x = (clampf(setv.x, minv.x, maxv.x) - minv.x) / (maxv.x - minv.x);
|
||||
setv.x = clampf(setv.x, minv.x, maxv.x);
|
||||
char *caption = va("%5.2f", setv.x);
|
||||
setv.x = (setv.x - minv.x) / (maxv.x - minv.x);
|
||||
|
||||
if( (touched = ui_slider2(label, &setv.x, va("%5.2f", setv.x))) != 0 ) {
|
||||
if( (touched = ui_slider2(label, &setv.x, caption)) != 0 ) {
|
||||
setv.x = clampf(minv.x + setv.x * (maxv.x-minv.x), minv.x, maxv.x); // min..max range
|
||||
}
|
||||
}
|
||||
|
@ -10608,28 +10691,20 @@ int ui_shader(unsigned shader) {
|
|||
setv = clamp4(setv,minv,maxv);
|
||||
}
|
||||
}
|
||||
else if( tip ) ui_label( tip );
|
||||
|
||||
if( touched ) {
|
||||
// send to shader
|
||||
GLint shader_bak; glGetIntegerv(GL_CURRENT_PROGRAM, &shader_bak);
|
||||
glUseProgram(shader);
|
||||
/**/ if(type[0] == 'i') glUniform1i(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[0] == 'f') glUniform1f(glGetUniformLocation(shader, name), setv.x);
|
||||
else if(type[3] == '2') glUniform2fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '3') glUniform3fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
else if(type[3] == '4') glUniform4fv(glGetUniformLocation(shader, name), 1, &setv.x);
|
||||
glUseProgram(shader_bak);
|
||||
|
||||
// upgrade value
|
||||
*ptr = FREE(*ptr);
|
||||
*ptr = stringf("%s %s %s ///set:%s min:%s max:%s tip:%s", uniform,type,name,ftoa4(setv),ftoa4(minv),ftoa4(maxv),tip?tip:"");
|
||||
|
||||
// apply
|
||||
shader_apply_param(shader, i);
|
||||
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(num_properties) ui_separator();
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -10637,13 +10712,14 @@ int ui_shaders() {
|
|||
if( !map_count(shader_reflect) ) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("Shaders", 0) : ui_panel("Shaders", 0) ) ) {
|
||||
for each_map_ptr(shader_reflect, unsigned, k, array(char*), v) {
|
||||
ui_section(va("Shader %d",*k));
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
char *id = va("##SHD%d", *k);
|
||||
char *title = va("Shader %d", *k);
|
||||
for( int p = (open = ui_collapse(title, id)), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_label(va("Shader %d",*k));
|
||||
changed |= ui_shader(*k);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
@ -10698,7 +10774,7 @@ void write_barrier(){
|
|||
glMemoryBarrier(GL_ALL_BARRIER_BITS);
|
||||
}
|
||||
|
||||
void image_write_barrier(){
|
||||
void write_barrier_image(){
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
}
|
||||
|
||||
|
@ -13556,9 +13632,9 @@ void postfx_clear(postfx *fx) {
|
|||
|
||||
int ui_postfx(postfx *fx, int pass) {
|
||||
int on = ui_enabled();
|
||||
ui_enable( postfx_enabled(fx,pass) );
|
||||
( postfx_enabled(fx,pass) ? ui_enable : ui_disable )();
|
||||
int rc = ui_shader(fx->pass[pass].program);
|
||||
ui_enable( on );
|
||||
( on ? ui_enable : ui_disable )();
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -13739,16 +13815,12 @@ int ui_fxs() {
|
|||
if(!fx.num_loaded) return 0;
|
||||
|
||||
int changed = 0;
|
||||
int has_menu = ui_has_menubar();
|
||||
if( (has_menu ? ui_window("FX", 0) : ui_panel("FX", 0) ) ) {
|
||||
for( int i = 0; i < 64; ++i ) {
|
||||
char *name = fx_name(i); if( !name ) break;
|
||||
bool b = fx_enabled(i);
|
||||
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||
ui_fx(i);
|
||||
}
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
@ -17786,8 +17858,8 @@ default_hue = 0.52;
|
|||
struct nk_color active = nk_hsv_f( 0.600, 0.00, 0.150); // bright b/w
|
||||
struct nk_color table[NK_COLOR_COUNT] = {0};
|
||||
table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 215);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220);
|
||||
table[NK_COLOR_WINDOW] = nk_rgba(42, 42, 42, 245);
|
||||
table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 245);
|
||||
table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255);
|
||||
table[NK_COLOR_BUTTON] = main;
|
||||
table[NK_COLOR_BUTTON_HOVER] = hover;
|
||||
|
@ -18178,7 +18250,7 @@ int ui_active() {
|
|||
}
|
||||
|
||||
static
|
||||
int ui_enable_(int enabled) {
|
||||
int ui_set_enable_(int enabled) {
|
||||
static struct nk_style off, on;
|
||||
do_once {
|
||||
off = on = ui_ctx->style;
|
||||
|
@ -18416,8 +18488,11 @@ int ui_enable_(int enabled) {
|
|||
}
|
||||
|
||||
static int ui_is_enabled = 1;
|
||||
int ui_enable(int on) {
|
||||
return ui_is_enabled == on ? 0 : ui_enable_(ui_is_enabled = on);
|
||||
int ui_enable() {
|
||||
return ui_is_enabled == 1 ? 0 : ui_set_enable_(ui_is_enabled = 1);
|
||||
}
|
||||
int ui_disable() {
|
||||
return ui_is_enabled == 0 ? 0 : ui_set_enable_(ui_is_enabled = 0);
|
||||
}
|
||||
int ui_enabled() {
|
||||
return ui_is_enabled;
|
||||
|
@ -19199,6 +19274,20 @@ ui_label_icon_clicked_R.x = is_hovering ? ( (int)((input->mouse.pos.x - bounds.x
|
|||
|
||||
return ui_label_icon_clicked_R.x;
|
||||
}
|
||||
int ui_label2_bool(const char *text, bool value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_label2_float(const char *text, float value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_label2_wrap(const char *label, const char *str) { // @fixme: does not work (remove dynamic layout?)
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
nk_text_wrap(ui_ctx, str, strlen(str));
|
||||
return 0;
|
||||
}
|
||||
int ui_label2_toolbar(const char *label, const char *icons) {
|
||||
int mouse_click = ui_label2(label, va(">%s", icons));
|
||||
int choice = !mouse_click ? 0 : 1 + -mouse_click / (UI_ICON_FONTSIZE + UI_ICON_SPACING_X); // divided by px per ICON_MD_ glyph approximately
|
||||
|
@ -19313,18 +19402,6 @@ int ui_button(const char *s) {
|
|||
return ui_buttons(1, s);
|
||||
}
|
||||
|
||||
int ui_const_bool(const char *text, const double value) {
|
||||
bool b = !!value;
|
||||
return ui_bool(text, &b), 0;
|
||||
}
|
||||
int ui_const_float(const char *text, const double value) {
|
||||
float f = (float)value;
|
||||
return ui_float(text, &f), 0;
|
||||
}
|
||||
int ui_const_string(const char *label, const char *text) {
|
||||
return ui_label2(label, text);
|
||||
}
|
||||
|
||||
int ui_toggle(const char *label, bool *value) {
|
||||
nk_layout_row_dynamic(ui_ctx, 0, 2 - (label ? !label[0] : 1));
|
||||
ui_label_(label, NK_TEXT_LEFT);
|
||||
|
@ -19588,13 +19665,6 @@ 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);
|
||||
|
@ -19718,8 +19788,8 @@ int ui_dialog(const char *title, const char *text, int choices, bool *show) { //
|
|||
return *show;
|
||||
}
|
||||
|
||||
#define ui_bits_template(X) \
|
||||
int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
||||
#define ui_bitmask_template(X) \
|
||||
int ui_bitmask##X(const char *label, uint##X##_t *enabled) { \
|
||||
/* @fixme: better way to retrieve widget width? nk_layout_row_dynamic() seems excessive */ \
|
||||
nk_layout_row_dynamic(ui_ctx, 1, 1); \
|
||||
struct nk_rect bounds = nk_widget_bounds(ui_ctx); \
|
||||
|
@ -19750,9 +19820,9 @@ int ui_bits##X(const char *label, uint##X##_t *enabled) { \
|
|||
return copy ^ *enabled; \
|
||||
}
|
||||
|
||||
ui_bits_template(8);
|
||||
ui_bits_template(16);
|
||||
//ui_bits_template(32);
|
||||
ui_bitmask_template(8);
|
||||
ui_bitmask_template(16);
|
||||
//ui_bitmask_template(32);
|
||||
|
||||
int ui_console() { // @fixme: buggy
|
||||
static char *cmd = 0;
|
||||
|
@ -19913,13 +19983,15 @@ int ui_demo(int do_windows) {
|
|||
if(choice == 2) ui_notify(va("My random toast (%d)", rand()), va("This is notification #%d", ++hits));
|
||||
if(choice == 3) disable_all ^= 1;
|
||||
|
||||
if( disable_all ) ui_enable(0);
|
||||
if( disable_all ) ui_disable();
|
||||
|
||||
if( ui_browse(&browsed_file, &show_browser) ) puts(browsed_file);
|
||||
|
||||
if( ui_section("Labels")) {}
|
||||
if( ui_label("my label")) {}
|
||||
if( ui_label("my label with tooltip@built on " __DATE__ " " __TIME__)) {}
|
||||
if( ui_label2_toolbar("my toolbar", ICON_MD_STAR ICON_MD_STAR_OUTLINE ICON_MD_BOOKMARK ICON_MD_BOOKMARK_BORDER) ) {}
|
||||
//if( ui_label2_wrap("my long label", "and some long long long long text wrapped")) {}
|
||||
|
||||
if( ui_section("Types")) {}
|
||||
if( ui_bool("my bool", &boolean) ) puts("bool changed");
|
||||
|
@ -19952,7 +20024,7 @@ int ui_demo(int do_windows) {
|
|||
}
|
||||
|
||||
if( ui_section("Others")) {}
|
||||
if( ui_bits8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_bitmask8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||
if( ui_toggle("my toggle", &toggle) ) printf("toggle %s\n", toggle ? "on":"off");
|
||||
if( ui_image("my image", texture_checker().id, 0, 0) ) { puts("image clicked"); }
|
||||
|
||||
|
@ -19962,7 +20034,7 @@ int ui_demo(int do_windows) {
|
|||
if( ui_buttons(3, "yes", "no", "maybe") ) { puts("button clicked"); }
|
||||
if( ui_dialog("my dialog", __FILE__ "\n" __DATE__ "\n" "Public Domain.", 2/*two buttons*/, &show_dialog) ) {}
|
||||
|
||||
if( disable_all ) ui_enable(1);
|
||||
if( disable_all ) ui_enable(); // restore enabled state
|
||||
|
||||
ui_panel_end();
|
||||
}
|
||||
|
@ -20054,30 +20126,14 @@ int ui_demo(int do_windows) {
|
|||
profiler_t profiler;
|
||||
int profiler_enabled = 1;
|
||||
|
||||
void (profile_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profile_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (profile_render)() {
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) return;
|
||||
// @transparent
|
||||
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
if( frames <= 0 ) return;
|
||||
}
|
||||
}
|
||||
|
||||
if( has_menu ? ui_window("Profiler", 0) : ui_panel("Profiler", 0) ) {
|
||||
void (profiler_init)() { map_init(profiler, less_str, hash_str); profiler_enabled &= !!profiler; }
|
||||
int (profiler_enable)(bool on) { return profiler_enabled = on; }
|
||||
void (ui_profiler)() {
|
||||
// @todo: ui_plot()
|
||||
|
||||
double fps = window_fps();
|
||||
profile_setstat("Render.num_fps", fps);
|
||||
|
||||
if(1) { // @todo: ui_plot()
|
||||
// draw fps-meter: 300 samples, [0..70] range each, 70px height plot.
|
||||
nk_layout_row_dynamic(ui_ctx, 70, 1);
|
||||
|
||||
|
@ -20106,7 +20162,6 @@ void (profile_render)() {
|
|||
if( index >= 0 ) {
|
||||
nk_tooltipf(ui_ctx, "%.2f fps", (float)values[index]);
|
||||
}
|
||||
}
|
||||
|
||||
for each_map_ptr_sorted(profiler, const char *, key, struct profile_t, val ) {
|
||||
if( isnan(val->stat) ) {
|
||||
|
@ -20117,9 +20172,6 @@ void (profile_render)() {
|
|||
ui_slider2(*key, &v, va("%.2f", val->stat));
|
||||
val->stat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -20716,7 +20768,7 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
#if is(ems)
|
||||
if( FLAGS_FULLSCREEN ) window_fullscreen(1);
|
||||
#else
|
||||
gladLoadGL(glfwGetProcAddress);
|
||||
int gl_version = gladLoadGL(glfwGetProcAddress);
|
||||
#endif
|
||||
|
||||
glDebugEnable();
|
||||
|
@ -20740,6 +20792,8 @@ bool window_create_from_handle(void *handle, float scale, unsigned flags) {
|
|||
PRINTF("GPU driver: %s\n", glGetString(GL_VERSION));
|
||||
|
||||
#if !is(ems)
|
||||
PRINTF("GPU OpenGL: %d.%d\n", GLAD_VERSION_MAJOR(gl_version), GLAD_VERSION_MINOR(gl_version));
|
||||
|
||||
if( FLAGS_TRANSPARENT ) { // @transparent
|
||||
glfwSetWindowAttrib(window, GLFW_DECORATED, GLFW_FALSE);
|
||||
if( scale >= 1 ) glfwMaximizeWindow(window);
|
||||
|
@ -20868,10 +20922,51 @@ int window_frame_begin() {
|
|||
|
||||
ui_create();
|
||||
|
||||
profile_render();
|
||||
bool may_render_stats = 1;
|
||||
|
||||
ui_shaders();
|
||||
int has_menu = ui_has_menubar();
|
||||
if( !has_menu ) {
|
||||
static int cook_on_demand; do_once cook_on_demand = COOK_ON_DEMAND;
|
||||
if( !cook_on_demand ) {
|
||||
// render profiler, unless we are in the cook progress screen
|
||||
static unsigned frames = 0; if(frames <= 0) frames += cook_progress() >= 100;
|
||||
may_render_stats = (frames > 0);
|
||||
}
|
||||
}
|
||||
|
||||
// @transparent
|
||||
static bool has_transparent_attrib = 0; do_once has_transparent_attrib = glfwGetWindowAttrib(window_handle(), GLFW_TRANSPARENT_FRAMEBUFFER) == GLFW_TRUE;
|
||||
if( has_transparent_attrib ) may_render_stats = 0;
|
||||
// @transparent
|
||||
|
||||
// generate Debug panel contents
|
||||
if( may_render_stats ) {
|
||||
if( has_menu ? ui_window("Debug", 0) : ui_panel("Debug", 0) ) {
|
||||
|
||||
int open = 0, clicked_or_toggled = 0;
|
||||
|
||||
for( int p = (open = ui_collapse("FXs", "Debug.FXs")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_fxs();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Profiler", "Debug.Profiler")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_profiler();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Shaders", "Debug.Shaders")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
ui_shaders();
|
||||
}
|
||||
for( int p = (open = ui_collapse("Keyboard", "Debug.Keyboard")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Mouse", "Debug.Mouse")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
for( int p = (open = ui_collapse("Gamepads", "Debug.Gamepads")), dummy = (clicked_or_toggled = ui_collapse_clicked()); p; ui_collapse_end(), p = 0) {
|
||||
|
||||
}
|
||||
|
||||
(has_menu ? ui_window_end : ui_panel_end)();
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 // deprecated
|
||||
// run user-defined hooks
|
||||
|
@ -22884,22 +22979,20 @@ int main() {
|
|||
// ----------------------------------------------------------------------------
|
||||
|
||||
static void v4k_pre_init() {
|
||||
window_icon(va("%s.png", app_name()));
|
||||
ifdef(win32,window_icon(va("%s.ico", app_name())));
|
||||
const char *appname = app_name();
|
||||
window_icon(va("%s.png", appname));
|
||||
ifdef(win32,window_icon(va("%s.ico", appname)));
|
||||
|
||||
glfwPollEvents();
|
||||
|
||||
int i;
|
||||
#if 1 // #ifdef PARALLEL_INIT
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for( i = 0; i <= 3; ++i) {
|
||||
/**/ if( i == 0 ) ddraw_init();// init this on thread#0 since it will be compiling shaders, and shaders need to be compiled from the very same thread than glfwMakeContextCurrent() was set up
|
||||
else if( i == 1 ) sprite_init();
|
||||
else if( i == 2 ) profile_init();
|
||||
else if( i == 2 ) profiler_init();
|
||||
else if( i == 3 ) storage_mount("save/"), storage_read(), touch_init(); // for ems
|
||||
}
|
||||
;
|
||||
|
||||
// window_swap();
|
||||
}
|
||||
|
|
43
engine/v4k.h
43
engine/v4k.h
|
@ -309,14 +309,14 @@ extern "C" {
|
|||
// system headers
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // for linux
|
||||
#define _GNU_SOURCE ///- for linux
|
||||
#endif
|
||||
|
||||
#if is(cl) && is(win32) // for VC IDE
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _WIN32_WINNT 0x0600 // 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#define _CRT_SECURE_NO_WARNINGS ///-
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE ///-
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS ///-
|
||||
#define _WIN32_WINNT 0x0600 ///- 0x0502 // GetInfoAddrW/FreeAddrInfoW for X86
|
||||
#endif
|
||||
|
||||
#if is(cl)
|
||||
|
@ -2428,9 +2428,9 @@ static __thread void *obj_tmpalloc;
|
|||
# define profile(section) for(int macro(i) = 1; macro(i); macro(i) = 0)
|
||||
# define profile_incstat(name, accum) do {} while(0)
|
||||
# define profile_setstat(name, value) do {} while(0)
|
||||
# define profile_init() do {} while(0)
|
||||
# define profile_render() do {} while(0)
|
||||
# define profile_enable(x) 0
|
||||
# define profiler_init() do {} while(0)
|
||||
# define profiler_enable(x) 0
|
||||
# define ui_profiler() do {} while(0)
|
||||
#else
|
||||
# define profile(section) for( \
|
||||
struct profile_t *found = profiler_enabled ? \
|
||||
|
@ -2443,7 +2443,7 @@ static __thread void *obj_tmpalloc;
|
|||
# define profile_setstat(name, value) for( \
|
||||
struct profile_t *found = profiler_enabled ? map_find_or_add(profiler, name, (struct profile_t){0}) : NULL; \
|
||||
found; found->stat = value, found = NULL) ///+
|
||||
API int profile_enable(bool on);
|
||||
API int profiler_enable(bool on);
|
||||
|
||||
struct profile_t { double stat; int32_t cost, avg; }; ///-
|
||||
typedef map(char *, struct profile_t) profiler_t; ///-
|
||||
|
@ -2798,6 +2798,9 @@ API void shader_destroy(unsigned shader);
|
|||
API unsigned shader_properties(unsigned shader);
|
||||
API char** shader_property(unsigned shader, unsigned property_no);
|
||||
|
||||
API void shader_apply_param(unsigned shader, unsigned param_no);
|
||||
API void shader_apply_params(unsigned shader, const char *parameter_mask);
|
||||
|
||||
API int ui_shader(unsigned shader);
|
||||
API int ui_shaders();
|
||||
|
||||
|
@ -2842,12 +2845,12 @@ API void shader_image_unit(unsigned texture, unsigned unit, unsigned level, int
|
|||
|
||||
// gpu memory barriers
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void image_write_barrier();
|
||||
|
||||
/// Blocks main thread until all memory operations are done by the GPU.
|
||||
API void write_barrier();
|
||||
|
||||
/// Blocks main thread until all image operations are done by the GPU.
|
||||
API void write_barrier_image();
|
||||
|
||||
// ssbo
|
||||
/// `STATIC`, `DYNAMIC` AND `STREAM` specify the frequency at which we intend to access the data.
|
||||
/// `DRAW` favors CPU->GPU operations.
|
||||
|
@ -3568,7 +3571,6 @@ 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]
|
||||
|
@ -3590,18 +3592,17 @@ API int ui_image(const char *label, handle id, unsigned w, unsigned h); //(w,
|
|||
API int ui_subimage(const char *label, handle id, unsigned iw, unsigned ih, unsigned sx, unsigned sy, unsigned sw, unsigned sh);
|
||||
API int ui_colormap(const char *label, colormap_t *cm); // returns num member changed: 1 for color, 2 for texture map
|
||||
API int ui_separator();
|
||||
API int ui_bits8(const char *label, uint8_t *bits);
|
||||
API int ui_bits16(const char *label, uint16_t *bits);
|
||||
API int ui_bitmask8(const char *label, uint8_t *bits);
|
||||
API int ui_bitmask16(const char *label, uint16_t *bits);
|
||||
API int ui_console();
|
||||
API int ui_clampf(const char *label, float *value, float minf, float maxf);
|
||||
API int ui_label(const char *label);
|
||||
API int ui_label2(const char *label, const char *caption);
|
||||
API int ui_label2_bool(const char *label, bool enabled);
|
||||
API int ui_label2_float(const char *label, float value);
|
||||
API int ui_label2_toolbar(const char *label, const char *icons);
|
||||
API int ui_slider(const char *label, float *value);
|
||||
API int ui_slider2(const char *label, float *value, const char *caption);
|
||||
API int ui_const_bool(const char *label, const double value);
|
||||
API int ui_const_float(const char *label, const double value);
|
||||
API int ui_const_string(const char *label, const char *value);
|
||||
API int ui_contextual_end();
|
||||
API int ui_collapse_clicked();
|
||||
API int ui_collapse_end();
|
||||
|
@ -3611,10 +3612,12 @@ API int ui_window_end();
|
|||
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(int on);
|
||||
API int ui_enabled();
|
||||
API vec2 ui_get_dims();
|
||||
|
||||
API int ui_enable();
|
||||
API int ui_enabled();
|
||||
API int ui_disable();
|
||||
|
||||
API int ui_has_menubar();
|
||||
API int ui_menu(const char *items); // semicolon-separated or comma-separated items
|
||||
API int ui_menu_editbox(char *buf, int bufcap);
|
||||
|
|
31
hello.c
31
hello.c
|
@ -27,8 +27,7 @@ int main() {
|
|||
|
||||
// animated models loading (no flags)
|
||||
model_t girl = model("kgirl/kgirls01.fbx", 0);
|
||||
vec3 pos = vec3(0,0,0), sca = vec3(2,2,2), rot = vec3(-90,0,0);
|
||||
compose44( girl.pivot, pos, eulerq(rot), sca); // position, rotation, scale
|
||||
compose44( girl.pivot, vec3(0,0,0), eulerq(vec3(-90,0,0)), vec3(2,2,2)); // position, rotation, scale
|
||||
|
||||
// camera
|
||||
camera_t cam = camera();
|
||||
|
@ -38,7 +37,7 @@ int main() {
|
|||
|
||||
// audio (both clips & streams)
|
||||
audio_t SFX1 = audio_clip( "coin.wav" ), SFX2 = audio_clip( "pew.sfxr" );
|
||||
audio_t BGM1 = audio_stream( "waterworld-map.fur"), BGM2 = audio_stream( "larry.mid" ), BGM = BGM1;
|
||||
audio_t BGM1 = audio_stream( "waterworld-map.fur" ), BGM2 = audio_stream( "larry.mid" ), BGM = BGM1;
|
||||
audio_play(SFX1, 0);
|
||||
audio_play(BGM, 0);
|
||||
|
||||
|
@ -61,17 +60,17 @@ int main() {
|
|||
camera_fps(&cam, mouse.x,mouse.y);
|
||||
window_cursor( !active );
|
||||
|
||||
// debug draw
|
||||
ddraw_grid(0);
|
||||
if(do_debugdraw) ddraw_demo(); // showcase many debugdraw shapes
|
||||
ddraw_flush();
|
||||
|
||||
// draw skybox
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
|
||||
// apply post-fxs from here
|
||||
fx_begin();
|
||||
|
||||
// debug draw
|
||||
ddraw_ground(0);
|
||||
if(do_debugdraw) ddraw_demo(); // showcase many debugdraw shapes
|
||||
ddraw_flush();
|
||||
|
||||
// draw skybox
|
||||
skybox_render(&sky, cam.proj, cam.view);
|
||||
|
||||
// animate girl
|
||||
float delta = window_delta() * 30; // 30fps anim
|
||||
girl.curframe = model_animate(girl, girl.curframe + delta);
|
||||
|
@ -82,10 +81,6 @@ int main() {
|
|||
// post-fxs end here
|
||||
fx_end();
|
||||
|
||||
gizmo(&pos, &rot, &sca);
|
||||
model_render_skeleton(girl, girl.pivot);
|
||||
compose44( girl.pivot, pos, eulerq(rot), sca); // position, rotation, scale
|
||||
|
||||
// font demo
|
||||
font_print(va(FONT_BOTTOM FONT_RIGHT FONT_H6 "%5.2f FPS", window_fps()));
|
||||
|
||||
|
@ -115,12 +110,6 @@ int main() {
|
|||
if( ui_label2_toolbar("SFX: Coin", ICON_MD_VOLUME_UP)) audio_play(SFX1, 0);
|
||||
if( ui_label2_toolbar("SFX: Pew", ICON_MD_VOLUME_UP)) audio_play(SFX2, 0);
|
||||
|
||||
ui_section("FX");
|
||||
for( int i = 0, on; i < 64 && fx_name(i); ++i ) {
|
||||
bool enabled = fx_enabled(i);
|
||||
if( ui_bool(fx_name(i), &enabled) ) fx_enable(i, enabled);
|
||||
}
|
||||
|
||||
ui_panel_end();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue