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:
Clément Foucault 2017-04-25 18:46:59 +02:00
parent 00f5c621a6
commit 041a50291b
13 changed files with 410 additions and 37 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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
/** \} */

View File

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

View File

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

View File

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

View File

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