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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ uniform mat4 ModelViewMatrix;
|
||||
uniform mat4 ProjectionMatrix;
|
||||
#endif
|
||||
uniform mat4 ModelViewMatrixInverse;
|
||||
uniform mat4 ViewMatrixInverse;
|
||||
uniform mat4 ProjectionMatrixInverse;
|
||||
uniform mat3 NormalMatrix;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user