Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/draw/CMakeLists.txt3
-rw-r--r--source/blender/draw/engines/eevee/eevee.c49
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c437
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h86
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl72
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl90
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_geom.glsl21
-rw-r--r--source/blender/draw/engines/eevee/shaders/shadow_vert.glsl11
-rw-r--r--source/blender/draw/intern/DRW_render.h4
-rw-r--r--source/blender/draw/intern/draw_manager.c18
-rw-r--r--source/blender/gpu/GPU_lamp.h10
-rw-r--r--source/blender/gpu/GPU_viewport.h2
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c3
-rw-r--r--source/blender/gpu/intern/gpu_lamp.c17
-rw-r--r--source/blender/gpu/intern/gpu_texture.c20
16 files changed, 710 insertions, 136 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index e921a65bfe8..67a1a6d5e88 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -103,6 +103,9 @@ data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_geom.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/shadow_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/tonemap_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
diff --git a/source/blender/draw/engines/eevee/eevee.c b/source/blender/draw/engines/eevee/eevee.c
index 7588ebede0c..2013df35deb 100644
--- a/source/blender/draw/engines/eevee/eevee.c
+++ b/source/blender/draw/engines/eevee/eevee.c
@@ -38,8 +38,10 @@ static struct {
struct GPUShader *default_lit;
struct GPUShader *depth_sh;
struct GPUShader *tonemap;
+ struct GPUShader *shadow_sh;
struct GPUTexture *ltc_mat;
struct GPUTexture *ltc_mag;
+
float camera_pos[3];
} e_data = {NULL}; /* Engine data */
@@ -49,6 +51,9 @@ extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_lit_surface_frag_glsl[];
extern char datatoc_lit_surface_vert_glsl[];
extern char datatoc_tonemap_frag_glsl[];
+extern char datatoc_shadow_frag_glsl[];
+extern char datatoc_shadow_geom_glsl[];
+extern char datatoc_shadow_vert_glsl[];
/* *********** FUNCTIONS *********** */
@@ -79,11 +84,20 @@ static void EEVEE_engine_init(void *vedata)
lib_str = BLI_dynstr_get_cstring(ds_vert);
BLI_dynstr_free(ds_vert);
- e_data.default_lit = DRW_shader_create_with_lib(datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, lib_str, "#define MAX_LIGHT 128\n");
+ e_data.default_lit = DRW_shader_create_with_lib(datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, lib_str,
+ "#define MAX_LIGHT 128\n"
+ "#define MAX_SHADOW_CUBE 42\n"
+ "#define MAX_SHADOW_MAP 64\n"
+ "#define MAX_SHADOW_CASCADE 8\n"
+ "#define MAX_CASCADE_NUM 4\n");
MEM_freeN(lib_str);
}
+ if (!e_data.shadow_sh) {
+ e_data.shadow_sh = DRW_shader_create(datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
+ }
+
if (!e_data.tonemap) {
e_data.tonemap = DRW_shader_create_fullscreen(datatoc_tonemap_frag_glsl, NULL);
}
@@ -96,8 +110,9 @@ static void EEVEE_engine_init(void *vedata)
e_data.ltc_mag = DRW_texture_create_2D(64, 64, DRW_TEX_R_16, DRW_TEX_FILTER, ltc_mag_ggx);
}
- if (stl->lights_info == NULL)
+ if (stl->lamps == NULL) {
EEVEE_lights_init(stl);
+ }
// EEVEE_lights_update(stl);
{
@@ -120,6 +135,14 @@ static void EEVEE_cache_init(void *vedata)
}
{
+ /* Shadow Pass */
+ psl->shadow_pass = DRW_pass_create("Shadow Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ stl->g_data->shadow_shgrp = DRW_shgroup_create(e_data.shadow_sh, psl->shadow_pass);
+ DRW_shgroup_uniform_mat4(stl->g_data->shadow_shgrp, "ShadowMatrix", (float *)stl->lamps->shadowmat);
+ DRW_shgroup_uniform_int(stl->g_data->shadow_shgrp, "Layer", &stl->lamps->layer, 1);
+ }
+
+ {
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);
@@ -132,11 +155,13 @@ static void EEVEE_cache_init(void *vedata)
psl->pass = DRW_pass_create("Default Light Pass", state);
stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->pass);
- DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "light_block", stl->lights_ubo, 0);
- DRW_shgroup_uniform_int(stl->g_data->default_lit_grp, "light_count", &stl->lights_info->light_count, 1);
+ DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "light_block", stl->light_ubo, 0);
+ DRW_shgroup_uniform_block(stl->g_data->default_lit_grp, "shadow_block", stl->shadow_ubo, 1);
+ DRW_shgroup_uniform_int(stl->g_data->default_lit_grp, "light_count", &stl->lamps->num_light, 1);
DRW_shgroup_uniform_vec3(stl->g_data->default_lit_grp, "cameraPos", e_data.camera_pos, 1);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMat", e_data.ltc_mat, 0);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "ltcMag", e_data.ltc_mag, 1);
+ /* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
}
{
@@ -167,6 +192,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
DRW_shgroup_call_add(stl->g_data->default_lit_grp, geom, ob->obmat);
+ DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
}
else if (ob->type == OB_LAMP) {
EEVEE_lights_cache_add(stl, ob);
@@ -176,8 +202,14 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
static void EEVEE_cache_finish(void *vedata)
{
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
+ EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
- EEVEE_lights_cache_finish(stl);
+ EEVEE_lights_cache_finish(stl, txl, fbl);
+
+ /* Shadows binding */
+ DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 2);
+ DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 3);
}
static void EEVEE_draw_scene(void *vedata)
@@ -189,6 +221,9 @@ static void EEVEE_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
+ /* Refresh shadows */
+ EEVEE_draw_shadows((EEVEE_Data *)vedata);
+
/* Attach depth to the hdr buffer and bind it */
DRW_framebuffer_texture_detach(dtxl->depth);
DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0);
@@ -197,7 +232,7 @@ static void EEVEE_draw_scene(void *vedata)
/* Clear Depth */
/* TODO do background */
float clearcol[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- DRW_framebuffer_clear(true, true, true, clearcol, 1.0f);
+ DRW_framebuffer_clear(true, true, false, clearcol, 1.0f);
DRW_draw_pass(psl->depth_pass);
DRW_draw_pass(psl->depth_pass_cull);
@@ -215,6 +250,8 @@ static void EEVEE_engine_free(void)
{
if (e_data.default_lit)
DRW_shader_free(e_data.default_lit);
+ if (e_data.shadow_sh)
+ DRW_shader_free(e_data.shadow_sh);
if (e_data.tonemap)
DRW_shader_free(e_data.tonemap);
if (e_data.ltc_mat)
diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c
index 6a6947bdc3f..9a06c665ae2 100644
--- a/source/blender/draw/engines/eevee/eevee_lights.c
+++ b/source/blender/draw/engines/eevee/eevee_lights.c
@@ -25,138 +25,393 @@
#include "DRW_render.h"
+#include "eevee.h"
#include "eevee_private.h"
-#define MAX_LIGHT 210 /* TODO : find size by dividing UBO max size by light data size */
+typedef struct EEVEE_LightData {
+ short light_id, shadow_id;
+} EEVEE_LightData;
-typedef struct EEVEE_Light {
- float position[3], dist;
- float color[3], spec;
- float spotsize, spotblend, radius, shadowid;
- float rightvec[3], sizex;
- float upvec[3], sizey;
- float forwardvec[3], lamptype;
-} EEVEE_Light;
+typedef struct EEVEE_ShadowCubeData {
+ short light_id, shadow_id;
+ float viewprojmat[6][4][4];
+} EEVEE_ShadowCubeData;
+typedef struct EEVEE_ShadowMapData {
+ short light_id, shadow_id;
+ float viewprojmat[4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
+} EEVEE_ShadowMapData;
+
+typedef struct EEVEE_ShadowCascadeData {
+ short light_id, shadow_id;
+ float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */
+} EEVEE_ShadowCascadeData;
+
+/* *********** FUNCTIONS *********** */
void EEVEE_lights_init(EEVEE_StorageList *stl)
{
- stl->lights_info = MEM_callocN(sizeof(EEVEE_LightsInfo), "EEVEE_LightsInfo");
- stl->lights_data = MEM_mallocN(sizeof(EEVEE_Light) * MAX_LIGHT, "EEVEE_LightsUboStorage");
- stl->lights_ref = MEM_mallocN(sizeof(Object *) * MAX_LIGHT, "EEVEE lights_ref");
- stl->lights_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
+ const unsigned int shadow_ubo_size = sizeof(EEVEE_ShadowCube) * MAX_SHADOW_CUBE +
+ sizeof(EEVEE_ShadowMap) * MAX_SHADOW_MAP +
+ sizeof(EEVEE_ShadowCascade) * MAX_SHADOW_CASCADE;
+
+ if (!stl->lamps) {
+ stl->lamps = MEM_callocN(sizeof(EEVEE_LampsInfo), "EEVEE_LampsInfo");
+ stl->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL);
+ stl->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL);
+ }
}
void EEVEE_lights_cache_init(EEVEE_StorageList *stl)
{
- BLI_listbase_clear(&stl->g_data->lamps);
- stl->lights_info->light_count = 0;
-}
+ EEVEE_LampsInfo *linfo = stl->lamps;
-void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
-{
- BLI_addtail(&stl->g_data->lamps, BLI_genericNodeN(ob));
- stl->lights_info->light_count += 1;
+ linfo->num_light = linfo->num_cube = linfo->num_map = linfo->num_cascade = 0;
+ memset(linfo->light_ref, 0, sizeof(linfo->light_ref));
+ memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref));
+ memset(linfo->shadow_map_ref, 0, sizeof(linfo->shadow_map_ref));
+ memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref));
}
-void EEVEE_lights_cache_finish(EEVEE_StorageList *stl)
+void EEVEE_lights_cache_add(EEVEE_StorageList *stl, Object *ob)
{
- int light_ct = stl->lights_info->light_count;
+ EEVEE_LampsInfo *linfo = stl->lamps;
- if (light_ct > MAX_LIGHT) {
+ /* Step 1 find all lamps in the scene and setup them */
+ if (linfo->num_light > MAX_LIGHT) {
printf("Too much lamps in the scene !!!\n");
- stl->lights_info->light_count = MAX_LIGHT;
+ linfo->num_light = MAX_LIGHT;
}
+ else {
+ Lamp *la = (Lamp *)ob->data;
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
- if (light_ct > 0) {
- int i = 0;
- for (LinkData *link = stl->g_data->lamps.first; link && i < MAX_LIGHT; link = link->next, i++) {
- Object *ob = (Object *)link->data;
- stl->lights_ref[i] = ob;
+ DRW_lamp_engine_data_free((void *)led);
+
+ if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) {
+ if (la->type == LA_SUN && linfo->num_map < MAX_SHADOW_MAP) {
+ led->sto = MEM_mallocN(sizeof(EEVEE_ShadowMapData), "EEVEE_ShadowMapData");
+ ((EEVEE_ShadowMapData *)led->sto)->shadow_id = linfo->num_map;
+ linfo->shadow_map_ref[linfo->num_map] = ob;
+ linfo->num_map++;
+ }
+ else if ((la->type == LA_SPOT || la->type == LA_LOCAL || la->type == LA_AREA)
+ && linfo->num_cube < MAX_SHADOW_CUBE) {
+ led->sto = MEM_mallocN(sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData");
+ ((EEVEE_ShadowCubeData *)led->sto)->shadow_id = linfo->num_cube;
+ linfo->shadow_cube_ref[linfo->num_cube] = ob;
+ linfo->num_cube++;
+ }
}
+
+ if (!led->sto) {
+ led->sto = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData");
+ ((EEVEE_LightData *)led->sto)->shadow_id = -1;
+ }
+
+ ((EEVEE_LightData *)led->sto)->light_id = linfo->num_light;
+ linfo->light_ref[linfo->num_light] = ob;
+ linfo->num_light++;
}
- BLI_freelistN(&stl->g_data->lamps);
+}
+
+void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl)
+{
+ EEVEE_LampsInfo *linfo = stl->lamps;
- /* We changed light data so we need to upload it */
+ /* Step 4 Update Lamp UBOs */
EEVEE_lights_update(stl);
+
+ /* Step 5 Setup enough layers */
+ /* Free textures if number mismatch */
+ if (linfo->num_cube != linfo->cache_num_cube) {
+ if (txl->shadow_depth_cube_pool) {
+ DRW_texture_free(txl->shadow_depth_cube_pool);
+ txl->shadow_depth_cube_pool = NULL;
+ }
+ linfo->cache_num_cube = linfo->num_cube;
+ }
+ if (linfo->num_map != linfo->cache_num_map) {
+ if (txl->shadow_depth_map_pool) {
+ DRW_texture_free(txl->shadow_depth_map_pool);
+ txl->shadow_depth_map_pool = NULL;
+ }
+ linfo->cache_num_map = linfo->num_map;
+ }
+ if (linfo->num_cascade != linfo->cache_num_cascade) {
+ if (txl->shadow_depth_cascade_pool) {
+ DRW_texture_free(txl->shadow_depth_cascade_pool);
+ txl->shadow_depth_cascade_pool = NULL;
+ }
+ linfo->cache_num_cascade = linfo->num_cascade;
+ }
+
+ /* Initialize Textures Arrays first so DRW_framebuffer_init just bind them */
+ if (!txl->shadow_depth_cube_pool) {
+ txl->shadow_depth_cube_pool = DRW_texture_create_2D_array(512, 512, MAX2(1, linfo->num_cube * 6), DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
+ if (fbl->shadow_cube_fb)
+ DRW_framebuffer_texture_attach(fbl->shadow_cube_fb, txl->shadow_depth_cube_pool, 0);
+ }
+ if (!txl->shadow_depth_map_pool) {
+ txl->shadow_depth_map_pool = DRW_texture_create_2D_array(512, 512, MAX2(1, linfo->num_map), DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
+ if (fbl->shadow_map_fb)
+ DRW_framebuffer_texture_attach(fbl->shadow_map_fb, txl->shadow_depth_map_pool, 0);
+ }
+ if (!txl->shadow_depth_cascade_pool) {
+ txl->shadow_depth_cascade_pool = DRW_texture_create_2D_array(512, 512, MAX2(1, linfo->num_cascade), DRW_TEX_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE, NULL);
+ if (fbl->shadow_cascade_fb)
+ DRW_framebuffer_texture_attach(fbl->shadow_cascade_fb, txl->shadow_depth_map_pool, 0);
+ }
+
+ DRWFboTexture tex_cube = {&txl->shadow_depth_cube_pool, DRW_BUF_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
+ DRW_framebuffer_init(&fbl->shadow_cube_fb, 512, 512, &tex_cube, 1);
+
+ DRWFboTexture tex_map = {&txl->shadow_depth_map_pool, DRW_BUF_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
+ DRW_framebuffer_init(&fbl->shadow_map_fb, 512, 512, &tex_map, 1);
+
+ DRWFboTexture tex_cascade = {&txl->shadow_depth_cascade_pool, DRW_BUF_DEPTH_24, DRW_TEX_FILTER | DRW_TEX_COMPARE};
+ DRW_framebuffer_init(&fbl->shadow_cascade_fb, 512, 512, &tex_cascade, 1);
}
-void EEVEE_lights_update(EEVEE_StorageList *stl)
+/* Update buffer with lamp data */
+static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
{
- int light_ct = stl->lights_info->light_count;
-
/* TODO only update if data changes */
- /* Update buffer with lamp data */
- for (int i = 0; i < light_ct; ++i) {
- EEVEE_Light *evli = stl->lights_data + i;
- Object *ob = stl->lights_ref[i];
- Lamp *la = (Lamp *)ob->data;
- float mat[4][4], scale[3], power;
+ EEVEE_LightData *evld = led->sto;
+ EEVEE_Light *evli = linfo->light_data + evld->light_id;
+ Lamp *la = (Lamp *)ob->data;
+ float mat[4][4], scale[3], power;
- /* Position */
- copy_v3_v3(evli->position, ob->obmat[3]);
+ /* Position */
+ copy_v3_v3(evli->position, ob->obmat[3]);
- /* Color */
- evli->color[0] = la->r * la->energy;
- evli->color[1] = la->g * la->energy;
- evli->color[2] = la->b * la->energy;
+ /* Color */
+ evli->color[0] = la->r * la->energy;
+ evli->color[1] = la->g * la->energy;
+ evli->color[2] = la->b * la->energy;
- /* Influence Radius */
- evli->dist = la->dist;
+ /* Influence Radius */
+ evli->dist = la->dist;
- /* Vectors */
- normalize_m4_m4_ex(mat, ob->obmat, scale);
- copy_v3_v3(evli->forwardvec, mat[2]);
- normalize_v3(evli->forwardvec);
- negate_v3(evli->forwardvec);
+ /* Vectors */
+ normalize_m4_m4_ex(mat, ob->obmat, scale);
+ copy_v3_v3(evli->forwardvec, mat[2]);
+ normalize_v3(evli->forwardvec);
+ negate_v3(evli->forwardvec);
- copy_v3_v3(evli->rightvec, mat[0]);
- normalize_v3(evli->rightvec);
+ copy_v3_v3(evli->rightvec, mat[0]);
+ normalize_v3(evli->rightvec);
- copy_v3_v3(evli->upvec, mat[1]);
- normalize_v3(evli->upvec);
+ copy_v3_v3(evli->upvec, mat[1]);
+ normalize_v3(evli->upvec);
- /* Spot size & blend */
- if (la->type == LA_SPOT) {
- evli->sizex = scale[0] / scale[2];
- evli->sizey = scale[1] / scale[2];
- evli->spotsize = cosf(la->spotsize * 0.5f);
- evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
- }
- else if (la->type == LA_AREA) {
- evli->sizex = MAX2(0.0001f, la->area_size * scale[0] * 0.5f);
- if (la->area_shape == LA_AREA_RECT) {
- evli->sizey = MAX2(0.0001f, la->area_sizey * scale[1] * 0.5f);
- }
- else {
- evli->sizey = evli->sizex;
- }
+ /* Spot size & blend */
+ if (la->type == LA_SPOT) {
+ evli->sizex = scale[0] / scale[2];
+ evli->sizey = scale[1] / scale[2];
+ evli->spotsize = cosf(la->spotsize * 0.5f);
+ evli->spotblend = (1.0f - evli->spotsize) * la->spotblend;
+ evli->radius = MAX2(0.001f, la->area_size);
+ }
+ else if (la->type == LA_AREA) {
+ evli->sizex = MAX2(0.0001f, la->area_size * scale[0] * 0.5f);
+ if (la->area_shape == LA_AREA_RECT) {
+ evli->sizey = MAX2(0.0001f, la->area_sizey * scale[1] * 0.5f);
}
else {
- evli->sizex = MAX2(0.001f, la->area_size);
+ evli->sizey = evli->sizex;
}
+ }
+ else {
+ evli->radius = MAX2(0.001f, la->area_size);
+ }
- /* Make illumination power constant */
- if (la->type == LA_AREA) {
- power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) /* 1/(w*h*Pi) */
- * 80.0f; /* XXX : Empirical, Fit cycles power */
- }
- else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
- power = 1.0f / (4.0f * evli->sizex * evli->sizex * M_PI * M_PI) /* 1/(4*r²*Pi²) */
- * M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
+ /* Make illumination power constant */
+ if (la->type == LA_AREA) {
+ power = 1.0f / (evli->sizex * evli->sizey * 4.0f * M_PI) /* 1/(w*h*Pi) */
+ * 80.0f; /* XXX : Empirical, Fit cycles power */
+ }
+ else if (la->type == LA_SPOT || la->type == LA_LOCAL) {
+ power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) /* 1/(4*r²*Pi²) */
+ * M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */
- /* for point lights (a.k.a radius == 0.0) */
- // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
- }
- else {
- power = 1.0f;
+ /* for point lights (a.k.a radius == 0.0) */
+ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */
+ }
+ else {
+ power = 1.0f;
+ }
+ mul_v3_fl(evli->color, power);
+
+ /* Lamp Type */
+ evli->lamptype = (float)la->type;
+
+ /* No shadow by default */
+ evli->shadowid = -1.0f;
+}
+
+static float texcomat[4][4] = { /* From NDC to TexCo */
+ {0.5, 0.0, 0.0, 0.0},
+ {0.0, 0.5, 0.0, 0.0},
+ {0.0, 0.0, 0.5, 0.0},
+ {0.5, 0.5, 0.5, 1.0}
+};
+
+static float cubefacemat[6][4][4] = {
+ /* Pos X */
+ {{0.0, 0.0, -1.0, 0.0},
+ {0.0, -1.0, 0.0, 0.0},
+ {-1.0, 0.0, 0.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+ /* Neg X */
+ {{0.0, 0.0, 1.0, 0.0},
+ {0.0, -1.0, 0.0, 0.0},
+ {1.0, 0.0, 0.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+ /* Pos Y */
+ {{1.0, 0.0, 0.0, 0.0},
+ {0.0, 0.0, 1.0, 0.0},
+ {0.0, -1.0, 0.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+ /* Neg Y */
+ {{1.0, 0.0, 0.0, 0.0},
+ {0.0, 0.0, -1.0, 0.0},
+ {0.0, 1.0, 0.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+ /* Pos Z */
+ {{1.0, 0.0, 0.0, 0.0},
+ {0.0, -1.0, 0.0, 0.0},
+ {0.0, 0.0, -1.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+ /* Neg Z */
+ {{-1.0, 0.0, 0.0, 0.0},
+ {0.0, -1.0, 0.0, 0.0},
+ {0.0, 0.0, 1.0, 0.0},
+ {0.0, 0.0, 0.0, 1.0}},
+};
+
+static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+{
+ float projmat[4][4];
+
+ EEVEE_ShadowCubeData *evsmp = (EEVEE_ShadowCubeData *)led->sto;
+ EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
+ EEVEE_ShadowCube *evsh = linfo->shadow_cube_data + evsmp->shadow_id;
+ Lamp *la = (Lamp *)ob->data;
+
+ perspective_m4(projmat, -la->clipsta, la->clipsta, -la->clipsta, la->clipsta, la->clipsta, la->clipend);
+
+ for (int i = 0; i < 6; ++i) {
+ float tmp[4][4];
+ unit_m4(tmp);
+ negate_v3_v3(tmp[3], ob->obmat[3]);
+ mul_m4_m4m4(tmp, cubefacemat[i], tmp);
+ mul_m4_m4m4(evsmp->viewprojmat[i], projmat, tmp);
+ }
+
+ evsh->bias = 0.05f * la->bias;
+ evsh->near = la->clipsta;
+ evsh->far = la->clipend;
+
+ evli->shadowid = (float)(evsmp->shadow_id);
+}
+
+static void eevee_shadow_map_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
+{
+ float viewmat[4][4], projmat[4][4];
+
+ EEVEE_ShadowMapData *evsmp = (EEVEE_ShadowMapData *)led->sto;
+ EEVEE_Light *evli = linfo->light_data + evsmp->light_id;
+ EEVEE_ShadowMap *evsh = linfo->shadow_map_data + evsmp->shadow_id;
+ Lamp *la = (Lamp *)ob->data;
+
+ invert_m4_m4(viewmat, ob->obmat);
+ normalize_v3(viewmat[0]);
+ normalize_v3(viewmat[1]);
+ normalize_v3(viewmat[2]);
+
+ float wsize = la->shadow_frustum_size;
+ orthographic_m4(projmat, -wsize, wsize, -wsize, wsize, la->clipsta, la->clipend);
+
+ mul_m4_m4m4(evsmp->viewprojmat, projmat, viewmat);
+ mul_m4_m4m4(evsh->shadowmat, texcomat, evsmp->viewprojmat);
+
+ evsh->bias = 0.005f * la->bias;
+
+ evli->shadowid = (float)(MAX_SHADOW_CUBE + evsmp->shadow_id);
+}
+
+void EEVEE_lights_update(EEVEE_StorageList *stl)
+{
+ EEVEE_LampsInfo *linfo = stl->lamps;
+ Object *ob;
+ int i;
+
+ for (i = 0; (ob = linfo->light_ref[i]) && (i < MAX_LIGHT); i++) {
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ eevee_light_setup(ob, linfo, led);
+ }
+
+ for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ eevee_shadow_cube_setup(ob, linfo, led);
+ }
+
+ for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) {
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ eevee_shadow_map_setup(ob, linfo, led);
+ }
+
+ // for (i = 0; (ob = linfo->shadow_cascade_ref[i]) && (i < MAX_SHADOW_CASCADE); i++) {
+ // EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ // eevee_shadow_map_setup(ob, linfo, led);
+ // }
+
+ DRW_uniformbuffer_update(stl->light_ubo, &linfo->light_data);
+ DRW_uniformbuffer_update(stl->shadow_ubo, &linfo->shadow_cube_data); /* Update all data at once */
+}
+
+/* this refresh lamps shadow buffers */
+void EEVEE_draw_shadows(EEVEE_Data *vedata)
+{
+ EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_FramebufferList *fbl = vedata->fbl;
+ EEVEE_LampsInfo *linfo = stl->lamps;
+ Object *ob;
+ int i;
+
+ /* Cube Shadow Maps */
+ /* For old hardware support, we render each face of the shadow map
+ * onto 6 layer of a big 2D texture array and sample manualy the right layer
+ * in the fragment shader. */
+ DRW_framebuffer_bind(fbl->shadow_cube_fb);
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Render each shadow to one layer of the array */
+ for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) {
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->sto;
+
+ for (int j = 0; j < 6; ++j) {
+ linfo->layer = i * 6 + j;
+ copy_m4_m4(linfo->shadowmat, evscd->viewprojmat[j]);
+ DRW_draw_pass(vedata->psl->shadow_pass);
}
- mul_v3_fl(evli->color, power);
+ }
+
+ /* Standard Shadow Maps */
+ DRW_framebuffer_bind(fbl->shadow_map_fb);
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Render each shadow to one layer of the array */
+ for (i = 0; (ob = linfo->shadow_map_ref[i]) && (i < MAX_SHADOW_MAP); i++) {
+ EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)DRW_lamp_engine_data_get(ob, &viewport_eevee_type);
+ EEVEE_ShadowMapData *evsmd = (EEVEE_ShadowMapData *)led->sto;
- /* Lamp Type */
- evli->lamptype = (float)la->type;
+ linfo->layer = i;
+ copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
+ DRW_draw_pass(vedata->psl->shadow_pass);
}
- /* Upload buffer to GPU */
- DRW_uniformbuffer_update(stl->lights_ubo, stl->lights_data);
+ // DRW_framebuffer_bind(e_data.shadow_cascade_fb);
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 401b39fbd3e..7ed80ac68c2 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -25,8 +25,16 @@
struct Object;
+/* Minimum UBO is 16384 bytes */
+#define MAX_LIGHT 128 /* TODO : find size by dividing UBO max size by light data size */
+#define MAX_SHADOW_CUBE 42 /* TODO : Make this depends on GL_MAX_ARRAY_TEXTURE_LAYERS */
+#define MAX_SHADOW_MAP 64
+#define MAX_SHADOW_CASCADE 8
+#define MAX_CASCADE_NUM 4
+
/* keep it under MAX_PASSES */
typedef struct EEVEE_PassList {
+ struct DRWPass *shadow_pass;
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
struct DRWPass *pass;
@@ -36,26 +44,78 @@ typedef struct EEVEE_PassList {
/* keep it under MAX_BUFFERS */
typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *main; /* HDR */
+ struct GPUFrameBuffer *shadow_cube_fb;
+ struct GPUFrameBuffer *shadow_map_fb;
+ struct GPUFrameBuffer *shadow_cascade_fb;
} EEVEE_FramebufferList;
/* keep it under MAX_TEXTURES */
typedef struct EEVEE_TextureList {
struct GPUTexture *color; /* R11_G11_B10 */
+ struct GPUTexture *shadow_depth_cube_pool;
+ struct GPUTexture *shadow_depth_map_pool;
+ struct GPUTexture *shadow_depth_cascade_pool;
} EEVEE_TextureList;
/* keep it under MAX_STORAGE */
typedef struct EEVEE_StorageList {
- /* Lights */
- struct EEVEE_LightsInfo *lights_info; /* Number of lights, ... */
- struct EEVEE_Light *lights_data; /* Array, Packed lights data info, duplication of what is in the Uniform Buffer in Vram */
- struct Object **lights_ref; /* List of all lights in the buffer. */
- struct GPUUniformBuffer *lights_ubo;
+ /* Lamps */
+ /* XXX this should be per-scenelayer and not per_viewport */
+ struct EEVEE_LampsInfo *lamps;
+ struct GPUUniformBuffer *light_ubo;
+ struct GPUUniformBuffer *shadow_ubo;
+
struct g_data *g_data;
} EEVEE_StorageList;
-typedef struct EEVEE_LightsInfo {
- int light_count;
-} EEVEE_LightsInfo;
+/* ************ LIGHT UBO ************* */
+typedef struct EEVEE_Light {
+ float position[3], dist;
+ float color[3], spec;
+ float spotsize, spotblend, radius, shadowid;
+ float rightvec[3], sizex;
+ float upvec[3], sizey;
+ float forwardvec[3], lamptype;
+} EEVEE_Light;
+
+typedef struct EEVEE_ShadowCube {
+ float near, far, bias, pad;
+} EEVEE_ShadowCube;
+
+typedef struct EEVEE_ShadowMap {
+ float shadowmat[4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
+ float near, far, bias, pad;
+} EEVEE_ShadowMap;
+
+typedef struct EEVEE_ShadowCascade {
+ float shadowmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC->Tex : used for sampling the shadow map. */
+ float bias, count, pad[2];
+ float near[MAX_CASCADE_NUM];
+ float far[MAX_CASCADE_NUM];
+} EEVEE_ShadowCascade;
+
+/* ************ LIGHT DATA ************* */
+typedef struct EEVEE_LampsInfo {
+ /* For rendering shadows */
+ float shadowmat[4][4];
+ int layer;
+
+ int num_light, cache_num_light;
+ int num_cube, cache_num_cube;
+ int num_map, cache_num_map;
+ int num_cascade, cache_num_cascade;
+ /* List of lights in the scene. */
+ struct Object *light_ref[MAX_LIGHT];
+ struct Object *shadow_cube_ref[MAX_SHADOW_CUBE];
+ struct Object *shadow_map_ref[MAX_SHADOW_MAP];
+ struct Object *shadow_cascade_ref[MAX_SHADOW_CASCADE];
+ /* UBO Storage : data used by UBO */
+ struct EEVEE_Light light_data[MAX_LIGHT];
+ struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE];
+ struct EEVEE_ShadowMap shadow_map_data[MAX_SHADOW_MAP];
+ struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
+} EEVEE_LampsInfo;
+/* *********************************** */
typedef struct EEVEE_Data {
void *engine_type;
@@ -65,8 +125,15 @@ typedef struct EEVEE_Data {
EEVEE_StorageList *stl;
} EEVEE_Data;
+/* Keep it sync with MAX_LAMP_DATA */
+typedef struct EEVEE_LampEngineData {
+ void *sto;
+ void *pad;
+} EEVEE_LampEngineData;
+
typedef struct g_data{
struct DRWShadingGroup *default_lit_grp;
+ struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *depth_shgrp;
struct DRWShadingGroup *depth_shgrp_select;
struct DRWShadingGroup *depth_shgrp_active;
@@ -81,5 +148,6 @@ typedef struct g_data{
void EEVEE_lights_init(EEVEE_StorageList *stl);
void EEVEE_lights_cache_init(EEVEE_StorageList *stl);
void EEVEE_lights_cache_add(EEVEE_StorageList *stl, struct Object *ob);
-void EEVEE_lights_cache_finish(EEVEE_StorageList *stl);
+void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl);
void EEVEE_lights_update(EEVEE_StorageList *stl);
+void EEVEE_draw_shadows(EEVEE_Data *vedata); \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index 5067155aced..ef684e3b970 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -7,12 +7,12 @@
/* ------- Structures -------- */
struct LightData {
- vec4 position_influence; /* w : InfluenceRadius */
- vec4 color_spec; /* w : Spec Intensity */
- vec4 spotdata_shadow; /* x : spot size, y : spot blend */
- vec4 rightvec_sizex; /* xyz: Normalized up vector, w: Lamp Type */
- vec4 upvec_sizey; /* xyz: Normalized right vector, w: Lamp Type */
- vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */
+ vec4 position_influence; /* w : InfluenceRadius */
+ vec4 color_spec; /* w : Spec Intensity */
+ vec4 spotdata_radius_shadow; /* x : spot size, y : spot blend, z : radius, w: shadow id */
+ vec4 rightvec_sizex; /* xyz: Normalized up vector, w: area size X or spot scale X */
+ vec4 upvec_sizey; /* xyz: Normalized right vector, w: area size Y or spot scale Y */
+ vec4 forwardvec_type; /* xyz: Normalized forward vector, w: Lamp Type */
};
/* convenience aliases */
@@ -21,14 +21,48 @@ struct LightData {
#define l_position position_influence.xyz
#define l_influence position_influence.w
#define l_sizex rightvec_sizex.w
-#define l_radius rightvec_sizex.w
#define l_sizey upvec_sizey.w
#define l_right rightvec_sizex.xyz
#define l_up upvec_sizey.xyz
#define l_forward forwardvec_type.xyz
#define l_type forwardvec_type.w
-#define l_spot_size spotdata_shadow.x
-#define l_spot_blend spotdata_shadow.y
+#define l_spot_size spotdata_radius_shadow.x
+#define l_spot_blend spotdata_radius_shadow.y
+#define l_radius spotdata_radius_shadow.z
+#define l_shadowid spotdata_radius_shadow.w
+
+
+struct ShadowCubeData {
+ vec4 near_far_bias;
+};
+
+/* convenience aliases */
+#define sh_cube_near near_far_bias.x
+#define sh_cube_far near_far_bias.y
+#define sh_cube_bias near_far_bias.z
+
+
+struct ShadowMapData {
+ mat4 shadowmat;
+ vec4 near_far_bias;
+};
+
+/* convenience aliases */
+#define sh_map_near near_far_bias.x
+#define sh_map_far near_far_bias.y
+#define sh_map_bias near_far_bias.z
+
+struct ShadowCascadeData {
+ mat4 shadowmat[MAX_CASCADE_NUM];
+ vec4 bias_count;
+ float near[MAX_CASCADE_NUM];
+ float far[MAX_CASCADE_NUM];
+};
+
+/* convenience aliases */
+#define sh_cascade_bias bias_count.x
+#define sh_cascade_count bias_count.y
+
struct AreaData {
vec3 corner[4];
@@ -64,6 +98,26 @@ float hypot(float x, float y) { return sqrt(x*x + y*y); }
float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); }
+float linear_depth(float z, float zf, float zn)
+{
+ if (gl_ProjectionMatrix[3][3] == 0.0) {
+ return (zn * zf) / (z * (zn - zf) + zf);
+ }
+ else {
+ return (z * 2.0 - 1.0) * zf;
+ }
+}
+
+float buffer_depth(float z, float zf, float zn)
+{
+ if (gl_ProjectionMatrix[3][3] == 0.0) {
+ return (zf * (zn - z)) / (z * (zn - zf));
+ }
+ else {
+ return (z / (zf * 2.0)) + 0.5;
+ }
+}
+
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
{
return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index ced22074be3..6c62e7c2e47 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -3,10 +3,18 @@ uniform int light_count;
uniform vec3 cameraPos;
uniform vec3 eye;
uniform mat4 ProjectionMatrix;
-
+uniform sampler2DArrayShadow shadowCubes;
+uniform sampler2DArrayShadow shadowMaps;
+// uniform sampler2DArrayShadow shadowCascades;
layout(std140) uniform light_block {
- LightData lights_data[MAX_LIGHT];
+ LightData lights_data[MAX_LIGHT];
+};
+
+layout(std140) uniform shadow_block {
+ ShadowCubeData shadows_cube_data[MAX_SHADOW_CUBE];
+ ShadowMapData shadows_map_data[MAX_SHADOW_MAP];
+ ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE];
};
in vec3 worldPosition;
@@ -69,6 +77,80 @@ float light_visibility(LightData ld, ShadingData sd)
vis *= step(0.0, -dot(sd.L, ld.l_forward));
}
+ /* shadowing */
+ if (ld.l_shadowid >= (MAX_SHADOW_MAP + MAX_SHADOW_CUBE)) {
+ /* Shadow Cascade */
+ }
+ else if (ld.l_shadowid >= MAX_SHADOW_CUBE) {
+ /* Shadow Map */
+ float shid = ld.l_shadowid - MAX_SHADOW_CUBE;
+ ShadowMapData smd = shadows_map_data[int(shid)];
+ vec4 shpos = smd.shadowmat * vec4(sd.W, 1.0);
+ shpos.z -= smd.sh_map_bias * shpos.w;
+ shpos.xyz /= shpos.w;
+
+ if (shpos.w > 0.0 && min(shpos.x, shpos.y) > 0.0 && max(shpos.x, shpos.y) < 1.0) {
+ vis *= texture(shadowMaps, vec4(shpos.xy, shid, shpos.z));
+ }
+ }
+ else {
+ /* Shadow Cube */
+ float shid = ld.l_shadowid;
+ ShadowCubeData scd = shadows_cube_data[int(shid)];
+
+ float face;
+ vec2 uvs;
+ vec3 Linv = sd.L;
+ vec3 Labs = abs(Linv);
+ vec3 maj_axis;
+
+ if (max(Labs.y, Labs.z) < Labs.x) {
+ if (Linv.x > 0.0) {
+ face = 1.0;
+ uvs = vec2(1.0, -1.0) * Linv.zy / -Linv.x;
+ maj_axis = vec3(1.0, 0.0, 0.0);
+ }
+ else {
+ face = 0.0;
+ uvs = -Linv.zy / Linv.x;
+ maj_axis = vec3(-1.0, 0.0, 0.0);
+ }
+ }
+ else if (max(Labs.x, Labs.z) < Labs.y) {
+ if (Linv.y > 0.0) {
+ face = 2.0;
+ uvs = vec2(-1.0, 1.0) * Linv.xz / Linv.y;
+ maj_axis = vec3(0.0, 1.0, 0.0);
+ }
+ else {
+ face = 3.0;
+ uvs = -Linv.xz / -Linv.y;
+ maj_axis = vec3(0.0, -1.0, 0.0);
+ }
+ }
+ else {
+ if (Linv.z > 0.0) {
+ face = 5.0;
+ uvs = Linv.xy / Linv.z;
+ maj_axis = vec3(0.0, 0.0, 1.0);
+ }
+ else {
+ face = 4.0;
+ uvs = vec2(-1.0, 1.0) * Linv.xy / -Linv.z;
+ maj_axis = vec3(0.0, 0.0, -1.0);
+ }
+ }
+
+ uvs = uvs * 0.5 + 0.5;
+
+ /* Depth in lightspace to compare against shadow map */
+ float w = dot(maj_axis, sd.l_vector);
+ w -= scd.sh_map_bias * w;
+ float shdepth = buffer_depth(w, scd.sh_cube_far, scd.sh_cube_near);
+
+ vis *= texture(shadowCubes, vec4(uvs, shid * 6.0 + face, shdepth));
+ }
+
return vis;
}
@@ -108,8 +190,8 @@ void main()
sd.R = reflect(-sd.V, sd.N);
/* hardcoded test vars */
- vec3 albedo = vec3(0.0);
- vec3 specular = mix(vec3(1.0), vec3(1.0), pow(max(0.0, 1.0 - dot(sd.N, sd.V)), 5.0));
+ vec3 albedo = vec3(0.8);
+ vec3 specular = mix(vec3(0.03), vec3(1.0), pow(max(0.0, 1.0 - dot(sd.N, sd.V)), 5.0));
float roughness = 0.1;
sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughness);
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl
new file mode 100644
index 00000000000..29335207851
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_frag.glsl
@@ -0,0 +1,3 @@
+
+void main() {
+}
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
new file mode 100644
index 00000000000..1032fe4e956
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_geom.glsl
@@ -0,0 +1,21 @@
+
+layout(triangles) in;
+layout(triangle_strip, max_vertices=3) out;
+
+uniform mat4 ShadowMatrix;
+uniform int Layer;
+
+in vec4 vPos[];
+
+void main() {
+ gl_Layer = Layer;
+ gl_Position = ShadowMatrix * vPos[0];
+ EmitVertex();
+ gl_Layer = Layer;
+ gl_Position = ShadowMatrix * vPos[1];
+ EmitVertex();
+ gl_Layer = Layer;
+ gl_Position = ShadowMatrix * vPos[2];
+ EmitVertex();
+ EndPrimitive();
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
new file mode 100644
index 00000000000..1adf2ccfab9
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/shadow_vert.glsl
@@ -0,0 +1,11 @@
+
+uniform mat4 ShadowMatrix;
+uniform mat4 ModelMatrix;
+
+in vec3 pos;
+
+out vec4 vPos;
+
+void main() {
+ vPos = ModelMatrix * vec4(pos, 1.0);
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 1e99b95f27c..7475e562833 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -61,6 +61,8 @@ struct Object;
struct Batch;
struct DefaultFramebufferList;
struct DefaultTextureList;
+struct LampEngineData;
+struct RenderEngineType;
typedef struct DRWUniform DRWUniform;
typedef struct DRWInterface DRWInterface;
@@ -252,6 +254,8 @@ struct DefaultTextureList *DRW_viewport_texture_list_get(void);
/* Objects */
void **DRW_object_engine_data_get(Object *ob, DrawEngineType *det);
+struct LampEngineData *DRW_lamp_engine_data_get(Object *ob, struct RenderEngineType *engine_type);
+void DRW_lamp_engine_data_free(struct LampEngineData *led);
/* Settings */
bool DRW_is_object_renderable(struct Object *ob);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 3f150a06cb7..20a91fc9d43 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -50,6 +50,7 @@
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
+#include "GPU_lamp.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
@@ -1197,6 +1198,7 @@ void DRW_state_reset(void) {}
#endif /* WITH_CLAY_ENGINE */
+
/* ****************************************** Settings ******************************************/
bool DRW_is_object_renderable(Object *ob)
@@ -1234,7 +1236,6 @@ static GPUTextureFormat convert_tex_format(int fbo_format, int *channels, bool *
}
}
-
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX],
int texnbr)
{
@@ -1431,6 +1432,21 @@ void DRW_object_engine_data_free(Object *ob)
BLI_freelistN(&ob->drawdata);
}
+LampEngineData *DRW_lamp_engine_data_get(Object *ob, RenderEngineType *engine_type)
+{
+ BLI_assert(ob->type == OB_LAMP);
+
+ Scene *scene = CTX_data_scene(DST.context);
+
+ /* TODO Dupliobjects */
+ return GPU_lamp_engine_data_get(scene, ob, NULL, engine_type);
+}
+
+void DRW_lamp_engine_data_free(LampEngineData *led)
+{
+ return GPU_lamp_engine_data_free(led);
+}
+
/* **************************************** RENDERING ************************************** */
#define TIMER_FALLOFF 0.1f
diff --git a/source/blender/gpu/GPU_lamp.h b/source/blender/gpu/GPU_lamp.h
index 32793830479..e08fbede80a 100644
--- a/source/blender/gpu/GPU_lamp.h
+++ b/source/blender/gpu/GPU_lamp.h
@@ -42,15 +42,17 @@ struct RenderEngineType;
typedef struct GPULamp GPULamp;
+#define MAX_LAMP_DATA 2
+
typedef struct LampEngineData {
- struct GPUFrameBuffer *framebuffers[4];
- struct GPUTexture *textures[4];
- void *storage[4];
+ void *storage[MAX_LAMP_DATA];
} LampEngineData;
-GPULamp *GPU_lamp_from_engine(struct Scene *scene, struct Object *ob, Object *par, struct RenderEngineType *re);
+LampEngineData *GPU_lamp_engine_data_get(struct Scene *scene, struct Object *ob, struct Object *par, struct RenderEngineType *re);
+
GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par);
void GPU_lamp_free(struct Object *ob);
+void GPU_lamp_engine_data_free(LampEngineData *led);
bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma);
bool GPU_lamp_has_shadow_buffer(GPULamp *lamp);
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 2411fe755af..8bc7bdb6df2 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -44,7 +44,7 @@ typedef struct GPUViewport GPUViewport;
#define MAX_BUFFERS 8
#define MAX_TEXTURES 16
#define MAX_PASSES 16
-#define MAX_STORAGE 5 /* extend if needed */
+#define MAX_STORAGE 9 /* extend if needed */
/* All FramebufferLists are just the same pointers with different names */
typedef struct FramebufferList {
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 425fcecae0c..fb02efb8e99 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -143,8 +143,7 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo
else
attachment = GL_COLOR_ATTACHMENT0 + slot;
- glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
- GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0);
+ glFramebufferTexture(GL_FRAMEBUFFER, attachment, GPU_texture_opengl_bindcode(tex), 0);
if (GPU_texture_depth(tex))
fb->depthtex = tex;
diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c
index ee0bcb83a6a..75198122ab5 100644
--- a/source/blender/gpu/intern/gpu_lamp.c
+++ b/source/blender/gpu/intern/gpu_lamp.c
@@ -214,7 +214,7 @@ static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size)
return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL);
}
-GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re)
+LampEngineData *GPU_lamp_engine_data_get(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re)
{
GPULamp *lamp;
LinkData *link;
@@ -223,7 +223,7 @@ GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct Rend
lamp = (GPULamp *)link->data;
if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re))
- return link->data;
+ return &lamp->data;
}
lamp = MEM_callocN(sizeof(GPULamp), "GPULamp");
@@ -238,7 +238,7 @@ GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct Rend
lamp->la = ob->data;
lamp->re = re;
- return lamp;
+ return &lamp->data;
}
GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
@@ -364,6 +364,16 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
+void GPU_lamp_engine_data_free(LampEngineData *led)
+{
+ for (int i = 0; i < MAX_LAMP_DATA; ++i) {
+ if (led->storage[i]) {
+ MEM_freeN(led->storage[i]);
+ led->storage[i] = NULL;
+ }
+ }
+}
+
void GPU_lamp_free(Object *ob)
{
GPULamp *lamp;
@@ -384,6 +394,7 @@ void GPU_lamp_free(Object *ob)
}
gpu_lamp_shadow_free(lamp);
+ GPU_lamp_engine_data_free(&lamp->data);
MEM_freeN(lamp);
}
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index f4c3e16c0b5..4b3570e3831 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -169,9 +169,11 @@ static bool GPU_texture_try_alloc(
case GL_PROXY_TEXTURE_1D:
glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL);
break;
+ case GL_PROXY_TEXTURE_1D_ARRAY:
case GL_PROXY_TEXTURE_2D:
glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL);
break;
+ case GL_PROXY_TEXTURE_2D_ARRAY:
case GL_PROXY_TEXTURE_3D:
glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL);
break;
@@ -279,14 +281,20 @@ static GPUTexture *GPU_texture_create_nD(
glBindTexture(tex->target, tex->bindcode);
/* Check if texture fit in VRAM */
- if (d > 0) {
- proxy = GL_PROXY_TEXTURE_3D;
+ if (n == 1) {
+ if (h == 0)
+ proxy = GL_PROXY_TEXTURE_1D;
+ else
+ proxy = GL_PROXY_TEXTURE_1D_ARRAY;
}
- else if (h > 0) {
- proxy = GL_PROXY_TEXTURE_2D;
+ else if (n == 2) {
+ if (d == 0)
+ proxy = GL_PROXY_TEXTURE_2D;
+ else
+ proxy = GL_PROXY_TEXTURE_2D_ARRAY;
}
- else {
- proxy = GL_PROXY_TEXTURE_1D;
+ else if (n == 3) {
+ proxy = GL_PROXY_TEXTURE_3D;
}
valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels,