improve pcf shadows substantially

main
Dominik Madarász 2024-09-02 13:10:35 +02:00
parent ccd9702a26
commit 82ec9fc3be
18 changed files with 53352 additions and 1055 deletions

View File

@ -1206,6 +1206,9 @@ typedef struct shadowmap_t {
uint64_t vram_usage_csm;
handle depth_texture;
handle depth_texture_2d;
int filter_size, window_size;
float offset_radius;
handle offsets_texture;
struct {
int gen;
unsigned shadow_technique;
@ -1218,8 +1221,11 @@ typedef struct shadowmap_t {
handle saved_pass;
int saved_vp[4];
int gen;
int old_filter_size;
int old_window_size;
} shadowmap_t;
shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width);
void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size);
void shadowmap_destroy(shadowmap_t *s);
void shadowmap_begin(shadowmap_t *s);
bool shadowmap_step(shadowmap_t *s);

View File

@ -90,7 +90,7 @@ int main(int argc, char** argv) {
if( !initialized ) {
initialized = 1;
sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0);
sm = shadowmap(512, 4096);
sm = shadowmap(512, 2048);
// sm.blur_pcf = 1;
// sm.blur_scale
mdl = model(OBJ_MDLS[OBJ_MDL], 0);
@ -111,12 +111,14 @@ int main(int argc, char** argv) {
enum {
POINT, SPOT, DIR, ALL
};
static unsigned mode = ALL;
static unsigned mode = DIR;
if (input_down(KEY_1)) mode = POINT;
if (input_down(KEY_2)) mode = SPOT;
if (input_down(KEY_3)) mode = DIR;
if (input_down(KEY_4)) mode = ALL;
if (active) {
if (input_down(KEY_1)) mode = POINT;
if (input_down(KEY_2)) mode = SPOT;
if (input_down(KEY_3)) mode = DIR;
if (input_down(KEY_4)) mode = ALL;
}
light_t *lights = 0;
switch (mode) {
case POINT: lights = point_lights; break;

16
demos/99-objtest.c 100644
View File

@ -0,0 +1,16 @@
#include "v4k.h" // Minimal C sample
void game(unsigned frame, float dt, double t) {
}
int main() {
window_create(75.0, 0); // 75% size, no extra flags
window_swap();
while( window_swap() ) {
editor_frame(game);
}
}

View File

@ -1,6 +1,16 @@
# Blender 4.2.1 LTS MTL File: 'None'
# www.blender.org
newmtl DefaultMaterial
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.081348 0.800323 0.061622
Ks 0.500000 0.500000 0.500000
Ke 0.000000 0.000000 0.000000
Ni 1.500000
d 1.000000
illum 2
newmtl floor
Ns 10.000005
Ka 1.000000 1.000000 1.000000

File diff suppressed because it is too large Load Diff

2
depot

@ -1 +1 @@
Subproject commit bb66860b116accac3c50e06e7c927bad2529ab01
Subproject commit 26a37542d2f24e639559af49c48b2d3eb4da42fb

View File

@ -7,9 +7,14 @@ uniform bool u_shadow_receiver;
uniform float u_cascade_distances[MAX_LIGHTS * NUM_SHADOW_CASCADES];
uniform samplerCube shadowMap[MAX_LIGHTS];
uniform sampler2D shadowMap2D[MAX_LIGHTS * NUM_SHADOW_CASCADES];
uniform sampler3D shadow_offsets;
uniform int shadow_filter_size;
uniform int shadow_window_size;
uniform float shadow_offset_radius;
// const float bias_modifier[NUM_SHADOW_CASCADES] = float[NUM_SHADOW_CASCADES](0.95, 0.35, 0.20, 0.1, 0.1, 0.1);
const float bias_modifier[NUM_SHADOW_CASCADES] = float[NUM_SHADOW_CASCADES](0.95, 0.35, 0.20, 0.15);
const float bias_modifier[NUM_SHADOW_CASCADES] = float[NUM_SHADOW_CASCADES](1.0, 6.0, 9.0, 16.0);
// 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 min_variance, float variance_transition) {
@ -85,6 +90,7 @@ float shadow_csm(float distance, vec3 lightDir, int light_index, float shadow_bi
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
vec4 sc = vec4(projCoords, 1.0);
float currentDepth = projCoords.z;
@ -94,35 +100,50 @@ float shadow_csm(float distance, vec3 lightDir, int light_index, float shadow_bi
// Calculate bias
vec3 normal = normalize(vneye.xyz);
float bias = max(normal_bias * (1.0 - dot(normal, lightDir)), shadow_bias);
bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[matrix_index]);
float bias = max(normal_bias * bias_modifier[matrix_index] * (1.0 - dot(normal, lightDir)), shadow_bias);
bias *= 1 / (u_cascade_distances[cascade_index]);
// CSM
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap2D[cascade_index], 0);
#if 1
for(int x = -3; x <= 3; ++x)
{
for(int y = -3; y <= 3; ++y)
{
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;
}
// Get the offset coordinates
ivec3 ofs_coord = ivec3(0);
vec2 ofs = mod(gl_FragCoord.xy, vec2(shadow_window_size));
ofs_coord.yz = ivec2(ofs);
float ofs_sum = 0.0;
int samples_div2 = int(shadow_filter_size * shadow_filter_size / 2.0);
for (int i = 0; i < 4; i++) {
ofs_coord.x = i;
vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_offset_radius;
sc.xy = projCoords.xy + offsets.rg * texelSize;
float csmDepth = texture(shadowMap2D[cascade_index], sc.xy).r;
ofs_sum += currentDepth - bias > csmDepth ? 1.0 : 0.0;
sc.xy = projCoords.xy + offsets.ba * texelSize;
csmDepth = texture(shadowMap2D[cascade_index], sc.xy).r;
ofs_sum += currentDepth - bias > csmDepth ? 1.0 : 0.0;
}
shadow /= 36.0;
#else
for(int x = -1; x <= 1; ++x)
{
for(int y = -1; y <= 1; ++y)
{
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;
float shadow_sum = ofs_sum / 8.0;
if (shadow_sum != 0.0 && shadow_sum != 1.0) {
for (int i = 4; i < samples_div2; i++) {
ofs_coord.x = i;
vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_offset_radius;
sc.xy = projCoords.xy + offsets.rg * texelSize;
float csmDepth = texture(shadowMap2D[cascade_index], sc.xy).r;
ofs_sum += currentDepth - bias > csmDepth ? 1.0 : 0.0;
sc.xy = projCoords.xy + offsets.ba * texelSize;
csmDepth = texture(shadowMap2D[cascade_index], sc.xy).r;
ofs_sum += currentDepth - bias > csmDepth ? 1.0 : 0.0;
}
shadow_sum = ofs_sum / (samples_div2 * 2.0);
}
shadow /= 9.0;
#endif
return 1.0 - shadow;
return 1.0 - shadow_sum;
}
vec4 shadowmap(int idx, in vec4 peye, in vec4 neye) {

View File

@ -17348,6 +17348,11 @@ typedef struct shadowmap_t {
handle depth_texture;
handle depth_texture_2d;
// shadowmap offsets texture;
int filter_size, window_size;
float offset_radius;
handle offsets_texture;
struct {
int gen;
unsigned shadow_technique;
@ -17362,10 +17367,13 @@ typedef struct shadowmap_t {
handle saved_pass;
int saved_vp[4];
int gen;
int old_filter_size;
int old_window_size;
} shadowmap_t;
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size);
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
@ -383301,7 +383309,7 @@ light_t light() {
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.shadow_bias = 0.15f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
@ -383516,6 +383524,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
s.blur_vsm = false;
s.csm_blur_scale = 0.5f;
s.vsm_blur_scale = 0.75f;
s.filter_size = 8;
s.window_size = 10;
s.offset_radius = 7.0f;
#if 0
s.cascade_splits[0] = 0.1f;
s.cascade_splits[1] = 0.3f;
@ -383552,6 +383563,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
return s;
}
static inline
float shadowmap_offsets_build_jitter() {
return (randf() - 0.5f);
}
static inline
float *shadowmap_offsets_build_data(int filter_size, int window_size) {
int bufsize = filter_size * filter_size * window_size * window_size * 2;
float *data = MALLOC(bufsize * sizeof(float));
int index = 0;
for (int y = 0; y < window_size; y++) {
for (int x = 0; x < window_size; x++) {
for (int v = filter_size-1; v >= 0; v--) {
for (int u = 0; u < filter_size; u++) {
float x = ((float)(u + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
float y = ((float)(v + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
ASSERT(index + 1 < bufsize);
data[index+0] = sqrtf(y) * cosf(2 * M_PI * x);
data[index+1] = sqrtf(y) * sinf(2 * M_PI * x);
index += 2;
}
}
}
}
return data;
}
void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size) {
s->filter_size = filter_size;
s->window_size = window_size;
int num_samples = filter_size * filter_size;
float *data = shadowmap_offsets_build_data(filter_size, window_size);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &s->offsets_texture);
glBindTexture(GL_TEXTURE_3D, s->offsets_texture);
glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA32F, num_samples / 2, window_size, window_size);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, num_samples / 2, window_size, window_size, GL_RGBA, GL_FLOAT, data);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_3D, 0);
FREE(data);
}
static inline
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
s->maps[light_index].gen = 0;
@ -383612,6 +383671,12 @@ void shadowmap_begin(shadowmap_t *s) {
}
}
if (s->filter_size != s->old_filter_size || s->window_size != s->old_window_size) {
shadowmap_offsets_build(s, s->filter_size, s->window_size);
s->old_filter_size = s->filter_size;
s->old_window_size = s->window_size;
}
s->step = 0;
s->light_step = 0;
s->cascade_index = 0;
@ -384053,6 +384118,13 @@ void ui_shadowmap(shadowmap_t *s) {
ui_int("Texture Width (VSM)", &vsm_width);
ui_int("Texture Width (CSM)", &csm_width);
if (ui_collapse("Shadowmap Offsets", "shadowmap_offsets")) {
ui_int("Filter Size", &s->filter_size);
ui_int("Window Size", &s->window_size);
ui_float("Random Radius", &s->offset_radius);
ui_collapse_end();
}
if (ui_collapse("VRAM Usage", "vram_usage")) {
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 1024));
@ -386247,6 +386319,15 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]);
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, m.shadow_map->offsets_texture);
shader_int("shadow_filter_size", m.shadow_map->filter_size);
shader_int("shadow_window_size", m.shadow_map->window_size);
shader_float("shadow_offset_radius", m.shadow_map->offset_radius);
}
}
else if (m.shadow_map == NULL || !m.shadow_receiver) {
for (int i = 0; i < MAX_LIGHTS; i++) {
@ -386255,6 +386336,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, 0);
}
shader_bool("u_shadow_receiver", GL_FALSE);
}
}

View File

@ -1484,7 +1484,7 @@ light_t light() {
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.shadow_bias = 0.15f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
@ -1699,6 +1699,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
s.blur_vsm = false;
s.csm_blur_scale = 0.5f;
s.vsm_blur_scale = 0.75f;
s.filter_size = 8;
s.window_size = 10;
s.offset_radius = 7.0f;
#if 0
s.cascade_splits[0] = 0.1f;
s.cascade_splits[1] = 0.3f;
@ -1735,6 +1738,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
return s;
}
static inline
float shadowmap_offsets_build_jitter() {
return (randf() - 0.5f);
}
static inline
float *shadowmap_offsets_build_data(int filter_size, int window_size) {
int bufsize = filter_size * filter_size * window_size * window_size * 2;
float *data = MALLOC(bufsize * sizeof(float));
int index = 0;
for (int y = 0; y < window_size; y++) {
for (int x = 0; x < window_size; x++) {
for (int v = filter_size-1; v >= 0; v--) {
for (int u = 0; u < filter_size; u++) {
float x = ((float)(u + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
float y = ((float)(v + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
ASSERT(index + 1 < bufsize);
data[index+0] = sqrtf(y) * cosf(2 * M_PI * x);
data[index+1] = sqrtf(y) * sinf(2 * M_PI * x);
index += 2;
}
}
}
}
return data;
}
void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size) {
s->filter_size = filter_size;
s->window_size = window_size;
int num_samples = filter_size * filter_size;
float *data = shadowmap_offsets_build_data(filter_size, window_size);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &s->offsets_texture);
glBindTexture(GL_TEXTURE_3D, s->offsets_texture);
glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA32F, num_samples / 2, window_size, window_size);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, num_samples / 2, window_size, window_size, GL_RGBA, GL_FLOAT, data);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_3D, 0);
FREE(data);
}
static inline
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
s->maps[light_index].gen = 0;
@ -1795,6 +1846,12 @@ void shadowmap_begin(shadowmap_t *s) {
}
}
if (s->filter_size != s->old_filter_size || s->window_size != s->old_window_size) {
shadowmap_offsets_build(s, s->filter_size, s->window_size);
s->old_filter_size = s->filter_size;
s->old_window_size = s->window_size;
}
s->step = 0;
s->light_step = 0;
s->cascade_index = 0;
@ -2236,6 +2293,13 @@ void ui_shadowmap(shadowmap_t *s) {
ui_int("Texture Width (VSM)", &vsm_width);
ui_int("Texture Width (CSM)", &csm_width);
if (ui_collapse("Shadowmap Offsets", "shadowmap_offsets")) {
ui_int("Filter Size", &s->filter_size);
ui_int("Window Size", &s->window_size);
ui_float("Random Radius", &s->offset_radius);
ui_collapse_end();
}
if (ui_collapse("VRAM Usage", "vram_usage")) {
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 1024));
@ -4430,6 +4494,15 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]);
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, m.shadow_map->offsets_texture);
shader_int("shadow_filter_size", m.shadow_map->filter_size);
shader_int("shadow_window_size", m.shadow_map->window_size);
shader_float("shadow_offset_radius", m.shadow_map->offset_radius);
}
}
else if (m.shadow_map == NULL || !m.shadow_receiver) {
for (int i = 0; i < MAX_LIGHTS; i++) {
@ -4438,6 +4511,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, 0);
}
shader_bool("u_shadow_receiver", GL_FALSE);
}
}

View File

@ -380,6 +380,11 @@ typedef struct shadowmap_t {
handle depth_texture;
handle depth_texture_2d;
// shadowmap offsets texture;
int filter_size, window_size;
float offset_radius;
handle offsets_texture;
struct {
int gen;
unsigned shadow_technique;
@ -394,10 +399,13 @@ typedef struct shadowmap_t {
handle saved_pass;
int saved_vp[4];
int gen;
int old_filter_size;
int old_window_size;
} shadowmap_t;
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size);
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false

View File

@ -18338,7 +18338,7 @@ light_t light() {
l.processed_shadows = false;
l.shadow_distance = 200.0f;
l.shadow_near_clip = 0.01f;
l.shadow_bias = 0.005f;
l.shadow_bias = 0.15f;
l.normal_bias = 0.05f;
l.min_variance = 0.00002f;
l.variance_transition = 0.2f;
@ -18553,6 +18553,9 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
s.blur_vsm = false;
s.csm_blur_scale = 0.5f;
s.vsm_blur_scale = 0.75f;
s.filter_size = 8;
s.window_size = 10;
s.offset_radius = 7.0f;
#if 0
s.cascade_splits[0] = 0.1f;
s.cascade_splits[1] = 0.3f;
@ -18589,6 +18592,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
return s;
}
static inline
float shadowmap_offsets_build_jitter() {
return (randf() - 0.5f);
}
static inline
float *shadowmap_offsets_build_data(int filter_size, int window_size) {
int bufsize = filter_size * filter_size * window_size * window_size * 2;
float *data = MALLOC(bufsize * sizeof(float));
int index = 0;
for (int y = 0; y < window_size; y++) {
for (int x = 0; x < window_size; x++) {
for (int v = filter_size-1; v >= 0; v--) {
for (int u = 0; u < filter_size; u++) {
float x = ((float)(u + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
float y = ((float)(v + 0.5f + shadowmap_offsets_build_jitter()) / (float)filter_size);
ASSERT(index + 1 < bufsize);
data[index+0] = sqrtf(y) * cosf(2 * M_PI * x);
data[index+1] = sqrtf(y) * sinf(2 * M_PI * x);
index += 2;
}
}
}
}
return data;
}
void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size) {
s->filter_size = filter_size;
s->window_size = window_size;
int num_samples = filter_size * filter_size;
float *data = shadowmap_offsets_build_data(filter_size, window_size);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &s->offsets_texture);
glBindTexture(GL_TEXTURE_3D, s->offsets_texture);
glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA32F, num_samples / 2, window_size, window_size);
glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, num_samples / 2, window_size, window_size, GL_RGBA, GL_FLOAT, data);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_3D, 0);
FREE(data);
}
static inline
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
s->maps[light_index].gen = 0;
@ -18649,6 +18700,12 @@ void shadowmap_begin(shadowmap_t *s) {
}
}
if (s->filter_size != s->old_filter_size || s->window_size != s->old_window_size) {
shadowmap_offsets_build(s, s->filter_size, s->window_size);
s->old_filter_size = s->filter_size;
s->old_window_size = s->window_size;
}
s->step = 0;
s->light_step = 0;
s->cascade_index = 0;
@ -19090,6 +19147,13 @@ void ui_shadowmap(shadowmap_t *s) {
ui_int("Texture Width (VSM)", &vsm_width);
ui_int("Texture Width (CSM)", &csm_width);
if (ui_collapse("Shadowmap Offsets", "shadowmap_offsets")) {
ui_int("Filter Size", &s->filter_size);
ui_int("Window Size", &s->window_size);
ui_float("Random Radius", &s->offset_radius);
ui_collapse_end();
}
if (ui_collapse("VRAM Usage", "vram_usage")) {
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 1024));
@ -21284,6 +21348,15 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_float(va("u_cascade_distances[%d]", i * NUM_SHADOW_CASCADES + j), m.shadow_map->maps[i].cascade_distances[j]);
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, m.shadow_map->offsets_texture);
shader_int("shadow_filter_size", m.shadow_map->filter_size);
shader_int("shadow_window_size", m.shadow_map->window_size);
shader_float("shadow_offset_radius", m.shadow_map->offset_radius);
}
}
else if (m.shadow_map == NULL || !m.shadow_receiver) {
for (int i = 0; i < MAX_LIGHTS; i++) {
@ -21292,6 +21365,13 @@ void model_set_uniforms(model_t m, int shader, mat44 mv, mat44 proj, mat44 view,
shader_texture_unit(va("shadowMap2D[%d]", i * NUM_SHADOW_CASCADES + j), 0, texture_unit());
}
}
{
int unit = texture_unit();
shader_int("shadow_offsets", unit);
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(GL_TEXTURE_3D, 0);
}
shader_bool("u_shadow_receiver", GL_FALSE);
}
}

