Eevee: Make default shaders works.
- Added New Batch cache routine to get the split mesh for each material. (optimization needed) - Did some shader modifications to create default_frag and support a somwhat correct fresnel for lamps (to finish)
This commit is contained in:
parent
00f5c621a6
commit
041a50291b
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
@ -425,6 +431,23 @@ static void EEVEE_cache_init(void *vedata)
|
|||
/* NOTE : Adding Shadow Map textures uniform in EEVEE_cache_finish */
|
||||
}
|
||||
|
||||
{
|
||||
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 */
|
||||
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
/** \} */
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue