diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-03-28 01:09:45 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-03-28 01:09:45 +0300 |
commit | 6d21970aa06a31398ed4a78b1c596f30a0b9ee87 (patch) | |
tree | afd21bd7a3f0c98020c9207d631e1e96da73dfb0 | |
parent | 4d3d10f6251c09006890ebb00f490d4915d47a96 (diff) |
Eevee: Diffuse Lights (1 / 2)
I added srgb tonemapping for previewing purpose. Also since the color buffer is still not HDR, there is ugly artifacts (fixed in part2)
7 files changed, 210 insertions, 9 deletions
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt index 19cc0f4c24d..04f25ab1fad 100644 --- a/source/blender/draw/CMakeLists.txt +++ b/source/blender/draw/CMakeLists.txt @@ -103,6 +103,8 @@ 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/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) data_to_c_simple(modes/shaders/common_globals_lib.glsl SRC) data_to_c_simple(modes/shaders/edit_overlay_frag.glsl SRC) diff --git a/source/blender/draw/engines/eevee/eevee.c b/source/blender/draw/engines/eevee/eevee.c index eceb72279f6..fea62f73615 100644 --- a/source/blender/draw/engines/eevee/eevee.c +++ b/source/blender/draw/engines/eevee/eevee.c @@ -25,6 +25,8 @@ #include "DRW_render.h" +#include "BLI_dynstr.h" + #include "eevee.h" #include "eevee_private.h" @@ -37,6 +39,8 @@ static struct { struct GPUShader *tonemap; } e_data = {NULL}; /* Engine data */ +extern char datatoc_bsdf_common_lib_glsl[]; +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[]; @@ -61,7 +65,17 @@ static void EEVEE_engine_init(void *vedata) } if (!e_data.default_lit) { - e_data.default_lit = DRW_shader_create(datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, "#define MAX_LIGHT 128\n"); + 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_direct_lib_glsl); + 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"); + + MEM_freeN(lib_str); } if (!e_data.tonemap) { diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index c0359cdd042..c073175a0b2 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -30,9 +30,12 @@ #define MAX_LIGHT 210 /* TODO : find size by dividing UBO max size by light data size */ typedef struct EEVEE_Light { - float position[3], pad; + float position[3], dist; float color[3], spec; - float spot_size, spot_blend, area_x, area_y; + float spotsize, spotblend, radius, shadowid; + float rightvec[3], sizex; + float upvec[3], sizey; + float forwardvec[3], lamptype; } EEVEE_Light; @@ -88,11 +91,44 @@ void EEVEE_lights_update(EEVEE_StorageList *stl) EEVEE_Light *evli = stl->lights_data + i; Object *ob = stl->lights_ref[i]; Lamp *la = (Lamp *)ob->data; + float mat[4][4], scale[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; + + /* 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_SPOT) { + + // } + + /* Lamp Type */ + evli->lamptype = (float)la->type; } /* Upload buffer to GPU */ diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl new file mode 100644 index 00000000000..0ed35509061 --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -0,0 +1,3 @@ + +#define M_PI 3.14159265358979323846 /* pi */ +#define M_1_PI 0.318309886183790671538 /* 1/pi */
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl new file mode 100644 index 00000000000..4f66b79024d --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -0,0 +1,68 @@ +/* Bsdf direct light function */ +/* in other word, how materials react to scene lamps */ + +/* Naming convention + * N World Normal (normalized) + * L Outgoing Light Vector (Surface to Light in World Space) (normalized) + * Ldist Distance from surface to the light + * W World Pos + */ + +/* ------------ Diffuse ------------- */ + +float direct_diffuse_point(vec3 N, vec3 L, float Ldist) +{ + float bsdf = max(0.0, dot(N, L)); + bsdf /= Ldist * Ldist; + bsdf *= M_1_PI; /* Normalize */ + return bsdf; +} +#if 0 +float direct_diffuse_sphere(vec3 N, vec3 L) +{ + +} + +float direct_diffuse_rectangle(vec3 N, vec3 L) +{ + +} +#endif + +/* infinitly far away point source, no decay */ +float direct_diffuse_sun(vec3 N, vec3 L) +{ + float bsdf = max(0.0, dot(N, L)); + bsdf *= M_1_PI; /* Normalize */ + return bsdf; +} + +#if 0 +float direct_diffuse_unit_disc(vec3 N, vec3 L) +{ + +} + +/* ----------- GGx ------------ */ +float direct_ggx_point(vec3 N, vec3 L) +{ + float bsdf = max(0.0, dot(N, L)); + bsdf *= M_1_PI; /* Normalize */ + return bsdf; +} + +float direct_ggx_sphere(vec3 N, vec3 L) +{ + +} + +float direct_ggx_rectangle(vec3 N, vec3 L) +{ + +} + +float direct_ggx_disc(vec3 N, vec3 L) +{ + +} +#endif
\ No newline at end of file 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 bd0f3da74c8..19498a611e8 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -2,11 +2,28 @@ uniform int light_count; struct LightData { - vec4 position; - vec4 colorAndSpec; /* w : Spec Intensity */ - vec4 spotAndAreaData; + vec4 positionAndInfluence; /* w : InfluenceRadius */ + vec4 colorAndSpec; /* w : Spec Intensity */ + vec4 spotDataRadiusShadow; /* x : spot size, y : spot blend */ + vec4 rightVecAndSizex; /* xyz: Normalized up vector, w: Lamp Type */ + vec4 upVecAndSizey; /* xyz: Normalized right vector, w: Lamp Type */ + vec4 forwardVecAndType; /* xyz: Normalized forward vector, w: Lamp Type */ }; +/* convenience aliases */ +#define lampColor colorAndSpec.rgb +#define lampSpec colorAndSpec.a +#define lampPosition positionAndInfluence.xyz +#define lampInfluence positionAndInfluence.w +#define lampSizeX rightVecAndSizex.w +#define lampSizeY upVecAndSizey.w +#define lampRight rightVecAndSizex.xyz +#define lampUp upVecAndSizey.xyz +#define lampForward forwardVecAndType.xyz +#define lampType forwardVecAndType.w +#define lampSpotSize spotDataRadiusShadow.x +#define lampSpotBlend spotDataRadiusShadow.y + layout(std140) uniform light_block { LightData lights_data[MAX_LIGHT]; }; @@ -16,14 +33,57 @@ in vec3 worldNormal; out vec4 fragColor; +/* type */ +#define POINT 0.0 +#define SUN 1.0 +#define SPOT 2.0 +#define HEMI 3.0 +#define AREA 4.0 + +vec3 light_diffuse(LightData ld, vec3 N, vec3 W, vec3 color) { + vec3 light, wL, L; + + if (ld.lampType == SUN) { + L = -ld.lampForward; + light = color * direct_diffuse_sun(N, L) * ld.lampColor; + } + else { + wL = ld.lampPosition - W; + float dist = length(wL); + light = color * direct_diffuse_point(N, wL / dist, dist) * ld.lampColor; + } + + if (ld.lampType == SPOT) { + float z = dot(ld.lampForward, wL); + vec3 lL = wL / z; + float x = dot(ld.lampRight, lL) / ld.lampSizeX; + float y = dot(ld.lampUp, lL) / ld.lampSizeY; + + float ellipse = 1.0 / sqrt(1.0 + x * x + y * y); + + float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.lampSpotSize) / ld.lampSpotBlend); + + light *= spotmask; + } + + return light; +} + +vec3 light_specular(LightData ld, vec3 V, vec3 N, vec3 T, vec3 B, vec3 spec, float roughness) { + vec3 L = normalize(ld.lampPosition - worldPosition); + vec3 light = L; + + return light; +} + void main() { vec3 n = normalize(worldNormal); vec3 diffuse = vec3(0.0); + vec3 albedo = vec3(1.0, 1.0, 1.0); + for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { - LightData ld = lights_data[i]; - vec3 l = normalize(ld.position.xyz - worldPosition); - diffuse += max(0.0, dot(l, n)) * ld.colorAndSpec.rgb / 3.14159; + diffuse += light_diffuse(lights_data[i], n, worldPosition, albedo); } fragColor = vec4(diffuse,1.0); diff --git a/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl b/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl index 6800b6f738d..cb2ceb5ed07 100644 --- a/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/tonemap_frag.glsl @@ -5,6 +5,24 @@ in vec4 uvcoordsvar; out vec4 fragColor; +float linearrgb_to_srgb(float c) +{ + if (c < 0.0031308) + return (c < 0.0) ? 0.0 : c * 12.92; + else + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; +} + +void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) +{ + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; +} + void main() { fragColor = texture(hdrColorBuf, uvcoordsvar.st); + + linearrgb_to_srgb(fragColor, fragColor); }
\ No newline at end of file |