Eevee: Introduction of world preconvolved envmap.

For now only compute GGX convolution. The GGX LUT used for the split sum approximation (UE4) is merged with the LTX mag LUT that uses the same parameters (theta and roughness)
This commit is contained in:
2017-04-18 12:50:09 +02:00
parent f1fb605ec9
commit edcf128ce2
22 changed files with 1867 additions and 103 deletions

View File

@@ -65,6 +65,7 @@ set(SRC
engines/eevee/eevee.c
engines/eevee/eevee_lights.c
engines/eevee/eevee_probes.c
engines/eevee/eevee.h
engines/eevee/eevee_private.h
@@ -103,12 +104,18 @@ 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/probe_filter_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/probe_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/probe_geom.glsl SRC)
data_to_c_simple(engines/eevee/shaders/probe_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_lut_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)
data_to_c_simple(engines/eevee/shaders/bsdf_sampling_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/ltc_lib.glsl SRC)
data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC)

View File

@@ -26,6 +26,8 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
#include "BLI_rand.h"
#include "GPU_glew.h"
#include "eevee.h"
#include "eevee_private.h"
@@ -39,29 +41,162 @@ static struct {
struct GPUShader *depth_sh;
struct GPUShader *tonemap;
struct GPUShader *shadow_sh;
/* Temp : use world shader */
struct GPUShader *probe_sh;
struct GPUShader *probe_filter_sh;
struct GPUTexture *ltc_mat;
struct GPUTexture *ltc_mag;
struct GPUTexture *brdf_lut;
struct GPUTexture *hammersley;
struct GPUTexture *jitter;
float camera_pos[3];
} e_data = {NULL}; /* Engine data */
extern char datatoc_ltc_lib_glsl[];
extern char datatoc_bsdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_direct_lib_glsl[];
extern char datatoc_bsdf_sampling_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[];
extern char datatoc_probe_filter_frag_glsl[];
extern char datatoc_probe_frag_glsl[];
extern char datatoc_probe_geom_glsl[];
extern char datatoc_probe_vert_glsl[];
/* Van der Corput sequence */
/* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */
static float radical_inverse(int i) {
unsigned int bits = (unsigned int)i;
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return (float)bits * 2.3283064365386963e-10f;
}
static struct GPUTexture *create_hammersley_sample_texture(int samples)
{
struct GPUTexture *tex;
float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * samples, "hammersley_tex");
int i;
for (i = 0; i < samples; i++) {
float phi = radical_inverse(i) * 2.0f * M_PI;
texels[i][0] = cos(phi);
texels[i][1] = sinf(phi);
}
tex = DRW_texture_create_1D(samples, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
MEM_freeN(texels);
return tex;
}
static struct GPUTexture *create_jitter_texture(int w, int h)
{
struct GPUTexture *tex;
float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * w * h, "jitter_tex");
int i;
/* TODO replace by something more evenly distributed like blue noise */
for (i = 0; i < w * h; i++) {
texels[i][0] = 2.0f * BLI_frand() - 1.0f;
texels[i][1] = 2.0f * BLI_frand() - 1.0f;
normalize_v2(texels[i]);
}
tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_WRAP, (float *)texels);
MEM_freeN(texels);
return tex;
}
static struct GPUTexture *create_ggx_lut_texture(int w, int h)
{
struct GPUTexture *tex;
#if 0 /* Used only to generate the LUT values */
struct GPUFrameBuffer *fb = NULL;
static float samples_ct = 8192.0f;
static float inv_samples_ct = 1.0f / 8192.0f;
char *lib_str = NULL;
DynStr *ds_vert = BLI_dynstr_new();
BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
lib_str = BLI_dynstr_get_cstring(ds_vert);
BLI_dynstr_free(ds_vert);
struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str,
"#define HAMMERSLEY_SIZE 8192\n"
"#define BRDF_LUT_SIZE 64\n"
"#define NOISE_SIZE 64\n");
DRWPass *pass = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1);
DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley, 0);
DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter, 1);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_add(grp, geom, NULL);
float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
tex = DRW_texture_create_2D(w, h, DRW_TEX_RG_16, DRW_TEX_FILTER, (float *)texels);
DRWFboTexture tex_filter = {&tex, DRW_BUF_RG_16, DRW_TEX_FILTER};
DRW_framebuffer_init(&fb, w, h, &tex_filter, 1);
DRW_framebuffer_bind(fb);
DRW_draw_pass(pass);
float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
glReadBuffer(GL_COLOR_ATTACHMENT0);
glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
printf("{");
for (int i = 0; i < w*h * 3; i+=3) {
printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
printf("%ff, %ff, ", data[i], data[i+1]); i+=3;
printf("%ff, %ff, \n", data[i], data[i+1]);
}
printf("}");
MEM_freeN(texels);
MEM_freeN(data);
#else
float (*texels)[3] = MEM_mallocN(sizeof(float[3]) * 64 * 64, "bsdf lut texels");
for (int i = 0; i < 64 * 64; i++) {
texels[i][0] = bsdf_split_sum_ggx[i*2 + 0];
texels[i][1] = bsdf_split_sum_ggx[i*2 + 1];
texels[i][2] = ltc_mag_ggx[i];
}
tex = DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER, (float *)texels);
MEM_freeN(texels);
#endif
return tex;
}
/* *********** FUNCTIONS *********** */
static void EEVEE_engine_init(void *vedata)
static void EEVEE_engine_init(void *ved)
{
EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
EEVEE_Data *vedata = (EEVEE_Data *)ved;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_StorageList *stl = vedata->stl;
DRWFboTexture tex = {&txl->color, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
@@ -98,6 +233,26 @@ static void EEVEE_engine_init(void *vedata)
e_data.shadow_sh = DRW_shader_create(datatoc_shadow_vert_glsl, datatoc_shadow_geom_glsl, datatoc_shadow_frag_glsl, NULL);
}
if (!e_data.probe_sh) {
e_data.probe_sh = DRW_shader_create(datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_probe_frag_glsl, NULL);
}
if (!e_data.probe_filter_sh) {
char *lib_str = NULL;
DynStr *ds_vert = BLI_dynstr_new();
BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl);
lib_str = BLI_dynstr_get_cstring(ds_vert);
BLI_dynstr_free(ds_vert);
e_data.probe_filter_sh = DRW_shader_create_with_lib(datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, datatoc_probe_filter_frag_glsl, lib_str,
"#define HAMMERSLEY_SIZE 8192\n"
"#define NOISE_SIZE 64\n");
MEM_freeN(lib_str);
}
if (!e_data.tonemap) {
e_data.tonemap = DRW_shader_create_fullscreen(datatoc_tonemap_frag_glsl, NULL);
}
@@ -106,21 +261,40 @@ static void EEVEE_engine_init(void *vedata)
e_data.ltc_mat = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, DRW_TEX_FILTER, ltc_mat_ggx);
}
if (!e_data.ltc_mag) {
e_data.ltc_mag = DRW_texture_create_2D(64, 64, DRW_TEX_R_16, DRW_TEX_FILTER, ltc_mag_ggx);
if (!e_data.hammersley) {
e_data.hammersley = create_hammersley_sample_texture(8192);
}
if (stl->lamps == NULL) {
EEVEE_lights_init(stl);
if (!e_data.jitter) {
e_data.jitter = create_jitter_texture(64, 64);
}
if (!e_data.brdf_lut) {
e_data.brdf_lut = create_ggx_lut_texture(64, 64);
}
// EEVEE_lights_update(stl);
{
float viewinvmat[4][4];
DRW_viewport_matrix_get(viewinvmat, DRW_MAT_VIEWINV);
copy_v3_v3(e_data.camera_pos, viewinvmat[3]);
}
EEVEE_lights_init(stl);
EEVEE_probes_init(vedata);
// EEVEE_lights_update(stl);
}
static DRWShadingGroup *eevee_cube_shgroup(struct GPUShader *sh, DRWPass *pass, struct Batch *geom)
{
DRWShadingGroup *grp = DRW_shgroup_instance_create(sh, pass, geom);
for (int i = 0; i < 6; ++i)
DRW_shgroup_dynamic_call_add(grp);
return grp;
}
static void EEVEE_cache_init(void *vedata)
@@ -135,13 +309,37 @@ 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->probe_background = DRW_pass_create("Probe Background Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = eevee_cube_shgroup(e_data.probe_sh, psl->probe_background, geom);
DRW_shgroup_uniform_int(grp, "Layer", &stl->probes->layer, 1);
DRW_shgroup_uniform_buffer(grp, "probeLatLong", &stl->probes->backgroundtex, 0);
}
{
psl->probe_prefilter = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = eevee_cube_shgroup(e_data.probe_filter_sh, psl->probe_prefilter, geom);
DRW_shgroup_uniform_float(grp, "sampleCount", &stl->probes->samples_ct, 1);
DRW_shgroup_uniform_float(grp, "invSampleCount", &stl->probes->invsamples_ct, 1);
DRW_shgroup_uniform_float(grp, "roughnessSquared", &stl->probes->roughness, 1);
DRW_shgroup_uniform_float(grp, "lodFactor", &stl->probes->lodfactor, 1);
DRW_shgroup_uniform_float(grp, "lodMax", &stl->probes->lodmax, 1);
DRW_shgroup_uniform_int(grp, "Layer", &stl->probes->layer, 1);
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley, 0);
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", txl->probe_rt, 3);
}
{
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);
@@ -158,9 +356,11 @@ static void EEVEE_cache_init(void *vedata)
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_float(stl->g_data->default_lit_grp, "lodMax", &stl->probes->lodmax, 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);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "brdfLut", e_data.brdf_lut, 1);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "probeFiltered", txl->probe_pool, 2);
/* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
}
@@ -208,8 +408,8 @@ static void EEVEE_cache_finish(void *vedata)
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);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 4);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 5);
}
static void EEVEE_draw_scene(void *vedata)
@@ -221,6 +421,9 @@ static void EEVEE_draw_scene(void *vedata)
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Refresh Probes */
EEVEE_refresh_probe((EEVEE_Data *)vedata);
/* Refresh shadows */
EEVEE_draw_shadows((EEVEE_Data *)vedata);
@@ -250,9 +453,13 @@ static void EEVEE_engine_free(void)
{
DRW_SHADER_FREE_SAFE(e_data.default_lit);
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_sh);
DRW_SHADER_FREE_SAFE(e_data.tonemap);
DRW_TEXTURE_FREE_SAFE(e_data.ltc_mat);
DRW_TEXTURE_FREE_SAFE(e_data.ltc_mag);
DRW_TEXTURE_FREE_SAFE(e_data.brdf_lut);
DRW_TEXTURE_FREE_SAFE(e_data.hammersley);
DRW_TEXTURE_FREE_SAFE(e_data.jitter);
}
static void EEVEE_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)

View File

@@ -241,46 +241,6 @@ static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngi
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];

File diff suppressed because it is too large Load Diff

View File

@@ -33,7 +33,14 @@ struct Object;
#define MAX_CASCADE_NUM 4
typedef struct EEVEE_PassList {
/* Shadows */
struct DRWPass *shadow_pass;
/* Probes */
struct DRWPass *probe_background;
struct DRWPass *probe_prefilter;
struct DRWPass *probe_sh;
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
struct DRWPass *pass;
@@ -41,17 +48,29 @@ typedef struct EEVEE_PassList {
} EEVEE_PassList;
typedef struct EEVEE_FramebufferList {
struct GPUFrameBuffer *main; /* HDR */
/* Shadows */
struct GPUFrameBuffer *shadow_cube_fb;
struct GPUFrameBuffer *shadow_map_fb;
struct GPUFrameBuffer *shadow_cascade_fb;
/* Probes */
struct GPUFrameBuffer *probe_fb;
struct GPUFrameBuffer *probe_filter_fb;
struct GPUFrameBuffer *probe_sh_fb;
struct GPUFrameBuffer *main; /* HDR */
} EEVEE_FramebufferList;
typedef struct EEVEE_TextureList {
struct GPUTexture *color; /* R11_G11_B10 */
/* Shadows */
struct GPUTexture *shadow_depth_cube_pool;
struct GPUTexture *shadow_depth_map_pool;
struct GPUTexture *shadow_depth_cascade_pool;
/* Probes */
struct GPUTexture *probe_rt; /* R16_G16_B16 */
struct GPUTexture *probe_depth_rt;
struct GPUTexture *probe_pool; /* R11_G11_B10 */
struct GPUTexture *color; /* R16_G16_B16 */
} EEVEE_TextureList;
typedef struct EEVEE_StorageList {
@@ -61,6 +80,9 @@ typedef struct EEVEE_StorageList {
struct GPUUniformBuffer *light_ubo;
struct GPUUniformBuffer *shadow_ubo;
/* Probes */
struct EEVEE_ProbesInfo *probes;
struct g_data *g_data;
} EEVEE_StorageList;
@@ -111,6 +133,20 @@ typedef struct EEVEE_LampsInfo {
struct EEVEE_ShadowMap shadow_map_data[MAX_SHADOW_MAP];
struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE];
} EEVEE_LampsInfo;
/* ************ PROBE DATA ************* */
typedef struct EEVEE_ProbesInfo {
/* For rendering probes */
float probemat[6][4][4];
int layer;
float samples_ct;
float invsamples_ct;
float roughness;
float lodfactor;
float lodmax;
struct GPUTexture *backgroundtex;
} EEVEE_ProbesInfo;
/* *********************************** */
typedef struct EEVEE_Data {
@@ -131,11 +167,7 @@ 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;
struct DRWShadingGroup *depth_shgrp_cull;
struct DRWShadingGroup *depth_shgrp_cull_select;
struct DRWShadingGroup *depth_shgrp_cull_active;
struct ListBase lamps; /* Lamps gathered during cache iteration */
} g_data; /* Transient data */
@@ -146,4 +178,54 @@ 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, EEVEE_TextureList *txl, EEVEE_FramebufferList *fbl);
void EEVEE_lights_update(EEVEE_StorageList *stl);
void EEVEE_draw_shadows(EEVEE_Data *vedata);
void EEVEE_draw_shadows(EEVEE_Data *vedata);
/* eevee_probes.c */
void EEVEE_probes_init(EEVEE_Data *vedata);
void EEVEE_probes_cache_init(EEVEE_Data *vedata);
void EEVEE_probes_cache_add(EEVEE_Data *vedata, Object *ob);
void EEVEE_probes_cache_finish(EEVEE_Data *vedata);
void EEVEE_probes_update(EEVEE_Data *vedata);
void EEVEE_refresh_probe(EEVEE_Data *vedata);
/* Shadow Matrix */
static const 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}
};
/* Cubemap Matrices */
static const 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}},
};

View File

@@ -0,0 +1,209 @@
/*
* Copyright 2016, Blender Foundation.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Blender Institute
*
*/
/** \file eevee_lights.c
* \ingroup DNA
*/
#include "DNA_world_types.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
#include "DRW_render.h"
#include "eevee.h"
#include "eevee_private.h"
#include "GPU_texture.h"
#include "GPU_glew.h"
typedef struct EEVEE_ProbeData {
short probe_id, shadow_id;
} EEVEE_ProbeData;
/* TODO Option */
#define PROBE_SIZE 512
/* *********** FUNCTIONS *********** */
void EEVEE_probes_init(EEVEE_Data *vedata)
{
EEVEE_StorageList *stl = vedata->stl;
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
if (!stl->probes) {
stl->probes = MEM_callocN(sizeof(EEVEE_ProbesInfo), "EEVEE_ProbesInfo");
}
if (!txl->probe_rt) {
float *test_tex;
const float face_col[6][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
test_tex = MEM_mallocN(sizeof(float) * 6 * PROBE_SIZE * PROBE_SIZE * 4, "test tex");
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < PROBE_SIZE * PROBE_SIZE; ++j) {
copy_v4_v4(test_tex + i * PROBE_SIZE * PROBE_SIZE * 4 + j * 4, face_col[i]);
}
}
txl->probe_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, (float *)test_tex);
txl->probe_depth_rt = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_DEPTH_24, DRW_TEX_FILTER, NULL);
MEM_freeN(test_tex);
}
DRWFboTexture tex_probe[2] = {{&txl->probe_depth_rt, DRW_BUF_DEPTH_24, DRW_TEX_FILTER},
{&txl->probe_rt, DRW_BUF_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}};
DRW_framebuffer_init(&fbl->probe_fb, PROBE_SIZE, PROBE_SIZE, tex_probe, 2);
if (!txl->probe_pool) {
float *test_tex;
const float face_col[6][4] = {{1.0f, 0.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 0.0f, 1.0f, 1.0f},
{1.0f, 0.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {0.0f, 1.0f, 1.0f, 1.0f}};
test_tex = MEM_mallocN(sizeof(float) * 6 * PROBE_SIZE * PROBE_SIZE * 4, "test tex");
for (int i = 0; i < 6; ++i) {
for (int j = 0; j < PROBE_SIZE * PROBE_SIZE; ++j) {
copy_v4_v4(test_tex + i * PROBE_SIZE * PROBE_SIZE * 4 + j * 4, face_col[i]);
}
}
/* TODO array */
txl->probe_pool = DRW_texture_create_cube(PROBE_SIZE, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, (float *)test_tex);
MEM_freeN(test_tex);
}
DRWFboTexture tex_filter = {&txl->probe_pool, DRW_BUF_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
DRW_framebuffer_init(&fbl->probe_filter_fb, PROBE_SIZE, PROBE_SIZE, &tex_filter, 1);
}
void EEVEE_probes_cache_init(EEVEE_Data *UNUSED(vedata))
{
return;
}
void EEVEE_probes_cache_add(EEVEE_Data *UNUSED(vedata), Object *UNUSED(ob))
{
return;
}
void EEVEE_probes_cache_finish(EEVEE_Data *UNUSED(vedata))
{
return;
}
void EEVEE_probes_update(EEVEE_Data *UNUSED(vedata))
{
return;
}
void EEVEE_refresh_probe(EEVEE_Data *vedata)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_TextureList *txl = vedata->txl;
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_ProbesInfo *pinfo = stl->probes;
const bContext *C = DRW_get_context();
Scene *scene = CTX_data_scene(C);
World *world = scene->world;
float projmat[4][4];
/* 1 - Render to cubemap target using geometry shader. */
/* We don't need to clear since we render the background. */
pinfo->layer = 0;
perspective_m4(projmat, -0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 100.0f);
for (int i = 0; i < 6; ++i) {
mul_m4_m4m4(pinfo->probemat[i], projmat, cubefacemat[i]);
}
/* Debug Tex : Use World 1st Tex Slot */
if (world && world->mtex[0]) {
MTex *mtex = world->mtex[0];
if (mtex && mtex->tex) {
Tex *tex = mtex->tex;
if (tex->ima) {
pinfo->backgroundtex = GPU_texture_from_blender(tex->ima, &tex->iuser, GL_TEXTURE_2D, true, 0.0, 0);
DRW_framebuffer_bind(fbl->probe_fb);
DRW_draw_pass(psl->probe_background);
}
}
}
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
/* Bind next framebuffer to be able to write to probe_rt. */
DRW_framebuffer_bind(fbl->probe_filter_fb);
DRW_texture_generate_mipmaps(txl->probe_rt);
/* 3 - Render to probe array to the specified layer, do prefiltering. */
/* Detach to rebind the right mipmap. */
DRW_framebuffer_texture_detach(txl->probe_pool);
float mipsize = PROBE_SIZE * 2;
int miplevels = 1 + (int)floorf(log2f(PROBE_SIZE));
for (int i = 0; i < miplevels - 2; i++) {
float bias = (i == 0) ? 0.0f : 1.0f;
mipsize /= 2;
CLAMP_MIN(mipsize, 1);
pinfo->layer = 0;
pinfo->roughness = (float)i / ((float)miplevels - 3.0f);
pinfo->roughness *= pinfo->roughness; /* Disney Roughness */
pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */
CLAMP(pinfo->roughness, 1e-8f, 0.99999f); /* Avoid artifacts */
#if 1 /* Variable Sample count (fast) */
switch (i) {
case 0: pinfo->samples_ct = 1.0f; break;
case 1: pinfo->samples_ct = 16.0f; break;
case 2: pinfo->samples_ct = 32.0f; break;
case 3: pinfo->samples_ct = 64.0f; break;
default: pinfo->samples_ct = 128.0f; break;
}
#else /* Constant Sample count (slow) */
pinfo->samples_ct = 1024.0f;
#endif
pinfo->invsamples_ct = 1.0f / pinfo->samples_ct;
pinfo->lodfactor = bias + 0.5f * log((float)(PROBE_SIZE * PROBE_SIZE) * pinfo->invsamples_ct) / log(2);
pinfo->lodmax = (float)miplevels - 3.0f;
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, i);
DRW_framebuffer_viewport_size(fbl->probe_filter_fb, mipsize, mipsize);
DRW_draw_pass(psl->probe_prefilter);
DRW_framebuffer_texture_detach(txl->probe_pool);
}
/* reattach to have a valid framebuffer. */
DRW_framebuffer_texture_attach(fbl->probe_filter_fb, txl->probe_pool, 0, 0);
/* 4 - Compute spherical harmonics */
/* TODO */
// DRW_framebuffer_bind(fbl->probe_sh_fb);
// DRW_draw_pass(psl->probe_sh);
}

View File

@@ -1,5 +1,6 @@
#define M_PI 3.14159265358979323846 /* pi */
#define M_PI_2 1.57079632679489661923 /* pi/2 */
#define M_1_PI 0.318309886183790671538 /* 1/pi */
#define M_1_2PI 0.159154943091895335768 /* 1/(2*pi) */
#define M_1_PI2 0.101321183642337771443 /* 1/(pi^2) */
@@ -52,6 +53,10 @@ struct ShadowMapData {
#define sh_map_far near_far_bias.y
#define sh_map_bias near_far_bias.z
#ifndef MAX_CASCADE_NUM
#define MAX_CASCADE_NUM 1
#endif
struct ShadowCascadeData {
mat4 shadowmat[MAX_CASCADE_NUM];
vec4 bias_count;
@@ -98,26 +103,6 @@ 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);
@@ -149,6 +134,45 @@ vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 plan
return lineorigin + linedirection * dist;
}
/* -- Tangent Space conversion -- */
vec3 tangent_to_world(vec3 vector, vec3 N, vec3 T, vec3 B)
{
return T * vector.x + B * vector.y + N * vector.z;
}
vec3 world_to_tangent(vec3 vector, vec3 N, vec3 T, vec3 B)
{
return vec3( dot(T, vector), dot(B, vector), dot(N, vector));
}
void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
{
vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0,0.0,1.0) : vec3(1.0,0.0,0.0);
T = normalize( cross(UpVector, N) );
B = cross(N, T);
}
/* ---- Opengl Depth conversion ---- */
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 rectangle_solid_angle(AreaData ad)
{
vec3 n0 = normalize(cross(ad.corner[0], ad.corner[1]));
@@ -166,7 +190,9 @@ float rectangle_solid_angle(AreaData ad)
vec3 get_specular_dominant_dir(vec3 N, vec3 R, float roughness)
{
return normalize(mix(N, R, 1.0 - roughness * roughness));
float smoothness = 1.0 - roughness;
float fac = smoothness * (sqrt(smoothness) + roughness);
return normalize(mix(N, R, fac));
}
/* From UE4 paper */

View File

@@ -129,7 +129,7 @@ float direct_ggx_sphere(LightData ld, ShadingData sd, float roughness)
bsdf *= 1.25331413731;
#endif
bsdf *= texture(ltcMag, uv).r; /* Bsdf intensity */
bsdf *= texture(brdfLut, uv).b; /* Bsdf intensity */
bsdf *= M_1_2PI * M_1_PI;
#else
float energy_conservation;
@@ -150,7 +150,7 @@ float direct_ggx_rectangle(LightData ld, ShadingData sd, float roughness)
mat3 ltcmat = ltc_matrix(uv);
float bsdf = ltc_evaluate(sd.N, sd.V, ltcmat, sd.area_data.corner);
bsdf *= texture(ltcMag, uv).r; /* Bsdf intensity */
bsdf *= texture(brdfLut, uv).b; /* Bsdf intensity */
bsdf *= M_1_2PI;
#else
float energy_conservation;

View File

@@ -0,0 +1,46 @@
out vec4 FragColor;
void main() {
vec3 N, T, B, V;
float NV = ( 1.0 - (clamp(gl_FragCoord.y / BRDF_LUT_SIZE, 1e-4, 0.9999)));
float sqrtRoughness = clamp(gl_FragCoord.x / BRDF_LUT_SIZE, 1e-4, 0.9999);
float a = sqrtRoughness * sqrtRoughness;
float a2 = a * a;
N = vec3(0.0, 0.0, 1.0);
T = vec3(1.0, 0.0, 0.0);
B = vec3(0.0, 1.0, 0.0);
V = vec3(sqrt(1.0 - NV * NV), 0.0, NV);
setup_noise();
/* Integrating BRDF */
float brdf_accum = 0.0;
float fresnel_accum = 0.0;
for (float i = 0; i < sampleCount; i++) {
vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */
vec3 L = -reflect(V, H);
float NL = L.z;
if (NL > 0.0) {
float NH = max(H.z, 0.0);
float VH = max(dot(V, H), 0.0);
float G1_v = G1_Smith_GGX(NV, a2);
float G1_l = G1_Smith_GGX(NL, a2);
float G_smith = 4.0 * NV * NL / (G1_v * G1_l); /* See G1_Smith_GGX for explanations. */
float brdf = (G_smith * VH) / (NH * NV);
float Fc = pow(1.0 - VH, 5.0);
brdf_accum += (1.0 - Fc) * brdf;
fresnel_accum += Fc * brdf;
}
}
brdf_accum /= sampleCount;
fresnel_accum /= sampleCount;
FragColor = vec4(brdf_accum, fresnel_accum, 0.0, 1.0);
}

View File

@@ -0,0 +1,54 @@
uniform sampler1D texHammersley;
uniform sampler2D texJitter;
uniform float sampleCount;
uniform float invSampleCount;
vec2 jitternoise = vec2(0.0);
void setup_noise(void)
{
jitternoise = texture(texJitter, gl_FragCoord.xy / NOISE_SIZE, 0).rg; /* Global variable */
}
vec3 hammersley_3d(float i, float invsamplenbr)
{
vec3 Xi; /* Theta, cos(Phi), sin(Phi) */
Xi.x = i * invsamplenbr; /* i/samples */
Xi.x = fract(Xi.x + jitternoise.x);
int u = int(mod(i + jitternoise.y * HAMMERSLEY_SIZE, HAMMERSLEY_SIZE));
Xi.yz = texelFetch(texHammersley, u, 0).rg;
return Xi;
}
vec3 hammersley_3d(float i)
{
return hammersley_3d(i, invSampleCount);
}
/* -------------- BSDFS -------------- */
float pdf_ggx_reflect(float NH, float a2)
{
return NH * a2 / D_ggx_opti(NH, a2);
}
vec3 sample_ggx(float nsample, float a2, vec3 N, vec3 T, vec3 B)
{
vec3 Xi = hammersley_3d(nsample);
/* Theta is the aperture angle of the cone */
float z = sqrt( (1.0 - Xi.x) / ( 1.0 + a2 * Xi.x - Xi.x ) ); /* cos theta */
float r = sqrt( 1.0 - z * z ); /* sin theta */
float x = r * Xi.y;
float y = r * Xi.z;
/* Microfacet Normal */
vec3 Ht = vec3(x, y, z);
return tangent_to_world(Ht, N, T, B);
}

View File

@@ -3,6 +3,13 @@ uniform int light_count;
uniform vec3 cameraPos;
uniform vec3 eye;
uniform mat4 ProjectionMatrix;
uniform samplerCube probeFiltered;
uniform float lodMax;
#ifndef USE_LTC
uniform sampler2D brdfLut;
#endif
uniform sampler2DArrayShadow shadowCubes;
uniform sampler2DArrayShadow shadowMaps;
// uniform sampler2DArrayShadow shadowCascades;
@@ -190,13 +197,16 @@ void main()
sd.R = reflect(-sd.V, sd.N);
/* hardcoded test vars */
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;
vec3 albedo = vec3(0.0);
vec3 f0 = mix(vec3(0.83, 0.5, 0.1), vec3(0.03, 0.03, 0.03), saturate(worldPosition.y/2));
vec3 specular = mix(f0, vec3(1.0), pow(max(0.0, 1.0 - dot(sd.N, sd.V)), 5.0));
float roughness = saturate(worldPosition.x/lodMax);
sd.spec_dominant_dir = get_specular_dominant_dir(sd.N, sd.R, roughness);
vec3 radiance = vec3(0.0);
/* Analitic Lights */
for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) {
LightData ld = lights_data[i];
@@ -212,5 +222,11 @@ void main()
radiance += vis * (albedo * diff + specular * spec) * ld.l_color;
}
/* Envmaps */
vec2 uv = ltc_coords(dot(sd.N, sd.V), sqrt(roughness));
vec2 brdf_lut = texture(brdfLut, uv).rg;
vec3 Li = textureLod(probeFiltered, sd.spec_dominant_dir, roughness * lodMax).rgb;
radiance += Li * brdf_lut.y + f0 * Li * brdf_lut.x;
fragColor = vec4(radiance, 1.0);
}

View File

@@ -4,7 +4,7 @@
#define LTC_LUT_SIZE 64
uniform sampler2D ltcMat;
uniform sampler2D ltcMag;
uniform sampler2D brdfLut;
/* from Real-Time Area Lighting: a Journey from Research to Production
* Stephen Hill and Eric Heitz */

View File

@@ -0,0 +1,49 @@
uniform samplerCube probeHdr;
uniform float roughnessSquared;
uniform float lodFactor;
uniform float lodMax;
in vec3 worldPosition;
out vec4 FragColor;
void main() {
vec3 N, T, B, V;
vec3 R = normalize(worldPosition);
/* Isotropic assumption */
N = V = R;
make_orthonormal_basis(N, T, B); /* Generate tangent space */
/* Noise to dither the samples */
/* Note : ghosting is better looking than noise. */
// setup_noise();
/* Integrating Envmap */
float weight = 0.0;
vec3 out_radiance = vec3(0.0);
for (float i = 0; i < sampleCount; i++) {
vec3 H = sample_ggx(i, roughnessSquared, N, T, B); /* Microfacet normal */
vec3 L = -reflect(V, H);
float NL = dot(N, L);
if (NL > 0.0) {
float NH = max(1e-8, dot(N, H)); /* cosTheta */
/* Coarse Approximation of the mapping distortion
* Unit Sphere -> Cubemap Face */
const float dist = 4.0 * M_PI / 6.0;
float pdf = pdf_ggx_reflect(NH, roughnessSquared);
/* http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html : Equation 13 */
float lod = clamp(lodFactor - 0.5 * log2(pdf * dist), 0.0, lodMax) ;
out_radiance += textureCubeLod(probeHdr, L, lod).rgb * NL;
weight += NL;
}
}
FragColor = vec4(out_radiance / weight, 1.0);
}

View File

@@ -0,0 +1,26 @@
in vec3 worldPosition;
uniform sampler2D probeLatLong;
out vec4 FragColor;
float hypot(float x, float y) { return sqrt(x*x + y*y); }
void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
{
vec3 nco = normalize(co);
float u = -atan(nco.y, nco.x) / (2.0 * 3.1415) + 0.5;
float v = atan(nco.z, hypot(nco.x, nco.y)) / 3.1415 + 0.5;
color = texture2D(ima, vec2(u, v));
}
void main() {
vec3 L = normalize(worldPosition);
vec2 uvs = gl_FragCoord.xy / 256.0;
float dist = dot(L, vec3(0.0,1.0,0.0));
dist = (dist > 0.99) ? 1e1 : 0.0;
FragColor = vec4(dist,dist,dist, 1.0);
node_tex_environment_equirectangular(L, probeLatLong, FragColor);
}

View File

@@ -0,0 +1,28 @@
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
uniform int Layer;
in vec4 vPos[];
in int face[];
out vec3 worldPosition;
out vec3 worldNormal;
const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0));
const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0));
const vec3 y_axis[6] = vec3[6](vec3(0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0), vec3( 0.0, -1.0, 0.0), vec3( 0.0, -1.0, 0.0));
void main() {
int f = face[0];
gl_Layer = Layer + f;
for (int v = 0; v < 3; ++v) {
gl_Position = vPos[v];
worldPosition = x_axis[f] * vPos[v].x + y_axis[f] * vPos[v].y + maj_axes[f];
EmitVertex();
}
EndPrimitive();
}

View File

@@ -0,0 +1,10 @@
in vec3 pos;
out vec4 vPos;
out int face;
void main() {
vPos = vec4(pos, 1.0);
face = gl_InstanceID;
}

View File

@@ -1,5 +1,4 @@
uniform mat4 ShadowMatrix;
uniform mat4 ModelMatrix;
in vec3 pos;

View File

@@ -142,6 +142,7 @@ typedef enum {
DRW_TEX_FILTER = (1 << 0),
DRW_TEX_WRAP = (1 << 1),
DRW_TEX_COMPARE = (1 << 2),
DRW_TEX_MIPMAP = (1 << 3),
} DRWTextureFlag;
struct GPUTexture *DRW_texture_create_1D(
@@ -152,6 +153,7 @@ struct GPUTexture *DRW_texture_create_2D_array(
int w, int h, int d, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
struct GPUTexture *DRW_texture_create_cube(
int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
void DRW_texture_generate_mipmaps(struct GPUTexture *tex);
void DRW_texture_free(struct GPUTexture *tex);
#define DRW_TEXTURE_FREE_SAFE(tex) do { \
if (tex != NULL) { \
@@ -176,9 +178,6 @@ void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
#define DRW_BUF_RG_8 6
#define DRW_BUF_RG_16 7
#define DRW_BUF_RG_32 8
#define DRW_BUF_RGB_8 9
#define DRW_BUF_RGB_16 10
#define DRW_BUF_RGB_32 11
#define DRW_BUF_RGBA_8 12
#define DRW_BUF_RGBA_16 13
#define DRW_BUF_RGBA_32 14
@@ -194,9 +193,10 @@ typedef struct DRWFboTexture {
void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
void DRW_framebuffer_clear(bool color, bool depth, bool stencil, float clear_col[4], float clear_depth);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip);
void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer *fb_write, bool depth);
void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int w, int h);
/* Shaders */
struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);

View File

@@ -210,6 +210,7 @@ static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *da
switch (format) {
case DRW_TEX_RGBA_8: *data_type = GPU_RGBA8; break;
case DRW_TEX_RGBA_16: *data_type = GPU_RGBA16F; break;
case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
case DRW_TEX_RG_16: *data_type = GPU_RG16F; break;
case DRW_TEX_RG_32: *data_type = GPU_RG32F; break;
case DRW_TEX_R_8: *data_type = GPU_R8; break;
@@ -217,7 +218,6 @@ static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *da
#if 0
case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break;
case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break;
case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break;
case DRW_TEX_RG_8: *data_type = GPU_RG8; break;
case DRW_TEX_R_32: *data_type = GPU_R32F; break;
@@ -257,6 +257,10 @@ static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
{
GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
if (flags & DRW_TEX_MIPMAP) {
GPU_texture_mipmap_mode(tex, true);
DRW_texture_generate_mipmaps(tex);
}
GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP);
GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
GPU_texture_unbind(tex);
@@ -314,6 +318,13 @@ GPUTexture *DRW_texture_create_cube(int w, DRWTextureFormat format, DRWTextureFl
return tex;
}
void DRW_texture_generate_mipmaps(GPUTexture *tex)
{
GPU_texture_bind(tex, 0);
GPU_texture_generate_mipmap(tex);
GPU_texture_unbind(tex);
}
void DRW_texture_free(GPUTexture *tex)
{
GPU_texture_free(tex);
@@ -1222,6 +1233,7 @@ static GPUTextureFormat convert_tex_format(int fbo_format, int *channels, bool *
(fbo_format == DRW_BUF_DEPTH_24));
switch (fbo_format) {
case DRW_BUF_RG_16: *channels = 2; return GPU_RG16F;
case DRW_BUF_RGBA_8: *channels = 4; return GPU_RGBA8;
case DRW_BUF_RGBA_16: *channels = 4; return GPU_RGBA16F;
case DRW_BUF_DEPTH_24: *channels = 1; return GPU_DEPTH_COMPONENT24;
@@ -1241,19 +1253,19 @@ void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRW
*fb = GPU_framebuffer_create();
for (int i = 0; i < texnbr; ++i) {
int channels;
bool is_depth;
DRWFboTexture fbotex = textures[i];
GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels, &is_depth);
if (!*fbotex.tex) {
int channels;
bool is_depth;
GPUTextureFormat gpu_format = convert_tex_format(fbotex.format, &channels, &is_depth);
*fbotex.tex = GPU_texture_create_2D_custom(width, height, channels, gpu_format, NULL, NULL);
drw_texture_set_parameters(*fbotex.tex, fbotex.flag);
}
if (!is_depth) {
++color_attachment;
}
if (!is_depth) {
++color_attachment;
}
GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment, 0);
@@ -1305,6 +1317,11 @@ void DRW_framebuffer_blit(struct GPUFrameBuffer *fb_read, struct GPUFrameBuffer
GPU_framebuffer_blit(fb_read, 0, fb_write, 0, depth);
}
void DRW_framebuffer_viewport_size(struct GPUFrameBuffer *UNUSED(fb_read), int w, int h)
{
glViewport(0, 0, w, h);
}
/* ****************************************** Viewport ******************************************/
static void *DRW_viewport_engine_data_get(void *engine_type)

View File

@@ -105,6 +105,7 @@ typedef enum GPUTextureFormat {
GPU_DEPTH24_STENCIL8,
/* Texture only format */
GPU_RGB16F,
#if 0
GPU_RGBA16_SNORM,
GPU_RGBA8_SNORM,
@@ -112,7 +113,6 @@ typedef enum GPUTextureFormat {
GPU_RGB32I,
GPU_RGB32UI,
GPU_RGB16_SNORM,
GPU_RGB16F,
GPU_RGB16I,
GPU_RGB16UI,
GPU_RGB16,

View File

@@ -2263,6 +2263,7 @@ void GPU_state_init(void)
/* TODO: remove this when we switch to core profile */
glEnable(GL_POINT_SPRITE);
glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
glDepthFunc(GL_LEQUAL);
/* scaling matrices */

View File

@@ -104,6 +104,7 @@ static GLenum gpu_texture_get_format(
/* Formats texture & renderbuffer */
case GPU_RGBA16F: return GL_RGBA16F;
case GPU_RG32F: return GL_RG32F;
case GPU_RGB16F: return GL_RGB16F;
case GPU_RG16F: return GL_RG16F;
case GPU_RGBA8: return GL_RGBA8;
case GPU_R16F: return GL_R16F;