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.
This commit is contained in:
Clément Foucault 2017-04-10 12:06:17 +02:00
parent 0811d089b4
commit f2f16a2568
16 changed files with 723 additions and 149 deletions

View File

@ -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)

View File

@ -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);
{
@ -119,6 +134,14 @@ static void EEVEE_cache_init(void *vedata)
stl->g_data = MEM_mallocN(sizeof(g_data), "g_data");
}
{
/* 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)

View File

@ -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;
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_add(EEVEE_StorageList *stl, Object *ob)
{
BLI_addtail(&stl->g_data->lamps, BLI_genericNodeN(ob));
stl->lights_info->light_count += 1;
EEVEE_LampsInfo *linfo = stl->lamps;
/* 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");
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);
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++;
}
}
void EEVEE_lights_cache_finish(EEVEE_StorageList *stl)
void EEVEE_lights_cache_finish(EEVEE_StorageList *stl, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl)
{
int light_ct = stl->lights_info->light_count;
EEVEE_LampsInfo *linfo = stl->lamps;
if (light_ct > MAX_LIGHT) {
printf("Too much lamps in the scene !!!\n");
stl->lights_info->light_count = MAX_LIGHT;
/* 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;
}
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;
/* 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);
}
/* Update buffer with lamp data */
static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led)
{
/* TODO only update if data changes */
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]);
/* 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;
/* 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->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;
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->sizey = evli->sizex;
}
}
BLI_freelistN(&stl->g_data->lamps);
else {
evli->radius = MAX2(0.001f, la->area_size);
}
/* We changed light data so we need to upload it */
EEVEE_lights_update(stl);
/* 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;
}
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)
{
int light_ct = stl->lights_info->light_count;
EEVEE_LampsInfo *linfo = stl->lamps;
Object *ob;
int i;
/* 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;
/* 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;
/* 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);
copy_v3_v3(evli->rightvec, mat[0]);
normalize_v3(evli->rightvec);
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;
}
}
else {
evli->sizex = 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 */
/* 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;
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);
}
/* Upload buffer to GPU */
DRW_uniformbuffer_update(stl->lights_ubo, stl->lights_data);
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);
}
}
/* 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;
linfo->layer = i;
copy_m4_m4(linfo->shadowmat, evsmd->viewprojmat);
DRW_draw_pass(vedata->psl->shadow_pass);
}
// DRW_framebuffer_bind(e_data.shadow_cascade_fb);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -0,0 +1,3 @@
void main() {
}

View File

@ -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();
}

View File

@ -0,0 +1,11 @@
uniform mat4 ShadowMatrix;
uniform mat4 ModelMatrix;
in vec3 pos;
out vec4 vPos;
void main() {
vPos = ModelMatrix * vec4(pos, 1.0);
}

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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);
}

View File

@ -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,15 +281,21 @@ static GPUTexture *GPU_texture_create_nD(
glBindTexture(tex->target, tex->bindcode);
/* Check if texture fit in VRAM */
if (d > 0) {
if (n == 1) {
if (h == 0)
proxy = GL_PROXY_TEXTURE_1D;
else
proxy = GL_PROXY_TEXTURE_1D_ARRAY;
}
else if (n == 2) {
if (d == 0)
proxy = GL_PROXY_TEXTURE_2D;
else
proxy = GL_PROXY_TEXTURE_2D_ARRAY;
}
else if (n == 3) {
proxy = GL_PROXY_TEXTURE_3D;
}
else if (h > 0) {
proxy = GL_PROXY_TEXTURE_2D;
}
else {
proxy = GL_PROXY_TEXTURE_1D;
}
valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels,
&rescaled_fpixels);