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:
authorClément Foucault <foucault.clem@gmail.com>2017-04-10 13:06:17 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-04-10 13:36:32 +0300
commitf2f16a2568c2006b46ba0daa851961355a42f20b (patch)
tree105dd51aacc1d5ca57d9da13bbaad4baf78df7d4 /source/blender
parent0811d089b4b88ff553b6514771b1e324025e15ad (diff)
Eevee: First Shadows implementation
Using Texture Arrays to store shadow maps so less texture slots are used when shading. This means a large amount of shadows can be supported. Support Projection Shadow Map for sun like in old BI/BGE. Support Cube Shadow Map for Point/Spot/Area lights. the benefit of using it for spot light is that the spot angle does not change shadow resolution (at the cost of more memory used). The implementation of the cubemap sampling is targeted for 3.3 core. We rely on 2D texture arrays to store cubemaps faces and sample the right one manualy. Significant performance improvement can be done using Cubemap Arrays on supported hardware. Shadows are only hardware filtered. Prefiltered shadows and settings comming next.
Diffstat (limited to 'source/blender')
-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,