improve pcf shadows substantially
parent
ccd9702a26
commit
82ec9fc3be
|
@ -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);
|
||||
|
|
|
@ -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 (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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
2
depot
|
@ -1 +1 @@
|
|||
Subproject commit bb66860b116accac3c50e06e7c927bad2529ab01
|
||||
Subproject commit 26a37542d2f24e639559af49c48b2d3eb4da42fb
|
|
@ -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;
|
||||
}
|
||||
|
||||
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 /= 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;
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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,9 +17367,12 @@ 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_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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,9 +399,12 @@ 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_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);
|
||||
|
|
82
engine/v4k.c
82
engine/v4k.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,9 +3434,12 @@ 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_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);
|
||||
|
|
|
@ -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.
|
@ -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
|
||||
|
|
|
@ -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.
|
@ -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
|
Loading…
Reference in New Issue