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:
authorClément Foucault <foucault.clem@gmail.com>2017-05-15 17:12:51 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-05-15 17:14:18 +0300
commite053fade993204bbfaa98ced1b056e02226a3e61 (patch)
tree3990b649fe9a0b3d73ded25f9fab47b1aeca4790 /source/blender
parentae9da3786a3ea2e62b1ece7e28628c2dbadf0605 (diff)
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.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenlib/BLI_math_vector.h1
-rw-r--r--source/blender/blenlib/intern/math_vector_inline.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c8
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl2
-rw-r--r--source/blender/draw/intern/DRW_render.h1
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c51
-rw-r--r--source/blender/draw/intern/draw_manager.c57
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c12
8 files changed, 86 insertions, 54 deletions
diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h
index 3a34a199ba8..c1e5c1177cc 100644
--- a/source/blender/blenlib/BLI_math_vector.h
+++ b/source/blender/blenlib/BLI_math_vector.h
@@ -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]);
diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c
index 75bbfda3f5b..4f658ef015f 100644
--- a/source/blender/blenlib/intern/math_vector_inline.c
+++ b/source/blender/blenlib/intern/math_vector_inline.c
@@ -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]);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 8ab07685c9d..14dc4a0dbc0 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -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);
}
}
}
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index 4dd6bb1e287..7f1c32c8edf 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -23,6 +23,6 @@ void main() {
worldNormal = normalize(WorldNormalMatrix * nor);
#ifdef ATTRIB
- pass_attrib();
+ pass_attrib(pos);
#endif
} \ 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 652d79980e7..9096eda5f70 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -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]);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 37ecf89bf26..cf8f11f6ed2 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -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);
+ }
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index a6f6b14a1d7..7d37869e0c8 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -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);
}
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 8e97b208877..33655396d88 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -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);