forked from bartvdbraak/blender
Eevee: Replace Cubemaps by octahedron maps for env. probes.
This enables us to use 2D texture arrays for multiple probes. There is a little artifact with very high roughness caused elongated pixel due to the projection (along every 90° meridian).
This commit is contained in:
parent
1fa216487d
commit
5773f58762
@ -62,7 +62,6 @@ static struct {
|
|||||||
|
|
||||||
struct GPUTexture *ltc_mat;
|
struct GPUTexture *ltc_mat;
|
||||||
struct GPUTexture *brdf_lut;
|
struct GPUTexture *brdf_lut;
|
||||||
struct GPUTexture *hammersley;
|
|
||||||
struct GPUTexture *jitter;
|
struct GPUTexture *jitter;
|
||||||
|
|
||||||
float camera_pos[3];
|
float camera_pos[3];
|
||||||
@ -89,35 +88,6 @@ extern char datatoc_background_vert_glsl[];
|
|||||||
extern Material defmaterial;
|
extern Material defmaterial;
|
||||||
extern GlobalsUboStorage ts;
|
extern GlobalsUboStorage ts;
|
||||||
|
|
||||||
/* Van der Corput sequence */
|
|
||||||
/* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */
|
|
||||||
static float radical_inverse(int i) {
|
|
||||||
unsigned int bits = (unsigned int)i;
|
|
||||||
bits = (bits << 16u) | (bits >> 16u);
|
|
||||||
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
|
||||||
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
|
||||||
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
|
||||||
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
|
||||||
return (float)bits * 2.3283064365386963e-10f;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct GPUTexture *create_hammersley_sample_texture(int samples)
|
|
||||||
{
|
|
||||||
struct GPUTexture *tex;
|
|
||||||
float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < samples; i++) {
|
|
||||||
float phi = radical_inverse(i) * 2.0f * M_PI;
|
|
||||||
texels[i][0] = cos(phi);
|
|
||||||
texels[i][1] = sinf(phi);
|
|
||||||
}
|
|
||||||
|
|
||||||
tex = DRW_texture_create_1D(samples, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
|
|
||||||
MEM_freeN(texels);
|
|
||||||
return tex;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct GPUTexture *create_jitter_texture(int w, int h)
|
static struct GPUTexture *create_jitter_texture(int w, int h)
|
||||||
{
|
{
|
||||||
struct GPUTexture *tex;
|
struct GPUTexture *tex;
|
||||||
@ -270,36 +240,10 @@ static void EEVEE_engine_init(void *ved)
|
|||||||
e_data.default_background = DRW_shader_create_fullscreen(datatoc_default_world_frag_glsl, NULL);
|
e_data.default_background = DRW_shader_create_fullscreen(datatoc_default_world_frag_glsl, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!e_data.probe_filter_sh) {
|
|
||||||
char *shader_str = NULL;
|
|
||||||
|
|
||||||
DynStr *ds_frag = BLI_dynstr_new();
|
|
||||||
BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
|
|
||||||
BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
|
|
||||||
BLI_dynstr_append(ds_frag, datatoc_probe_filter_frag_glsl);
|
|
||||||
shader_str = BLI_dynstr_get_cstring(ds_frag);
|
|
||||||
BLI_dynstr_free(ds_frag);
|
|
||||||
|
|
||||||
e_data.probe_filter_sh = DRW_shader_create(
|
|
||||||
datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, shader_str,
|
|
||||||
"#define HAMMERSLEY_SIZE 8192\n"
|
|
||||||
"#define NOISE_SIZE 64\n");
|
|
||||||
|
|
||||||
MEM_freeN(shader_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e_data.probe_spherical_harmonic_sh) {
|
|
||||||
e_data.probe_spherical_harmonic_sh = DRW_shader_create_fullscreen(datatoc_probe_sh_frag_glsl, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e_data.ltc_mat) {
|
if (!e_data.ltc_mat) {
|
||||||
e_data.ltc_mat = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, DRW_TEX_FILTER, ltc_mat_ggx);
|
e_data.ltc_mat = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, DRW_TEX_FILTER, ltc_mat_ggx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!e_data.hammersley) {
|
|
||||||
e_data.hammersley = create_hammersley_sample_texture(8192);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e_data.jitter) {
|
if (!e_data.jitter) {
|
||||||
e_data.jitter = create_jitter_texture(64, 64);
|
e_data.jitter = create_jitter_texture(64, 64);
|
||||||
}
|
}
|
||||||
@ -439,34 +383,6 @@ static void EEVEE_cache_init(void *vedata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
psl->probe_prefilter = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
|
|
||||||
|
|
||||||
struct Batch *geom = DRW_cache_fullscreen_quad_get();
|
|
||||||
DRWShadingGroup *grp = eevee_cube_shgroup(e_data.probe_filter_sh, psl->probe_prefilter, geom);
|
|
||||||
DRW_shgroup_uniform_float(grp, "sampleCount", &stl->probes->samples_ct, 1);
|
|
||||||
DRW_shgroup_uniform_float(grp, "invSampleCount", &stl->probes->invsamples_ct, 1);
|
|
||||||
DRW_shgroup_uniform_float(grp, "roughnessSquared", &stl->probes->roughness, 1);
|
|
||||||
DRW_shgroup_uniform_float(grp, "lodFactor", &stl->probes->lodfactor, 1);
|
|
||||||
DRW_shgroup_uniform_float(grp, "lodMax", &stl->probes->lodmax, 1);
|
|
||||||
DRW_shgroup_uniform_int(grp, "Layer", &stl->probes->layer, 1);
|
|
||||||
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
|
|
||||||
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
|
|
||||||
DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
psl->probe_sh_compute = DRW_pass_create("Probe SH Compute", DRW_STATE_WRITE_COLOR);
|
|
||||||
|
|
||||||
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_spherical_harmonic_sh, psl->probe_sh_compute);
|
|
||||||
DRW_shgroup_uniform_int(grp, "probeSize", &stl->probes->shres, 1);
|
|
||||||
DRW_shgroup_uniform_float(grp, "lodBias", &stl->probes->lodfactor, 1);
|
|
||||||
DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt);
|
|
||||||
|
|
||||||
struct Batch *geom = DRW_cache_fullscreen_quad_get();
|
|
||||||
DRW_shgroup_call_add(grp, geom, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
|
||||||
stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
|
stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.depth_sh, psl->depth_pass);
|
||||||
@ -512,9 +428,8 @@ static void EEVEE_cache_init(void *vedata)
|
|||||||
psl->material_pass = DRW_pass_create("Material Shader Pass", state);
|
psl->material_pass = DRW_pass_create("Material Shader Pass", state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EEVEE_probes_cache_init(vedata);
|
||||||
EEVEE_lights_cache_init(stl, psl, txl);
|
EEVEE_lights_cache_init(stl, psl, txl);
|
||||||
|
|
||||||
EEVEE_effects_cache_init(vedata);
|
EEVEE_effects_cache_init(vedata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -669,6 +584,7 @@ static void EEVEE_cache_finish(void *vedata)
|
|||||||
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
|
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
|
||||||
|
|
||||||
EEVEE_lights_cache_finish(stl, txl, fbl);
|
EEVEE_lights_cache_finish(stl, txl, fbl);
|
||||||
|
EEVEE_probes_cache_finish(vedata);
|
||||||
|
|
||||||
/* Shadows binding */
|
/* Shadows binding */
|
||||||
eevee_bind_shadow_data data;
|
eevee_bind_shadow_data data;
|
||||||
@ -713,6 +629,7 @@ static void EEVEE_engine_free(void)
|
|||||||
{
|
{
|
||||||
EEVEE_effects_free();
|
EEVEE_effects_free();
|
||||||
EEVEE_lights_free();
|
EEVEE_lights_free();
|
||||||
|
EEVEE_probes_free();
|
||||||
|
|
||||||
MEM_SAFE_FREE(e_data.frag_shader_lib);
|
MEM_SAFE_FREE(e_data.frag_shader_lib);
|
||||||
DRW_SHADER_FREE_SAFE(e_data.default_lit);
|
DRW_SHADER_FREE_SAFE(e_data.default_lit);
|
||||||
@ -723,7 +640,6 @@ static void EEVEE_engine_free(void)
|
|||||||
DRW_SHADER_FREE_SAFE(e_data.probe_spherical_harmonic_sh);
|
DRW_SHADER_FREE_SAFE(e_data.probe_spherical_harmonic_sh);
|
||||||
DRW_TEXTURE_FREE_SAFE(e_data.ltc_mat);
|
DRW_TEXTURE_FREE_SAFE(e_data.ltc_mat);
|
||||||
DRW_TEXTURE_FREE_SAFE(e_data.brdf_lut);
|
DRW_TEXTURE_FREE_SAFE(e_data.brdf_lut);
|
||||||
DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
|
|
||||||
DRW_TEXTURE_FREE_SAFE(e_data.jitter);
|
DRW_TEXTURE_FREE_SAFE(e_data.jitter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,7 +209,7 @@ void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, E
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!txl->shadow_depth_cube_pool) {
|
if (!txl->shadow_depth_cube_pool) {
|
||||||
/* Cubemap / octahedra map pool */
|
/* Cubemap / octahedral map pool */
|
||||||
/* TODO Cubemap array */
|
/* TODO Cubemap array */
|
||||||
txl->shadow_depth_cube_pool = DRW_texture_create_2D_array(
|
txl->shadow_depth_cube_pool = DRW_texture_create_2D_array(
|
||||||
512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_32,
|
512, 512, max_ff(1, linfo->num_cube), DRW_TEX_R_32,
|
||||||
|
@ -190,6 +190,8 @@ typedef struct EEVEE_ProbesInfo {
|
|||||||
/* For rendering probes */
|
/* For rendering probes */
|
||||||
float probemat[6][4][4];
|
float probemat[6][4][4];
|
||||||
int layer;
|
int layer;
|
||||||
|
float texel_size;
|
||||||
|
float padding_size;
|
||||||
float samples_ct;
|
float samples_ct;
|
||||||
float invsamples_ct;
|
float invsamples_ct;
|
||||||
float roughness;
|
float roughness;
|
||||||
@ -282,6 +284,7 @@ void EEVEE_probes_cache_add(EEVEE_Data *vedata, Object *ob);
|
|||||||
void EEVEE_probes_cache_finish(EEVEE_Data *vedata);
|
void EEVEE_probes_cache_finish(EEVEE_Data *vedata);
|
||||||
void EEVEE_probes_update(EEVEE_Data *vedata);
|
void EEVEE_probes_update(EEVEE_Data *vedata);
|
||||||
void EEVEE_refresh_probe(EEVEE_Data *vedata);
|
void EEVEE_refresh_probe(EEVEE_Data *vedata);
|
||||||
|
void EEVEE_probes_free(void);
|
||||||
|
|
||||||
/* eevee_effects.c */
|
/* eevee_effects.c */
|
||||||
void EEVEE_effects_init(EEVEE_Data *vedata);
|
void EEVEE_effects_init(EEVEE_Data *vedata);
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
#include "DNA_texture_types.h"
|
#include "DNA_texture_types.h"
|
||||||
#include "DNA_image_types.h"
|
#include "DNA_image_types.h"
|
||||||
|
|
||||||
|
#include "BLI_dynstr.h"
|
||||||
|
|
||||||
#include "DRW_render.h"
|
#include "DRW_render.h"
|
||||||
|
|
||||||
#include "eevee_engine.h"
|
#include "eevee_engine.h"
|
||||||
@ -39,33 +41,105 @@ typedef struct EEVEE_ProbeData {
|
|||||||
} EEVEE_ProbeData;
|
} EEVEE_ProbeData;
|
||||||
|
|
||||||
/* TODO Option */
|
/* TODO Option */
|
||||||
#define PROBE_SIZE 512
|
#define PROBE_CUBE_SIZE 512
|
||||||
|
#define PROBE_SIZE 1024
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
struct GPUShader *probe_filter_sh;
|
||||||
|
struct GPUShader *probe_spherical_harmonic_sh;
|
||||||
|
|
||||||
|
struct GPUTexture *hammersley;
|
||||||
|
|
||||||
|
float camera_pos[3];
|
||||||
|
} e_data = {NULL}; /* Engine data */
|
||||||
|
|
||||||
|
extern char datatoc_probe_filter_frag_glsl[];
|
||||||
|
extern char datatoc_probe_sh_frag_glsl[];
|
||||||
|
extern char datatoc_probe_geom_glsl[];
|
||||||
|
extern char datatoc_probe_vert_glsl[];
|
||||||
|
extern char datatoc_bsdf_common_lib_glsl[];
|
||||||
|
extern char datatoc_bsdf_sampling_lib_glsl[];
|
||||||
|
|
||||||
/* *********** FUNCTIONS *********** */
|
/* *********** FUNCTIONS *********** */
|
||||||
|
|
||||||
|
/* Van der Corput sequence */
|
||||||
|
/* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */
|
||||||
|
static float radical_inverse(int i) {
|
||||||
|
unsigned int bits = (unsigned int)i;
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return (float)bits * 2.3283064365386963e-10f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct GPUTexture *create_hammersley_sample_texture(int samples)
|
||||||
|
{
|
||||||
|
struct GPUTexture *tex;
|
||||||
|
float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < samples; i++) {
|
||||||
|
float phi = radical_inverse(i) * 2.0f * M_PI;
|
||||||
|
texels[i][0] = cos(phi);
|
||||||
|
texels[i][1] = sinf(phi);
|
||||||
|
}
|
||||||
|
|
||||||
|
tex = DRW_texture_create_1D(samples, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
|
||||||
|
MEM_freeN(texels);
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
void EEVEE_probes_init(EEVEE_Data *vedata)
|
void EEVEE_probes_init(EEVEE_Data *vedata)
|
||||||
{
|
{
|
||||||
EEVEE_StorageList *stl = vedata->stl;
|
EEVEE_StorageList *stl = vedata->stl;
|
||||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||||
EEVEE_TextureList *txl = vedata->txl;
|
EEVEE_TextureList *txl = vedata->txl;
|
||||||
|
|
||||||
|
if (!e_data.probe_filter_sh) {
|
||||||
|
char *shader_str = NULL;
|
||||||
|
|
||||||
|
DynStr *ds_frag = BLI_dynstr_new();
|
||||||
|
BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
|
||||||
|
BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl);
|
||||||
|
BLI_dynstr_append(ds_frag, datatoc_probe_filter_frag_glsl);
|
||||||
|
shader_str = BLI_dynstr_get_cstring(ds_frag);
|
||||||
|
BLI_dynstr_free(ds_frag);
|
||||||
|
|
||||||
|
e_data.probe_filter_sh = DRW_shader_create(
|
||||||
|
datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, shader_str,
|
||||||
|
"#define HAMMERSLEY_SIZE 1024\n"
|
||||||
|
"#define NOISE_SIZE 64\n");
|
||||||
|
|
||||||
|
MEM_freeN(shader_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e_data.hammersley) {
|
||||||
|
e_data.hammersley = create_hammersley_sample_texture(1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e_data.probe_spherical_harmonic_sh) {
|
||||||
|
e_data.probe_spherical_harmonic_sh = DRW_shader_create_fullscreen(datatoc_probe_sh_frag_glsl, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (!stl->probes) {
|
if (!stl->probes) {
|
||||||
stl->probes = MEM_callocN(sizeof(EEVEE_ProbesInfo), "EEVEE_ProbesInfo");
|
stl->probes = MEM_callocN(sizeof(EEVEE_ProbesInfo), "EEVEE_ProbesInfo");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!txl->probe_rt) {
|
if (!txl->probe_rt) {
|
||||||
txl->probe_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
|
txl->probe_rt = DRW_texture_create_cube(PROBE_CUBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
|
||||||
txl->probe_depth_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_DEPTH_24, DRW_TEX_FILTER, NULL);
|
txl->probe_depth_rt = DRW_texture_create_cube(PROBE_CUBE_SIZE, DRW_TEX_DEPTH_24, DRW_TEX_FILTER, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWFboTexture tex_probe[2] = {{&txl->probe_depth_rt, DRW_TEX_DEPTH_24, DRW_TEX_FILTER},
|
DRWFboTexture tex_probe[2] = {{&txl->probe_depth_rt, DRW_TEX_DEPTH_24, DRW_TEX_FILTER},
|
||||||
{&txl->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
|
{&txl->probe_rt, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
|
||||||
|
|
||||||
DRW_framebuffer_init(&fbl->probe_fb, &draw_engine_eevee_type, PROBE_SIZE, PROBE_SIZE, tex_probe, 2);
|
DRW_framebuffer_init(&fbl->probe_fb, &draw_engine_eevee_type, PROBE_CUBE_SIZE, PROBE_CUBE_SIZE, tex_probe, 2);
|
||||||
|
|
||||||
if (!txl->probe_pool) {
|
if (!txl->probe_pool) {
|
||||||
/* TODO array */
|
/* TODO array */
|
||||||
txl->probe_pool = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
|
txl->probe_pool = DRW_texture_create_2D(PROBE_SIZE, PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
DRWFboTexture tex_filter = {&txl->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
|
DRWFboTexture tex_filter = {&txl->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
|
||||||
@ -78,9 +152,44 @@ void EEVEE_probes_init(EEVEE_Data *vedata)
|
|||||||
DRW_framebuffer_init(&fbl->probe_sh_fb, &draw_engine_eevee_type, 9, 1, &tex_sh, 1);
|
DRW_framebuffer_init(&fbl->probe_sh_fb, &draw_engine_eevee_type, 9, 1, &tex_sh, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EEVEE_probes_cache_init(EEVEE_Data *UNUSED(vedata))
|
void EEVEE_probes_cache_init(EEVEE_Data *vedata)
|
||||||
{
|
{
|
||||||
return;
|
EEVEE_StorageList *stl = vedata->stl;
|
||||||
|
EEVEE_TextureList *txl = vedata->txl;
|
||||||
|
EEVEE_PassList *psl = vedata->psl;
|
||||||
|
|
||||||
|
{
|
||||||
|
psl->probe_prefilter = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
|
||||||
|
|
||||||
|
struct Batch *geom = DRW_cache_fullscreen_quad_get();
|
||||||
|
|
||||||
|
DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_sh, psl->probe_prefilter, geom);
|
||||||
|
DRW_shgroup_uniform_float(grp, "sampleCount", &stl->probes->samples_ct, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "invSampleCount", &stl->probes->invsamples_ct, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "roughnessSquared", &stl->probes->roughness, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "lodFactor", &stl->probes->lodfactor, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "lodMax", &stl->probes->lodmax, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "texelSize", &stl->probes->texel_size, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "paddingSize", &stl->probes->padding_size, 1);
|
||||||
|
DRW_shgroup_uniform_int(grp, "Layer", &stl->probes->layer, 1);
|
||||||
|
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
|
||||||
|
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
|
||||||
|
DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt);
|
||||||
|
|
||||||
|
DRW_shgroup_call_dynamic_add_empty(grp);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
psl->probe_sh_compute = DRW_pass_create("Probe SH Compute", DRW_STATE_WRITE_COLOR);
|
||||||
|
|
||||||
|
DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_spherical_harmonic_sh, psl->probe_sh_compute);
|
||||||
|
DRW_shgroup_uniform_int(grp, "probeSize", &stl->probes->shres, 1);
|
||||||
|
DRW_shgroup_uniform_float(grp, "lodBias", &stl->probes->lodfactor, 1);
|
||||||
|
DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt);
|
||||||
|
|
||||||
|
struct Batch *geom = DRW_cache_fullscreen_quad_get();
|
||||||
|
DRW_shgroup_call_add(grp, geom, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EEVEE_probes_cache_add(EEVEE_Data *UNUSED(vedata), Object *UNUSED(ob))
|
void EEVEE_probes_cache_add(EEVEE_Data *UNUSED(vedata), Object *UNUSED(ob))
|
||||||
@ -120,23 +229,36 @@ void EEVEE_refresh_probe(EEVEE_Data *vedata)
|
|||||||
DRW_draw_pass(psl->probe_background);
|
DRW_draw_pass(psl->probe_background);
|
||||||
|
|
||||||
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
|
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
|
||||||
/* Bind next framebuffer to be able to write to probe_rt. */
|
/* Bind next framebuffer to be able to gen. mips for probe_rt. */
|
||||||
DRW_framebuffer_bind(fbl->probe_filter_fb);
|
DRW_framebuffer_bind(fbl->probe_filter_fb);
|
||||||
DRW_texture_generate_mipmaps(txl->probe_rt);
|
DRW_texture_generate_mipmaps(txl->probe_rt);
|
||||||
|
|
||||||
/* 3 - Render to probe array to the specified layer, do prefiltering. */
|
/* 3 - Render to probe array to the specified layer, do prefiltering. */
|
||||||
/* Detach to rebind the right mipmap. */
|
/* Detach to rebind the right mipmap. */
|
||||||
DRW_framebuffer_texture_detach(txl->probe_pool);
|
DRW_framebuffer_texture_detach(txl->probe_pool);
|
||||||
float mipsize = PROBE_SIZE * 2;
|
float mipsize = PROBE_SIZE;
|
||||||
int miplevels = 1 + (int)floorf(log2f(PROBE_SIZE));
|
const int maxlevel = (int)floorf(log2f(PROBE_SIZE));
|
||||||
for (int i = 0; i < miplevels - 2; i++) {
|
const int min_lod_level = 3;
|
||||||
|
for (int i = 0; i < maxlevel - min_lod_level; i++) {
|
||||||
float bias = (i == 0) ? 0.0f : 1.0f;
|
float bias = (i == 0) ? 0.0f : 1.0f;
|
||||||
|
pinfo->texel_size = 1.0f / mipsize;
|
||||||
mipsize /= 2;
|
pinfo->padding_size = powf(2.0f, (float)(maxlevel - min_lod_level - 1 - i));
|
||||||
CLAMP_MIN(mipsize, 1);
|
/* XXX : WHY THE HECK DO WE NEED THIS ??? */
|
||||||
|
/* padding is incorrect without this! float precision issue? */
|
||||||
|
if (pinfo->padding_size > 32) {
|
||||||
|
pinfo->padding_size += 5;
|
||||||
|
}
|
||||||
|
if (pinfo->padding_size > 16) {
|
||||||
|
pinfo->padding_size += 4;
|
||||||
|
}
|
||||||
|
else if (pinfo->padding_size > 8) {
|
||||||
|
pinfo->padding_size += 2;
|
||||||
|
}
|
||||||
|
else if (pinfo->padding_size > 4) {
|
||||||
|
pinfo->padding_size += 1;
|
||||||
|
}
|
||||||
pinfo->layer = 0;
|
pinfo->layer = 0;
|
||||||
pinfo->roughness = (float)i / ((float)miplevels - 3.0f);
|
pinfo->roughness = (float)i / ((float)maxlevel - 4.0f);
|
||||||
pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
|
pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
|
||||||
pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
|
pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
|
||||||
CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
|
CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
|
||||||
@ -154,14 +276,19 @@ void EEVEE_refresh_probe(EEVEE_Data *vedata)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
|
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
|
||||||
pinfo->lodfactor = bias + 0.5f * log((float)(PROBE_SIZE * PROBE_SIZE) * pinfo->invsamples_ct) / log(2);
|
pinfo->lodfactor = bias + 0.5f * log((float)(PROBE_CUBE_SIZE * PROBE_CUBE_SIZE) * pinfo->invsamples_ct) / log(2);
|
||||||
pinfo->lodmax = (float)miplevels - 3.0f;
|
pinfo->lodmax = floorf(log2f(PROBE_CUBE_SIZE)) - 2.0f;
|
||||||
|
|
||||||
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, i);
|
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, i);
|
||||||
DRW_framebuffer_viewport_size(fbl->probe_filter_fb, mipsize, mipsize);
|
DRW_framebuffer_viewport_size(fbl->probe_filter_fb, mipsize, mipsize);
|
||||||
DRW_draw_pass(psl->probe_prefilter);
|
DRW_draw_pass(psl->probe_prefilter);
|
||||||
DRW_framebuffer_texture_detach(txl->probe_pool);
|
DRW_framebuffer_texture_detach(txl->probe_pool);
|
||||||
|
|
||||||
|
mipsize /= 2;
|
||||||
|
CLAMP_MIN(mipsize, 1);
|
||||||
}
|
}
|
||||||
|
/* For shading, save max level of the octahedron map */
|
||||||
|
pinfo->lodmax = (float)(maxlevel - min_lod_level) - 1.0f;
|
||||||
/* reattach to have a valid framebuffer. */
|
/* reattach to have a valid framebuffer. */
|
||||||
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, 0);
|
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, 0);
|
||||||
|
|
||||||
@ -173,3 +300,10 @@ void EEVEE_refresh_probe(EEVEE_Data *vedata)
|
|||||||
DRW_draw_pass(psl->probe_sh_compute);
|
DRW_draw_pass(psl->probe_sh_compute);
|
||||||
DRW_framebuffer_read_data(0, 0, 9, 1, 3, 0, (float *)pinfo->shcoefs);
|
DRW_framebuffer_read_data(0, 0, 9, 1, 3, 0, (float *)pinfo->shcoefs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EEVEE_probes_free(void)
|
||||||
|
{
|
||||||
|
DRW_SHADER_FREE_SAFE(e_data.probe_filter_sh);
|
||||||
|
DRW_SHADER_FREE_SAFE(e_data.probe_spherical_harmonic_sh);
|
||||||
|
DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
|
||||||
|
}
|
@ -4,7 +4,7 @@ uniform vec3 cameraPos;
|
|||||||
uniform vec3 eye;
|
uniform vec3 eye;
|
||||||
uniform mat4 ProjectionMatrix;
|
uniform mat4 ProjectionMatrix;
|
||||||
|
|
||||||
uniform samplerCube probeFiltered;
|
uniform sampler2D probeFiltered;
|
||||||
uniform float lodMax;
|
uniform float lodMax;
|
||||||
uniform vec3 shCoefs[9];
|
uniform vec3 shCoefs[9];
|
||||||
|
|
||||||
@ -42,6 +42,44 @@ in vec3 viewNormal;
|
|||||||
#define HEMI 3.0
|
#define HEMI 3.0
|
||||||
#define AREA 4.0
|
#define AREA 4.0
|
||||||
|
|
||||||
|
vec2 mapping_octahedron(vec3 cubevec, vec2 texel_size)
|
||||||
|
{
|
||||||
|
/* projection onto octahedron */
|
||||||
|
cubevec /= dot( vec3(1), abs(cubevec) );
|
||||||
|
|
||||||
|
/* out-folding of the downward faces */
|
||||||
|
if ( cubevec.z < 0.0 ) {
|
||||||
|
cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mapping to [0;1]ˆ2 texture space */
|
||||||
|
vec2 uvs = cubevec.xy * (0.5) + 0.5;
|
||||||
|
|
||||||
|
/* edge filtering fix */
|
||||||
|
uvs *= 1.0 - 2.0 * texel_size;
|
||||||
|
uvs += texel_size;
|
||||||
|
|
||||||
|
return uvs;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 textureLod_octahedron(sampler2D tex, vec3 cubevec, float lod)
|
||||||
|
{
|
||||||
|
vec2 texelSize = 1.0 / vec2(textureSize(tex, int(lodMax)));
|
||||||
|
|
||||||
|
vec2 uvs = mapping_octahedron(cubevec, texelSize);
|
||||||
|
|
||||||
|
return textureLod(tex, uvs, lod);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 texture_octahedron(sampler2DArray tex, vec4 cubevec)
|
||||||
|
{
|
||||||
|
vec2 texelSize = 1.0 / vec2(textureSize(tex, 0));
|
||||||
|
|
||||||
|
vec2 uvs = mapping_octahedron(cubevec.xyz, texelSize);
|
||||||
|
|
||||||
|
return texture(tex, vec3(uvs, cubevec.w));
|
||||||
|
}
|
||||||
|
|
||||||
void light_shade(
|
void light_shade(
|
||||||
LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0,
|
LightData ld, ShadingData sd, vec3 albedo, float roughness, vec3 f0,
|
||||||
out vec3 diffuse, out vec3 specular)
|
out vec3 diffuse, out vec3 specular)
|
||||||
@ -139,20 +177,7 @@ void light_visibility(LightData ld, ShadingData sd, out float vis)
|
|||||||
vec3 cubevec = sd.W - ld.l_position;
|
vec3 cubevec = sd.W - ld.l_position;
|
||||||
float dist = length(cubevec);
|
float dist = length(cubevec);
|
||||||
|
|
||||||
/* projection onto octahedron */
|
float z = texture_octahedron(shadowCubes, vec4(cubevec, shid)).r;
|
||||||
cubevec /= dot( vec3(1), abs(cubevec) );
|
|
||||||
|
|
||||||
/* out-folding of the downward faces */
|
|
||||||
if ( cubevec.z < 0.0 ) {
|
|
||||||
cubevec.xy = (1.0 - abs(cubevec.yx)) * sign(cubevec.xy);
|
|
||||||
}
|
|
||||||
vec2 texelSize = vec2(1.0 / 512.0);
|
|
||||||
|
|
||||||
/* mapping to [0;1]ˆ2 texture space */
|
|
||||||
vec2 uvs = cubevec.xy * (0.5) + 0.5;
|
|
||||||
uvs = uvs * (1.0 - 2.0 * texelSize) + 1.0 * texelSize; /* edge filtering fix */
|
|
||||||
|
|
||||||
float z = texture(shadowCubes, vec3(uvs, shid)).r;
|
|
||||||
|
|
||||||
float esm_test = min(1.0, exp(-5.0 * dist) * z);
|
float esm_test = min(1.0, exp(-5.0 * dist) * z);
|
||||||
float sh_test = step(0, z - dist);
|
float sh_test = step(0, z - dist);
|
||||||
@ -194,7 +219,7 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness,
|
|||||||
/* Envmaps */
|
/* Envmaps */
|
||||||
vec2 uv = lut_coords(dot(sd.N, sd.V), roughness);
|
vec2 uv = lut_coords(dot(sd.N, sd.V), roughness);
|
||||||
vec3 brdf_lut = texture(brdfLut, uv).rgb;
|
vec3 brdf_lut = texture(brdfLut, uv).rgb;
|
||||||
vec3 Li = textureLod(probeFiltered, spec_dir, roughness * lodMax).rgb;
|
vec3 Li = textureLod_octahedron(probeFiltered, spec_dir, roughness * lodMax).rgb;
|
||||||
indirect_radiance += Li * F_ibl(f0, brdf_lut.rg);
|
indirect_radiance += Li * F_ibl(f0, brdf_lut.rg);
|
||||||
indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
|
indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
|
||||||
|
|
||||||
|
@ -1,17 +1,54 @@
|
|||||||
|
|
||||||
uniform samplerCube probeHdr;
|
uniform samplerCube probeHdr;
|
||||||
uniform float roughnessSquared;
|
uniform float roughnessSquared;
|
||||||
|
uniform float texelSize;
|
||||||
uniform float lodFactor;
|
uniform float lodFactor;
|
||||||
uniform float lodMax;
|
uniform float lodMax;
|
||||||
|
uniform float paddingSize;
|
||||||
|
|
||||||
in vec3 worldPosition;
|
in vec3 worldPosition;
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
vec3 octahedral_to_cubemap_proj(vec2 co)
|
||||||
|
{
|
||||||
|
co = co * 2.0 - 1.0;
|
||||||
|
|
||||||
|
vec2 abs_co = abs(co);
|
||||||
|
vec3 v = vec3(co, 1.0 - (abs_co.x + abs_co.y));
|
||||||
|
|
||||||
|
if ( abs_co.x + abs_co.y > 1.0 ) {
|
||||||
|
v.xy = (abs(co.yx) - 1.0) * -sign(co.xy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
vec2 uvs = gl_FragCoord.xy * texelSize;
|
||||||
|
|
||||||
|
/* Add a N pixel border to ensure filtering is correct
|
||||||
|
* for N mipmap levels. */
|
||||||
|
uvs += uvs * texelSize * paddingSize * 2.0;
|
||||||
|
uvs -= texelSize * paddingSize;
|
||||||
|
|
||||||
|
/* edge mirroring : only mirror if directly adjacent
|
||||||
|
* (not diagonally adjacent) */
|
||||||
|
vec2 m = abs(uvs - 0.5) + 0.5;
|
||||||
|
vec2 f = floor(m);
|
||||||
|
if (f.x - f.y != 0.0) {
|
||||||
|
uvs = 1.0 - uvs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clamp to [0-1] */
|
||||||
|
uvs = fract(uvs);
|
||||||
|
|
||||||
|
/* get cubemap vector */
|
||||||
|
vec3 cubevec = octahedral_to_cubemap_proj(uvs);
|
||||||
|
|
||||||
vec3 N, T, B, V;
|
vec3 N, T, B, V;
|
||||||
|
|
||||||
vec3 R = normalize(worldPosition);
|
vec3 R = normalize(cubevec);
|
||||||
|
|
||||||
/* Isotropic assumption */
|
/* Isotropic assumption */
|
||||||
N = V = R;
|
N = V = R;
|
||||||
|
Loading…
Reference in New Issue
Block a user