2017-04-18 12:50:09 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright 2016, Blender Foundation.
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): Blender Institute
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/** \file eevee_lights.c
|
|
|
|
|
* \ingroup DNA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
|
#include "DNA_texture_types.h"
|
|
|
|
|
#include "DNA_image_types.h"
|
|
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
|
|
|
|
|
2017-04-26 17:42:39 +10:00
|
|
|
#include "eevee_engine.h"
|
2017-04-18 12:50:09 +02:00
|
|
|
#include "eevee_private.h"
|
|
|
|
|
#include "GPU_texture.h"
|
|
|
|
|
#include "GPU_glew.h"
|
|
|
|
|
|
|
|
|
|
typedef struct EEVEE_ProbeData {
|
|
|
|
|
short probe_id, shadow_id;
|
|
|
|
|
} EEVEE_ProbeData;
|
|
|
|
|
|
|
|
|
|
/* TODO Option */
|
|
|
|
|
#define PROBE_SIZE 512
|
|
|
|
|
|
|
|
|
|
/* *********** FUNCTIONS *********** */
|
|
|
|
|
|
|
|
|
|
void EEVEE_probes_init(EEVEE_Data *vedata)
|
|
|
|
|
{
|
|
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
|
|
|
|
|
|
|
|
|
if (!stl->probes) {
|
|
|
|
|
stl->probes = MEM_callocN(sizeof(EEVEE_ProbesInfo), "EEVEE_ProbesInfo");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!txl->probe_rt) {
|
|
|
|
|
float *test_tex;
|
|
|
|
|
const float face_col[6][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f},
|
|
|
|
|
{1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
|
|
|
|
|
|
|
|
|
|
test_tex = MEM_mallocN(sizeof(float) * 6 * PROBE_SIZE * PROBE_SIZE * 4, "test tex");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
|
for (int j = 0; j < PROBE_SIZE * PROBE_SIZE; ++j) {
|
|
|
|
|
copy_v4_v4(test_tex + i * PROBE_SIZE * PROBE_SIZE * 4 + j * 4, face_col[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
txl->probe_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, (float *)test_tex);
|
|
|
|
|
txl->probe_depth_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_DEPTH_24, DRW_TEX_FILTER, NULL);
|
|
|
|
|
|
|
|
|
|
MEM_freeN(test_tex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DRWFboTexture tex_probe[2] = {{&txl->probe_depth_rt, DRW_BUF_DEPTH_24, DRW_TEX_FILTER},
|
|
|
|
|
{&txl->probe_rt, DRW_BUF_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
|
|
|
|
|
|
2017-05-16 03:03:58 +02:00
|
|
|
DRW_framebuffer_init(&fbl->probe_fb, &draw_engine_eevee_type, PROBE_SIZE, PROBE_SIZE, tex_probe, 2);
|
2017-04-18 12:50:09 +02:00
|
|
|
|
|
|
|
|
if (!txl->probe_pool) {
|
|
|
|
|
float *test_tex;
|
|
|
|
|
const float face_col[6][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f},
|
|
|
|
|
{1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
|
|
|
|
|
|
|
|
|
|
test_tex = MEM_mallocN(sizeof(float) * 6 * PROBE_SIZE * PROBE_SIZE * 4, "test tex");
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
|
for (int j = 0; j < PROBE_SIZE * PROBE_SIZE; ++j) {
|
|
|
|
|
copy_v4_v4(test_tex + i * PROBE_SIZE * PROBE_SIZE * 4 + j * 4, face_col[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* TODO array */
|
|
|
|
|
txl->probe_pool = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, (float *)test_tex);
|
|
|
|
|
MEM_freeN(test_tex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DRWFboTexture tex_filter = {&txl->probe_pool, DRW_BUF_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
|
|
|
|
|
|
2017-05-16 03:03:58 +02:00
|
|
|
DRW_framebuffer_init(&fbl->probe_filter_fb, &draw_engine_eevee_type, PROBE_SIZE, PROBE_SIZE, &tex_filter, 1);
|
2017-04-18 21:02:02 +02:00
|
|
|
|
|
|
|
|
/* Spherical Harmonic Buffer */
|
|
|
|
|
DRWFboTexture tex_sh = {&txl->probe_sh, DRW_BUF_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
|
|
|
|
|
|
2017-05-16 03:03:58 +02:00
|
|
|
DRW_framebuffer_init(&fbl->probe_sh_fb, &draw_engine_eevee_type, 9, 1, &tex_sh, 1);
|
2017-04-18 12:50:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EEVEE_probes_cache_init(EEVEE_Data *UNUSED(vedata))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EEVEE_probes_cache_add(EEVEE_Data *UNUSED(vedata), Object *UNUSED(ob))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EEVEE_probes_cache_finish(EEVEE_Data *UNUSED(vedata))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EEVEE_probes_update(EEVEE_Data *UNUSED(vedata))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void EEVEE_refresh_probe(EEVEE_Data *vedata)
|
|
|
|
|
{
|
|
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
|
|
|
|
EEVEE_PassList *psl = vedata->psl;
|
|
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
|
EEVEE_ProbesInfo *pinfo = stl->probes;
|
|
|
|
|
|
|
|
|
|
float projmat[4][4];
|
|
|
|
|
|
|
|
|
|
/* 1 - Render to cubemap target using geometry shader. */
|
|
|
|
|
/* We don't need to clear since we render the background. */
|
|
|
|
|
pinfo->layer = 0;
|
|
|
|
|
perspective_m4(projmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 100.0f);
|
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
|
mul_m4_m4m4(pinfo->probemat[i], projmat, cubefacemat[i]);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 23:48:26 +02:00
|
|
|
DRW_framebuffer_bind(fbl->probe_fb);
|
|
|
|
|
DRW_draw_pass(psl->probe_background);
|
2017-04-18 12:50:09 +02:00
|
|
|
|
|
|
|
|
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
|
|
|
|
|
/* Bind next framebuffer to be able to write to probe_rt. */
|
|
|
|
|
DRW_framebuffer_bind(fbl->probe_filter_fb);
|
|
|
|
|
DRW_texture_generate_mipmaps(txl->probe_rt);
|
|
|
|
|
|
|
|
|
|
/* 3 - Render to probe array to the specified layer, do prefiltering. */
|
|
|
|
|
/* Detach to rebind the right mipmap. */
|
|
|
|
|
DRW_framebuffer_texture_detach(txl->probe_pool);
|
|
|
|
|
float mipsize = PROBE_SIZE * 2;
|
|
|
|
|
int miplevels = 1 + (int)floorf(log2f(PROBE_SIZE));
|
|
|
|
|
for (int i = 0; i < miplevels - 2; i++) {
|
|
|
|
|
float bias = (i == 0) ? 0.0f : 1.0f;
|
|
|
|
|
|
|
|
|
|
mipsize /= 2;
|
|
|
|
|
CLAMP_MIN(mipsize, 1);
|
|
|
|
|
|
|
|
|
|
pinfo->layer = 0;
|
|
|
|
|
pinfo->roughness = (float)i / ((float)miplevels - 3.0f);
|
|
|
|
|
pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
|
|
|
|
|
pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
|
|
|
|
|
CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
|
|
|
|
|
|
|
|
|
|
#if 1 /* Variable Sample count (fast) */
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 0: pinfo->samples_ct = 1.0f; break;
|
|
|
|
|
case 1: pinfo->samples_ct = 16.0f; break;
|
|
|
|
|
case 2: pinfo->samples_ct = 32.0f; break;
|
|
|
|
|
case 3: pinfo->samples_ct = 64.0f; break;
|
|
|
|
|
default: pinfo->samples_ct = 128.0f; break;
|
|
|
|
|
}
|
|
|
|
|
#else /* Constant Sample count (slow) */
|
|
|
|
|
pinfo->samples_ct = 1024.0f;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
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->lodmax = (float)miplevels - 3.0f;
|
|
|
|
|
|
|
|
|
|
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, i);
|
|
|
|
|
DRW_framebuffer_viewport_size(fbl->probe_filter_fb, mipsize, mipsize);
|
|
|
|
|
DRW_draw_pass(psl->probe_prefilter);
|
|
|
|
|
DRW_framebuffer_texture_detach(txl->probe_pool);
|
|
|
|
|
}
|
|
|
|
|
/* reattach to have a valid framebuffer. */
|
|
|
|
|
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, 0);
|
|
|
|
|
|
|
|
|
|
/* 4 - Compute spherical harmonics */
|
2017-04-18 21:25:57 +02:00
|
|
|
/* Tweaking parameters to balance perf. vs precision */
|
|
|
|
|
pinfo->shres = 16; /* Less texture fetches & reduce branches */
|
|
|
|
|
pinfo->lodfactor = 4.0f; /* Improve cache reuse */
|
2017-04-18 21:02:02 +02:00
|
|
|
DRW_framebuffer_bind(fbl->probe_sh_fb);
|
|
|
|
|
DRW_draw_pass(psl->probe_sh_compute);
|
|
|
|
|
DRW_framebuffer_read_data(0, 0, 9, 1, 3, 0, (float *)pinfo->shcoefs);
|
2017-04-18 12:50:09 +02:00
|
|
|
}
|