View File

@ -3415,6 +3415,11 @@ typedef struct shadowmap_t {
handle depth_texture;
handle depth_texture_2d;
// shadowmap offsets texture;
int filter_size, window_size;
float offset_radius;
handle offsets_texture;
struct {
int gen;
unsigned shadow_technique;
@ -3429,10 +3434,13 @@ typedef struct shadowmap_t {
handle saved_pass;
int saved_vp[4];
int gen;
int old_filter_size;
int old_window_size;
} shadowmap_t;
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_offsets_build(shadowmap_t *s, int filter_size, int window_size);
API void shadowmap_destroy(shadowmap_t *s);
API void shadowmap_begin(shadowmap_t *s);
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false

View File

@ -1551,6 +1551,19 @@ flags |= (doflipUV ? aiProcess_FlipUVs : 0);
file = stdout;
}
// Iterate through lights
for (int i = 0; i < scene->mNumLights; i++) {
const struct aiLight* light = scene->mLights[i];
printf("Light %u:\n", i);
printf(" Name: %s\n", light->mName.data);
printf(" Type: %d\n", light->mType);
printf(" Position: %f, %f, %f\n", light->mPosition.x, light->mPosition.y, light->mPosition.z);
printf(" Direction: %f, %f, %f\n", light->mDirection.x, light->mDirection.y, light->mDirection.z);
printf(" Color: %f, %f, %f\n", light->mColorDiffuse.r, light->mColorDiffuse.g, light->mColorDiffuse.b);
// Add more properties as needed
}
fprintf(file, "# Inter-Quake Export\n");
if (dobone) {

Binary file not shown.

View File

@ -39,7 +39,7 @@ icon=ico
image=jpg,jpeg,png,bmp,psd,pic,pnm,hdr
texture=pvr,ktx,ktx2,dds,astc,basis,tga
anim=fbx
model=iqm,iqe,gltf,gltf2,glb,fbx,obj,dae,blend,md3,md5,ms3d,smd,x,3ds,bvh,dxf,lwo
model=iqm,iqe,gltf,gltf2,glb,fbx,obj,dae,usdc,md3,md5,ms3d,smd,x,3ds,bvh,dxf,lwo
audio=wav,flac,ogg,mp1,mp3,mid,sfxr ; ,mod,xm
audio-module=mod,xm,s3m,it
audio-furnace=fur

View File

@ -38,7 +38,7 @@ ART=../engine/art,../demos/html5/art ; comma-separated folder(s) that
font=ttf,ttc,otf
text=json,xml,csv,ini,cfg,doc,txt,md,c,h,inl,cpp,hpp,htm,html
shader=hlsl,fx,dxil,dxbc,glsl,vert,frag,geom,tese,tesc,comp,vs,fs,gs,ts,cs,spirv,spv,slang
model=iqm,iqe,gltf,gltf2,glb,fbx,obj,dae,blend,md3,md5,ms3d,smd,x,3ds,bvh,dxf,lwo
model=iqm,iqe,gltf,gltf2,glb,fbx,obj,dae,usdc,md3,md5,ms3d,smd,x,3ds,bvh,dxf,lwo
texture=pvr,ktx,ktx2,dds,astc,basis,tga
; ------------------------------------------------------------------------------

Binary file not shown.

View File

@ -1,30 +0,0 @@
[Outliner]
x=-0.000000
y=0.052117
w=0.292969
h=0.946206
visible=1
[Properties]
x=0.723415
y=0.052117
w=0.276585
h=0.946236
visible=1
[Scene 󰙅]
x=0.000000
y=0.052117
w=0.209707
h=0.946108
visible=0
[Nodes 󱁉]
x=0.000916
y=0.053746
w=0.999084
h=0.944625
visible=0
[Script 󰯂]
x=0.212454
y=0.052117
w=0.787546
h=0.946100
visible=0