GPUMaterial: Add support for tangent node.
authorClément Foucault <foucault.clem@gmail.com>
Thu, 18 May 2017 12:29:57 +0000 (14:29 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Thu, 18 May 2017 14:05:03 +0000 (16:05 +0200)
source/blender/draw/intern/draw_cache_impl_mesh.c
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/nodes/shader/nodes/node_shader_geometry.c
source/blender/nodes/shader/nodes/node_shader_tangent.c

index 841092f1c8d243924c8dcaa5e92dfc23bf26b4c7..999ce0a95e44c0605cb26234f4f13c892b82fb30 100644 (file)
@@ -1754,6 +1754,8 @@ static VertexBuffer *mesh_batch_cache_get_tri_shading_data(MeshRenderData *rdata
 
                        /* Tangent */
                        attrib_name = mesh_render_data_tangent_layer_uuid_get(rdata, i);
+                       /* WATCH IT : only specifying 3 component instead of 4 (4th is sign).
+                        * That may cause some problem but I could not make it to fail (fclem) */
 #ifdef USE_COMP_MESH_DATA
 #  if USE_10_10_10 && 0 /* Tangents need more precision than this */
                        tangent_id[i] = VertexFormat_add_attrib(format, attrib_name, COMP_I10, 3, NORMALIZE_INT_TO_FLOAT);
index 33655396d885e9b94367cb6404dac4fe0666041e..734474465cd186d689e2d724e81b0bbee011f6fd 100644 (file)
@@ -626,6 +626,8 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
                                        BLI_dynstr_append(ds, "viewinv");
                                else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS)
                                        BLI_dynstr_append(ds, "camtexfac");
+                               else if (input->builtin == GPU_OBJECT_MATRIX)
+                                       BLI_dynstr_append(ds, "objmat");
                                else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX)
                                        BLI_dynstr_append(ds, "objinv");
                                else if (input->builtin == GPU_VIEW_POSITION)
