scene: WIP lighting pass
parent
8129920be2
commit
0beb264e2b
9
MAKE.bat
9
MAKE.bat
|
@ -13,6 +13,7 @@ if "%1"=="help" (
|
|||
echo %0 [cook] ; cook .zipfiles with tools/cook.ini cookbook
|
||||
echo %0 [sync] ; sync repo to latest
|
||||
echo %0 [fwk] ; prepare files for fwk PR
|
||||
echo %0 [fwk_sync] ; update fwk-mirror fork
|
||||
echo %0 [lua] ; execute lua script with v4k
|
||||
echo %0 [html5] ; build HTML5 demo
|
||||
echo %0 [web] ; run Python webserver in html5 dir
|
||||
|
@ -214,6 +215,14 @@ if "%1"=="vps" (
|
|||
exit /b
|
||||
)
|
||||
|
||||
if "%1"=="fwk_sync" (
|
||||
pushd ..\fwk-mirror
|
||||
call MAKE.bat sync
|
||||
popd
|
||||
call MAKE.bat fwk
|
||||
exit /b
|
||||
)
|
||||
|
||||
if "%1"=="fwk" (
|
||||
if not exist "_fwk" mkdir "_fwk"
|
||||
if not exist "_fwk\demos" mkdir "_fwk\demos"
|
||||
|
|
|
@ -39,6 +39,10 @@ int main() {
|
|||
object_move(obj3, vec3(-10+5*1,0,-10));
|
||||
object_pivot(obj3, vec3(0,90,0));
|
||||
|
||||
// create point light
|
||||
light_t* l = scene_spawn_light();
|
||||
light_type(l, LIGHT_POINT);
|
||||
|
||||
while(window_swap() && !input(KEY_ESC)) {
|
||||
// draw environment
|
||||
viewport_color( RGB3(22,22,32) );
|
||||
|
@ -47,8 +51,11 @@ int main() {
|
|||
// update video
|
||||
video_decode( v );
|
||||
|
||||
// update light position
|
||||
light_teleport(l, cam.position);
|
||||
|
||||
// draw scene
|
||||
scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND);
|
||||
scene_render(SCENE_FOREGROUND|SCENE_BACKGROUND|SCENE_UPDATE_SH_COEF);
|
||||
|
||||
// fps camera
|
||||
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||
|
|
|
@ -6,8 +6,8 @@ uniform bool u_lit = false;
|
|||
uniform bool u_matcaps = false;
|
||||
uniform vec4 u_diffuse = vec4(1.0,1.0,1.0,1.0);
|
||||
|
||||
#ifdef RIM
|
||||
in vec3 v_position;
|
||||
#ifdef RIM
|
||||
uniform mat4 M; // RIM
|
||||
uniform vec3 u_rimcolor = vec3(0.2,0.2,0.2);
|
||||
uniform vec3 u_rimrange = vec3(0.11,0.98,0.5);
|
||||
|
@ -28,54 +28,102 @@ vec4 shadowing() {
|
|||
return shadowmap(vpeye, vneye, v_texcoord, sc);
|
||||
}
|
||||
|
||||
uniform int u_num_lights;
|
||||
|
||||
struct light_t {
|
||||
int type;
|
||||
vec3 color;
|
||||
vec3 pos;
|
||||
vec3 dir;
|
||||
float radius;
|
||||
};
|
||||
|
||||
#define MAX_LIGHTS 16
|
||||
const int LIGHT_DIRECTIONAL = 0;
|
||||
const int LIGHT_POINT = 1;
|
||||
const int LIGHT_SPOT = 2;
|
||||
|
||||
uniform light_t u_lights[MAX_LIGHTS];
|
||||
|
||||
vec3 calculate_light(light_t l, vec3 normal, vec3 fragPos, vec3 viewDir) {
|
||||
vec3 lightColor = l.color;
|
||||
|
||||
vec3 lightDir;
|
||||
float attenuation = 1.0;
|
||||
|
||||
if (l.type == LIGHT_DIRECTIONAL) {
|
||||
lightDir = normalize(-l.dir);
|
||||
} else if (l.type == LIGHT_POINT) {
|
||||
vec3 toLight = fragPos - l.pos;
|
||||
lightDir = normalize(toLight);
|
||||
float distance = length(toLight);
|
||||
float factor = distance / l.radius;
|
||||
attenuation = clamp(1.0 - factor, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
vec3 diffuse = diff * lightColor;
|
||||
|
||||
// vec3 reflectDir = reflect(-lightDir, normal);
|
||||
// float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
|
||||
// vec3 specular = spec * lightColor;
|
||||
|
||||
return (diffuse /* + specular */) * l.color;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 n = /*normalize*/(v_normal);
|
||||
vec3 n = /*normalize*/(v_normal);
|
||||
|
||||
vec4 lit = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
// SH lighting
|
||||
{
|
||||
vec3 SHLightResult[9];
|
||||
SHLightResult[0] = 0.282095f * u_coefficients_sh[0];
|
||||
SHLightResult[1] = -0.488603f * u_coefficients_sh[1] * n.y;
|
||||
SHLightResult[2] = 0.488603f * u_coefficients_sh[2] * n.z;
|
||||
SHLightResult[3] = -0.488603f * u_coefficients_sh[3] * n.x;
|
||||
SHLightResult[4] = 1.092548f * u_coefficients_sh[4] * n.x * n.y;
|
||||
SHLightResult[5] = -1.092548f * u_coefficients_sh[5] * n.y * n.z;
|
||||
SHLightResult[6] = 0.315392f * u_coefficients_sh[6] * (3.0f * n.z * n.z - 1.0f);
|
||||
SHLightResult[7] = -1.092548f * u_coefficients_sh[7] * n.x * n.z;
|
||||
SHLightResult[8] = 0.546274f * u_coefficients_sh[8] * (n.x * n.x - n.y * n.y);
|
||||
vec3 result = vec3(0.0);
|
||||
for (int i = 0; i < 9; ++i)
|
||||
result += SHLightResult[i];
|
||||
if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) lit = vec4(result, 1.0);
|
||||
}
|
||||
|
||||
// SH lighting
|
||||
vec4 lit = vec4(1.0, 1.0, 1.0, 1.0);
|
||||
vec3 SHLightResult[9];
|
||||
SHLightResult[0] = 0.282095f * u_coefficients_sh[0];
|
||||
SHLightResult[1] = -0.488603f * u_coefficients_sh[1] * n.y;
|
||||
SHLightResult[2] = 0.488603f * u_coefficients_sh[2] * n.z;
|
||||
SHLightResult[3] = -0.488603f * u_coefficients_sh[3] * n.x;
|
||||
SHLightResult[4] = 1.092548f * u_coefficients_sh[4] * n.x * n.y;
|
||||
SHLightResult[5] = -1.092548f * u_coefficients_sh[5] * n.y * n.z;
|
||||
SHLightResult[6] = 0.315392f * u_coefficients_sh[6] * (3.0f * n.z * n.z - 1.0f);
|
||||
SHLightResult[7] = -1.092548f * u_coefficients_sh[7] * n.x * n.z;
|
||||
SHLightResult[8] = 0.546274f * u_coefficients_sh[8] * (n.x * n.x - n.y * n.y);
|
||||
vec3 result = vec3(0.0);
|
||||
for (int i = 0; i < 9; ++i)
|
||||
result += SHLightResult[i];
|
||||
// analytical lights (phong shading)
|
||||
// @todo: support more shading models (blinn-phong, ue4 brdf, ...)
|
||||
// for (int i=0; i<u_num_lights; i++) {
|
||||
// lit += vec4(calculate_light(u_lights[i], n, v_position, /* @todo: push vdeye */ vec3(1.0,1.0,1.0)), 0.0);
|
||||
// }
|
||||
|
||||
if( (result.x*result.x+result.y*result.y+result.z*result.z) > 0.0 ) lit = vec4(result, 1.0);
|
||||
// base
|
||||
vec4 diffuse;
|
||||
|
||||
|
||||
// base
|
||||
vec4 diffuse;
|
||||
if(u_matcaps) {
|
||||
vec2 muv = vec2(view * vec4(v_normal_ws, 0))*0.5+vec2(0.5,0.5); // normal (model space) to view space
|
||||
diffuse = texture(u_texture2d, vec2(muv.x, 1.0-muv.y));
|
||||
if(u_matcaps) {
|
||||
vec2 muv = vec2(view * vec4(v_normal_ws, 0))*0.5+vec2(0.5,0.5); // normal (model space) to view space
|
||||
diffuse = texture(u_texture2d, vec2(muv.x, 1.0-muv.y));
|
||||
} else if(u_textured) {
|
||||
diffuse = texture(u_texture2d, v_texcoord);
|
||||
} else {
|
||||
diffuse = u_diffuse; // * v_color;
|
||||
}
|
||||
|
||||
// lighting mix
|
||||
fragcolor = diffuse * lit * shadowing();
|
||||
|
||||
// rimlight
|
||||
#ifdef RIM
|
||||
{vec3 n = normalize(mat3(M) * v_normal); // convert normal to view space
|
||||
vec3 p = (M * vec4(v_position,1.0)).xyz; // convert position to view space
|
||||
vec3 v = vec3(0,-1,0);
|
||||
if (!u_rimambient) {
|
||||
v = normalize(u_rimpivot-p);
|
||||
}
|
||||
float rim = 1.0 - max(dot(v,n), 0.0);
|
||||
vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z));
|
||||
fragcolor += vec4(col, 1.0);}
|
||||
#endif
|
||||
diffuse = u_diffuse; // * v_color;
|
||||
}
|
||||
|
||||
// lighting mix
|
||||
fragcolor = diffuse * lit * shadowing();
|
||||
|
||||
// rimlight
|
||||
#ifdef RIM
|
||||
{vec3 n = normalize(mat3(M) * v_normal); // convert normal to view space
|
||||
vec3 p = (M * vec4(v_position,1.0)).xyz; // convert position to view space
|
||||
vec3 v = vec3(0,-1,0);
|
||||
if (!u_rimambient) {
|
||||
v = normalize(u_rimpivot-p);
|
||||
}
|
||||
float rim = 1.0 - max(dot(v,n), 0.0);
|
||||
vec3 col = u_rimcolor*(pow(smoothstep(1.0-u_rimrange.x,u_rimrange.y,rim), u_rimrange.z));
|
||||
fragcolor += vec4(col, 1.0);}
|
||||
#endif
|
||||
}
|
|
@ -1392,6 +1392,17 @@ ffi.cdef([[
|
|||
//lcpp INF [0000] vec3: macro name but used as C declaration in:API void object_scale(object_t *obj, vec3 sca);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void object_scale(object_t *obj, vec3 sca);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in: void object_scale(object_t *obj, vec3 sca);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:vec3 color;
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:vec3 pos, dir;
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:API void light_color(light_t* l, vec3 color);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void light_color(light_t* l, vec3 color);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in: void light_color(light_t* l, vec3 color);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:API void light_teleport(light_t* l, vec3 pos);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void light_teleport(light_t* l, vec3 pos);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in: void light_teleport(light_t* l, vec3 pos);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:API void light_dir(light_t* l, vec3 dir);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void light_dir(light_t* l, vec3 dir);
|
||||
//lcpp INF [0000] vec3: macro name but used as C declaration in: void light_dir(light_t* l, vec3 dir);
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 ui_get_dims();
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 ui_get_dims();
|
||||
//lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 ui_get_dims();
|
||||
|
@ -2660,6 +2671,7 @@ handle* textures;
|
|||
model_t model;
|
||||
aabb bounds;
|
||||
unsigned billboard;
|
||||
bool light_cached;
|
||||
} object_t;
|
||||
object_t object();
|
||||
void object_rotate(object_t *obj, vec3 euler);
|
||||
|
@ -2673,15 +2685,39 @@ unsigned billboard;
|
|||
void object_diffuse_push(object_t *obj, texture_t tex);
|
||||
void object_diffuse_pop(object_t *obj);
|
||||
void object_billboard(object_t *obj, unsigned mode);
|
||||
enum LIGHT_TYPE {
|
||||
LIGHT_DIRECTIONAL,
|
||||
LIGHT_POINT,
|
||||
LIGHT_SPOT,
|
||||
};
|
||||
enum LIGHT_FLAGS {
|
||||
LIGHT_CAST_SHADOWS = 1,
|
||||
};
|
||||
typedef struct light_t {
|
||||
char type;
|
||||
vec3 color;
|
||||
vec3 pos, dir;
|
||||
float radius;
|
||||
bool cached;
|
||||
} light_t;
|
||||
light_t light();
|
||||
void light_type(light_t* l, char type);
|
||||
void light_color(light_t* l, vec3 color);
|
||||
void light_teleport(light_t* l, vec3 pos);
|
||||
void light_dir(light_t* l, vec3 dir);
|
||||
void light_radius(light_t* l, float radius);
|
||||
void light_update(unsigned num_lights, light_t *lv);
|
||||
enum SCENE_FLAGS {
|
||||
SCENE_WIREFRAME = 1,
|
||||
SCENE_CULLFACE = 2,
|
||||
SCENE_BACKGROUND = 4,
|
||||
SCENE_FOREGROUND = 8,
|
||||
SCENE_UPDATE_SH_COEF = 16,
|
||||
};
|
||||
typedef struct scene_t {
|
||||
handle program;
|
||||
object_t* objs;
|
||||
light_t* lights;
|
||||
skybox_t skybox;
|
||||
int u_coefficients_sh;
|
||||
} scene_t;
|
||||
|
@ -2693,6 +2729,9 @@ int u_coefficients_sh;
|
|||
object_t* scene_spawn();
|
||||
unsigned scene_count();
|
||||
object_t* scene_index(unsigned index);
|
||||
light_t* scene_spawn_light();
|
||||
unsigned scene_count_light();
|
||||
light_t* scene_index_light(unsigned index);
|
||||
void script_init();
|
||||
void script_run(const char *script);
|
||||
void script_runfile(const char *pathfile);
|
||||
|
|
|
@ -17131,6 +17131,7 @@ typedef struct object_t {
|
|||
model_t model;
|
||||
aabb bounds;
|
||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||
bool light_cached; //< used by scene to update light data
|
||||
} object_t;
|
||||
|
||||
API object_t object();
|
||||
|
@ -17149,6 +17150,37 @@ API void object_billboard(object_t *obj, unsigned mode);
|
|||
|
||||
// object_pose(transform); // @todo
|
||||
|
||||
|
||||
// light
|
||||
enum LIGHT_TYPE {
|
||||
LIGHT_DIRECTIONAL,
|
||||
LIGHT_POINT,
|
||||
LIGHT_SPOT,
|
||||
};
|
||||
|
||||
enum LIGHT_FLAGS {
|
||||
LIGHT_CAST_SHADOWS = 1,
|
||||
};
|
||||
|
||||
typedef struct light_t {
|
||||
char type;
|
||||
vec3 color;
|
||||
vec3 pos, dir;
|
||||
float radius;
|
||||
bool cached; //< used by scene to invalidate cached light data
|
||||
//@todo: inner/outer cone, flags, cookie, flare
|
||||
} light_t;
|
||||
|
||||
API light_t light();
|
||||
// API void light_flags(int flags);
|
||||
API void light_type(light_t* l, char type);
|
||||
API void light_color(light_t* l, vec3 color);
|
||||
API void light_teleport(light_t* l, vec3 pos);
|
||||
API void light_dir(light_t* l, vec3 dir);
|
||||
API void light_radius(light_t* l, float radius);
|
||||
// API void light_cone(light_t* l, float inner, float outer);
|
||||
API void light_update(unsigned num_lights, light_t *lv);
|
||||
|
||||
// scene
|
||||
|
||||
enum SCENE_FLAGS {
|
||||
|
@ -17156,12 +17188,14 @@ enum SCENE_FLAGS {
|
|||
SCENE_CULLFACE = 2,
|
||||
SCENE_BACKGROUND = 4,
|
||||
SCENE_FOREGROUND = 8,
|
||||
SCENE_UPDATE_SH_COEF = 16,
|
||||
};
|
||||
|
||||
typedef struct scene_t {
|
||||
handle program;
|
||||
|
||||
array(object_t) objs;
|
||||
array(light_t) lights;
|
||||
|
||||
// special objects below:
|
||||
skybox_t skybox;
|
||||
|
@ -17178,6 +17212,10 @@ API void scene_render(int flags);
|
|||
API object_t* scene_spawn();
|
||||
API unsigned scene_count();
|
||||
API object_t* scene_index(unsigned index);
|
||||
|
||||
API light_t* scene_spawn_light();
|
||||
API unsigned scene_count_light();
|
||||
API light_t* scene_index_light(unsigned index);
|
||||
#line 0
|
||||
|
||||
#line 1 "v4k_script.h"
|
||||
|
@ -342062,6 +342100,7 @@ skybox_t skybox(const char *asset, int flags) {
|
|||
shader_float("uRayleighScaleHeight", 8000.0);
|
||||
shader_float("uMieScaleHeight", 1200.0);
|
||||
shader_float("uMiePreferredDirection", 0.758);
|
||||
skybox_mie_calc_sh(&sky, 1.2);
|
||||
}
|
||||
|
||||
return sky;
|
||||
|
@ -345154,6 +345193,54 @@ void object_billboard(object_t *obj, unsigned mode) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
light_t light() {
|
||||
light_t l = {0};
|
||||
l.color = vec3(1,1,1);
|
||||
l.radius = 2.5f;
|
||||
l.dir = vec3(1,-1,-1);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void light_type(light_t* l, char type) {
|
||||
l->cached = 0;
|
||||
l->type = type;
|
||||
}
|
||||
|
||||
void light_color(light_t* l, vec3 color) {
|
||||
l->cached = 0;
|
||||
l->color = color;
|
||||
}
|
||||
|
||||
void light_teleport(light_t* l, vec3 pos) {
|
||||
l->cached = 0;
|
||||
l->pos = pos;
|
||||
}
|
||||
|
||||
void light_dir(light_t* l, vec3 dir) {
|
||||
l->cached = 0;
|
||||
l->dir = dir;
|
||||
}
|
||||
|
||||
void light_radius(light_t* l, float radius) {
|
||||
l->cached = 0;
|
||||
l->radius = radius;
|
||||
}
|
||||
|
||||
void light_update(unsigned num_lights, light_t *lv) {
|
||||
shader_int("u_num_lights", num_lights);
|
||||
|
||||
for (unsigned i=0; i < num_lights; ++i) {
|
||||
lv[i].cached = 1;
|
||||
shader_int(va("u_lights[%d].type", i), lv[i].type);
|
||||
shader_vec3(va("u_lights[%d].color", i), lv[i].color);
|
||||
shader_vec3(va("u_lights[%d].pos", i), lv[i].pos);
|
||||
shader_vec3(va("u_lights[%d].dir", i), lv[i].dir);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
array(scene_t*) scenes;
|
||||
scene_t* last_scene;
|
||||
|
||||
|
@ -345257,6 +345344,24 @@ object_t* scene_index(unsigned obj_index) {
|
|||
return &last_scene->objs[obj_index];
|
||||
}
|
||||
|
||||
light_t* scene_spawn_light() {
|
||||
light_t l = light();
|
||||
array_push(last_scene->lights, l);
|
||||
|
||||
return array_back(last_scene->lights);
|
||||
}
|
||||
|
||||
unsigned scene_count_light() {
|
||||
return array_count(last_scene->lights);
|
||||
}
|
||||
|
||||
light_t* scene_index_light(unsigned light_index) {
|
||||
unsigned light_count = scene_count_light();
|
||||
ASSERT(light_index < light_count, "Light index %d exceeds number (%d) of spawned lights", light_index, light_count);
|
||||
return &last_scene->lights[light_index];
|
||||
}
|
||||
|
||||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
|
@ -345293,6 +345398,14 @@ void scene_render(int flags) {
|
|||
// @todo texture mode
|
||||
|
||||
if( flags & SCENE_FOREGROUND ) {
|
||||
bool do_relighting = 0;
|
||||
for (unsigned j = 0; j < array_count(last_scene->lights); ++j) {
|
||||
if (!last_scene->lights[j].cached) {
|
||||
do_relighting = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||
object_t *obj = scene_index(j);
|
||||
model_t *model = &obj->model;
|
||||
|
@ -345309,6 +345422,17 @@ void scene_render(int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( do_relighting || !obj->light_cached ) {
|
||||
obj->light_cached = 1;
|
||||
shader_bind(model->program);
|
||||
light_update(array_count(last_scene->lights), last_scene->lights);
|
||||
}
|
||||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
shader_bind(model->program);
|
||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||
}
|
||||
|
||||
model->billboard = obj->billboard;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||
|
||||
|
|
|
@ -2490,6 +2490,7 @@ skybox_t skybox(const char *asset, int flags) {
|
|||
shader_float("uRayleighScaleHeight", 8000.0);
|
||||
shader_float("uMieScaleHeight", 1200.0);
|
||||
shader_float("uMiePreferredDirection", 0.758);
|
||||
skybox_mie_calc_sh(&sky, 1.2);
|
||||
}
|
||||
|
||||
return sky;
|
||||
|
|
|
@ -241,6 +241,54 @@ void object_billboard(object_t *obj, unsigned mode) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
light_t light() {
|
||||
light_t l = {0};
|
||||
l.color = vec3(1,1,1);
|
||||
l.radius = 2.5f;
|
||||
l.dir = vec3(1,-1,-1);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void light_type(light_t* l, char type) {
|
||||
l->cached = 0;
|
||||
l->type = type;
|
||||
}
|
||||
|
||||
void light_color(light_t* l, vec3 color) {
|
||||
l->cached = 0;
|
||||
l->color = color;
|
||||
}
|
||||
|
||||
void light_teleport(light_t* l, vec3 pos) {
|
||||
l->cached = 0;
|
||||
l->pos = pos;
|
||||
}
|
||||
|
||||
void light_dir(light_t* l, vec3 dir) {
|
||||
l->cached = 0;
|
||||
l->dir = dir;
|
||||
}
|
||||
|
||||
void light_radius(light_t* l, float radius) {
|
||||
l->cached = 0;
|
||||
l->radius = radius;
|
||||
}
|
||||
|
||||
void light_update(unsigned num_lights, light_t *lv) {
|
||||
shader_int("u_num_lights", num_lights);
|
||||
|
||||
for (unsigned i=0; i < num_lights; ++i) {
|
||||
lv[i].cached = 1;
|
||||
shader_int(va("u_lights[%d].type", i), lv[i].type);
|
||||
shader_vec3(va("u_lights[%d].color", i), lv[i].color);
|
||||
shader_vec3(va("u_lights[%d].pos", i), lv[i].pos);
|
||||
shader_vec3(va("u_lights[%d].dir", i), lv[i].dir);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
array(scene_t*) scenes;
|
||||
scene_t* last_scene;
|
||||
|
||||
|
@ -344,6 +392,24 @@ object_t* scene_index(unsigned obj_index) {
|
|||
return &last_scene->objs[obj_index];
|
||||
}
|
||||
|
||||
light_t* scene_spawn_light() {
|
||||
light_t l = light();
|
||||
array_push(last_scene->lights, l);
|
||||
|
||||
return array_back(last_scene->lights);
|
||||
}
|
||||
|
||||
unsigned scene_count_light() {
|
||||
return array_count(last_scene->lights);
|
||||
}
|
||||
|
||||
light_t* scene_index_light(unsigned light_index) {
|
||||
unsigned light_count = scene_count_light();
|
||||
ASSERT(light_index < light_count, "Light index %d exceeds number (%d) of spawned lights", light_index, light_count);
|
||||
return &last_scene->lights[light_index];
|
||||
}
|
||||
|
||||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
|
@ -380,6 +446,14 @@ void scene_render(int flags) {
|
|||
// @todo texture mode
|
||||
|
||||
if( flags & SCENE_FOREGROUND ) {
|
||||
bool do_relighting = 0;
|
||||
for (unsigned j = 0; j < array_count(last_scene->lights); ++j) {
|
||||
if (!last_scene->lights[j].cached) {
|
||||
do_relighting = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||
object_t *obj = scene_index(j);
|
||||
model_t *model = &obj->model;
|
||||
|
@ -396,6 +470,17 @@ void scene_render(int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( do_relighting || !obj->light_cached ) {
|
||||
obj->light_cached = 1;
|
||||
shader_bind(model->program);
|
||||
light_update(array_count(last_scene->lights), last_scene->lights);
|
||||
}
|
||||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
shader_bind(model->program);
|
||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||
}
|
||||
|
||||
model->billboard = obj->billboard;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ typedef struct object_t {
|
|||
model_t model;
|
||||
aabb bounds;
|
||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||
bool light_cached; //< used by scene to update light data
|
||||
} object_t;
|
||||
|
||||
API object_t object();
|
||||
|
@ -51,6 +52,37 @@ API void object_billboard(object_t *obj, unsigned mode);
|
|||
|
||||
// object_pose(transform); // @todo
|
||||
|
||||
|
||||
// light
|
||||
enum LIGHT_TYPE {
|
||||
LIGHT_DIRECTIONAL,
|
||||
LIGHT_POINT,
|
||||
LIGHT_SPOT,
|
||||
};
|
||||
|
||||
enum LIGHT_FLAGS {
|
||||
LIGHT_CAST_SHADOWS = 1,
|
||||
};
|
||||
|
||||
typedef struct light_t {
|
||||
char type;
|
||||
vec3 color;
|
||||
vec3 pos, dir;
|
||||
float radius;
|
||||
bool cached; //< used by scene to invalidate cached light data
|
||||
//@todo: inner/outer cone, flags, cookie, flare
|
||||
} light_t;
|
||||
|
||||
API light_t light();
|
||||
// API void light_flags(int flags);
|
||||
API void light_type(light_t* l, char type);
|
||||
API void light_color(light_t* l, vec3 color);
|
||||
API void light_teleport(light_t* l, vec3 pos);
|
||||
API void light_dir(light_t* l, vec3 dir);
|
||||
API void light_radius(light_t* l, float radius);
|
||||
// API void light_cone(light_t* l, float inner, float outer);
|
||||
API void light_update(unsigned num_lights, light_t *lv);
|
||||
|
||||
// scene
|
||||
|
||||
enum SCENE_FLAGS {
|
||||
|
@ -58,12 +90,14 @@ enum SCENE_FLAGS {
|
|||
SCENE_CULLFACE = 2,
|
||||
SCENE_BACKGROUND = 4,
|
||||
SCENE_FOREGROUND = 8,
|
||||
SCENE_UPDATE_SH_COEF = 16,
|
||||
};
|
||||
|
||||
typedef struct scene_t {
|
||||
handle program;
|
||||
|
||||
array(object_t) objs;
|
||||
array(light_t) lights;
|
||||
|
||||
// special objects below:
|
||||
skybox_t skybox;
|
||||
|
@ -80,3 +114,7 @@ API void scene_render(int flags);
|
|||
API object_t* scene_spawn();
|
||||
API unsigned scene_count();
|
||||
API object_t* scene_index(unsigned index);
|
||||
|
||||
API light_t* scene_spawn_light();
|
||||
API unsigned scene_count_light();
|
||||
API light_t* scene_index_light(unsigned index);
|
||||
|
|
86
engine/v4k.c
86
engine/v4k.c
|
@ -12754,6 +12754,7 @@ skybox_t skybox(const char *asset, int flags) {
|
|||
shader_float("uRayleighScaleHeight", 8000.0);
|
||||
shader_float("uMieScaleHeight", 1200.0);
|
||||
shader_float("uMiePreferredDirection", 0.758);
|
||||
skybox_mie_calc_sh(&sky, 1.2);
|
||||
}
|
||||
|
||||
return sky;
|
||||
|
@ -15846,6 +15847,54 @@ void object_billboard(object_t *obj, unsigned mode) {
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
light_t light() {
|
||||
light_t l = {0};
|
||||
l.color = vec3(1,1,1);
|
||||
l.radius = 2.5f;
|
||||
l.dir = vec3(1,-1,-1);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void light_type(light_t* l, char type) {
|
||||
l->cached = 0;
|
||||
l->type = type;
|
||||
}
|
||||
|
||||
void light_color(light_t* l, vec3 color) {
|
||||
l->cached = 0;
|
||||
l->color = color;
|
||||
}
|
||||
|
||||
void light_teleport(light_t* l, vec3 pos) {
|
||||
l->cached = 0;
|
||||
l->pos = pos;
|
||||
}
|
||||
|
||||
void light_dir(light_t* l, vec3 dir) {
|
||||
l->cached = 0;
|
||||
l->dir = dir;
|
||||
}
|
||||
|
||||
void light_radius(light_t* l, float radius) {
|
||||
l->cached = 0;
|
||||
l->radius = radius;
|
||||
}
|
||||
|
||||
void light_update(unsigned num_lights, light_t *lv) {
|
||||
shader_int("u_num_lights", num_lights);
|
||||
|
||||
for (unsigned i=0; i < num_lights; ++i) {
|
||||
lv[i].cached = 1;
|
||||
shader_int(va("u_lights[%d].type", i), lv[i].type);
|
||||
shader_vec3(va("u_lights[%d].color", i), lv[i].color);
|
||||
shader_vec3(va("u_lights[%d].pos", i), lv[i].pos);
|
||||
shader_vec3(va("u_lights[%d].dir", i), lv[i].dir);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
array(scene_t*) scenes;
|
||||
scene_t* last_scene;
|
||||
|
||||
|
@ -15949,6 +15998,24 @@ object_t* scene_index(unsigned obj_index) {
|
|||
return &last_scene->objs[obj_index];
|
||||
}
|
||||
|
||||
light_t* scene_spawn_light() {
|
||||
light_t l = light();
|
||||
array_push(last_scene->lights, l);
|
||||
|
||||
return array_back(last_scene->lights);
|
||||
}
|
||||
|
||||
unsigned scene_count_light() {
|
||||
return array_count(last_scene->lights);
|
||||
}
|
||||
|
||||
light_t* scene_index_light(unsigned light_index) {
|
||||
unsigned light_count = scene_count_light();
|
||||
ASSERT(light_index < light_count, "Light index %d exceeds number (%d) of spawned lights", light_index, light_count);
|
||||
return &last_scene->lights[light_index];
|
||||
}
|
||||
|
||||
|
||||
void scene_render(int flags) {
|
||||
camera_t *cam = camera_get_active();
|
||||
|
||||
|
@ -15985,6 +16052,14 @@ void scene_render(int flags) {
|
|||
// @todo texture mode
|
||||
|
||||
if( flags & SCENE_FOREGROUND ) {
|
||||
bool do_relighting = 0;
|
||||
for (unsigned j = 0; j < array_count(last_scene->lights); ++j) {
|
||||
if (!last_scene->lights[j].cached) {
|
||||
do_relighting = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned j = 0, obj_count = scene_count(); j < obj_count; ++j ) {
|
||||
object_t *obj = scene_index(j);
|
||||
model_t *model = &obj->model;
|
||||
|
@ -16001,6 +16076,17 @@ void scene_render(int flags) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( do_relighting || !obj->light_cached ) {
|
||||
obj->light_cached = 1;
|
||||
shader_bind(model->program);
|
||||
light_update(array_count(last_scene->lights), last_scene->lights);
|
||||
}
|
||||
|
||||
if ( flags&SCENE_UPDATE_SH_COEF ) {
|
||||
shader_bind(model->program);
|
||||
shader_vec3v("u_coefficients_sh", 9, last_scene->skybox.cubemap.sh);
|
||||
}
|
||||
|
||||
model->billboard = obj->billboard;
|
||||
model_render(*model, cam->proj, cam->view, obj->transform, 0);
|
||||
|
||||
|
|
38
engine/v4k.h
38
engine/v4k.h
|
@ -3214,6 +3214,7 @@ typedef struct object_t {
|
|||
model_t model;
|
||||
aabb bounds;
|
||||
unsigned billboard; // [0..7] x(4),y(2),z(1) masks
|
||||
bool light_cached; //< used by scene to update light data
|
||||
} object_t;
|
||||
|
||||
API object_t object();
|
||||
|
@ -3232,6 +3233,37 @@ API void object_billboard(object_t *obj, unsigned mode);
|
|||
|
||||
// object_pose(transform); // @todo
|
||||
|
||||
|
||||
// light
|
||||
enum LIGHT_TYPE {
|
||||
LIGHT_DIRECTIONAL,
|
||||
LIGHT_POINT,
|
||||
LIGHT_SPOT,
|
||||
};
|
||||
|
||||
enum LIGHT_FLAGS {
|
||||
LIGHT_CAST_SHADOWS = 1,
|
||||
};
|
||||
|
||||
typedef struct light_t {
|
||||
char type;
|
||||
vec3 color;
|
||||
vec3 pos, dir;
|
||||
float radius;
|
||||
bool cached; //< used by scene to invalidate cached light data
|
||||
//@todo: inner/outer cone, flags, cookie, flare
|
||||
} light_t;
|
||||
|
||||
API light_t light();
|
||||
// API void light_flags(int flags);
|
||||
API void light_type(light_t* l, char type);
|
||||
API void light_color(light_t* l, vec3 color);
|
||||
API void light_teleport(light_t* l, vec3 pos);
|
||||
API void light_dir(light_t* l, vec3 dir);
|
||||
API void light_radius(light_t* l, float radius);
|
||||
// API void light_cone(light_t* l, float inner, float outer);
|
||||
API void light_update(unsigned num_lights, light_t *lv);
|
||||
|
||||
// scene
|
||||
|
||||
enum SCENE_FLAGS {
|
||||
|
@ -3239,12 +3271,14 @@ enum SCENE_FLAGS {
|
|||
SCENE_CULLFACE = 2,
|
||||
SCENE_BACKGROUND = 4,
|
||||
SCENE_FOREGROUND = 8,
|
||||
SCENE_UPDATE_SH_COEF = 16,
|
||||
};
|
||||
|
||||
typedef struct scene_t {
|
||||
handle program;
|
||||
|
||||
array(object_t) objs;
|
||||
array(light_t) lights;
|
||||
|
||||
// special objects below:
|
||||
skybox_t skybox;
|
||||
|
@ -3261,6 +3295,10 @@ API void scene_render(int flags);
|
|||
API object_t* scene_spawn();
|
||||
API unsigned scene_count();
|
||||
API object_t* scene_index(unsigned index);
|
||||
|
||||
API light_t* scene_spawn_light();
|
||||
API unsigned scene_count_light();
|
||||
API light_t* scene_index_light(unsigned index);
|
||||
#line 0
|
||||
|
||||
#line 1 "v4k_script.h"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; this is where you specify and configure the V4K pipeline.
|
||||
; this is where you specify and configure the FWK pipeline.
|
||||
; tweak the pipeline and add new importers just by editing this file.
|
||||
; there is no flow control in this script file: lines are parsed and evaluated, from top to bottom.
|
||||
|
||||
|
|
|
@ -112,14 +112,14 @@ int main() {
|
|||
load_asset(file);
|
||||
show_browser = 1;
|
||||
}
|
||||
ui_panel_end();
|
||||
}
|
||||
ui_panel_end();
|
||||
|
||||
static bool show_main_window = 1;
|
||||
if ( ui_window("Workbench", &show_main_window) ) {
|
||||
ui_label("v4.games");
|
||||
ui_window_end();
|
||||
}
|
||||
ui_window_end();
|
||||
|
||||
for (int i=0; i<array_count(assets); i++) {
|
||||
asset_t *f = (assets+i);
|
||||
|
@ -145,8 +145,8 @@ int main() {
|
|||
array_erase(assets, i);
|
||||
--i;
|
||||
}
|
||||
ui_window_end();
|
||||
}
|
||||
ui_window_end();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue