Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py84
-rw-r--r--source/blender/draw/CMakeLists.txt1
-rw-r--r--source/blender/draw/engines/eevee/eevee.c73
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h4
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl24
-rw-r--r--source/blender/draw/intern/DRW_render.h2
-rw-r--r--source/blender/draw/intern/draw_cache.c29
-rw-r--r--source/blender/draw/intern/draw_cache.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h1
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c198
-rw-r--r--source/blender/draw/intern/draw_manager.c12
13 files changed, 410 insertions, 37 deletions
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 06ae1847d06..0e8acf6e6c5 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -1054,6 +1054,88 @@ class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
_property_type = bpy.types.Material
+class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
+ bl_label = ""
+ bl_context = "material"
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ mat = context.material
+ ob = context.object
+ slot = context.material_slot
+ space = context.space_data
+
+ if ob:
+ is_sortable = len(ob.material_slots) > 1
+ rows = 1
+ if (is_sortable):
+ rows = 4
+
+ row = layout.row()
+
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.material_slot_add", icon='ZOOMIN', text="")
+ col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
+
+ col.menu("MATERIAL_MT_specials", icon='DOWNARROW_HLT', text="")
+
+ if is_sortable:
+ col.separator()
+
+ col.operator("object.material_slot_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("object.material_slot_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
+
+ if ob.mode == 'EDIT':
+ row = layout.row(align=True)
+ row.operator("object.material_slot_assign", text="Assign")
+ row.operator("object.material_slot_select", text="Select")
+ row.operator("object.material_slot_deselect", text="Deselect")
+
+ split = layout.split(percentage=0.65)
+
+ if ob:
+ split.template_ID(ob, "active_material", new="material.new")
+ row = split.row()
+
+ if slot:
+ row.prop(slot, "link", text="")
+ else:
+ row.label()
+ elif mat:
+ split.template_ID(space, "pin_id")
+ split.separator()
+
+
+class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel):
+ bl_label = "Surface"
+ bl_context = "material"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return context.material and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self.layout
+
+ mat = context.material
+ if not mat.use_nodes:
+ layout.prop(mat, "diffuse_color", text="Diffuse")
+ layout.prop(mat, "specular_color", text="Specular")
+ layout.prop(mat, "specular_hardness", text="Glossiness")
+
+
classes = (
MATERIAL_MT_sss_presets,
MATERIAL_MT_specials,
@@ -1082,6 +1164,8 @@ classes = (
MATERIAL_PT_volume_integration,
MATERIAL_PT_volume_options,
MATERIAL_PT_custom_props,
+ EEVEE_MATERIAL_PT_context_material,
+ EEVEE_MATERIAL_PT_surface,
)
if __name__ == "__main__": # only for live edit.
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 61f95f8a176..14dbd50c487 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -109,6 +109,7 @@ data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/default_frag.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)
diff --git a/source/blender/draw/engines/eevee/eevee.c b/source/blender/draw/engines/eevee/eevee.c
index 26e82467cd7..69d6c19b8a7 100644
--- a/source/blender/draw/engines/eevee/eevee.c
+++ b/source/blender/draw/engines/eevee/eevee.c
@@ -54,6 +54,7 @@ static struct {
float camera_pos[3];
} e_data = {NULL}; /* Engine data */
+extern char datatoc_default_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
extern char datatoc_bsdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
@@ -71,6 +72,8 @@ extern char datatoc_probe_frag_glsl[];
extern char datatoc_probe_geom_glsl[];
extern char datatoc_probe_vert_glsl[];
+extern Material defmaterial;
+
/* Van der Corput sequence */
/* From http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html */
static float radical_inverse(int i) {
@@ -213,24 +216,26 @@ static void EEVEE_engine_init(void *ved)
}
if (!e_data.default_lit) {
- char *lib_str = NULL;
+ char *frag_str = NULL;
- DynStr *ds_vert = BLI_dynstr_new();
- BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_vert, datatoc_ltc_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);
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
+ frag_str = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
- e_data.default_lit = DRW_shader_create_with_lib(
- datatoc_lit_surface_vert_glsl, NULL, datatoc_lit_surface_frag_glsl, lib_str,
+ e_data.default_lit = DRW_shader_create(
+ datatoc_lit_surface_vert_glsl, NULL, frag_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);
+ MEM_freeN(frag_str);
}
if (!e_data.shadow_sh) {
@@ -409,10 +414,11 @@ static void EEVEE_cache_init(void *vedata)
}
{
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_EQUAL;
- psl->pass = DRW_pass_create("Default Light Pass", state);
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
+ psl->default_pass = DRW_pass_create("Default Shader Pass", state);
- stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->pass);
+ /* NOTE : this shading grp does not contain any geom, it's just here to setup uniforms & textures. */
+ stl->g_data->default_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->default_pass);
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);
@@ -426,6 +432,23 @@ static void EEVEE_cache_init(void *vedata)
}
{
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL;
+ psl->material_pass = DRW_pass_create("Material Shader Pass", state);
+
+ /* NOTE : this shading grp does not contain any geom, it's just here to setup uniforms & textures. */
+ stl->g_data->material_lit_grp = DRW_shgroup_create(e_data.default_lit, psl->material_pass);
+ DRW_shgroup_uniform_block(stl->g_data->material_lit_grp, "light_block", stl->light_ubo, 0);
+ DRW_shgroup_uniform_block(stl->g_data->material_lit_grp, "shadow_block", stl->shadow_ubo, 1);
+ DRW_shgroup_uniform_int(stl->g_data->material_lit_grp, "light_count", &stl->lamps->num_light, 1);
+ DRW_shgroup_uniform_float(stl->g_data->material_lit_grp, "lodMax", &stl->probes->lodmax, 1);
+ DRW_shgroup_uniform_vec3(stl->g_data->material_lit_grp, "shCoefs[0]", (float *)stl->probes->shcoefs, 9);
+ DRW_shgroup_uniform_vec3(stl->g_data->material_lit_grp, "cameraPos", e_data.camera_pos, 1);
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "ltcMat", e_data.ltc_mat, 0);
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "brdfLut", e_data.brdf_lut, 1);
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "probeFiltered", txl->probe_pool, 2);
+ /* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
+ }
+ {
/* Final pass : Map HDR color to LDR color.
* Write result to the default color buffer */
psl->tonemap = DRW_pass_create("Tone Mapping", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
@@ -453,7 +476,22 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
/* Depth Prepass */
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);
+ /* Get per-material split surface */
+ struct Batch **mat_geom = DRW_cache_object_surface_material_get(ob);
+ for (int i = 0; i < MAX2(1, ob->totcol); ++i) {
+ Material *ma = give_current_material(ob, i + 1);
+
+ if (ma == NULL)
+ ma = &defmaterial;
+
+ DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit, psl->material_pass);
+ DRW_shgroup_uniform_vec3(shgrp, "diffuse_col", &ma->r, 1);
+ DRW_shgroup_uniform_vec3(shgrp, "specular_col", &ma->specr, 1);
+ DRW_shgroup_uniform_short(shgrp, "hardness", &ma->har, 1);
+ DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
+ }
+ // GPUMaterial *gpumat = GPU_material_from_nodetree(struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options)
+
// DRW_shgroup_call_add(stl->g_data->shadow_shgrp, geom, ob->obmat);
eevee_cascade_shadow_shgroup(psl, stl, geom, ob->obmat);
eevee_cube_shadow_shgroup(psl, stl, geom, ob->obmat);
@@ -475,6 +513,10 @@ static void EEVEE_cache_finish(void *vedata)
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);
DRW_shgroup_uniform_texture(stl->g_data->default_lit_grp, "shadowCascades", txl->shadow_depth_cascade_pool, 6);
+
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowMaps", txl->shadow_depth_map_pool, 4);
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowCubes", txl->shadow_depth_cube_pool, 5);
+ DRW_shgroup_uniform_texture(stl->g_data->material_lit_grp, "shadowCascades", txl->shadow_depth_cascade_pool, 6);
}
static void EEVEE_draw_scene(void *vedata)
@@ -505,7 +547,8 @@ static void EEVEE_draw_scene(void *vedata)
DRW_draw_pass(psl->depth_pass);
DRW_draw_pass(psl->depth_pass_cull);
- DRW_draw_pass(psl->pass);
+ DRW_draw_pass(psl->default_pass);
+ DRW_draw_pass(psl->material_pass);
/* Restore default framebuffer */
DRW_framebuffer_texture_detach(dtxl->depth);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 48c991aecf9..02dc32ddd9a 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -45,7 +45,8 @@ typedef struct EEVEE_PassList {
struct DRWPass *depth_pass;
struct DRWPass *depth_pass_cull;
- struct DRWPass *pass;
+ struct DRWPass *default_pass;
+ struct DRWPass *material_pass;
struct DRWPass *tonemap;
} EEVEE_PassList;
@@ -174,6 +175,7 @@ typedef struct EEVEE_LampEngineData {
typedef struct g_data{
struct DRWShadingGroup *default_lit_grp;
+ struct DRWShadingGroup *material_lit_grp;
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *depth_shgrp;
struct DRWShadingGroup *depth_shgrp_cull;
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 5762ca45b71..fddc9c54cb2 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -271,6 +271,13 @@ vec3 mrp_area(LightData ld, ShadingData sd, vec3 dir, inout float roughness, out
return closest_point_on_rectangle / len;
}
+/* Fresnel */
+vec3 F_schlick(vec3 f0, float cos_theta)
+{
+ float fac = pow(1.0 - cos_theta, 5);
+ return f0 + (1.0 - f0) * fac;
+}
+
/* GGX */
float D_ggx_opti(float NH, float a2)
{
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
new file mode 100644
index 00000000000..02ececf7a68
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -0,0 +1,10 @@
+
+uniform vec3 diffuse_col;
+uniform vec3 specular_col;
+uniform int hardness;
+
+void main()
+{
+ float roughness = 1.0 - float(hardness) / 511.0;
+ fragColor = vec4(eevee_surface_lit(worldNormal, diffuse_col, specular_col, roughness), 1.0);
+}
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 7e0c0462b30..dca3c99453e 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -198,6 +198,14 @@ float light_visibility(LightData ld, ShadingData sd)
return vis;
}
+vec3 light_fresnel(LightData ld, ShadingData sd, vec3 f0)
+{
+ vec3 H = normalize(sd.L + sd.V);
+ float NH = max(dot(sd.N, H), 1e-8);
+
+ return F_schlick(f0, NH);
+}
+
/* Calculation common to all bsdfs */
float light_common(inout LightData ld, inout ShadingData sd)
{
@@ -223,22 +231,15 @@ float light_common(inout LightData ld, inout ShadingData sd)
return vis;
}
-void main()
+vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness)
{
ShadingData sd;
- sd.N = normalize(worldNormal);
+ sd.N = normalize(world_normal);
sd.V = (ProjectionMatrix[3][3] == 0.0) /* if perspective */
? normalize(cameraPos - worldPosition)
: normalize(eye);
sd.W = worldPosition;
sd.R = reflect(-sd.V, sd.N);
-
- /* hardcoded test vars */
- vec3 albedo = mix(vec3(0.0, 0.0, 0.0), vec3(0.8, 0.8, 0.8), saturate(worldPosition.y/2));
- 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);
@@ -255,8 +256,9 @@ void main()
float vis = light_visibility(ld, sd);
float spec = light_specular(ld, sd, roughness);
float diff = light_diffuse(ld, sd);
+ vec3 fresnel = light_fresnel(ld, sd, f0);
- radiance += vis * (albedo * diff + specular * spec) * ld.l_color;
+ radiance += vis * (albedo * diff + fresnel * spec) * ld.l_color;
}
/* Envmaps */
@@ -267,5 +269,5 @@ void main()
radiance += spherical_harmonics(sd.N, shCoefs) * albedo;
- fragColor = vec4(radiance, 1.0);
+ return radiance;
} \ 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 cf86a6a81e8..93fd8d610ea 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -30,6 +30,7 @@
#include "BKE_context.h"
#include "BKE_layer.h"
+#include "BKE_material.h"
#include "BKE_scene.h"
#include "BLI_listbase.h"
@@ -270,6 +271,7 @@ void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const
void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_short(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize);
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 259d066d4f4..f28e7ac3d6f 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -469,6 +469,16 @@ Batch *DRW_cache_object_surface_get(Object *ob)
}
}
+Batch **DRW_cache_object_surface_material_get(struct Object *ob)
+{
+ switch (ob->type) {
+ case OB_MESH:
+ return DRW_cache_mesh_surface_shaded_get(ob);
+ default:
+ return NULL;
+ }
+}
+
/** \} */
@@ -1586,6 +1596,15 @@ Batch *DRW_cache_mesh_surface_get(Object *ob)
return DRW_mesh_batch_cache_get_triangles_with_normals(me);
}
+/* Return list of batches */
+Batch **DRW_cache_mesh_surface_shaded_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_MESH);
+
+ Mesh *me = ob->data;
+ return DRW_mesh_batch_cache_get_surface_shaded(me);
+}
+
Batch *DRW_cache_mesh_surface_verts_get(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
@@ -1734,12 +1753,4 @@ Batch *DRW_cache_lattice_vert_overlay_get(Object *ob)
return DRW_lattice_batch_cache_get_overlay_verts(lt);
}
-/** \} */
-
-
-#if 0 /* TODO */
-struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
- /* TODO */
- return NULL;
-}
-#endif
+/** \} */ \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
index 17e9467d1d9..ad122ac5222 100644
--- a/source/blender/draw/intern/draw_cache.h
+++ b/source/blender/draw/intern/draw_cache.h
@@ -40,6 +40,7 @@ struct Batch *DRW_cache_screenspace_circle_get(void);
/* Common Object */
struct Batch *DRW_cache_object_surface_get(struct Object *ob);
+struct Batch **DRW_cache_object_surface_material_get(struct Object *ob);
/* Empties */
struct Batch *DRW_cache_plain_axes_get(void);
@@ -91,6 +92,7 @@ struct Batch *DRW_cache_mesh_wire_outline_get(struct Object *ob);
struct Batch *DRW_cache_mesh_surface_get(struct Object *ob);
struct Batch *DRW_cache_mesh_surface_verts_get(struct Object *ob);
struct Batch *DRW_cache_mesh_verts_get(struct Object *ob);
+struct Batch **DRW_cache_mesh_surface_shaded_get(struct Object *ob);
/* Curve */
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index e4318aa576a..c988a5703dc 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -67,6 +67,7 @@ struct Batch *DRW_lattice_batch_cache_get_overlay_verts(struct Lattice *lt);
/* Mesh */
+struct Batch **DRW_mesh_batch_cache_get_surface_shaded(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_all_edges(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_all_triangles(struct Mesh *me);
struct Batch *DRW_mesh_batch_cache_get_triangles_with_normals(struct Mesh *me);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index eaf854edacb..66fd0663927 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -73,6 +73,11 @@ static int mesh_render_polys_len_get(Mesh *me)
return me->edit_btmesh ? me->edit_btmesh->bm->totface : me->totpoly;
}
+static int mesh_render_mat_ct_get(Mesh *me)
+{
+ return MAX2(1, me->totcol);
+}
+
static int UNUSED_FUNCTION(mesh_render_loops_len_get)(Mesh *me)
{
return me->edit_btmesh ? me->edit_btmesh->bm->totloop : me->totloop;
@@ -101,6 +106,7 @@ typedef struct MeshRenderData {
int tri_len;
int loop_len;
int poly_len;
+ int mat_ct;
int loose_vert_len;
int loose_edge_len;
@@ -171,6 +177,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types)
{
MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__);
rdata->types = types;
+ rdata->mat_ct = mesh_render_mat_ct_get(me);
if (me->edit_btmesh) {
BMEditMesh *embm = me->edit_btmesh;
@@ -329,6 +336,12 @@ static int mesh_render_data_looptri_len_get(const MeshRenderData *rdata)
return rdata->tri_len;
}
+static int mesh_render_data_mat_ct_get(const MeshRenderData *rdata)
+{
+ BLI_assert(rdata->types & MR_DATATYPE_POLY);
+ return rdata->mat_ct;
+}
+
static int UNUSED_FUNCTION(mesh_render_data_loops_len_get)(const MeshRenderData *rdata)
{
BLI_assert(rdata->types & MR_DATATYPE_LOOP);
@@ -520,6 +533,28 @@ static bool mesh_render_data_looptri_vert_indices_get(
return true;
}
+static bool mesh_render_data_looptri_mat_index_get(
+ const MeshRenderData *rdata, const int tri_idx,
+ short *r_face_mat)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (rdata->edit_bmesh) {
+ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx];
+ if (BM_elem_flag_test(bm_looptri[0]->f, BM_ELEM_HIDDEN)) {
+ return false;
+ }
+ *r_face_mat = ((BMFace *)bm_looptri[0]->f)->mat_nr;
+ }
+ else {
+ const int poly_idx = rdata->mlooptri[tri_idx].poly; ;
+ const MPoly *poly = &rdata->mpoly[poly_idx]; ;
+ *r_face_mat = poly->mat_nr;
+ }
+
+ return true;
+}
+
/**
* Version of #mesh_render_data_looptri_verts_indices_get that assigns
* edge indices too \a r_edges_idx (-1 for non-existant edges).
@@ -853,6 +888,12 @@ typedef struct MeshBatchCache {
Batch *points_with_normals;
Batch *fancy_edges; /* owns its vertex buffer (not shared) */
+ /* Maybe have shaded_triangles_data split into pos_nor and uv_tangent
+ * to minimise data transfer for skinned mesh. */
+ VertexBuffer *shaded_triangles_data;
+ ElementList **shaded_triangles_in_order;
+ Batch **shaded_triangles;
+
/* TODO : split in 2 buffers to avoid unnecessary
* data transfer when selecting/deselecting
* and combine into one batch and use offsets to render
@@ -868,6 +909,7 @@ typedef struct MeshBatchCache {
int tri_len;
int poly_len;
int vert_len;
+ int mat_ct;
bool is_editmode;
} MeshBatchCache;
@@ -881,6 +923,11 @@ static bool mesh_batch_cache_valid(Mesh *me)
return false;
}
+ /* XXX find another place for this */
+ if (cache->mat_ct != mesh_render_mat_ct_get(me)) {
+ cache->is_dirty = true;
+ }
+
if (cache->is_editmode != (me->edit_btmesh != NULL)) {
return false;
}
@@ -895,7 +942,8 @@ static bool mesh_batch_cache_valid(Mesh *me)
else if ((cache->vert_len != mesh_render_verts_len_get(me)) ||
(cache->edge_len != mesh_render_edges_len_get(me)) ||
(cache->tri_len != mesh_render_looptri_len_get(me)) ||
- (cache->poly_len != mesh_render_polys_len_get(me)))
+ (cache->poly_len != mesh_render_polys_len_get(me)) ||
+ (cache->mat_ct != mesh_render_mat_ct_get(me)))
{
return false;
}
@@ -924,6 +972,8 @@ static void mesh_batch_cache_init(Mesh *me)
cache->vert_len = mesh_render_verts_len_get(me);
}
+ cache->mat_ct = mesh_render_mat_ct_get(me);
+
cache->is_dirty = false;
}
@@ -983,6 +1033,21 @@ static void mesh_batch_cache_clear(Mesh *me)
VERTEXBUFFER_DISCARD_SAFE(cache->pos_with_normals);
BATCH_DISCARD_ALL_SAFE(cache->fancy_edges);
+
+ VERTEXBUFFER_DISCARD_SAFE(cache->shaded_triangles_data);
+ if (cache->shaded_triangles_in_order) {
+ for (int i = 0; i < cache->mat_ct; ++i) {
+ ELEMENTLIST_DISCARD_SAFE(cache->shaded_triangles_in_order[i]);
+ }
+ }
+ if (cache->shaded_triangles) {
+ for (int i = 0; i < cache->mat_ct; ++i) {
+ BATCH_DISCARD_SAFE(cache->shaded_triangles[i]);
+ }
+ }
+
+ MEM_SAFE_FREE(cache->shaded_triangles_in_order);
+ MEM_SAFE_FREE(cache->shaded_triangles);
}
void DRW_mesh_batch_cache_free(Mesh *me)
@@ -993,6 +1058,64 @@ void DRW_mesh_batch_cache_free(Mesh *me)
/* Batch cache usage. */
+static VertexBuffer *mesh_batch_cache_get_shading_data(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
+
+ if (cache->shaded_triangles_data == NULL) {
+ unsigned int vidx = 0, nidx = 0;
+
+ static VertexFormat format = { 0 };
+ static unsigned int pos_id, nor_id;
+ if (format.attrib_ct == 0) {
+ /* initialize vertex format */
+ /* TODO add tangent, UVs */
+ pos_id = VertexFormat_add_attrib(&format, "pos", COMP_F32, 3, KEEP_FLOAT);
+ nor_id = VertexFormat_add_attrib(&format, "nor", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
+ }
+
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+
+ VertexBuffer *vbo = cache->shaded_triangles_data = VertexBuffer_create_with_format(&format);
+
+ const int vbo_len_capacity = tri_len * 3;
+ int vbo_len_used = 0;
+ VertexBuffer_allocate_data(vbo, vbo_len_capacity);
+
+ /* TODO deduplicate all verts and make use of ElementList in mesh_batch_cache_get_shaded_triangles_in_order. */
+ for (int i = 0; i < tri_len; i++) {
+ float *tri_vert_cos[3];
+ short *tri_nor, *tri_vert_nors[3];
+ bool is_smooth;
+
+ if (mesh_render_data_looptri_cos_nors_smooth_get(
+ rdata, i, &tri_vert_cos, &tri_nor, &tri_vert_nors, &is_smooth))
+ {
+ if (is_smooth) {
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[0]);
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[1]);
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_vert_nors[2]);
+ }
+ else {
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor);
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor);
+ VertexBuffer_set_attrib(vbo, nor_id, nidx++, tri_nor);
+ }
+
+ VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[0]);
+ VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[1]);
+ VertexBuffer_set_attrib(vbo, pos_id, vidx++, tri_vert_cos[2]);
+ }
+ }
+ vbo_len_used = vidx;
+
+ if (vbo_len_capacity != vbo_len_used) {
+ VertexBuffer_resize_data(vbo, vbo_len_used);
+ }
+ }
+ return cache->shaded_triangles_data;
+}
+
static VertexBuffer *mesh_batch_cache_get_pos_and_normals(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_POLY));
@@ -1048,6 +1171,7 @@ static VertexBuffer *mesh_batch_cache_get_pos_and_normals(MeshRenderData *rdata,
}
return cache->pos_with_normals;
}
+
static VertexBuffer *mesh_batch_cache_get_pos_and_nor_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
{
BLI_assert(rdata->types & MR_DATATYPE_VERT);
@@ -1118,6 +1242,54 @@ static ElementList *mesh_batch_cache_get_triangles_in_order(MeshRenderData *rdat
return cache->triangles_in_order;
}
+static ElementList **mesh_batch_cache_get_shaded_triangles_in_order(MeshRenderData *rdata, MeshBatchCache *cache)
+{
+ BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY));
+
+ if (cache->shaded_triangles_in_order == NULL) {
+ const int tri_len = mesh_render_data_looptri_len_get(rdata);
+ const int mat_ct = mesh_render_data_mat_ct_get(rdata);
+
+ int *mat_tri_len = MEM_callocN(sizeof(*mat_tri_len) * mat_ct, "mat_tri_len");
+ cache->shaded_triangles_in_order = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_ct, "shaded_triangles_in_order");
+ ElementListBuilder *elb = MEM_callocN(sizeof(*elb) * mat_ct, "shaded ElementListBuilder");
+
+ for (int i = 0; i < tri_len; ++i) {
+ short ma_id;
+ if (mesh_render_data_looptri_mat_index_get(rdata, i, &ma_id)) {
+ mat_tri_len[ma_id] += 1;
+ }
+ }
+
+ /* Init ELBs. */
+ for (int i = 0; i < mat_ct; ++i) {
+ ElementListBuilder_init(&elb[i], PRIM_TRIANGLES, mat_tri_len[i], tri_len * 3);
+ }
+
+ /* Populate ELBs. */
+ unsigned int nidx = 0;
+ for (int i = 0; i < tri_len; ++i) {
+ short ma_id;
+
+ /* TODO deduplicate verts see mesh_batch_cache_get_shading_data */
+ if (mesh_render_data_looptri_mat_index_get(rdata, i, &ma_id)) {
+ add_triangle_vertices(&elb[ma_id], nidx + 0, nidx + 1, nidx + 2);
+ nidx += 3;
+ }
+ }
+
+ /* Build ELBs. */
+ for (int i = 0; i < mat_ct; ++i) {
+ cache->shaded_triangles_in_order[i] = ElementList_build(&elb[i]);
+ }
+
+ MEM_freeN(mat_tri_len);
+ MEM_freeN(elb);
+ }
+
+ return cache->shaded_triangles_in_order;
+}
+
Batch *DRW_mesh_batch_cache_get_all_edges(Mesh *me)
{
MeshBatchCache *cache = mesh_batch_cache_get(me);
@@ -1445,4 +1617,28 @@ Batch *DRW_mesh_batch_cache_get_overlay_facedots(Mesh *me)
return cache->overlay_facedots;
}
+Batch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me)
+{
+ MeshBatchCache *cache = mesh_batch_cache_get(me);
+
+ if (cache->shaded_triangles == NULL) {
+ /* create batch from DM */
+ MeshRenderData *rdata = mesh_render_data_create(me, MR_DATATYPE_VERT | MR_DATATYPE_LOOP | MR_DATATYPE_LOOPTRI | MR_DATATYPE_POLY);
+
+ const int mat_ct = mesh_render_data_mat_ct_get(rdata);
+
+ cache->shaded_triangles = MEM_callocN(sizeof(*cache->shaded_triangles) * mat_ct, "shaded triangles batches");
+
+ ElementList **el = mesh_batch_cache_get_shaded_triangles_in_order(rdata, cache);
+
+ for (int i = 0; i < mat_ct; ++i) {
+ cache->shaded_triangles[i] = Batch_create(PRIM_TRIANGLES, mesh_batch_cache_get_shading_data(rdata, cache), el[i]);
+ }
+
+ mesh_render_data_free(rdata);
+ }
+
+ return cache->shaded_triangles;
+}
+
#undef MESH_RENDER_FUNCTION
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 501c7d2dba0..6046db874b8 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -84,6 +84,7 @@ extern char datatoc_gpu_shader_fullscreen_vert_glsl[];
/* Structures */
typedef enum {
DRW_UNIFORM_BOOL,
+ DRW_UNIFORM_SHORT,
DRW_UNIFORM_INT,
DRW_UNIFORM_FLOAT,
DRW_UNIFORM_TEXTURE,
@@ -660,6 +661,11 @@ void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const
DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize, 0);
}
+void DRW_shgroup_uniform_short(DRWShadingGroup *shgroup, const char *name, const short *value, int arraysize)
+{
+ DRW_interface_uniform(shgroup, name, DRW_UNIFORM_SHORT, value, 1, arraysize, 0);
+}
+
void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
{
DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize, 0);
@@ -1042,6 +1048,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
DRWInterface *interface = shgroup->interface;
GPUTexture *tex;
+ int val;
if (DST.shader != shgroup->shader) {
if (DST.shader) GPU_shader_unbind();
@@ -1063,6 +1070,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup)
DRWBoundTexture *bound_tex;
switch (uni->type) {
+ case DRW_UNIFORM_SHORT:
+ val = (int)*((short *)uni->value);
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)&val);
+ break;
case DRW_UNIFORM_BOOL:
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(