improve pcf shadows substantially
parent
ccd9702a26
commit
82ec9fc3be
|
@ -1206,6 +1206,9 @@ typedef struct shadowmap_t {
|
||||||
uint64_t vram_usage_csm;
|
uint64_t vram_usage_csm;
|
||||||
handle depth_texture;
|
handle depth_texture;
|
||||||
handle depth_texture_2d;
|
handle depth_texture_2d;
|
||||||
|
int filter_size, window_size;
|
||||||
|
float offset_radius;
|
||||||
|
handle offsets_texture;
|
||||||
struct {
|
struct {
|
||||||
int gen;
|
int gen;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
|
@ -1218,8 +1221,11 @@ typedef struct shadowmap_t {
|
||||||
handle saved_pass;
|
handle saved_pass;
|
||||||
int saved_vp[4];
|
int saved_vp[4];
|
||||||
int gen;
|
int gen;
|
||||||
|
int old_filter_size;
|
||||||
|
int old_window_size;
|
||||||
} shadowmap_t;
|
} shadowmap_t;
|
||||||
shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width);
|
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_destroy(shadowmap_t *s);
|
||||||
void shadowmap_begin(shadowmap_t *s);
|
void shadowmap_begin(shadowmap_t *s);
|
||||||
bool shadowmap_step(shadowmap_t *s);
|
bool shadowmap_step(shadowmap_t *s);
|
||||||
|
|
|
@ -90,7 +90,7 @@ int main(int argc, char** argv) {
|
||||||
if( !initialized ) {
|
if( !initialized ) {
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0);
|
sky = skybox(flag("--mie") ? 0 : SKY_DIRS[SKY_DIR], 0);
|
||||||
sm = shadowmap(512, 4096);
|
sm = shadowmap(512, 2048);
|
||||||
// sm.blur_pcf = 1;
|
// sm.blur_pcf = 1;
|
||||||
// sm.blur_scale
|
// sm.blur_scale
|
||||||
mdl = model(OBJ_MDLS[OBJ_MDL], 0);
|
mdl = model(OBJ_MDLS[OBJ_MDL], 0);
|
||||||
|
@ -111,12 +111,14 @@ int main(int argc, char** argv) {
|
||||||
enum {
|
enum {
|
||||||
POINT, SPOT, DIR, ALL
|
POINT, SPOT, DIR, ALL
|
||||||
};
|
};
|
||||||
static unsigned mode = ALL;
|
static unsigned mode = DIR;
|
||||||
|
|
||||||
if (input_down(KEY_1)) mode = POINT;
|
if (active) {
|
||||||
if (input_down(KEY_2)) mode = SPOT;
|
if (input_down(KEY_1)) mode = POINT;
|
||||||
if (input_down(KEY_3)) mode = DIR;
|
if (input_down(KEY_2)) mode = SPOT;
|
||||||
if (input_down(KEY_4)) mode = ALL;
|
if (input_down(KEY_3)) mode = DIR;
|
||||||
|
if (input_down(KEY_4)) mode = ALL;
|
||||||
|
}
|
||||||
light_t *lights = 0;
|
light_t *lights = 0;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case POINT: lights = point_lights; break;
|
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'
|
# Blender 4.2.1 LTS MTL File: 'None'
|
||||||
# www.blender.org
|
# 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
|
newmtl floor
|
||||||
Ns 10.000005
|
Ns 10.000005
|
||||||
Ka 1.000000 1.000000 1.000000
|
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 float u_cascade_distances[MAX_LIGHTS * NUM_SHADOW_CASCADES];
|
||||||
uniform samplerCube shadowMap[MAX_LIGHTS];
|
uniform samplerCube shadowMap[MAX_LIGHTS];
|
||||||
uniform sampler2D shadowMap2D[MAX_LIGHTS * NUM_SHADOW_CASCADES];
|
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.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
|
//// From http://fabiensanglard.net/shadowmappingVSM/index.php
|
||||||
float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition) {
|
float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance, float variance_transition) {
|
||||||
|
@ -29,7 +34,7 @@ float shadow_vsm(float distance, vec3 dir, int light_index, float min_variance,
|
||||||
);
|
);
|
||||||
|
|
||||||
float shadow = 0.0;
|
float shadow = 0.0;
|
||||||
|
|
||||||
// Perform 3x3 PCF
|
// Perform 3x3 PCF
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
vec3 sampleDir = dir + offsets[i] * (rand(vec2(v_position_ws.x + offsets[i].x, v_position_ws.y + offsets[i].y))*1.75f + 1.25f);
|
vec3 sampleDir = dir + offsets[i] * (rand(vec2(v_position_ws.x + offsets[i].x, v_position_ws.y + offsets[i].y))*1.75f + 1.25f);
|
||||||
|
@ -85,6 +90,7 @@ float shadow_csm(float distance, vec3 lightDir, int light_index, float shadow_bi
|
||||||
|
|
||||||
// Transform to [0,1] range
|
// Transform to [0,1] range
|
||||||
projCoords = projCoords * 0.5 + 0.5;
|
projCoords = projCoords * 0.5 + 0.5;
|
||||||
|
vec4 sc = vec4(projCoords, 1.0);
|
||||||
|
|
||||||
float currentDepth = projCoords.z;
|
float currentDepth = projCoords.z;
|
||||||
|
|
||||||
|
@ -94,35 +100,50 @@ float shadow_csm(float distance, vec3 lightDir, int light_index, float shadow_bi
|
||||||
|
|
||||||
// Calculate bias
|
// Calculate bias
|
||||||
vec3 normal = normalize(vneye.xyz);
|
vec3 normal = normalize(vneye.xyz);
|
||||||
float bias = max(normal_bias * (1.0 - dot(normal, lightDir)), shadow_bias);
|
float bias = max(normal_bias * bias_modifier[matrix_index] * (1.0 - dot(normal, lightDir)), shadow_bias);
|
||||||
bias *= 1 / (u_cascade_distances[cascade_index] * bias_modifier[matrix_index]);
|
bias *= 1 / (u_cascade_distances[cascade_index]);
|
||||||
|
|
||||||
// CSM
|
// CSM
|
||||||
float shadow = 0.0;
|
float shadow = 0.0;
|
||||||
vec2 texelSize = 1.0 / textureSize(shadowMap2D[cascade_index], 0);
|
vec2 texelSize = 1.0 / textureSize(shadowMap2D[cascade_index], 0);
|
||||||
|
|
||||||
#if 1
|
// Get the offset coordinates
|
||||||
for(int x = -3; x <= 3; ++x)
|
ivec3 ofs_coord = ivec3(0);
|
||||||
{
|
vec2 ofs = mod(gl_FragCoord.xy, vec2(shadow_window_size));
|
||||||
for(int y = -3; y <= 3; ++y)
|
ofs_coord.yz = ivec2(ofs);
|
||||||
{
|
float ofs_sum = 0.0;
|
||||||
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;
|
int samples_div2 = int(shadow_filter_size * shadow_filter_size / 2.0);
|
||||||
shadow += currentDepth - bias > csmDepth ? 1.0 : 0.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
|
float shadow_sum = ofs_sum / 8.0;
|
||||||
for(int x = -1; x <= 1; ++x)
|
|
||||||
{
|
if (shadow_sum != 0.0 && shadow_sum != 1.0) {
|
||||||
for(int y = -1; y <= 1; ++y)
|
for (int i = 4; i < samples_div2; i++) {
|
||||||
{
|
ofs_coord.x = i;
|
||||||
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;
|
vec4 offsets = texelFetch(shadow_offsets, ofs_coord, 0) * shadow_offset_radius;
|
||||||
shadow += currentDepth - bias > csmDepth ? 1.0 : 0.0;
|
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;
|
return 1.0 - shadow_sum;
|
||||||
#endif
|
|
||||||
return 1.0 - shadow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 shadowmap(int idx, in vec4 peye, in vec4 neye) {
|
vec4 shadowmap(int idx, in vec4 peye, in vec4 neye) {
|
||||||
|
|
|
@ -17348,6 +17348,11 @@ typedef struct shadowmap_t {
|
||||||
handle depth_texture;
|
handle depth_texture;
|
||||||
handle depth_texture_2d;
|
handle depth_texture_2d;
|
||||||
|
|
||||||
|
// shadowmap offsets texture;
|
||||||
|
int filter_size, window_size;
|
||||||
|
float offset_radius;
|
||||||
|
handle offsets_texture;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int gen;
|
int gen;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
|
@ -17362,10 +17367,13 @@ typedef struct shadowmap_t {
|
||||||
handle saved_pass;
|
handle saved_pass;
|
||||||
int saved_vp[4];
|
int saved_vp[4];
|
||||||
int gen;
|
int gen;
|
||||||
|
int old_filter_size;
|
||||||
|
int old_window_size;
|
||||||
} shadowmap_t;
|
} shadowmap_t;
|
||||||
|
|
||||||
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
|
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 void shadowmap_begin(shadowmap_t *s);
|
||||||
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
|
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.processed_shadows = false;
|
||||||
l.shadow_distance = 200.0f;
|
l.shadow_distance = 200.0f;
|
||||||
l.shadow_near_clip = 0.01f;
|
l.shadow_near_clip = 0.01f;
|
||||||
l.shadow_bias = 0.005f;
|
l.shadow_bias = 0.15f;
|
||||||
l.normal_bias = 0.05f;
|
l.normal_bias = 0.05f;
|
||||||
l.min_variance = 0.00002f;
|
l.min_variance = 0.00002f;
|
||||||
l.variance_transition = 0.2f;
|
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.blur_vsm = false;
|
||||||
s.csm_blur_scale = 0.5f;
|
s.csm_blur_scale = 0.5f;
|
||||||
s.vsm_blur_scale = 0.75f;
|
s.vsm_blur_scale = 0.75f;
|
||||||
|
s.filter_size = 8;
|
||||||
|
s.window_size = 10;
|
||||||
|
s.offset_radius = 7.0f;
|
||||||
#if 0
|
#if 0
|
||||||
s.cascade_splits[0] = 0.1f;
|
s.cascade_splits[0] = 0.1f;
|
||||||
s.cascade_splits[1] = 0.3f;
|
s.cascade_splits[1] = 0.3f;
|
||||||
|
@ -383552,6 +383563,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
|
||||||
return s;
|
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
|
static inline
|
||||||
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
||||||
s->maps[light_index].gen = 0;
|
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->step = 0;
|
||||||
s->light_step = 0;
|
s->light_step = 0;
|
||||||
s->cascade_index = 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 (VSM)", &vsm_width);
|
||||||
ui_int("Texture Width (CSM)", &csm_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")) {
|
if (ui_collapse("VRAM Usage", "vram_usage")) {
|
||||||
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
||||||
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 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]);
|
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) {
|
else if (m.shadow_map == NULL || !m.shadow_receiver) {
|
||||||
for (int i = 0; i < MAX_LIGHTS; i++) {
|
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());
|
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);
|
shader_bool("u_shadow_receiver", GL_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1484,7 +1484,7 @@ light_t light() {
|
||||||
l.processed_shadows = false;
|
l.processed_shadows = false;
|
||||||
l.shadow_distance = 200.0f;
|
l.shadow_distance = 200.0f;
|
||||||
l.shadow_near_clip = 0.01f;
|
l.shadow_near_clip = 0.01f;
|
||||||
l.shadow_bias = 0.005f;
|
l.shadow_bias = 0.15f;
|
||||||
l.normal_bias = 0.05f;
|
l.normal_bias = 0.05f;
|
||||||
l.min_variance = 0.00002f;
|
l.min_variance = 0.00002f;
|
||||||
l.variance_transition = 0.2f;
|
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.blur_vsm = false;
|
||||||
s.csm_blur_scale = 0.5f;
|
s.csm_blur_scale = 0.5f;
|
||||||
s.vsm_blur_scale = 0.75f;
|
s.vsm_blur_scale = 0.75f;
|
||||||
|
s.filter_size = 8;
|
||||||
|
s.window_size = 10;
|
||||||
|
s.offset_radius = 7.0f;
|
||||||
#if 0
|
#if 0
|
||||||
s.cascade_splits[0] = 0.1f;
|
s.cascade_splits[0] = 0.1f;
|
||||||
s.cascade_splits[1] = 0.3f;
|
s.cascade_splits[1] = 0.3f;
|
||||||
|
@ -1735,6 +1738,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
|
||||||
return s;
|
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
|
static inline
|
||||||
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
||||||
s->maps[light_index].gen = 0;
|
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->step = 0;
|
||||||
s->light_step = 0;
|
s->light_step = 0;
|
||||||
s->cascade_index = 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 (VSM)", &vsm_width);
|
||||||
ui_int("Texture Width (CSM)", &csm_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")) {
|
if (ui_collapse("VRAM Usage", "vram_usage")) {
|
||||||
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
||||||
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 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]);
|
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) {
|
else if (m.shadow_map == NULL || !m.shadow_receiver) {
|
||||||
for (int i = 0; i < MAX_LIGHTS; i++) {
|
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());
|
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);
|
shader_bool("u_shadow_receiver", GL_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -380,6 +380,11 @@ typedef struct shadowmap_t {
|
||||||
handle depth_texture;
|
handle depth_texture;
|
||||||
handle depth_texture_2d;
|
handle depth_texture_2d;
|
||||||
|
|
||||||
|
// shadowmap offsets texture;
|
||||||
|
int filter_size, window_size;
|
||||||
|
float offset_radius;
|
||||||
|
handle offsets_texture;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int gen;
|
int gen;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
|
@ -394,10 +399,13 @@ typedef struct shadowmap_t {
|
||||||
handle saved_pass;
|
handle saved_pass;
|
||||||
int saved_vp[4];
|
int saved_vp[4];
|
||||||
int gen;
|
int gen;
|
||||||
|
int old_filter_size;
|
||||||
|
int old_window_size;
|
||||||
} shadowmap_t;
|
} shadowmap_t;
|
||||||
|
|
||||||
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
|
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 void shadowmap_begin(shadowmap_t *s);
|
||||||
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
|
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
|
||||||
|
|
82
engine/v4k.c
82
engine/v4k.c
|
@ -18338,7 +18338,7 @@ light_t light() {
|
||||||
l.processed_shadows = false;
|
l.processed_shadows = false;
|
||||||
l.shadow_distance = 200.0f;
|
l.shadow_distance = 200.0f;
|
||||||
l.shadow_near_clip = 0.01f;
|
l.shadow_near_clip = 0.01f;
|
||||||
l.shadow_bias = 0.005f;
|
l.shadow_bias = 0.15f;
|
||||||
l.normal_bias = 0.05f;
|
l.normal_bias = 0.05f;
|
||||||
l.min_variance = 0.00002f;
|
l.min_variance = 0.00002f;
|
||||||
l.variance_transition = 0.2f;
|
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.blur_vsm = false;
|
||||||
s.csm_blur_scale = 0.5f;
|
s.csm_blur_scale = 0.5f;
|
||||||
s.vsm_blur_scale = 0.75f;
|
s.vsm_blur_scale = 0.75f;
|
||||||
|
s.filter_size = 8;
|
||||||
|
s.window_size = 10;
|
||||||
|
s.offset_radius = 7.0f;
|
||||||
#if 0
|
#if 0
|
||||||
s.cascade_splits[0] = 0.1f;
|
s.cascade_splits[0] = 0.1f;
|
||||||
s.cascade_splits[1] = 0.3f;
|
s.cascade_splits[1] = 0.3f;
|
||||||
|
@ -18589,6 +18592,54 @@ shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width) { // = 512,
|
||||||
return s;
|
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
|
static inline
|
||||||
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
void shadowmap_destroy_light(shadowmap_t *s, int light_index) {
|
||||||
s->maps[light_index].gen = 0;
|
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->step = 0;
|
||||||
s->light_step = 0;
|
s->light_step = 0;
|
||||||
s->cascade_index = 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 (VSM)", &vsm_width);
|
||||||
ui_int("Texture Width (CSM)", &csm_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")) {
|
if (ui_collapse("VRAM Usage", "vram_usage")) {
|
||||||
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
ui_label2("Total VRAM", va("%lld KB", s->vram_usage_total / 1024));
|
||||||
ui_label2("VSM VRAM", va("%lld KB", s->vram_usage_vsm / 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]);
|
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) {
|
else if (m.shadow_map == NULL || !m.shadow_receiver) {
|
||||||
for (int i = 0; i < MAX_LIGHTS; i++) {
|
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());
|
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);
|
shader_bool("u_shadow_receiver", GL_FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
engine/v4k.h
10
engine/v4k.h
|
@ -3415,6 +3415,11 @@ typedef struct shadowmap_t {
|
||||||
handle depth_texture;
|
handle depth_texture;
|
||||||
handle depth_texture_2d;
|
handle depth_texture_2d;
|
||||||
|
|
||||||
|
// shadowmap offsets texture;
|
||||||
|
int filter_size, window_size;
|
||||||
|
float offset_radius;
|
||||||
|
handle offsets_texture;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int gen;
|
int gen;
|
||||||
unsigned shadow_technique;
|
unsigned shadow_technique;
|
||||||
|
@ -3429,10 +3434,13 @@ typedef struct shadowmap_t {
|
||||||
handle saved_pass;
|
handle saved_pass;
|
||||||
int saved_vp[4];
|
int saved_vp[4];
|
||||||
int gen;
|
int gen;
|
||||||
|
int old_filter_size;
|
||||||
|
int old_window_size;
|
||||||
} shadowmap_t;
|
} shadowmap_t;
|
||||||
|
|
||||||
API shadowmap_t shadowmap(int vsm_texture_width, int csm_texture_width); // = 512, 4096
|
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 void shadowmap_begin(shadowmap_t *s);
|
||||||
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
|
API bool shadowmap_step(shadowmap_t *s); //< roll over to the next light if it returns false
|
||||||
|
|
|
@ -1551,6 +1551,19 @@ flags |= (doflipUV ? aiProcess_FlipUVs : 0);
|
||||||
file = stdout;
|
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");
|
fprintf(file, "# Inter-Quake Export\n");
|
||||||
|
|
||||||
if (dobone) {
|
if (dobone) {
|
||||||
|
|
Binary file not shown.
|
@ -39,7 +39,7 @@ icon=ico
|
||||||
image=jpg,jpeg,png,bmp,psd,pic,pnm,hdr
|
image=jpg,jpeg,png,bmp,psd,pic,pnm,hdr
|
||||||
texture=pvr,ktx,ktx2,dds,astc,basis,tga
|
texture=pvr,ktx,ktx2,dds,astc,basis,tga
|
||||||
anim=fbx
|
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=wav,flac,ogg,mp1,mp3,mid,sfxr ; ,mod,xm
|
||||||
audio-module=mod,xm,s3m,it
|
audio-module=mod,xm,s3m,it
|
||||||
audio-furnace=fur
|
audio-furnace=fur
|
||||||
|
|
|
@ -38,7 +38,7 @@ ART=../engine/art,../demos/html5/art ; comma-separated folder(s) that
|
||||||
font=ttf,ttc,otf
|
font=ttf,ttc,otf
|
||||||
text=json,xml,csv,ini,cfg,doc,txt,md,c,h,inl,cpp,hpp,htm,html
|
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
|
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
|
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