diff options
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 3 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee.c | 49 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_lights.c | 437 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_private.h | 86 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl | 72 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl | 90 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/shadow_frag.glsl | 3 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/shadow_geom.glsl | 21 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/shadow_vert.glsl | 11 | ||||
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 4 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 18 | ||||
-rw-r--r-- | source/blender/gpu/GPU_lamp.h | 10 | ||||
-rw-r--r-- | source/blender/gpu/GPU_viewport.h | 2 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_lamp.c | 17 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_texture.c | 20 |
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, |