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.
This commit is contained in:
2017-05-01 18:09:50 +02:00
parent 19f86a3d5f
commit 62ea911e1a
6 changed files with 140 additions and 20 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -4,6 +4,7 @@ uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
#endif
uniform mat4 ModelViewMatrixInverse;
uniform mat4 ViewMatrixInverse;
uniform mat4 ProjectionMatrixInverse;
uniform mat3 NormalMatrix;

View File

@@ -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);