Support for Batchs split by material for objects of type Curve, Surface, and Text

**ToDo:**
- add vertbuff for UV (what can be adapted from `dl_surf_to_renderdata`)
This commit is contained in:
Germano Cavalcante 2017-12-14 12:21:38 -02:00
parent bb9d068ccc
commit 5b5de35604
6 changed files with 212 additions and 36 deletions

View File

@ -520,6 +520,12 @@ Gwn_Batch **DRW_cache_object_surface_material_get(
switch (ob->type) {
case OB_MESH:
return DRW_cache_mesh_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_CURVE:
return DRW_cache_curve_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_SURF:
return DRW_cache_surf_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
case OB_FONT:
return DRW_cache_text_surface_shaded_get(ob, gpumat_array, gpumat_array_len);
default:
return NULL;
}
@ -2334,6 +2340,16 @@ Gwn_Batch *DRW_cache_curve_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/* Return list of batches */
Gwn_Batch **DRW_cache_curve_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_CURVE);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
}
/** \} */
/* -------------------------------------------------------------------- */
@ -2372,6 +2388,17 @@ Gwn_Batch *DRW_cache_text_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
Gwn_Batch **DRW_cache_text_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_FONT);
struct Curve *cu = ob->data;
if (cu->editfont && (cu->flag & CU_FAST)) {
return NULL;
}
return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
}
Gwn_Batch *DRW_cache_text_cursor_overlay_get(Object *ob)
{
BLI_assert(ob->type == OB_FONT);
@ -2401,6 +2428,16 @@ Gwn_Batch *DRW_cache_surf_surface_get(Object *ob)
return DRW_curve_batch_cache_get_triangles_with_normals(cu, ob->curve_cache);
}
/* Return list of batches */
Gwn_Batch **DRW_cache_surf_surface_shaded_get(
Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len)
{
BLI_assert(ob->type == OB_SURF);
struct Curve *cu = ob->data;
return DRW_curve_batch_cache_get_surface_shaded(cu, ob->curve_cache, gpumat_array, gpumat_array_len);
}
/** \} */
/* -------------------------------------------------------------------- */

View File

@ -130,6 +130,8 @@ void DRW_cache_mesh_sculpt_coords_ensure(struct Object *ob);
/* Curve */
struct Gwn_Batch *DRW_cache_curve_surface_get(struct Object *ob);
struct Gwn_Batch **DRW_cache_curve_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
struct Gwn_Batch *DRW_cache_curve_surface_verts_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_curve_edge_wire_get(struct Object *ob);
/* edit-mode */
@ -140,12 +142,16 @@ struct Gwn_Batch *DRW_cache_curve_vert_overlay_get(struct Object *ob);
/* Font */
struct Gwn_Batch *DRW_cache_text_edge_wire_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_text_surface_get(struct Object *ob);
struct Gwn_Batch **DRW_cache_text_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* edit-mode */
struct Gwn_Batch *DRW_cache_text_cursor_overlay_get(struct Object *ob);
struct Gwn_Batch *DRW_cache_text_select_overlay_get(struct Object *ob);
/* Surface */
struct Gwn_Batch *DRW_cache_surf_surface_get(struct Object *ob);
struct Gwn_Batch **DRW_cache_surf_surface_shaded_get(
struct Object *ob, struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Lattice */
struct Gwn_Batch *DRW_cache_lattice_verts_get(struct Object *ob);

View File

@ -29,14 +29,16 @@
struct CurveCache;
struct GPUMaterial;
struct Gwn_Batch;
struct Gwn_IndexBuf;
struct Gwn_VertBuf;
struct ListBase;
struct MetaBall;
struct ModifierData;
struct ParticleSystem;
struct Curve;
struct Lattice;
struct Mesh;
struct MetaBall;
/* Expose via BKE callbacks */
void DRW_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
@ -62,6 +64,9 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_edges(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_verts(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(struct Curve *cu, struct CurveCache *ob_curve_cache);
struct Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
struct Curve *cu, struct CurveCache *ob_curve_cache,
struct GPUMaterial **gpumat_array, uint gpumat_array_len);
/* Metaball */
struct Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(struct Object *ob);
@ -71,7 +76,9 @@ struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_cursor(struct Curve *cu);
struct Gwn_Batch *DRW_curve_batch_cache_get_overlay_select(struct Curve *cu);
/* DispList */
struct Gwn_Batch *BLI_displist_batch_calc_surface(struct ListBase *lb);
struct Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(struct ListBase *lb);
struct Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(struct ListBase *lb);
struct Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(struct ListBase *lb, uint gpumat_array_len);
/* Lattice */
struct Gwn_Batch *DRW_lattice_batch_cache_get_all_edges(struct Lattice *lt, bool use_weight, const int actdef);

View File

@ -310,7 +310,11 @@ typedef struct CurveBatchCache {
} overlay;
struct {
Gwn_VertBuf *verts;
Gwn_IndexBuf *triangles_in_order;
Gwn_Batch **shaded_triangles;
Gwn_Batch *batch;
int mat_len;
} surface;
/* 3d text */
@ -444,6 +448,14 @@ static void curve_batch_cache_clear(Curve *cu)
GWN_BATCH_DISCARD_SAFE(cache->overlay.verts);
GWN_BATCH_DISCARD_SAFE(cache->overlay.edges);
GWN_VERTBUF_DISCARD_SAFE(cache->surface.verts);
GWN_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
if (cache->surface.shaded_triangles) {
for (int i = 0; i < cache->surface.mat_len; ++i) {
GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
}
}
MEM_SAFE_FREE(cache->surface.shaded_triangles);
GWN_BATCH_DISCARD_SAFE(cache->surface.batch);
/* don't own vbo & elems */
@ -796,8 +808,20 @@ static Gwn_Batch *curve_batch_cache_get_pos_and_normals(CurveRenderData *rdata,
{
BLI_assert(rdata->types & CU_DATATYPE_SURFACE);
if (cache->surface.batch == NULL) {
cache->surface.batch = BLI_displist_batch_calc_surface(&rdata->ob_curve_cache->disp);
ListBase *lb = &rdata->ob_curve_cache->disp;
if (cache->surface.verts == NULL) {
cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
}
if (cache->surface.verts) {
if (cache->surface.triangles_in_order == NULL) {
cache->surface.triangles_in_order = DRW_displist_indexbuf_calc_triangles_in_order(lb);
}
cache->surface.batch = GWN_batch_create_ex(
GWN_PRIM_TRIS, cache->surface.verts, cache->surface.triangles_in_order, 0);
}
}
return cache->surface.batch;
}
@ -997,6 +1021,48 @@ Gwn_Batch *DRW_curve_batch_cache_get_triangles_with_normals(
return cache->surface.batch;
}
Gwn_Batch **DRW_curve_batch_cache_get_surface_shaded(
struct Curve *cu, struct CurveCache *ob_curve_cache,
struct GPUMaterial **UNUSED(gpumat_array), uint gpumat_array_len)
{
CurveBatchCache *cache = curve_batch_cache_get(cu);
if (cache->surface.mat_len != gpumat_array_len) {
/* TODO: deduplicate code */
GWN_INDEXBUF_DISCARD_SAFE(cache->surface.triangles_in_order);
if (cache->surface.shaded_triangles) {
for (int i = 0; i < cache->surface.mat_len; ++i) {
GWN_BATCH_DISCARD_SAFE(cache->surface.shaded_triangles[i]);
}
}
MEM_SAFE_FREE(cache->surface.shaded_triangles);
}
if (cache->surface.shaded_triangles == NULL) {
CurveRenderData *rdata = curve_render_data_create(cu, ob_curve_cache, CU_DATATYPE_SURFACE);
ListBase *lb = &rdata->ob_curve_cache->disp;
cache->surface.mat_len = gpumat_array_len;
Gwn_IndexBuf **el = DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(lb, gpumat_array_len);
cache->surface.shaded_triangles = MEM_mallocN(sizeof(*cache->surface.shaded_triangles) * gpumat_array_len, __func__);
if (cache->surface.verts == NULL) {
cache->surface.verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
}
for (int i = 0; i < gpumat_array_len; ++i) {
cache->surface.shaded_triangles[i] = GWN_batch_create(
GWN_PRIM_TRIS, cache->surface.verts, el[i]);
/* TODO: Add vertbuff for UV */
}
MEM_freeN(el); /* Save `el` in cache? */
curve_render_data_free(rdata);
}
return cache->surface.shaded_triangles;
}
/* -------------------------------------------------------------------- */

View File

@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_alloca.h"
#include "BLI_utildefines.h"
#include "BLI_math_vector.h"
@ -86,7 +87,38 @@ static int curve_render_surface_tri_len_get(const ListBase *lb)
return tri_len;
}
Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
static void displist_indexbufbuilder_set(Gwn_IndexBufBuilder *elb, const DispList *dl, const int ofs)
{
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
const int *idx = dl->index;
if (dl->type == DL_INDEX3) {
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 3) {
GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
}
}
else if (dl->type == DL_SURF) {
const int i_end = dl->totindex;
for (int i = 0; i < i_end; i++, idx += 4) {
GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
}
}
else {
BLI_assert(dl->type == DL_INDEX4);
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 4) {
GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
if (idx[2] != idx[3]) {
GWN_indexbuf_add_tri_verts(elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
}
}
}
}
}
Gwn_VertBuf *DRW_displist_vertbuf_calc_pos_with_normals(ListBase *lb)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
if (tri_len == 0) {
@ -131,44 +163,64 @@ Gwn_Batch *BLI_displist_batch_calc_surface(ListBase *lb)
}
}
return vbo;
}
Gwn_IndexBuf *DRW_displist_indexbuf_calc_triangles_in_order(ListBase *lb)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
if (tri_len == 0) {
return NULL;
}
const int vert_len = curve_render_surface_vert_len_get(lb);
{
Gwn_IndexBufBuilder elb;
GWN_indexbuf_init(&elb, GWN_PRIM_TRIS, tri_len, vert_len);
int ofs = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
if (ELEM(dl->type, DL_INDEX3, DL_INDEX4, DL_SURF)) {
const int *idx = dl->index;
if (dl->type == DL_INDEX3) {
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 3) {
GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
}
}
else if (dl->type == DL_SURF) {
const int i_end = dl->totindex;
for (int i = 0; i < i_end; i++, idx += 4) {
GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
}
}
else {
BLI_assert(dl->type == DL_INDEX4);
const int i_end = dl->parts;
for (int i = 0; i < i_end; i++, idx += 4) {
GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[1] + ofs, idx[2] + ofs);
if (idx[2] != idx[3]) {
GWN_indexbuf_add_tri_verts(&elb, idx[0] + ofs, idx[2] + ofs, idx[3] + ofs);
}
}
}
ofs += dl_vert_len(dl);
}
displist_indexbufbuilder_set(&elb, dl, ofs);
ofs += dl_vert_len(dl);
}
return GWN_batch_create_ex(
GWN_PRIM_TRIS, vbo, GWN_indexbuf_build(&elb),
GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
return GWN_indexbuf_build(&elb);
}
}
Gwn_IndexBuf **DRW_displist_indexbuf_calc_triangles_in_order_split_by_material(ListBase *lb, uint gpumat_array_len)
{
const int tri_len = curve_render_surface_tri_len_get(lb);
if (tri_len == 0) {
return NULL;
}
const int vert_len = curve_render_surface_vert_len_get(lb);
Gwn_IndexBuf **shaded_triangles_in_order = MEM_callocN(sizeof(*shaded_triangles_in_order) * gpumat_array_len, __func__);
{
int i;
Gwn_IndexBufBuilder *elb = BLI_array_alloca(elb, gpumat_array_len);
/* Init each index buffer builder */
for (i = 0; i < gpumat_array_len; i++) {
GWN_indexbuf_init(&elb[i], GWN_PRIM_TRIS, tri_len, vert_len);
}
/* calc each index buffer builder */
int ofs = 0;
for (const DispList *dl = lb->first; dl; dl = dl->next) {
displist_indexbufbuilder_set(&elb[dl->col], dl, ofs);
ofs += dl_vert_len(dl);
}
/* build each indexbuf */
for (i = 0; i < gpumat_array_len; i++) {
shaded_triangles_in_order[i] = GWN_indexbuf_build(&elb[i]);
}
}
return shaded_triangles_in_order;
}

View File

@ -132,7 +132,15 @@ Gwn_Batch *DRW_metaball_batch_cache_get_triangles_with_normals(Object *ob)
MetaBallBatchCache *cache = metaball_batch_cache_get(mb);
if (cache->batch == NULL) {
cache->batch = BLI_displist_batch_calc_surface(&ob->curve_cache->disp);
ListBase *lb = &ob->curve_cache->disp;
Gwn_VertBuf *verts = DRW_displist_vertbuf_calc_pos_with_normals(lb);
if (verts) {
cache->batch = GWN_batch_create_ex(
GWN_PRIM_TRIS,
verts,
DRW_displist_indexbuf_calc_triangles_in_order(lb),
GWN_BATCH_OWNS_VBO | GWN_BATCH_OWNS_INDEX);
}
}
return cache->batch;