From 62ea911e1a22d2a717c225ea1bbd130ac5c367bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 1 May 2017 18:09:50 +0200 Subject: GPUMaterial: Making material node tree compatible with new drawmanager. - code_generate_fragment : Making sure that shaders uses the new uniforms. - code_generate_vertex_new : create require attribute based on their names and not their id (see draw_cache_impl_mesh.c). - add support for ramp textures. --- source/blender/draw/intern/draw_manager.c | 9 ++ source/blender/gpu/GPU_material.h | 2 +- source/blender/gpu/intern/gpu_codegen.c | 135 +++++++++++++++++++-- source/blender/gpu/intern/gpu_material.c | 7 +- .../blender/gpu/shaders/gpu_shader_material.glsl | 1 + .../nodes/shader/nodes/node_shader_tex_coord.c | 6 +- 6 files changed, 140 insertions(+), 20 deletions(-) diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 059ebc6eab3..bc11ab48d48 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -145,6 +145,7 @@ struct DRWInterface { int modelview; int projection; int view; + int viewinverse; int modelviewprojection; int viewprojection; int normal; @@ -505,6 +506,7 @@ static DRWInterface *DRW_interface_create(GPUShader *shader) interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix"); interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix"); interface->view = GPU_shader_get_uniform(shader, "ViewMatrix"); + interface->viewinverse = GPU_shader_get_uniform(shader, "ViewMatrixInverse"); interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix"); interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix"); interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix"); @@ -648,6 +650,10 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa DRW_shgroup_uniform_texture(grp, input->shadername, tex, max_tex - input->texid); } } + /* Color Ramps */ + else if (input->tex) { + DRW_shgroup_uniform_texture(grp, input->shadername, input->tex, max_tex - input->texid); + } /* Floats */ else { switch (input->type) { @@ -1191,6 +1197,9 @@ static void draw_geometry(DRWShadingGroup *shgroup, Batch *geom, const float (*o if (interface->modelviewprojection != -1) { GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp); } + if (interface->viewinverse != -1) { + GPU_shader_uniform_vector(shgroup->shader, interface->viewinverse, 16, 1, (float *)rv3d->viewinv); + } if (interface->viewprojection != -1) { GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)rv3d->persmat); } diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 31785a0121f..4345a31839a 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -220,7 +220,7 @@ GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]); /* High level functions to create and use GPU materials */ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo); GPUMaterial *GPU_material_from_nodetree( - struct bNodeTree *ntree, struct ListBase *gpumaterials, void *engine_type, int options, + struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, void *engine_type, int options, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines); GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv); GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 89c58eb8495..d291db2a84d 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -622,7 +622,11 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final "tmp", input->link->output->id); } else if (input->source == GPU_SOURCE_BUILTIN) { - if (input->builtin == GPU_VIEW_NORMAL) + if (input->builtin == GPU_INVERSE_VIEW_MATRIX) + BLI_dynstr_append(ds, "viewinv"); + else if (input->builtin == GPU_VIEW_POSITION) + BLI_dynstr_append(ds, "viewposition"); + else if (input->builtin == GPU_VIEW_NORMAL) BLI_dynstr_append(ds, "facingnormal"); else BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); @@ -660,7 +664,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ";\n"); } -static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) +static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, bool use_new_shading) { DynStr *ds = BLI_dynstr_new(); char *code; @@ -686,8 +690,23 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) BLI_dynstr_append(ds, "void main()\n{\n"); - if (builtins & GPU_VIEW_NORMAL) - BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n"); + if (use_new_shading) { + if (builtins & GPU_INVERSE_VIEW_MATRIX) + BLI_dynstr_append(ds, "\tmat4 viewinv = ViewMatrixInverse;\n"); + if (builtins & GPU_VIEW_NORMAL) + BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n"); + if (builtins & GPU_VIEW_POSITION) + BLI_dynstr_append(ds, "\tvec3 viewposition = viewPosition;\n"); + + } + else { + if (builtins & GPU_INVERSE_VIEW_MATRIX) + BLI_dynstr_append(ds, "\tmat4 viewinv = unfinvviewmat;\n"); + if (builtins & GPU_VIEW_NORMAL) + BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? varnormal: -varnormal;\n"); + if (builtins & GPU_VIEW_POSITION) + BLI_dynstr_append(ds, "\tvec3 viewposition = varposition;\n"); + } /* Calculate tangent space. */ #ifdef WITH_OPENSUBDIV @@ -733,6 +752,87 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output) return code; } +static const char *attrib_prefix_get(CustomDataType type) +{ + switch (type) { + case CD_ORCO: return "orco"; + case CD_MTFACE: return "u"; + case CD_TANGENT: return "t"; + case CD_MCOL: return "c"; + case CD_AUTO_FROM_NAME: return "a"; + default: BLI_assert(false && "Attrib Prefix type not found : This should not happen!"); return ""; + } +} + +static char *code_generate_vertex_new(ListBase *nodes, const char *vert_code) +{ + DynStr *ds = BLI_dynstr_new(); + GPUNode *node; + GPUInput *input; + char *code; + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + 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') { + 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)); + } + else { + unsigned int hash = BLI_ghashutil_strhash_p(input->attribname); + BLI_dynstr_appendf(ds, "in %s %s%u;\n", + GPU_DATATYPE_STR[input->type], attrib_prefix_get(input->attribtype), hash); + BLI_dynstr_appendf(ds, "#define att%d %s%u\n", + input->attribid, attrib_prefix_get(input->attribtype), hash); + } + BLI_dynstr_appendf(ds, "out %s var%d;\n", + GPU_DATATYPE_STR[input->type], input->attribid); + } + } + } + + BLI_dynstr_append(ds, "\n"); + + BLI_dynstr_append(ds, "#define ATTRIB\n"); + BLI_dynstr_append(ds, "uniform mat3 NormalMatrix;\n"); + BLI_dynstr_append(ds, "void pass_attrib(void) {\n"); + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { + if (input->attribtype == CD_TANGENT) { /* silly exception */ + BLI_dynstr_appendf( + ds, "\tvar%d.xyz = normalize(NormalMatrix * att%d.xyz);\n", + input->attribid, input->attribid); + BLI_dynstr_appendf( + ds, "\tvar%d.w = att%d.w;\n", + input->attribid, input->attribid); + } + else { + BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", + input->attribid, input->attribid); + } + } + } + } + + BLI_dynstr_append(ds, "}\n"); + + BLI_dynstr_append(ds, vert_code); + + code = BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); + +#if 0 + if (G.debug & G_DEBUG) printf("%s\n", code); +#endif + + return code; +} + static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) { DynStr *ds = BLI_dynstr_new(); @@ -1448,7 +1548,14 @@ GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name) { GPUNodeLink *link = GPU_node_link_create(); - link->attribtype = type; + /* Fall back to the UV layer, which matches old behavior. */ + if (type == CD_AUTO_FROM_NAME && name[0] == '\0') { + link->attribtype = CD_MTFACE; + } + else { + link->attribtype = type; + } + link->attribname = name; return link; @@ -1720,16 +1827,20 @@ GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink /* prune unused nodes */ gpu_nodes_prune(nodes, frag_outlink); + /* Hacky */ + GPUVertexAttribs attribs; + gpu_nodes_get_vertex_attributes(nodes, &attribs); + /* generate code and compile with opengl */ - fragmentgen = code_generate_fragment(nodes, frag_outlink->output); - // vertexgen = code_generate_vertex(nodes, GPU_MATERIAL_TYPE_MESH); + fragmentgen = code_generate_fragment(nodes, frag_outlink->output, true); + vertexgen = code_generate_vertex_new(nodes, vert_code); // geometrygen = code_generate_geometry(nodes, false); - UNUSED_VARS(vertexgen, geometrygen); + UNUSED_VARS(geometrygen); tmp = BLI_strdupcat(frag_lib, glsl_material_library); fragmentcode = BLI_strdupcat(tmp, fragmentgen); - vertexcode = BLI_strdup(vert_code); - geometrycode = BLI_strdup(geom_code); + vertexcode = BLI_strdup(vertexgen); + geometrycode = (geom_code) ? BLI_strdup(geom_code) : NULL; shader = GPU_shader_create(vertexcode, fragmentcode, @@ -1748,6 +1859,7 @@ GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink if (geometrycode) MEM_freeN(geometrycode); MEM_freeN(fragmentgen); + MEM_freeN(vertexgen); gpu_nodes_free(nodes); return NULL; } @@ -1765,6 +1877,7 @@ GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink gpu_nodes_free(nodes); MEM_freeN(fragmentgen); + MEM_freeN(vertexgen); return pass; } @@ -1794,7 +1907,7 @@ GPUPass *GPU_generate_pass( gpu_nodes_get_builtin_flag(nodes, builtins); /* generate code and compile with opengl */ - fragmentcode = code_generate_fragment(nodes, outlink->output); + fragmentcode = code_generate_fragment(nodes, outlink->output, false); vertexcode = code_generate_vertex(nodes, type); geometrycode = code_generate_geometry(nodes, use_opensubdiv); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 083b0596b1c..c00baef2856 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -477,10 +477,6 @@ void gpu_material_add_node(GPUMaterial *material, GPUNode *node) bool GPU_material_do_color_management(GPUMaterial *mat) { - /* XXX mat->scene == NULL in that case */ - if (mat->engine) - return true; - if (!BKE_scene_check_color_management_enabled(mat->scene)) return false; @@ -2109,7 +2105,7 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) /* TODO : This is supposed to replace GPU_material_from_blender/_world in the future */ GPUMaterial *GPU_material_from_nodetree( - struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options, + Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options, const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines) { GPUMaterial *mat; @@ -2127,6 +2123,7 @@ GPUMaterial *GPU_material_from_nodetree( /* allocate material */ mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */ + mat->scene = scene; mat->engine = engine_type; mat->options = options; diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index a0c56e9ebf4..8bfbd07bce8 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -4,6 +4,7 @@ uniform mat4 ModelViewMatrix; uniform mat4 ProjectionMatrix; #endif uniform mat4 ModelViewMatrixInverse; +uniform mat4 ViewMatrixInverse; uniform mat4 ProjectionMatrixInverse; uniform mat3 NormalMatrix; diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index be393582a42..23571e24501 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -48,14 +48,14 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ""); GPUMatType type = GPU_Material_get_type(mat); - if (type == GPU_MATERIAL_TYPE_MESH) { - return GPU_stack_link(mat, "node_tex_coord", in, out, + if (type == GPU_MATERIAL_TYPE_WORLD) { + return GPU_stack_link(mat, "node_tex_coord_background", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface); } else { - return GPU_stack_link(mat, "node_tex_coord_background", in, out, + return GPU_stack_link(mat, "node_tex_coord", in, out, GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX), GPU_builtin(GPU_CAMERA_TEXCO_FACTORS), orco, mtface); -- cgit v1.2.3