Mesh Batch Cache: get rid of the ORCO VBO data, and reconstruct it in shader.
With only one MADD instruction we recover the orco data and reduce both the storage and the fetching cost of an attrib layer.
This commit is contained in:
parent
ae9da3786a
commit
e053fade99
|
@ -151,6 +151,7 @@ MINLINE void negate_v3_short(short r[3]);
|
|||
MINLINE void negate_v3_db(double r[3]);
|
||||
|
||||
MINLINE void invert_v2(float r[2]);
|
||||
MINLINE void invert_v3(float r[3]);
|
||||
|
||||
MINLINE void abs_v2(float r[2]);
|
||||
MINLINE void abs_v2_v2(float r[2], const float a[2]);
|
||||
|
|
|
@ -658,6 +658,14 @@ MINLINE void invert_v2(float r[2])
|
|||
r[1] = 1.0f / r[1];
|
||||
}
|
||||
|
||||
MINLINE void invert_v3(float r[3])
|
||||
{
|
||||
BLI_assert(!ELEM(0.0f, r[0], r[1], r[2]));
|
||||
r[0] = 1.0f / r[0];
|
||||
r[1] = 1.0f / r[1];
|
||||
r[2] = 1.0f / r[2];
|
||||
}
|
||||
|
||||
MINLINE void abs_v2(float r[2])
|
||||
{
|
||||
r[0] = fabsf(r[0]);
|
||||
|
|
|
@ -564,7 +564,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
DRW_shgroup_call_sculpt_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, ob, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob->obmat);
|
||||
DRW_shgroup_call_object_add((do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp, geom, ob);
|
||||
}
|
||||
|
||||
/* Get per-material split surface */
|
||||
|
@ -605,7 +605,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
|
||||
DRW_shgroup_call_object_add(shgrp, mat_geom[i], ob);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -625,7 +625,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
|
||||
DRW_shgroup_call_object_add(shgrp, mat_geom[i], ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|||
DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat);
|
||||
}
|
||||
else {
|
||||
DRW_shgroup_call_add(shgrp, mat_geom[i], ob->obmat);
|
||||
DRW_shgroup_call_object_add(shgrp, mat_geom[i], ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,6 @@ void main() {
|
|||
worldNormal = normalize(WorldNormalMatrix * nor);
|
||||
|
||||
#ifdef ATTRIB
|
||||
pass_attrib();
|
||||
pass_attrib(pos);
|
||||
#endif
|
||||
}
|
|
@ -271,6 +271,7 @@ typedef void (DRWCallGenerateFn)(
|
|||
|
||||
void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
|
||||
void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]);
|
||||
void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, struct Batch *geom, struct Object *ob);
|
||||
void DRW_shgroup_call_sculpt_add(DRWShadingGroup *shgroup, struct Object *ob, float (*obmat)[4]);
|
||||
void DRW_shgroup_call_generate_add(
|
||||
DRWShadingGroup *shgroup, DRWCallGenerateFn *geometry_fn, void *user_data, float (*obmat)[4]);
|
||||
|
|
|
@ -1167,25 +1167,6 @@ static void mesh_render_data_looptri_tans_get(
|
|||
}
|
||||
}
|
||||
|
||||
static void mesh_render_data_looptri_orcos_get(
|
||||
MeshRenderData *rdata, const int tri_idx,
|
||||
float *(*r_vert_orcos)[3])
|
||||
{
|
||||
BLI_assert(rdata->types & (MR_DATATYPE_VERT | MR_DATATYPE_LOOPTRI | MR_DATATYPE_LOOP | MR_DATATYPE_SHADING));
|
||||
if (rdata->edit_bmesh) {
|
||||
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx];
|
||||
(*r_vert_orcos)[0] = rdata->orco[BM_elem_index_get(bm_looptri[0]->v)];
|
||||
(*r_vert_orcos)[1] = rdata->orco[BM_elem_index_get(bm_looptri[1]->v)];
|
||||
(*r_vert_orcos)[2] = rdata->orco[BM_elem_index_get(bm_looptri[2]->v)];
|
||||
}
|
||||
else {
|
||||
const MLoopTri *mlt = &rdata->mlooptri[tri_idx];
|
||||
(*r_vert_orcos)[0] = rdata->orco[rdata->mloop[mlt->tri[0]].v];
|
||||
(*r_vert_orcos)[1] = rdata->orco[rdata->mloop[mlt->tri[1]].v];
|
||||
(*r_vert_orcos)[2] = rdata->orco[rdata->mloop[mlt->tri[2]].v];
|
||||
}
|
||||
}
|
||||
|
||||
static bool mesh_render_data_looptri_cos_nors_smooth_get(
|
||||
MeshRenderData *rdata, const int tri_idx,
|
||||
float *(*r_vert_cos)[3], short **r_tri_nor, short *(*r_vert_nors)[3], bool *r_is_smooth)
|
||||
|
@ -1926,16 +1907,15 @@ static VertexBuffer *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata
|
|||
unsigned int vidx = 0;
|
||||
const char *attrib_name;
|
||||
|
||||
if (rdata->uv_len + rdata->vcol_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VertexFormat *format = &cache->shaded_triangles_format;
|
||||
|
||||
VertexFormat_clear(format);
|
||||
|
||||
/* initialize vertex format */
|
||||
#ifdef USE_COMP_MESH_DATA
|
||||
unsigned int orco_id = VertexFormat_add_attrib(format, "orco", COMP_I16, 3, NORMALIZE_INT_TO_FLOAT);
|
||||
#else
|
||||
unsigned int orco_id = VertexFormat_add_attrib(format, "orco", COMP_F32, 3, KEEP_FLOAT);
|
||||
#endif
|
||||
unsigned int *uv_id = MEM_mallocN(sizeof(*uv_id) * rdata->uv_len, "UV attrib format");
|
||||
unsigned int *vcol_id = MEM_mallocN(sizeof(*vcol_id) * rdata->vcol_len, "Vcol attrib format");
|
||||
unsigned int *tangent_id = MEM_mallocN(sizeof(*tangent_id) * rdata->uv_len, "Tangent attrib format");
|
||||
|
@ -1999,7 +1979,7 @@ static VertexBuffer *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata
|
|||
|
||||
/* 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_uvs[3], *tri_tans[3], *tri_orcos[3];
|
||||
float *tri_uvs[3], *tri_tans[3];
|
||||
unsigned char *tri_cols[3];
|
||||
|
||||
if (rdata->edit_bmesh == NULL ||
|
||||
|
@ -2052,19 +2032,7 @@ static VertexBuffer *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata
|
|||
VertexBuffer_set_attrib(vbo, vcol_id[j], vidx + 2, tri_cols[2]);
|
||||
}
|
||||
|
||||
/* ORCO */
|
||||
mesh_render_data_looptri_orcos_get(rdata, i, &tri_orcos);
|
||||
#ifdef USE_COMP_MESH_DATA
|
||||
short s_orco[3][3];
|
||||
normal_float_to_short_v3(s_orco[0], tri_orcos[0]);
|
||||
normal_float_to_short_v3(s_orco[1], tri_orcos[1]);
|
||||
normal_float_to_short_v3(s_orco[2], tri_orcos[2]);
|
||||
#else
|
||||
float **s_orco = tri_orcos;
|
||||
#endif
|
||||
VertexBuffer_set_attrib(vbo, orco_id, vidx++, s_orco[0]);
|
||||
VertexBuffer_set_attrib(vbo, orco_id, vidx++, s_orco[1]);
|
||||
VertexBuffer_set_attrib(vbo, orco_id, vidx++, s_orco[2]);
|
||||
vidx += 3;
|
||||
}
|
||||
}
|
||||
vbo_len_used = vidx;
|
||||
|
@ -3298,8 +3266,11 @@ Batch **DRW_mesh_batch_cache_get_surface_shaded(Mesh *me)
|
|||
VertexBuffer *vbo = mesh_batch_cache_get_tri_pos_and_normals(rdata, cache);
|
||||
for (int i = 0; i < mat_len; ++i) {
|
||||
cache->shaded_triangles[i] = Batch_create(
|
||||
PRIM_TRIANGLES, mesh_batch_cache_get_tri_shading_data(rdata, cache), el[i]);
|
||||
Batch_add_VertexBuffer(cache->shaded_triangles[i], vbo);
|
||||
PRIM_TRIANGLES, vbo, el[i]);
|
||||
VertexBuffer *vbo_shading = mesh_batch_cache_get_tri_shading_data(rdata, cache);
|
||||
if (vbo_shading) {
|
||||
Batch_add_VertexBuffer(cache->shaded_triangles[i], vbo_shading);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#include "BKE_depsgraph.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pbvh.h"
|
||||
#include "BKE_paint.h"
|
||||
|
||||
|
@ -166,6 +167,7 @@ struct DRWInterface {
|
|||
int normal;
|
||||
int worldnormal;
|
||||
int camtexfac;
|
||||
int orcotexfac;
|
||||
int eye;
|
||||
/* Textures */
|
||||
int tex_bind; /* next texture binding point */
|
||||
|
@ -197,6 +199,8 @@ typedef struct DRWCall {
|
|||
int type;
|
||||
float (*obmat)[4];
|
||||
Batch *geometry;
|
||||
|
||||
Object *ob; /* Optionnal */
|
||||
} DRWCall;
|
||||
|
||||
typedef struct DRWCallGenerate {
|
||||
|
@ -559,6 +563,7 @@ static DRWInterface *DRW_interface_create(GPUShader *shader)
|
|||
interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
|
||||
interface->worldnormal = GPU_shader_get_uniform(shader, "WorldNormalMatrix");
|
||||
interface->camtexfac = GPU_shader_get_uniform(shader, "CameraTexCoFactors");
|
||||
interface->orcotexfac = GPU_shader_get_uniform(shader, "OrcoTexCoFactors[0]");
|
||||
interface->eye = GPU_shader_get_uniform(shader, "eye");
|
||||
interface->instance_count = 0;
|
||||
interface->attribs_count = 0;
|
||||
|
@ -821,6 +826,24 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[
|
|||
BLI_addtail(&shgroup->calls, call);
|
||||
}
|
||||
|
||||
void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Batch *geom, Object *ob)
|
||||
{
|
||||
BLI_assert(geom != NULL);
|
||||
|
||||
DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
|
||||
|
||||
call->type = DRW_CALL_SINGLE;
|
||||
call->obmat = ob->obmat;
|
||||
call->geometry = geom;
|
||||
call->ob = ob;
|
||||
|
||||
#ifdef USE_GPU_SELECT
|
||||
call->select_id = g_DRW_select_id;
|
||||
#endif
|
||||
|
||||
BLI_addtail(&shgroup->calls, call);
|
||||
}
|
||||
|
||||
void DRW_shgroup_call_generate_add(
|
||||
DRWShadingGroup *shgroup,
|
||||
DRWCallGenerateFn *geometry_fn, void *user_data,
|
||||
|
@ -1418,12 +1441,14 @@ typedef struct DRWBoundTexture {
|
|||
GPUTexture *tex;
|
||||
} DRWBoundTexture;
|
||||
|
||||
static void draw_geometry_prepare(DRWShadingGroup *shgroup, const float (*obmat)[4])
|
||||
static void draw_geometry_prepare(
|
||||
DRWShadingGroup *shgroup, const float (*obmat)[4], const float *texcoloc, const float *texcosize)
|
||||
{
|
||||
RegionView3D *rv3d = DST.draw_ctx.rv3d;
|
||||
DRWInterface *interface = shgroup->interface;
|
||||
|
||||
float mvp[4][4], mv[4][4], mi[4][4], mvi[4][4], pi[4][4], n[3][3], wn[3][3];
|
||||
float orcofacs[2][3] = {{0.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}};
|
||||
float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
|
||||
|
||||
bool do_pi = (interface->projectioninverse != -1);
|
||||
|
@ -1434,6 +1459,7 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, const float (*obmat)
|
|||
bool do_n = (interface->normal != -1);
|
||||
bool do_wn = (interface->worldnormal != -1);
|
||||
bool do_eye = (interface->eye != -1);
|
||||
bool do_orco = (interface->orcotexfac != -1) && (texcoloc != NULL) && (texcosize != NULL);
|
||||
|
||||
if (do_pi) {
|
||||
invert_m4_m4(pi, rv3d->winmat);
|
||||
|
@ -1467,6 +1493,13 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, const float (*obmat)
|
|||
/* set eye vector, transformed to object coords */
|
||||
mul_m3_v3(tmp, eye);
|
||||
}
|
||||
if (do_orco) {
|
||||
mul_v3_v3fl(orcofacs[1], texcosize, 2.0f);
|
||||
invert_v3(orcofacs[1]);
|
||||
sub_v3_v3v3(orcofacs[0], texcoloc, texcosize);
|
||||
negate_v3(orcofacs[0]);
|
||||
mul_v3_v3(orcofacs[0], orcofacs[1]); /* result in a nice MADD in the shader */
|
||||
}
|
||||
|
||||
/* Should be really simple */
|
||||
/* step 1 : bind object dependent matrices */
|
||||
|
@ -1512,6 +1545,9 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, const float (*obmat)
|
|||
if (interface->camtexfac != -1) {
|
||||
GPU_shader_uniform_vector(shgroup->shader, interface->camtexfac, 4, 1, (float *)rv3d->viewcamtexcofac);
|
||||
}
|
||||
if (interface->orcotexfac != -1) {
|
||||
GPU_shader_uniform_vector(shgroup->shader, interface->orcotexfac, 3, 2, (float *)orcofacs);
|
||||
}
|
||||
if (interface->eye != -1) {
|
||||
GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
|
||||
}
|
||||
|
@ -1531,9 +1567,16 @@ static void draw_geometry_execute(DRWShadingGroup *shgroup, Batch *geom)
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4])
|
||||
static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*obmat)[4], Object *ob)
|
||||
{
|
||||
draw_geometry_prepare(shgroup, obmat);
|
||||
float *texcoloc = NULL;
|
||||
float *texcosize = NULL;
|
||||
|
||||
if (ob != NULL) {
|
||||
BKE_object_obdata_texspace_get(ob, NULL, &texcoloc, &texcosize, NULL);
|
||||
}
|
||||
|
||||
draw_geometry_prepare(shgroup, obmat, texcoloc, texcosize);
|
||||
|
||||
draw_geometry_execute(shgroup, geom);
|
||||
}
|
||||
|
@ -1637,13 +1680,13 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
|||
|
||||
if (shgroup->type == DRW_SHG_INSTANCE && interface->instance_count > 0) {
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(&shgroup->calls);
|
||||
draw_geometry(shgroup, shgroup->instance_geom, obmat);
|
||||
draw_geometry(shgroup, shgroup->instance_geom, obmat, NULL);
|
||||
}
|
||||
else {
|
||||
/* Some dynamic batch can have no geom (no call to aggregate) */
|
||||
if (shgroup->batch_geom) {
|
||||
GPU_SELECT_LOAD_IF_PICKSEL_LIST(&shgroup->calls);
|
||||
draw_geometry(shgroup, shgroup->batch_geom, obmat);
|
||||
draw_geometry(shgroup, shgroup->batch_geom, obmat, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1659,11 +1702,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
|
|||
GPU_SELECT_LOAD_IF_PICKSEL(call);
|
||||
|
||||
if (call->type == DRW_CALL_SINGLE) {
|
||||
draw_geometry(shgroup, call->geometry, call->obmat);
|
||||
draw_geometry(shgroup, call->geometry, call->obmat, call->ob);
|
||||
}
|
||||
else {
|
||||
DRWCallGenerate *callgen = ((DRWCallGenerate *)call);
|
||||
draw_geometry_prepare(shgroup, callgen->obmat);
|
||||
draw_geometry_prepare(shgroup, callgen->obmat, NULL, NULL);
|
||||
callgen->geometry_fn(shgroup, draw_geometry_execute, callgen->user_data);
|
||||
}
|
||||
|
||||
|
|
|
@ -787,7 +787,11 @@ static char *code_generate_vertex_new(ListBase *nodes, const char *vert_code)
|
|||
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
|
||||
/* XXX FIXME : see notes in mesh_render_data_create() */
|
||||
/* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
|
||||
if (input->attribname[0] == '\0') {
|
||||
if (input->attribtype == CD_ORCO) {
|
||||
/* orco is computed from local positions, see bellow */
|
||||
BLI_dynstr_appendf(ds, "uniform vec3 OrcoTexCoFactors[2];\n");
|
||||
}
|
||||
else if (input->attribname[0] == '\0') {
|
||||
BLI_dynstr_appendf(ds, "in %s %s;\n", GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype));
|
||||
BLI_dynstr_appendf(ds, "#define att%d %s\n", input->attribid, attrib_prefix_get(input->attribtype));
|
||||
}
|
||||
|
@ -808,7 +812,7 @@ static char *code_generate_vertex_new(ListBase *nodes, const char *vert_code)
|
|||
|
||||
BLI_dynstr_append(ds, "#define ATTRIB\n");
|
||||
BLI_dynstr_append(ds, "uniform mat3 NormalMatrix;\n");
|
||||
BLI_dynstr_append(ds, "void pass_attrib(void) {\n");
|
||||
BLI_dynstr_append(ds, "void pass_attrib(in vec3 position) {\n");
|
||||
|
||||
for (node = nodes->first; node; node = node->next) {
|
||||
for (input = node->inputs.first; input; input = input->next) {
|
||||
|
@ -821,6 +825,10 @@ static char *code_generate_vertex_new(ListBase *nodes, const char *vert_code)
|
|||
ds, "\tvar%d.w = att%d.w;\n",
|
||||
input->attribid, input->attribid);
|
||||
}
|
||||
else if (input->attribtype == CD_ORCO) {
|
||||
BLI_dynstr_appendf(ds, "\tvar%d = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n",
|
||||
input->attribid);
|
||||
}
|
||||
else {
|
||||
BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n",
|
||||
input->attribid, input->attribid);
|
||||
|
|
Loading…
Reference in New Issue