@@ -697,6 +699,8 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, bool use
        if (use_new_shading) {
                if (builtins & GPU_CAMERA_TEXCO_FACTORS)
                        BLI_dynstr_append(ds, "\tvec4 camtexfac = CameraTexCoFactors;\n");
+               if (builtins & GPU_OBJECT_MATRIX)
+                       BLI_dynstr_append(ds, "\tmat4 objmat = ModelMatrix;\n");
                if (builtins & GPU_INVERSE_OBJECT_MATRIX)
                        BLI_dynstr_append(ds, "\tmat4 objinv = ModelMatrixInverse;\n");
                if (builtins & GPU_INVERSE_VIEW_MATRIX)
@@ -709,6 +713,8 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, bool use
        else {
                if (builtins & GPU_CAMERA_TEXCO_FACTORS)
                        BLI_dynstr_append(ds, "\tvec4 camtexfac = unfcameratexfactors;\n");
+               if (builtins & GPU_OBJECT_MATRIX)
+                       BLI_dynstr_append(ds, "\tmat4 objmat = unfobmat;\n");
                if (builtins & GPU_INVERSE_OBJECT_MATRIX)
                        BLI_dynstr_append(ds, "\tmat4 objinv = unfinvobmat;\n");
                if (builtins & GPU_INVERSE_VIEW_MATRIX)
index 5a1f48f1f8322492154f71bc2dc6474d76c155ba..f179d9da7bf00ebcdd76ffc39267e3989f78e85b 100644 (file)
@@ -3,6 +3,7 @@ uniform mat4 ModelViewMatrix;
 #ifndef EEVEE_ENGINE
 uniform mat4 ProjectionMatrix;
 #endif
+uniform mat4 ModelMatrix;
 uniform mat4 ModelMatrixInverse;
 uniform mat4 ModelViewMatrixInverse;
 uniform mat4 ViewMatrixInverse;
@@ -2922,15 +2923,43 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
        outvec = attr_uv;
 }
 
+void tangent_orco_x(vec3 orco_in, out vec3 orco_out)
+{
+       orco_out = vec3(0.0, (orco_in.z - 0.5) * -0.5, (orco_in.y - 0.5) * 0.5);
+}
+
+void tangent_orco_y(vec3 orco_in, out vec3 orco_out)
+{
+       orco_out = vec3((orco_in.z - 0.5) * -0.5, 0.0, (orco_in.x - 0.5) * 0.5);
+}
+
+void tangent_orco_z(vec3 orco_in, out vec3 orco_out)
+{
+       orco_out = vec3((orco_in.y - 0.5) * -0.5, (orco_in.x - 0.5) * 0.5, 0.0);
+}
+
+void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent)
+{
+       tangent = (toworld * vec4(attr_tangent.xyz, 0.0)).xyz;
+}
+
+void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T)
+{
+       N = (toworld * vec4(N, 0.0)).xyz;
+       T = (objmat * vec4(orco, 0.0)).xyz;
+       T = cross(N, normalize(cross(T, N)));
+}
+
 void node_geometry(
-        vec3 I, vec3 N, mat4 toworld,
+        vec3 I, vec3 N, vec3 orco, mat4 objmat, mat4 toworld,
         out vec3 position, out vec3 normal, out vec3 tangent,
         out vec3 true_normal, out vec3 incoming, out vec3 parametric,
         out float backfacing, out float pointiness)
 {
        position = (toworld * vec4(I, 1.0)).xyz;
        normal = (toworld * vec4(N, 0.0)).xyz;
-       tangent = vec3(0.0);
+       tangent_orco_z(orco, orco);
+       node_tangent(N, orco, objmat, toworld, tangent);
        true_normal = normal;
 
        /* handle perspective/orthographic */
index 553ea65154f83855c4c23d764f003287de3c909b..7983303449874e139c1d96d61fca6131a983c2d7 100644 (file)
@@ -45,6 +45,7 @@ static int node_shader_gpu_geometry(GPUMaterial *mat, bNode *UNUSED(node), bNode
 {
        return GPU_stack_link(mat, "node_geometry", in, out,
                              GPU_builtin(GPU_VIEW_POSITION), GPU_builtin(GPU_VIEW_NORMAL),
+                             GPU_attribute(CD_ORCO, ""), GPU_builtin(GPU_OBJECT_MATRIX),
                              GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
 }
 
index 7aa7fb43221cbf0b6a63ccbaaa285b9ae65f82e1..9c853f9d86fa42e4f89f71dbcfdcd1da02f036cd 100644 (file)
@@ -41,6 +41,28 @@ static void node_shader_init_tangent(bNodeTree *UNUSED(ntree), bNode *node)
        node->storage = attr;
 }
 
+static int node_shader_gpu_tangent(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
+{
+       NodeShaderTangent *attr = node->storage;
+
+       if (attr->direction_type == SHD_TANGENT_UVMAP) {
+               return GPU_stack_link(mat, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, ""), GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+       }
+       else {
+               GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
+
+               if (attr->axis == SHD_TANGENT_AXIS_X)
+                       GPU_link(mat, "tangent_orco_x", orco, &orco);
+               else if (attr->axis == SHD_TANGENT_AXIS_Y)
+                       GPU_link(mat, "tangent_orco_y", orco, &orco);
+               else
+                       GPU_link(mat, "tangent_orco_z", orco, &orco);
+
+               return GPU_stack_link(mat, "node_tangent", in, out, GPU_builtin(GPU_VIEW_NORMAL), orco,
+                       GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX));
+       }
+}
+
 /* node type definition */
 void register_node_type_sh_tangent(void)
 {
@@ -51,6 +73,7 @@ void register_node_type_sh_tangent(void)
        node_type_socket_templates(&ntype, NULL, sh_node_tangent_out);
        node_type_size_preset(&ntype, NODE_SIZE_MIDDLE);
        node_type_init(&ntype, node_shader_init_tangent);
+       node_type_gpu(&ntype, node_shader_gpu_tangent);
        node_type_storage(&ntype, "NodeShaderTangent", node_free_standard_storage, node_copy_standard_storage);
 
        nodeRegisterType(&ntype);