UI changes + vram reduction

main
Dominik Madarász 2024-08-31 12:17:59 +02:00
parent 5eb53e7fa4
commit a3b747fd46
13 changed files with 584 additions and 232 deletions

View File

@ -1148,7 +1148,7 @@ enum SHADOW_TECHNIQUE {
SHADOW_CSM,
};
typedef struct light_t {
char type;
unsigned type;
vec3 diffuse, specular, ambient;
vec3 pos, dir;
struct {
@ -1158,12 +1158,16 @@ typedef struct light_t {
float specularPower;
float innerCone, outerCone;
bool cast_shadows;
bool processed_shadows;
unsigned shadow_technique;
float shadow_distance;
float shadow_bias;
float shadow_near_clip;
mat44 shadow_matrix[4];
float min_variance;
float variance_transition;
float shadow_bias;
float normal_bias;
bool cached;
bool processed_shadows;
} light_t;
light_t light();
void light_type(light_t* l, char type);
@ -1177,6 +1181,8 @@ typedef struct light_t {
void light_falloff(light_t* l, float constant, float linear, float quadratic);
void light_cone(light_t* l, float innerCone, float outerCone);
void light_update(unsigned num_lights, light_t *lv);
void ui_light(light_t *l);
void ui_lights(unsigned num_lights, light_t *lights);
typedef struct shadowmap_t {
mat44 V;
mat44 PV;
@ -1198,11 +1204,13 @@ typedef struct shadowmap_t {
uint64_t vram_usage_total;
uint64_t vram_usage_vsm;
uint64_t vram_usage_csm;
handle depth_texture;
handle depth_texture_2d;
struct {
int gen;
unsigned shadow_technique;
handle texture, depth_texture;
handle texture_2d[4], depth_texture_2d[4];
handle texture;
handle texture_2d[4];
handle blur_texture, blur_texture_2d;
float cascade_distances[4];
} maps[MAX_LIGHTS];
@ -2054,6 +2062,10 @@ enum PANEL_FLAGS {
int ui_int(const char *label, int *value);
int ui_bool(const char *label, bool *value);
int ui_short(const char *label, short *value);
int ui_float_(const char *label, float *value, float step);
int ui_float2_(const char *label, float value[2], float step);
int ui_float3_(const char *label, float value[3], float step);
int ui_float4_(const char *label, float value[4], float step);
int ui_float(const char *label, float *value);
int ui_float2(const char *label, float value[2]);
int ui_float3(const char *label, float value[3]);
@ -2090,6 +2102,7 @@ enum PANEL_FLAGS {
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, float step);
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);

View File

@ -206,6 +206,8 @@ int main(int argc, char** argv) {
must_reload = 1;
}
ui_separator();
ui_lights(array_count(lights), lights);
ui_separator();
ui_bool("CSM Blur", &sm.blur_csm);
ui_slider("CSM Blur Scale", &sm.csm_blur_scale);
ui_bool("VSM Blur", &sm.blur_vsm);

View File

@ -26,6 +26,10 @@ struct light_t {
// shadows
mat4 shadow_matrix[NUM_SHADOW_CASCADES];
float shadow_bias;
float normal_bias;
float min_variance;
float variance_transition;
};
const int LIGHT_DIRECTIONAL = 0;

View File

@ -12,7 +12,7 @@ uniform sampler2D shadowMap2D[MAX_LIGHTS * NUM_SHADOW_CASCADES];
const float bias_modifier[NUM_SHADOW_CASCADES] = float[NUM_SHADOW_CASCADES](0.95, 0.35, 0.20, 0.15);
//// From http://fabiensanglard.net/shadowmappingVSM/index.php
float shadow_vsm(float distance, vec3 dir, int light_index) {
float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition) {
distance = distance/200;
// Define offsets for 3x3 PCF
@ -49,9 +49,9 @@ float shadow_vsm(float distance, vec3 dir, int light_index) {
// Calculate VSM for this sample
float p = step(distance, moments.x);
float variance = max(moments.y - (moments.x * moments.x), 0.00002);
float variance = max(moments.y - (moments.x * moments.x), min_variance);
float d = distance - moments.x;
float p_max = linstep(0.2, 1.0, variance / (variance + d*d));
float p_max = linstep(variance_transition, 1.0, variance / (variance + d*d));
shadow += min(max(p, p_max), 1.0);
}
@ -60,7 +60,7 @@ float shadow_vsm(float distance, vec3 dir, int light_index) {
return shadow / 9.0;
}
float shadow_csm(float distance, vec3 lightDir, int light_index) {
float shadow_csm(float distance, vec3 lightDir, int light_index, float shadow_bias, float normal_bias) {
// Determine which cascade to use
int cascade_index = -1;
int min_cascades_range = light_index * NUM_SHADOW_CASCADES;
@ -94,7 +94,7 @@ float shadow_csm(float distance, vec3 lightDir, int light_index) {
// Calculate bias
vec3 normal = normalize(vneye.xyz);
float bias = max(0.05 * (1.0 - dot(normal, lightDir)), 0.005);
float bias = max(normal_bias * (1.0 - dot(normal, lightDir)), shadow_bias);
bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[matrix_index]);
// CSM
@ -116,7 +116,7 @@ float shadow_csm(float distance, vec3 lightDir, int light_index) {
{
for(int y = -1; y <= 1; ++y)
{
float csmDepth = texture(shadowMap2D[cascade_index], projCoords.xy + vec2(x, y) * texelSize).r;
float csmDepth = texture(shadowMap2D[cascade_index], projCoords.xy + vec2(x, y) * texelSize * (rand(vec2(projCoords.x + x, projCoords.y + y))*0.75f + 0.25f)).r;
shadow += currentDepth - bias > csmDepth ? 1.0 : 0.0;
}
}
@ -132,12 +132,12 @@ vec4 shadowmap(int idx, in vec4 peye, in vec4 neye) {
if (light.processed_shadows) {
if (light.type == LIGHT_DIRECTIONAL) {
shadowFactor = shadow_csm(-peye.z, light.dir, idx);
shadowFactor = shadow_csm(-peye.z, light.dir, idx, light.shadow_bias, light.normal_bias);
} else if (light.type == LIGHT_POINT || light.type == LIGHT_SPOT) {
vec3 light_pos = (view * vec4(light.pos, 1.0)).xyz;
vec3 dir = light_pos - fragment;
vec4 sc = inv_view * vec4(dir, 0.0);
shadowFactor = shadow_vsm(length(dir), -sc.xyz, idx);
shadowFactor = shadow_vsm(length(dir), -sc.xyz, idx, light.min_variance, light.variance_transition);
}
}

View File

@ -17270,7 +17270,7 @@ enum SHADOW_TECHNIQUE {
#define NUM_SHADOW_CASCADES 4
typedef struct light_t {
char type;
unsigned type;
vec3 diffuse, specular, ambient;
vec3 pos, dir;
struct {
@ -17283,14 +17283,18 @@ typedef struct light_t {
// Shadowmapping
bool cast_shadows;
bool processed_shadows;
unsigned shadow_technique;
float shadow_distance;
float shadow_bias;
float shadow_near_clip;
mat44 shadow_matrix[NUM_SHADOW_CASCADES];
float min_variance; //< VSM
float variance_transition; //< VSM
float shadow_bias; //< CSM
float normal_bias; //< CSM
// internals
bool cached; //< used by scene to invalidate cached light data
bool processed_shadows;
} light_t;
API light_t light();
@ -17307,6 +17311,10 @@ API void light_falloff(light_t* l, float constant, float linear, float quadra
API void light_cone(light_t* l, float innerCone, float outerCone);
API void light_update(unsigned num_lights, light_t *lv);
API void ui_light(light_t *l);
API void ui_lights(unsigned num_lights, light_t *lights);
// -----------------------------------------------------------------------------
// shadowmaps
@ -17336,11 +17344,15 @@ typedef struct shadowmap_t {
uint64_t vram_usage_vsm;
uint64_t vram_usage_csm;
// depth texture
handle depth_texture;
handle depth_texture_2d;
struct {
int gen;
unsigned shadow_technique;
handle texture, depth_texture;
handle texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle texture;
handle texture_2d[NUM_SHADOW_CASCADES];
handle blur_texture, blur_texture_2d;
// handle blur_fbo_cubemap, blur_texture_cubemap;
float cascade_distances[NUM_SHADOW_CASCADES];
@ -18699,6 +18711,10 @@ API int ui_section(const char *title);
API int ui_int(const char *label, int *value);
API int ui_bool(const char *label, bool *value);
API int ui_short(const char *label, short *value);
API int ui_float_(const char *label, float *value, float step);
API int ui_float2_(const char *label, float value[2], float step);
API int ui_float3_(const char *label, float value[3], float step);
API int ui_float4_(const char *label, float value[4], float step);
API int ui_float(const char *label, float *value);
API int ui_float2(const char *label, float value[2]);
API int ui_float3(const char *label, float value[3]);
@ -18735,6 +18751,7 @@ API int ui_separator();
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, float step);
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);
@ -228865,6 +228882,8 @@ struct nk_context {
#define NK_PI 3.141592654f
#define NK_UTF_INVALID 0xFFFD
#define NK_MAX_FLOAT_PRECISION 2
#define NK_MAX_FLOAT_PRECISION2 6
#define NK_FLOAT_DECIMAL_POS_THRESHOLD 0.0005
#define NK_UNUSED(x) ((void)(x))
#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
@ -251323,11 +251342,11 @@ nk_do_property(nk_flags *ws,
break;
case NK_PROPERTY_FLOAT:
NK_DTOA(string, (double)variant->value.f);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
case NK_PROPERTY_DOUBLE:
NK_DTOA(string, variant->value.d);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
}
size = font->width(font->userdata, font->height, string, num_len);
@ -251423,12 +251442,12 @@ nk_do_property(nk_flags *ws,
variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
break;
case NK_PROPERTY_FLOAT:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.f = nk_strtof(buffer, 0);
variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
break;
case NK_PROPERTY_DOUBLE:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.d = nk_strtod(buffer, 0);
variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
break;
@ -368386,13 +368405,42 @@ int ui_short(const char *label, short *v) {
return *v = (short)i, ret;
}
int ui_float(const char *label, float *v) {
static inline
float ui_float_adjust_step(float step) {
if ((input(KEY_LSHIFT) || input(KEY_RSHIFT))&&(input(KEY_LCTRL) || input(KEY_RCTRL))) step *= 100.0f;
else if (input(KEY_LSHIFT) || input(KEY_RSHIFT)) step *= 10.0f;
else if (input(KEY_LCTRL) || input(KEY_RCTRL)) step *= 0.1f;
else if (input(KEY_LALT) || input(KEY_RALT)) step *= 0.01f;
return step;
}
int ui_float_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, 0.01f,0.005f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, step, inc_per_pixel);
return prev != v[0];
}
int ui_float(const char *label, float *v) {
return ui_float_(label, v, 0.01f);
}
int ui_double_(const char *label, double *v, double step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
double prev = v[0]; v[0] = nk_propertyd(ui_ctx, "#", -DBL_MAX, v[0], DBL_MAX, step, inc_per_pixel);
return prev != v[0];
}
@ -368406,21 +368454,30 @@ int ui_double(const char *label, double *v) {
return prev != v[0];
}
int ui_clampf(const char *label, float *v, float minf, float maxf) {
int ui_clampf_(const char *label, float *v, float minf, float maxf, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
if( minf > maxf ) return ui_clampf(label, v, maxf, minf);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, 0.1f,0.05f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, step, inc_per_pixel);
return prev != v[0];
}
int ui_float2(const char *label, float *v) {
int ui_clampf(const char *label, float *v, float minf, float maxf) {
return ui_clampf_(label, v, minf, maxf, 0.1f);
}
int ui_float2_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -368430,17 +368487,23 @@ int ui_float2(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1];
}
return 0;
}
int ui_float3(const char *label, float *v) {
int ui_float2(const char *label, float *v) {
return ui_float2_(label, v, 1.0f);
}
int ui_float3_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -368450,18 +368513,25 @@ int ui_float3(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2];
}
return 0;
}
int ui_float4(const char *label, float *v) {
int ui_float3(const char *label, float *v) {
return ui_float3_(label, v, 1.0f);
}
int ui_float4_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -368471,10 +368541,10 @@ int ui_float4(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2] || prev3 != v[3];
}
@ -368482,6 +368552,10 @@ int ui_float4(const char *label, float *v) {
return 0;
}
int ui_float4(const char *label, float *v) {
return ui_float4_(label, v, 1.0f);
}
int ui_mat33(const char *label, float M[9]) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
@ -383226,7 +383300,11 @@ light_t light() {
l.cast_shadows = true;
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
return l;
}
@ -383305,6 +383383,10 @@ void light_update(unsigned num_lights, light_t *lv) {
shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic);
shader_float(va("u_lights[%d].innerCone", i), lv[i].innerCone);
shader_float(va("u_lights[%d].outerCone", i), lv[i].outerCone);
shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias);
shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias);
shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance);
shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition);
shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows);
if (lv[i].processed_shadows) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
@ -383314,10 +383396,58 @@ void light_update(unsigned num_lights, light_t *lv) {
}
}
void ui_light(light_t *l) {
ui_int("Type", &l->type);
ui_vec3("Position", &l->pos);
ui_vec3("Direction", &l->dir);
ui_color3f("Diffuse", &l->diffuse.x);
ui_color3f("Specular", &l->specular.x);
ui_color3f("Ambient", &l->ambient.x);
ui_float("Specular Power", &l->specularPower);
ui_clampf("Radius", &l->radius, 0.0f, FLT_MAX);
ui_clampf_("Constant Falloff", &l->falloff.constant, 0.0, FLT_MAX, 0.005);
ui_clampf_("Linear Falloff", &l->falloff.linear, 0.0, FLT_MAX, 0.005);
ui_clampf_("Quadratic Falloff", &l->falloff.quadratic, 0.0, FLT_MAX, 0.005);
ui_float("Inner Cone", &l->innerCone);
ui_float("Outer Cone", &l->outerCone);
ui_float_("Shadow Bias", &l->shadow_bias, 0.00005);
ui_float_("Normal Bias", &l->normal_bias, 0.00005);
ui_float_("Min Variance", &l->min_variance, 0.00005);
ui_float_("Variance Transition", &l->variance_transition, 0.0005);
}
void ui_lights(unsigned num_lights, light_t *lights) {
for (unsigned i = 0; i < num_lights; ++i) {
if (ui_collapse(va("Light %d", i), va("light_%d", i))) {
ui_light(&lights[i]);
ui_collapse_end();
}
}
}
// -----------------------------------------------------------------------------
// shadowmaps
static inline
void shadowmap_init_common_resources(shadowmap_t *s, int vsm_texture_width, int csm_texture_width) {
// Create a cubemap depth texture
glGenTextures(1, &s->depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, vsm_texture_width, vsm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
// Create a 2D depth texture
glGenTextures(1, &s->depth_texture_2d);
glBindTexture(GL_TEXTURE_2D, s->depth_texture_2d);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, csm_texture_width, csm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
static inline void
shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
float borderColor[] = {1.0, 1.0, 1.0, 1.0};
@ -383341,19 +383471,6 @@ shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
// Create a cubemap depth texture
glGenTextures(1, &s->maps[light_index].depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->maps[light_index].depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@ -383375,15 +383492,6 @@ shadowmap_init_caster_csm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glGenTextures(1, &s->maps[light_index].depth_texture_2d[i]);
glBindTexture(GL_TEXTURE_2D, s->maps[light_index].depth_texture_2d[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
}
glBindTexture(GL_TEXTURE_2D, 0);
@ -383434,6 +383542,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
}
#endif
shadowmap_init_common_resources(&s, vsm_texture_width, csm_texture_width);
glBindFramebuffer(GL_FRAMEBUFFER, s.saved_fb);
return s;
}
@ -383447,20 +383557,12 @@ void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
glDeleteTextures(1, &s->maps[light_index].texture);
s->maps[light_index].texture = 0;
}
if (s->maps[light_index].depth_texture) {
glDeleteTextures(1, &s->maps[light_index].depth_texture);
s->maps[light_index].depth_texture = 0;
}
for (int i = 0; i < NUM_SHADOW_CASCADES; i++) {
if (s->maps[light_index].texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].texture_2d[i]);
s->maps[light_index].texture_2d[i] = 0;
}
if (s->maps[light_index].depth_texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].depth_texture_2d[i]);
s->maps[light_index].depth_texture_2d[i] = 0;
}
}
if (s->maps[light_index].blur_texture_2d) {
@ -383478,6 +383580,18 @@ void shadowmap_destroy(shadowmap_t *s) {
for (int i = 0; i < MAX_LIGHTS; i++) {
shadowmap_destroy_light(s, i);
}
if (s->depth_texture) {
glDeleteTextures(1, &s->depth_texture);
s->depth_texture = 0;
}
if (s->depth_texture_2d) {
glDeleteTextures(1, &s->depth_texture_2d);
s->depth_texture_2d = 0;
}
shadowmap_t z = {0};
*s = z;
}
@ -383505,7 +383619,7 @@ void shadowmap_begin(shadowmap_t *s) {
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) {
if(dir<0) return;
mat44 P, V, PV;
perspective44(P, 90.0f, 1.0f, l->shadow_bias, l->shadow_distance);
perspective44(P, 90.0f, 1.0f, l->shadow_near_clip, l->shadow_distance);
vec3 lightPos = l->pos;
/**/ if(dir == 0) lookat44(V, lightPos, add3(lightPos, vec3(+1, 0, 0)), vec3(0, -1, 0)); // +X
@ -383558,7 +383672,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo
float near_plane = 0.0f;
if (s->cascade_index == 0) {
near_plane = l->shadow_bias;
near_plane = l->shadow_near_clip;
far_plane = l->shadow_distance * s->cascade_splits[0];
} else if (s->cascade_index < NUM_SHADOW_CASCADES - 1) {
near_plane = l->shadow_distance * s->cascade_splits[s->cascade_index-1];
@ -383873,12 +383987,12 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
if (l->type == LIGHT_DIRECTIONAL) {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s->maps[s->light_step].texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->maps[s->light_step].depth_texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->depth_texture_2d, 0);
shadowmap_clear_fbo();
} else {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].depth_texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->depth_texture, 0);
shadowmap_clear_fbo();
}
@ -383900,19 +384014,25 @@ void shadowmap_end(shadowmap_t *s) {
{
const int faces = 6;
const int cascades = NUM_SHADOW_CASCADES;
// Depth textures
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
for (int i = 0; i < MAX_LIGHTS; i++) {
// VSM textures
if (s->maps[i].texture != 0) {
// Color texture (GL_RG32F)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
}
// Color texture (GL_RG32F)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
// Color texture (GL_RG32F)
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
@ -383925,20 +384045,13 @@ void shadowmap_end(shadowmap_t *s) {
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
}
}
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
}
// VSM blur texture (if used)
@ -383946,8 +384059,6 @@ void shadowmap_end(shadowmap_t *s) {
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
}
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
// CSM blur texture (if used)
if (s->maps[i].blur_texture_2d != 0) {

View File

@ -5690,6 +5690,8 @@ struct nk_context {
#define NK_PI 3.141592654f
#define NK_UTF_INVALID 0xFFFD
#define NK_MAX_FLOAT_PRECISION 2
#define NK_MAX_FLOAT_PRECISION2 6
#define NK_FLOAT_DECIMAL_POS_THRESHOLD 0.0005
#define NK_UNUSED(x) ((void)(x))
#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
@ -28148,11 +28150,11 @@ nk_do_property(nk_flags *ws,
break;
case NK_PROPERTY_FLOAT:
NK_DTOA(string, (double)variant->value.f);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
case NK_PROPERTY_DOUBLE:
NK_DTOA(string, variant->value.d);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
}
size = font->width(font->userdata, font->height, string, num_len);
@ -28248,12 +28250,12 @@ nk_do_property(nk_flags *ws,
variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
break;
case NK_PROPERTY_FLOAT:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.f = nk_strtof(buffer, 0);
variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
break;
case NK_PROPERTY_DOUBLE:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.d = nk_strtod(buffer, 0);
variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
break;

View File

@ -1483,7 +1483,11 @@ light_t light() {
l.cast_shadows = true;
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
return l;
}
@ -1562,6 +1566,10 @@ void light_update(unsigned num_lights, light_t *lv) {
shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic);
shader_float(va("u_lights[%d].innerCone", i), lv[i].innerCone);
shader_float(va("u_lights[%d].outerCone", i), lv[i].outerCone);
shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias);
shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias);
shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance);
shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition);
shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows);
if (lv[i].processed_shadows) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
@ -1571,10 +1579,58 @@ void light_update(unsigned num_lights, light_t *lv) {
}
}
void ui_light(light_t *l) {
ui_int("Type", &l->type);
ui_vec3("Position", &l->pos);
ui_vec3("Direction", &l->dir);
ui_color3f("Diffuse", &l->diffuse.x);
ui_color3f("Specular", &l->specular.x);
ui_color3f("Ambient", &l->ambient.x);
ui_float("Specular Power", &l->specularPower);
ui_clampf("Radius", &l->radius, 0.0f, FLT_MAX);
ui_clampf_("Constant Falloff", &l->falloff.constant, 0.0, FLT_MAX, 0.005);
ui_clampf_("Linear Falloff", &l->falloff.linear, 0.0, FLT_MAX, 0.005);
ui_clampf_("Quadratic Falloff", &l->falloff.quadratic, 0.0, FLT_MAX, 0.005);
ui_float("Inner Cone", &l->innerCone);
ui_float("Outer Cone", &l->outerCone);
ui_float_("Shadow Bias", &l->shadow_bias, 0.00005);
ui_float_("Normal Bias", &l->normal_bias, 0.00005);
ui_float_("Min Variance", &l->min_variance, 0.00005);
ui_float_("Variance Transition", &l->variance_transition, 0.0005);
}
void ui_lights(unsigned num_lights, light_t *lights) {
for (unsigned i = 0; i < num_lights; ++i) {
if (ui_collapse(va("Light %d", i), va("light_%d", i))) {
ui_light(&lights[i]);
ui_collapse_end();
}
}
}
// -----------------------------------------------------------------------------
// shadowmaps
static inline
void shadowmap_init_common_resources(shadowmap_t *s, int vsm_texture_width, int csm_texture_width) {
// Create a cubemap depth texture
glGenTextures(1, &s->depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, vsm_texture_width, vsm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
// Create a 2D depth texture
glGenTextures(1, &s->depth_texture_2d);
glBindTexture(GL_TEXTURE_2D, s->depth_texture_2d);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, csm_texture_width, csm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
static inline void
shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
float borderColor[] = {1.0, 1.0, 1.0, 1.0};
@ -1598,19 +1654,6 @@ shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
// Create a cubemap depth texture
glGenTextures(1, &s->maps[light_index].depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->maps[light_index].depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@ -1632,15 +1675,6 @@ shadowmap_init_caster_csm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glGenTextures(1, &s->maps[light_index].depth_texture_2d[i]);
glBindTexture(GL_TEXTURE_2D, s->maps[light_index].depth_texture_2d[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
}
glBindTexture(GL_TEXTURE_2D, 0);
@ -1691,6 +1725,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
}
#endif
shadowmap_init_common_resources(&s, vsm_texture_width, csm_texture_width);
glBindFramebuffer(GL_FRAMEBUFFER, s.saved_fb);
return s;
}
@ -1704,20 +1740,12 @@ void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
glDeleteTextures(1, &s->maps[light_index].texture);
s->maps[light_index].texture = 0;
}
if (s->maps[light_index].depth_texture) {
glDeleteTextures(1, &s->maps[light_index].depth_texture);
s->maps[light_index].depth_texture = 0;
}
for (int i = 0; i < NUM_SHADOW_CASCADES; i++) {
if (s->maps[light_index].texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].texture_2d[i]);
s->maps[light_index].texture_2d[i] = 0;
}
if (s->maps[light_index].depth_texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].depth_texture_2d[i]);
s->maps[light_index].depth_texture_2d[i] = 0;
}
}
if (s->maps[light_index].blur_texture_2d) {
@ -1735,6 +1763,18 @@ void shadowmap_destroy(shadowmap_t *s) {
for (int i = 0; i < MAX_LIGHTS; i++) {
shadowmap_destroy_light(s, i);
}
if (s->depth_texture) {
glDeleteTextures(1, &s->depth_texture);
s->depth_texture = 0;
}
if (s->depth_texture_2d) {
glDeleteTextures(1, &s->depth_texture_2d);
s->depth_texture_2d = 0;
}
shadowmap_t z = {0};
*s = z;
}
@ -1762,7 +1802,7 @@ void shadowmap_begin(shadowmap_t *s) {
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) {
if(dir<0) return;
mat44 P, V, PV;
perspective44(P, 90.0f, 1.0f, l->shadow_bias, l->shadow_distance);
perspective44(P, 90.0f, 1.0f, l->shadow_near_clip, l->shadow_distance);
vec3 lightPos = l->pos;
/**/ if(dir == 0) lookat44(V, lightPos, add3(lightPos, vec3(+1, 0, 0)), vec3(0, -1, 0)); // +X
@ -1815,7 +1855,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo
float near_plane = 0.0f;
if (s->cascade_index == 0) {
near_plane = l->shadow_bias;
near_plane = l->shadow_near_clip;
far_plane = l->shadow_distance * s->cascade_splits[0];
} else if (s->cascade_index < NUM_SHADOW_CASCADES - 1) {
near_plane = l->shadow_distance * s->cascade_splits[s->cascade_index-1];
@ -2130,12 +2170,12 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
if (l->type == LIGHT_DIRECTIONAL) {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s->maps[s->light_step].texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->maps[s->light_step].depth_texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->depth_texture_2d, 0);
shadowmap_clear_fbo();
} else {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].depth_texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->depth_texture, 0);
shadowmap_clear_fbo();
}
@ -2157,19 +2197,25 @@ void shadowmap_end(shadowmap_t *s) {
{
const int faces = 6;
const int cascades = NUM_SHADOW_CASCADES;
// Depth textures
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
for (int i = 0; i < MAX_LIGHTS; i++) {
// VSM textures
if (s->maps[i].texture != 0) {
// Color texture (GL_RG32F)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
}
// Color texture (GL_RG32F)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
// Color texture (GL_RG32F)
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
@ -2182,20 +2228,13 @@ void shadowmap_end(shadowmap_t *s) {
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
}
}
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
}
// VSM blur texture (if used)
@ -2203,8 +2242,6 @@ void shadowmap_end(shadowmap_t *s) {
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
}
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
// CSM blur texture (if used)
if (s->maps[i].blur_texture_2d != 0) {

View File

@ -302,7 +302,7 @@ enum SHADOW_TECHNIQUE {
#define NUM_SHADOW_CASCADES 4
typedef struct light_t {
char type;
unsigned type;
vec3 diffuse, specular, ambient;
vec3 pos, dir;
struct {
@ -315,14 +315,18 @@ typedef struct light_t {
// Shadowmapping
bool cast_shadows;
bool processed_shadows;
unsigned shadow_technique;
float shadow_distance;
float shadow_bias;
float shadow_near_clip;
mat44 shadow_matrix[NUM_SHADOW_CASCADES];
float min_variance; //< VSM
float variance_transition; //< VSM
float shadow_bias; //< CSM
float normal_bias; //< CSM
// internals
bool cached; //< used by scene to invalidate cached light data
bool processed_shadows;
} light_t;
API light_t light();
@ -339,6 +343,10 @@ API void light_falloff(light_t* l, float constant, float linear, float quadra
API void light_cone(light_t* l, float innerCone, float outerCone);
API void light_update(unsigned num_lights, light_t *lv);
API void ui_light(light_t *l);
API void ui_lights(unsigned num_lights, light_t *lights);
// -----------------------------------------------------------------------------
// shadowmaps
@ -368,11 +376,15 @@ typedef struct shadowmap_t {
uint64_t vram_usage_vsm;
uint64_t vram_usage_csm;
// depth texture
handle depth_texture;
handle depth_texture_2d;
struct {
int gen;
unsigned shadow_technique;
handle texture, depth_texture;
handle texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle texture;
handle texture_2d[NUM_SHADOW_CASCADES];
handle blur_texture, blur_texture_2d;
// handle blur_fbo_cubemap, blur_texture_cubemap;
float cascade_distances[NUM_SHADOW_CASCADES];

View File

@ -2234,13 +2234,42 @@ int ui_short(const char *label, short *v) {
return *v = (short)i, ret;
}
int ui_float(const char *label, float *v) {
static inline
float ui_float_adjust_step(float step) {
if ((input(KEY_LSHIFT) || input(KEY_RSHIFT))&&(input(KEY_LCTRL) || input(KEY_RCTRL))) step *= 100.0f;
else if (input(KEY_LSHIFT) || input(KEY_RSHIFT)) step *= 10.0f;
else if (input(KEY_LCTRL) || input(KEY_RCTRL)) step *= 0.1f;
else if (input(KEY_LALT) || input(KEY_RALT)) step *= 0.01f;
return step;
}
int ui_float_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, 0.01f,0.005f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, step, inc_per_pixel);
return prev != v[0];
}
int ui_float(const char *label, float *v) {
return ui_float_(label, v, 0.01f);
}
int ui_double_(const char *label, double *v, double step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
double prev = v[0]; v[0] = nk_propertyd(ui_ctx, "#", -DBL_MAX, v[0], DBL_MAX, step, inc_per_pixel);
return prev != v[0];
}
@ -2254,21 +2283,30 @@ int ui_double(const char *label, double *v) {
return prev != v[0];
}
int ui_clampf(const char *label, float *v, float minf, float maxf) {
int ui_clampf_(const char *label, float *v, float minf, float maxf, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
if( minf > maxf ) return ui_clampf(label, v, maxf, minf);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, 0.1f,0.05f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, step, inc_per_pixel);
return prev != v[0];
}
int ui_float2(const char *label, float *v) {
int ui_clampf(const char *label, float *v, float minf, float maxf) {
return ui_clampf_(label, v, minf, maxf, 0.1f);
}
int ui_float2_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -2278,17 +2316,23 @@ int ui_float2(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1];
}
return 0;
}
int ui_float3(const char *label, float *v) {
int ui_float2(const char *label, float *v) {
return ui_float2_(label, v, 1.0f);
}
int ui_float3_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -2298,18 +2342,25 @@ int ui_float3(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2];
}
return 0;
}
int ui_float4(const char *label, float *v) {
int ui_float3(const char *label, float *v) {
return ui_float3_(label, v, 1.0f);
}
int ui_float4_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -2319,10 +2370,10 @@ int ui_float4(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2] || prev3 != v[3];
}
@ -2330,6 +2381,10 @@ int ui_float4(const char *label, float *v) {
return 0;
}
int ui_float4(const char *label, float *v) {
return ui_float4_(label, v, 1.0f);
}
int ui_mat33(const char *label, float M[9]) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;

View File

@ -19,6 +19,10 @@ API int ui_section(const char *title);
API int ui_int(const char *label, int *value);
API int ui_bool(const char *label, bool *value);
API int ui_short(const char *label, short *value);
API int ui_float_(const char *label, float *value, float step);
API int ui_float2_(const char *label, float value[2], float step);
API int ui_float3_(const char *label, float value[3], float step);
API int ui_float4_(const char *label, float value[4], float step);
API int ui_float(const char *label, float *value);
API int ui_float2(const char *label, float value[2]);
API int ui_float3(const char *label, float value[3]);
@ -55,6 +59,7 @@ API int ui_separator();
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, float step);
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);

View File

@ -209788,6 +209788,8 @@ struct nk_context {
#define NK_PI 3.141592654f
#define NK_UTF_INVALID 0xFFFD
#define NK_MAX_FLOAT_PRECISION 2
#define NK_MAX_FLOAT_PRECISION2 6
#define NK_FLOAT_DECIMAL_POS_THRESHOLD 0.0005
#define NK_UNUSED(x) ((void)(x))
#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
@ -232246,11 +232248,11 @@ nk_do_property(nk_flags *ws,
break;
case NK_PROPERTY_FLOAT:
NK_DTOA(string, (double)variant->value.f);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
case NK_PROPERTY_DOUBLE:
NK_DTOA(string, variant->value.d);
num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
num_len = nk_string_float_limit(string, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
break;
}
size = font->width(font->userdata, font->height, string, num_len);
@ -232346,12 +232348,12 @@ nk_do_property(nk_flags *ws,
variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
break;
case NK_PROPERTY_FLOAT:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.f = nk_strtof(buffer, 0);
variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
break;
case NK_PROPERTY_DOUBLE:
nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
nk_string_float_limit(buffer, variant->step.f <= NK_FLOAT_DECIMAL_POS_THRESHOLD ? NK_MAX_FLOAT_PRECISION2 : NK_MAX_FLOAT_PRECISION);
variant->value.d = nk_strtod(buffer, 0);
variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
break;

View File

@ -3442,13 +3442,42 @@ int ui_short(const char *label, short *v) {
return *v = (short)i, ret;
}
int ui_float(const char *label, float *v) {
static inline
float ui_float_adjust_step(float step) {
if ((input(KEY_LSHIFT) || input(KEY_RSHIFT))&&(input(KEY_LCTRL) || input(KEY_RCTRL))) step *= 100.0f;
else if (input(KEY_LSHIFT) || input(KEY_RSHIFT)) step *= 10.0f;
else if (input(KEY_LCTRL) || input(KEY_RCTRL)) step *= 0.1f;
else if (input(KEY_LALT) || input(KEY_RALT)) step *= 0.01f;
return step;
}
int ui_float_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, 0.01f,0.005f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", -FLT_MAX, v[0], FLT_MAX, step, inc_per_pixel);
return prev != v[0];
}
int ui_float(const char *label, float *v) {
return ui_float_(label, v, 0.01f);
}
int ui_double_(const char *label, double *v, double step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
double prev = v[0]; v[0] = nk_propertyd(ui_ctx, "#", -DBL_MAX, v[0], DBL_MAX, step, inc_per_pixel);
return prev != v[0];
}
@ -3462,21 +3491,30 @@ int ui_double(const char *label, double *v) {
return prev != v[0];
}
int ui_clampf(const char *label, float *v, float minf, float maxf) {
int ui_clampf_(const char *label, float *v, float minf, float maxf, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.005f);
step = ui_float_adjust_step(step);
if( minf > maxf ) return ui_clampf(label, v, maxf, minf);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, 0.1f,0.05f);
float prev = v[0]; v[0] = nk_propertyf(ui_ctx, "#", minf, v[0], maxf, step, inc_per_pixel);
return prev != v[0];
}
int ui_float2(const char *label, float *v) {
int ui_clampf(const char *label, float *v, float minf, float maxf) {
return ui_clampf_(label, v, minf, maxf, 0.1f);
}
int ui_float2_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -3486,17 +3524,23 @@ int ui_float2(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1];
}
return 0;
}
int ui_float3(const char *label, float *v) {
int ui_float2(const char *label, float *v) {
return ui_float2_(label, v, 1.0f);
}
int ui_float3_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -3506,18 +3550,25 @@ int ui_float3(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2];
}
return 0;
}
int ui_float4(const char *label, float *v) {
int ui_float3(const char *label, float *v) {
return ui_float3_(label, v, 1.0f);
}
int ui_float4_(const char *label, float *v, float step) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
float inc_per_pixel = ui_float_adjust_step(0.5f);
step = ui_float_adjust_step(step);
nk_layout_row_dynamic(ui_ctx, 0, 2);
ui_label_(label, NK_TEXT_LEFT);
@ -3527,10 +3578,10 @@ int ui_float4(const char *label, float *v) {
if (nk_combo_begin_label(ui_ctx, buffer, nk_vec2(200,200))) {
nk_layout_row_dynamic(ui_ctx, 0, 1);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, 1,0.5f);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, 1,0.5f);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, 1,0.5f);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, 1,0.5f);
float prev0 = v[0]; nk_property_float(ui_ctx, "#X:", -FLT_MAX, &v[0], FLT_MAX, step, inc_per_pixel);
float prev1 = v[1]; nk_property_float(ui_ctx, "#Y:", -FLT_MAX, &v[1], FLT_MAX, step, inc_per_pixel);
float prev2 = v[2]; nk_property_float(ui_ctx, "#Z:", -FLT_MAX, &v[2], FLT_MAX, step, inc_per_pixel);
float prev3 = v[3]; nk_property_float(ui_ctx, "#W:", -FLT_MAX, &v[3], FLT_MAX, step, inc_per_pixel);
nk_combo_end(ui_ctx);
return prev0 != v[0] || prev1 != v[1] || prev2 != v[2] || prev3 != v[3];
}
@ -3538,6 +3589,10 @@ int ui_float4(const char *label, float *v) {
return 0;
}
int ui_float4(const char *label, float *v) {
return ui_float4_(label, v, 1.0f);
}
int ui_mat33(const char *label, float M[9]) {
if( label && ui_filter && ui_filter[0] ) if( !strstri(label, ui_filter) ) return 0;
@ -18282,7 +18337,11 @@ light_t light() {
l.cast_shadows = true;
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_bias = 0.01f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
return l;
}
@ -18361,6 +18420,10 @@ void light_update(unsigned num_lights, light_t *lv) {
shader_float(va("u_lights[%d].quadratic", i), lv[i].falloff.quadratic);
shader_float(va("u_lights[%d].innerCone", i), lv[i].innerCone);
shader_float(va("u_lights[%d].outerCone", i), lv[i].outerCone);
shader_float(va("u_lights[%d].shadow_bias", i), lv[i].shadow_bias);
shader_float(va("u_lights[%d].normal_bias", i), lv[i].normal_bias);
shader_float(va("u_lights[%d].min_variance", i), lv[i].min_variance);
shader_float(va("u_lights[%d].variance_transition", i), lv[i].variance_transition);
shader_bool(va("u_lights[%d].processed_shadows", i), lv[i].processed_shadows);
if (lv[i].processed_shadows) {
for (int j = 0; j < NUM_SHADOW_CASCADES; j++) {
@ -18370,10 +18433,58 @@ void light_update(unsigned num_lights, light_t *lv) {
}
}
void ui_light(light_t *l) {
ui_int("Type", &l->type);
ui_vec3("Position", &l->pos);
ui_vec3("Direction", &l->dir);
ui_color3f("Diffuse", &l->diffuse.x);
ui_color3f("Specular", &l->specular.x);
ui_color3f("Ambient", &l->ambient.x);
ui_float("Specular Power", &l->specularPower);
ui_clampf("Radius", &l->radius, 0.0f, FLT_MAX);
ui_clampf_("Constant Falloff", &l->falloff.constant, 0.0, FLT_MAX, 0.005);
ui_clampf_("Linear Falloff", &l->falloff.linear, 0.0, FLT_MAX, 0.005);
ui_clampf_("Quadratic Falloff", &l->falloff.quadratic, 0.0, FLT_MAX, 0.005);
ui_float("Inner Cone", &l->innerCone);
ui_float("Outer Cone", &l->outerCone);
ui_float_("Shadow Bias", &l->shadow_bias, 0.00005);
ui_float_("Normal Bias", &l->normal_bias, 0.00005);
ui_float_("Min Variance", &l->min_variance, 0.00005);
ui_float_("Variance Transition", &l->variance_transition, 0.0005);
}
void ui_lights(unsigned num_lights, light_t *lights) {
for (unsigned i = 0; i < num_lights; ++i) {
if (ui_collapse(va("Light %d", i), va("light_%d", i))) {
ui_light(&lights[i]);
ui_collapse_end();
}
}
}
// -----------------------------------------------------------------------------
// shadowmaps
static inline
void shadowmap_init_common_resources(shadowmap_t *s, int vsm_texture_width, int csm_texture_width) {
// Create a cubemap depth texture
glGenTextures(1, &s->depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, vsm_texture_width, vsm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
// Create a 2D depth texture
glGenTextures(1, &s->depth_texture_2d);
glBindTexture(GL_TEXTURE_2D, s->depth_texture_2d);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, csm_texture_width, csm_texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}
static inline void
shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
float borderColor[] = {1.0, 1.0, 1.0, 1.0};
@ -18397,19 +18508,6 @@ shadowmap_init_caster_vsm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
// Create a cubemap depth texture
glGenTextures(1, &s->maps[light_index].depth_texture);
glBindTexture(GL_TEXTURE_CUBE_MAP, s->maps[light_index].depth_texture);
for (int i = 0; i < 6; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BORDER_COLOR, borderColor);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
@ -18431,15 +18529,6 @@ shadowmap_init_caster_csm(shadowmap_t *s, int light_index, int texture_width) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
glGenTextures(1, &s->maps[light_index].depth_texture_2d[i]);
glBindTexture(GL_TEXTURE_2D, s->maps[light_index].depth_texture_2d[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, texture_width, texture_width, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
}
glBindTexture(GL_TEXTURE_2D, 0);
@ -18490,6 +18579,8 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
}
#endif
shadowmap_init_common_resources(&s, vsm_texture_width, csm_texture_width);
glBindFramebuffer(GL_FRAMEBUFFER, s.saved_fb);
return s;
}
@ -18503,20 +18594,12 @@ void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
glDeleteTextures(1, &s->maps[light_index].texture);
s->maps[light_index].texture = 0;
}
if (s->maps[light_index].depth_texture) {
glDeleteTextures(1, &s->maps[light_index].depth_texture);
s->maps[light_index].depth_texture = 0;
}
for (int i = 0; i < NUM_SHADOW_CASCADES; i++) {
if (s->maps[light_index].texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].texture_2d[i]);
s->maps[light_index].texture_2d[i] = 0;
}
if (s->maps[light_index].depth_texture_2d[i]) {
glDeleteTextures(1, &s->maps[light_index].depth_texture_2d[i]);
s->maps[light_index].depth_texture_2d[i] = 0;
}
}
if (s->maps[light_index].blur_texture_2d) {
@ -18534,6 +18617,18 @@ void shadowmap_destroy(shadowmap_t *s) {
for (int i = 0; i < MAX_LIGHTS; i++) {
shadowmap_destroy_light(s, i);
}
if (s->depth_texture) {
glDeleteTextures(1, &s->depth_texture);
s->depth_texture = 0;
}
if (s->depth_texture_2d) {
glDeleteTextures(1, &s->depth_texture_2d);
s->depth_texture_2d = 0;
}
shadowmap_t z = {0};
*s = z;
}
@ -18561,7 +18656,7 @@ void shadowmap_begin(shadowmap_t *s) {
static void shadowmap_light_point(shadowmap_t *s, light_t *l, int dir) {
if(dir<0) return;
mat44 P, V, PV;
perspective44(P, 90.0f, 1.0f, l->shadow_bias, l->shadow_distance);
perspective44(P, 90.0f, 1.0f, l->shadow_near_clip, l->shadow_distance);
vec3 lightPos = l->pos;
/**/ if(dir == 0) lookat44(V, lightPos, add3(lightPos, vec3(+1, 0, 0)), vec3(0, -1, 0)); // +X
@ -18614,7 +18709,7 @@ static void shadowmap_light_directional(shadowmap_t *s, light_t *l, int dir, flo
float near_plane = 0.0f;
if (s->cascade_index == 0) {
near_plane = l->shadow_bias;
near_plane = l->shadow_near_clip;
far_plane = l->shadow_distance * s->cascade_splits[0];
} else if (s->cascade_index < NUM_SHADOW_CASCADES - 1) {
near_plane = l->shadow_distance * s->cascade_splits[s->cascade_index-1];
@ -18929,12 +19024,12 @@ void shadowmap_light(shadowmap_t *s, light_t *l, mat44 cam_proj, mat44 cam_view)
if (l->type == LIGHT_DIRECTIONAL) {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s->maps[s->light_step].texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->maps[s->light_step].depth_texture_2d[s->cascade_index], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, s->depth_texture_2d, 0);
shadowmap_clear_fbo();
} else {
glBindFramebuffer(GL_FRAMEBUFFER, s->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->maps[s->light_step].depth_texture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + step, s->depth_texture, 0);
shadowmap_clear_fbo();
}
@ -18956,19 +19051,25 @@ void shadowmap_end(shadowmap_t *s) {
{
const int faces = 6;
const int cascades = NUM_SHADOW_CASCADES;
// Depth textures
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
for (int i = 0; i < MAX_LIGHTS; i++) {
// VSM textures
if (s->maps[i].texture != 0) {
// Color texture (GL_RG32F)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
}
// Color texture (GL_RG32F)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 1;
// Color texture (GL_RG32F)
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // 8 bytes per pixel (2 * 32-bit float)
@ -18981,20 +19082,13 @@ void shadowmap_end(shadowmap_t *s) {
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage += s->csm_texture_width * s->csm_texture_width * 1;
}
}
for (int j = 0; j < cascades; j++) {
// Color texture (GL_R32F)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_total += s->csm_texture_width * s->csm_texture_width * 1;
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 4; // 4 bytes per pixel (1 * 32-bit float)
// Depth texture (GL_DEPTH_COMPONENT, assuming 8-bit depth)
s->vram_usage_csm += s->csm_texture_width * s->csm_texture_width * 1;
}
// VSM blur texture (if used)
@ -19002,8 +19096,6 @@ void shadowmap_end(shadowmap_t *s) {
s->vram_usage += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
}
s->vram_usage_total += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
s->vram_usage_vsm += s->vsm_texture_width * s->vsm_texture_width * faces * 8; // Assuming same format as VSM color texture
// CSM blur texture (if used)
if (s->maps[i].blur_texture_2d != 0) {

View File

@ -3337,7 +3337,7 @@ enum SHADOW_TECHNIQUE {
#define NUM_SHADOW_CASCADES 4
typedef struct light_t {
char type;
unsigned type;
vec3 diffuse, specular, ambient;
vec3 pos, dir;
struct {
@ -3350,14 +3350,18 @@ typedef struct light_t {
// Shadowmapping
bool cast_shadows;
bool processed_shadows;
unsigned shadow_technique;
float shadow_distance;
float shadow_bias;
float shadow_near_clip;
mat44 shadow_matrix[NUM_SHADOW_CASCADES];
float min_variance; //< VSM
float variance_transition; //< VSM
float shadow_bias; //< CSM
float normal_bias; //< CSM
// internals
bool cached; //< used by scene to invalidate cached light data
bool processed_shadows;
} light_t;
API light_t light();
@ -3374,6 +3378,10 @@ API void light_falloff(light_t* l, float constant, float linear, float quadra
API void light_cone(light_t* l, float innerCone, float outerCone);
API void light_update(unsigned num_lights, light_t *lv);
API void ui_light(light_t *l);
API void ui_lights(unsigned num_lights, light_t *lights);
// -----------------------------------------------------------------------------
// shadowmaps
@ -3403,11 +3411,15 @@ typedef struct shadowmap_t {
uint64_t vram_usage_vsm;
uint64_t vram_usage_csm;
// depth texture
handle depth_texture;
handle depth_texture_2d;
struct {
int gen;
unsigned shadow_technique;
handle texture, depth_texture;
handle texture_2d[NUM_SHADOW_CASCADES], depth_texture_2d[NUM_SHADOW_CASCADES];
handle texture;
handle texture_2d[NUM_SHADOW_CASCADES];
handle blur_texture, blur_texture_2d;
// handle blur_fbo_cubemap, blur_texture_cubemap;
float cascade_distances[NUM_SHADOW_CASCADES];
@ -4766,6 +4778,10 @@ API int ui_section(const char *title);
API int ui_int(const char *label, int *value);
API int ui_bool(const char *label, bool *value);
API int ui_short(const char *label, short *value);
API int ui_float_(const char *label, float *value, float step);
API int ui_float2_(const char *label, float value[2], float step);
API int ui_float3_(const char *label, float value[3], float step);
API int ui_float4_(const char *label, float value[4], float step);
API int ui_float(const char *label, float *value);
API int ui_float2(const char *label, float value[2]);
API int ui_float3(const char *label, float value[3]);
@ -4802,6 +4818,7 @@ API int ui_separator();
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, float step);
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);