Cleanup: more refactoring of GPU material attributes and textures

This further separates requested attributes and textures from the actual
node graph, that can be retained after the graph has been compiled and
freed. It makes it easier to add volume grids as a native concept, which
sits somewhere between an attribute and a texture.

It also adds explicit link types for UDIM tile mapping, rather than
relying on fairly hidden logic.
This commit is contained in:
Brecht Van Lommel 2020-02-27 13:55:29 +01:00
parent 1ec11363bd
commit e88a715364
18 changed files with 377 additions and 401 deletions

View File

@ -1203,6 +1203,19 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass
return grp;
}
static void drw_shgroup_material_texture(DRWShadingGroup *grp,
GPUMaterialTexture *tex,
const char *name,
int textarget)
{
GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
DRW_shgroup_uniform_texture(grp, name, gputex);
GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
*gputex_ref = gputex;
GPU_texture_ref(gputex);
}
static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
struct GPUMaterial *material)
{
@ -1210,35 +1223,20 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
/* Bind all textures needed by the material. */
for (GPUMaterialTexture *tex = textures.first; tex; tex = tex->next) {
GPUTexture *gputex;
if (tex->ima) {
/* Image */
GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
int textarget;
if (tex->type == GPU_TEX2D_ARRAY) {
textarget = GL_TEXTURE_2D_ARRAY;
}
else if (tex->type == GPU_TEX1D_ARRAY) {
textarget = GL_TEXTURE_1D_ARRAY;
if (tex->tiled_mapping_name[0]) {
drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY);
drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY);
}
else {
textarget = GL_TEXTURE_2D;
drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D);
}
*gputex_ref = gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
GPU_texture_ref(gputex);
}
else if (tex->colorband) {
/* Color Ramp */
gputex = *tex->colorband;
DRW_shgroup_uniform_texture(grp, tex->sampler_name, *tex->colorband);
}
else {
continue;
}
DRW_shgroup_uniform_texture(grp, tex->shadername, gputex);
}
GPUUniformBuffer *ubo = GPU_material_uniform_buffer_get(material);

View File

@ -64,6 +64,7 @@ typedef enum eGPUType {
GPU_VEC4 = 4,
GPU_MAT3 = 9,
GPU_MAT4 = 16,
GPU_MAX_CONSTANT_DATA = GPU_MAT4,
/* Values not in GPU_DATATYPE_STR */
GPU_TEX1D_ARRAY = 1001,
@ -137,10 +138,12 @@ typedef enum eGPUMaterialStatus {
GPU_MAT_SUCCESS,
} eGPUMaterialStatus;
GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_constant(float *num);
GPUNodeLink *GPU_uniform(float *num);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_builtin(eGPUBuiltin builtin);
@ -212,17 +215,19 @@ typedef struct GPUMaterialAttribute {
struct GPUMaterialAttribute *next, *prev;
int type; /* CustomDataType */
char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
eGPUType gputype;
int id;
int users;
} GPUMaterialAttribute;
typedef struct GPUMaterialTexture {
struct GPUMaterialTexture *next, *prev;
eGPUType type;
struct Image *ima;
struct ImageUser *iuser;
struct GPUTexture **colorband;
char shadername[32]; /* Name of sampler in GLSL. */
int id;
char sampler_name[32]; /* Name of sampler in GLSL. */
char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
int users;
} GPUMaterialTexture;
ListBase GPU_material_attributes(GPUMaterial *material);

View File

@ -216,16 +216,6 @@ static void codegen_print_datatype(DynStr *ds, const eGPUType type, float *data)
}
}
static int codegen_input_has_texture(GPUInput *input)
{
if (input->link) {
return 0;
}
else {
return (input->source == GPU_SOURCE_TEX);
}
}
static const char *gpu_builtin_name(eGPUBuiltin builtin)
{
if (builtin == GPU_VIEW_MATRIX) {
@ -299,14 +289,14 @@ static const char *gpu_builtin_name(eGPUBuiltin builtin)
}
}
static void codegen_set_unique_ids(ListBase *nodes)
static void codegen_set_unique_ids(GPUNodeGraph *graph)
{
GPUNode *node;
GPUInput *input;
GPUOutput *output;
int id = 1;
for (node = nodes->first; node; node = node->next) {
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
/* set id for unique names of uniform variables */
input->id = id++;
@ -322,7 +312,9 @@ static void codegen_set_unique_ids(ListBase *nodes)
/**
* It will create an UBO for GPUMaterial if there is any GPU_DYNAMIC_UBO.
*/
static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes)
static int codegen_process_uniforms_functions(GPUMaterial *material,
DynStr *ds,
GPUNodeGraph *graph)
{
GPUNode *node;
GPUInput *input;
@ -330,27 +322,29 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
int builtins = 0;
ListBase ubo_inputs = {NULL, NULL};
/* print uniforms */
for (node = nodes->first; node; node = node->next) {
/* Attributes */
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
BLI_dynstr_appendf(ds, "in %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
/* Textures */
for (GPUMaterialTexture *tex = graph->textures.first; tex; tex = tex->next) {
if (tex->colorband) {
BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->sampler_name);
}
else if (tex->tiled_mapping_name[0]) {
BLI_dynstr_appendf(ds, "uniform sampler2DArray %s;\n", tex->sampler_name);
BLI_dynstr_appendf(ds, "uniform sampler1DArray %s;\n", tex->tiled_mapping_name);
}
else {
BLI_dynstr_appendf(ds, "uniform sampler2D %s;\n", tex->sampler_name);
}
}
/* Print other uniforms */
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX) {
/* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex) {
const char *type;
if (input->colorband || input->type == GPU_TEX1D_ARRAY) {
type = "sampler1DArray";
}
else if (input->type == GPU_TEX2D_ARRAY) {
type = "sampler2DArray";
}
else {
BLI_assert(input->type == GPU_TEX2D);
type = "sampler2D";
}
BLI_dynstr_appendf(ds, "uniform %s samp%d;\n", type, input->texid);
}
}
else if (input->source == GPU_SOURCE_BUILTIN) {
if (input->source == GPU_SOURCE_BUILTIN) {
/* only define each builtin uniform/varying once */
if (!(builtins & input->builtin)) {
builtins |= input->builtin;
@ -385,10 +379,6 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
codegen_print_datatype(ds, input->type, input->vec);
BLI_dynstr_append(ds, ";\n");
}
else if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
BLI_dynstr_appendf(
ds, "in %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id);
}
}
}
@ -412,12 +402,12 @@ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds,
return builtins;
}
static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
static void codegen_declare_tmps(DynStr *ds, GPUNodeGraph *graph)
{
GPUNode *node;
GPUOutput *output;
for (node = nodes->first; node; node = node->next) {
for (node = graph->nodes.first; node; node = node->next) {
/* declare temporary variables for node output storage */
for (output = node->outputs.first; output; output = output->next) {
if (output->type == GPU_CLOSURE) {
@ -432,18 +422,21 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
BLI_dynstr_append(ds, "\n");
}
static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput)
static void codegen_call_functions(DynStr *ds, GPUNodeGraph *graph, GPUOutput *finaloutput)
{
GPUNode *node;
GPUInput *input;
GPUOutput *output;
for (node = nodes->first; node; node = node->next) {
for (node = graph->nodes.first; node; node = node->next) {
BLI_dynstr_appendf(ds, "\t%s(", node->name);
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX) {
BLI_dynstr_appendf(ds, "samp%d", input->texid);
BLI_dynstr_append(ds, input->texture->sampler_name);
}
else if (input->source == GPU_SOURCE_TEX_TILED_MAPPING) {
BLI_dynstr_append(ds, input->texture->tiled_mapping_name);
}
else if (input->source == GPU_SOURCE_OUTPUT) {
codegen_convert_datatype(
@ -507,7 +500,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_appendf(ds, "cons%d", input->id);
}
else if (input->source == GPU_SOURCE_ATTR) {
BLI_dynstr_appendf(ds, "var%d", input->attr_id);
BLI_dynstr_appendf(ds, "var%d", input->attr->id);
}
BLI_dynstr_append(ds, ", ");
@ -527,7 +520,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ";\n");
}
static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output)
static char *code_generate_fragment(GPUMaterial *material, GPUNodeGraph *graph)
{
DynStr *ds = BLI_dynstr_new();
char *code;
@ -537,8 +530,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO
BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
#endif
codegen_set_unique_ids(nodes);
builtins = codegen_process_uniforms_functions(material, ds, nodes);
codegen_set_unique_ids(graph);
builtins = codegen_process_uniforms_functions(material, ds, graph);
if (builtins & (GPU_OBJECT_INFO | GPU_OBJECT_COLOR)) {
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
@ -614,8 +607,8 @@ static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUO
BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n");
}
codegen_declare_tmps(ds, nodes);
codegen_call_functions(ds, nodes, output);
codegen_declare_tmps(ds, graph);
codegen_call_functions(ds, graph, graph->outlink->output);
BLI_dynstr_append(ds, "}\n");
@ -666,7 +659,7 @@ static const char *attr_prefix_get(CustomDataType type)
}
}
static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom)
static char *code_generate_vertex(GPUNodeGraph *graph, const char *vert_code, bool use_geom)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
@ -682,48 +675,44 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
"#define DEFINE_ATTR(type, attr) in type attr\n"
"#endif\n");
for (node = nodes->first; node; node = node->next) {
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
/* XXX FIXME : see notes in mesh_render_data_create() */
/* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */
if (attr->type == CD_ORCO) {
/* OPTI : orco is computed from local positions, but only if no modifier is present. */
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
}
else if (attr->name[0] == '\0') {
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s);\n",
gpu_data_type_to_string(attr->gputype),
attr_prefix_get(attr->type));
BLI_dynstr_appendf(ds, "#define att%d %s\n", attr->id, attr_prefix_get(attr->type));
}
else {
char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
GPU_vertformat_safe_attrib_name(attr->name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s%s);\n",
gpu_data_type_to_string(attr->gputype),
attr_prefix_get(attr->type),
attr_safe_name);
BLI_dynstr_appendf(
ds, "#define att%d %s%s\n", attr->id, attr_prefix_get(attr->type), attr_safe_name);
}
BLI_dynstr_appendf(ds,
"out %s var%d%s;\n",
gpu_data_type_to_string(attr->gputype),
attr->id,
use_geom ? "g" : "");
}
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
/* 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->attr_type == CD_ORCO) {
/* OPTI : orco is computed from local positions, but only if no modifier is present. */
BLI_dynstr_append(ds, datatoc_gpu_shader_common_obinfos_lib_glsl);
BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n");
}
else if (input->attr_name[0] == '\0') {
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s);\n",
gpu_data_type_to_string(input->type),
attr_prefix_get(input->attr_type));
BLI_dynstr_appendf(
ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type));
}
else {
char attr_safe_name[GPU_MAX_SAFE_ATTRIB_NAME];
GPU_vertformat_safe_attrib_name(
input->attr_name, attr_safe_name, GPU_MAX_SAFE_ATTRIB_NAME);
BLI_dynstr_appendf(ds,
"DEFINE_ATTR(%s, %s%s);\n",
gpu_data_type_to_string(input->type),
attr_prefix_get(input->attr_type),
attr_safe_name);
BLI_dynstr_appendf(ds,
"#define att%d %s%s\n",
input->attr_id,
attr_prefix_get(input->attr_type),
attr_safe_name);
}
BLI_dynstr_appendf(ds,
"out %s var%d%s;\n",
gpu_data_type_to_string(input->type),
input->attr_id,
use_geom ? "g" : "");
}
}
}
@ -800,30 +789,26 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n");
}
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
if (input->attr_type == CD_TANGENT) {
/* Not supported by hairs */
BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", input->attr_id, use_geom ? "g" : "");
}
else if (input->attr_type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
"vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
input->attr_id,
use_geom ? "g" : "");
/* TODO: fix ORCO with modifiers. */
}
else {
BLI_dynstr_appendf(ds,
"\tvar%d%s = hair_get_customdata_%s(att%d);\n",
input->attr_id,
use_geom ? "g" : "",
gpu_data_type_to_string(input->type),
input->attr_id);
}
}
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
if (attr->type == CD_TANGENT) {
/* Not supported by hairs */
BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", attr->id, use_geom ? "g" : "");
}
else if (attr->type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + (ModelMatrixInverse * "
"vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1].xyz;\n",
attr->id,
use_geom ? "g" : "");
/* TODO: fix ORCO with modifiers. */
}
else {
BLI_dynstr_appendf(ds,
"\tvar%d%s = hair_get_customdata_%s(att%d);\n",
attr->id,
use_geom ? "g" : "",
gpu_data_type_to_string(attr->gputype),
attr->id);
}
}
@ -837,49 +822,43 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n");
}
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
if (input->attr_type == CD_TANGENT) { /* silly exception */
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
input->attr_id,
use_geom ? "g" : "",
input->attr_id);
BLI_dynstr_appendf(
ds, "\tvar%d%s.w = att%d.w;\n", input->attr_id, use_geom ? "g" : "", input->attr_id);
/* Normalize only if vector is not null. */
BLI_dynstr_appendf(ds,
"\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n",
input->attr_id,
input->attr_id,
use_geom ? "g" : "",
input->attr_id,
use_geom ? "g" : "");
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n",
input->attr_id,
use_geom ? "g" : "",
input->attr_id,
input->attr_id);
}
else if (input->attr_type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
" OrcoTexCoFactors[1].xyz;\n",
input->attr_id,
use_geom ? "g" : "");
/* See mesh_create_loop_orco() for explanation. */
BLI_dynstr_appendf(ds,
"\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n",
input->attr_id,
use_geom ? "g" : "");
}
else {
BLI_dynstr_appendf(
ds, "\tvar%d%s = att%d;\n", input->attr_id, use_geom ? "g" : "", input->attr_id);
}
}
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
if (attr->type == CD_TANGENT) { /* silly exception */
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz = transpose(mat3(ModelMatrixInverse)) * att%d.xyz;\n",
attr->id,
use_geom ? "g" : "",
attr->id);
BLI_dynstr_appendf(ds, "\tvar%d%s.w = att%d.w;\n", attr->id, use_geom ? "g" : "", attr->id);
/* Normalize only if vector is not null. */
BLI_dynstr_appendf(ds,
"\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n",
attr->id,
attr->id,
use_geom ? "g" : "",
attr->id,
use_geom ? "g" : "");
BLI_dynstr_appendf(ds,
"\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n",
attr->id,
use_geom ? "g" : "",
attr->id,
attr->id);
}
else if (attr->type == CD_ORCO) {
BLI_dynstr_appendf(ds,
"\tvar%d%s = OrcoTexCoFactors[0].xyz + position *"
" OrcoTexCoFactors[1].xyz;\n",
attr->id,
use_geom ? "g" : "");
/* See mesh_create_loop_orco() for explanation. */
BLI_dynstr_appendf(ds,
"\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n",
attr->id,
use_geom ? "g" : "");
}
else {
BLI_dynstr_appendf(ds, "\tvar%d%s = att%d;\n", attr->id, use_geom ? "g" : "", attr->id);
}
}
BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n");
@ -899,7 +878,9 @@ static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool u
return code;
}
static char *code_generate_geometry(ListBase *nodes, const char *geom_code, const char *defines)
static char *code_generate_geometry(GPUNodeGraph *graph,
const char *geom_code,
const char *defines)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
@ -916,20 +897,19 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "#define USE_ATTR\n");
/* Generate varying declarations. */
for (node = nodes->first; node; node = node->next) {
for (node = graph->nodes.first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_BUILTIN) {
builtins |= input->builtin;
}
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
BLI_dynstr_appendf(
ds, "in %s var%dg[];\n", gpu_data_type_to_string(input->type), input->attr_id);
BLI_dynstr_appendf(
ds, "out %s var%d;\n", gpu_data_type_to_string(input->type), input->attr_id);
}
}
}
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
BLI_dynstr_appendf(ds, "in %s var%dg[];\n", gpu_data_type_to_string(attr->gputype), attr->id);
BLI_dynstr_appendf(ds, "out %s var%d;\n", gpu_data_type_to_string(attr->gputype), attr->id);
}
if (builtins & GPU_BARYCENTRIC_TEXCO) {
BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n");
BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n");
@ -1032,13 +1012,9 @@ static char *code_generate_geometry(ListBase *nodes, const char *geom_code, cons
BLI_dynstr_append(ds, "#endif\n");
}
for (node = nodes->first; node; node = node->next) {
for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTR && input->attr_first) {
/* TODO let shader choose what to do depending on what the attribute is. */
BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attr_id, input->attr_id);
}
}
for (GPUMaterialAttribute *attr = graph->attributes.first; attr; attr = attr->next) {
/* TODO let shader choose what to do depending on what the attribute is. */
BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", attr->id, attr->id);
}
BLI_dynstr_append(ds, "}\n");
@ -1053,94 +1029,6 @@ GPUShader *GPU_pass_shader_get(GPUPass *pass)
return pass->shader;
}
/* Requested Attributes */
static ListBase gpu_nodes_requested_attributes(ListBase *nodes)
{
ListBase attributes = {NULL};
int num_attributes = 0;
/* Convert attributes requested by node inputs to list, checking for
* checking for duplicates and assigning id's starting from zero. */
for (GPUNode *node = nodes->first; node; node = node->next) {
for (GPUInput *input = node->inputs.first; input; input = input->next) {
if (input->source != GPU_SOURCE_ATTR) {
continue;
}
GPUMaterialAttribute *attr = attributes.first;
for (; attr; attr = attr->next) {
if (attr->type == input->attr_type && STREQ(attr->name, input->attr_name)) {
break;
}
}
/* Add new requested attribute if it's within GPU limits. */
if (attr == NULL && num_attributes < GPU_MAX_ATTR) {
attr = MEM_callocN(sizeof(*attr), __func__);
attr->type = input->attr_type;
STRNCPY(attr->name, input->attr_name);
attr->id = num_attributes++;
BLI_addtail(&attributes, attr);
input->attr_id = attr->id;
input->attr_first = true;
}
else if (attr != NULL) {
input->attr_id = attr->id;
}
}
}
return attributes;
}
/* Requested Textures */
static ListBase gpu_nodes_requested_textures(ListBase *nodes)
{
ListBase textures = {NULL};
int num_textures = 0;
/* Convert textures requested by node inputs to list, checking for
* checking for duplicates and assigning id's starting from zero. */
for (GPUNode *node = nodes->first; node; node = node->next) {
for (GPUInput *input = node->inputs.first; input; input = input->next) {
if (!codegen_input_has_texture(input)) {
continue;
}
GPUMaterialTexture *tex = textures.first;
for (; tex; tex = tex->next) {
if (tex->ima == input->ima && tex->colorband == input->colorband &&
tex->type == input->type) {
break;
}
}
if (tex == NULL) {
tex = MEM_callocN(sizeof(*tex), __func__);
tex->ima = input->ima;
tex->iuser = input->iuser;
tex->colorband = input->colorband;
tex->id = num_textures++;
tex->type = input->type;
BLI_snprintf(tex->shadername, sizeof(tex->shadername), "samp%d", tex->id);
BLI_addtail(&textures, tex);
input->texid = tex->id;
input->bindtex = true;
}
else {
input->texid = tex->id;
input->bindtex = false;
}
}
}
return textures;
}
/* Pass create/free */
static bool gpu_pass_is_valid(GPUPass *pass)
@ -1160,11 +1048,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
* generated VBOs are ready to accept the future shader. */
gpu_node_graph_prune_unused(graph);
graph->attributes = gpu_nodes_requested_attributes(&graph->nodes);
graph->textures = gpu_nodes_requested_textures(&graph->nodes);
/* generate code */
char *fragmentgen = code_generate_fragment(material, &graph->nodes, graph->outlink->output);
char *fragmentgen = code_generate_fragment(material, graph);
/* Cache lookup: Reuse shaders already compiled */
uint32_t hash = gpu_pass_hash(fragmentgen, defines, &graph->attributes);
@ -1186,8 +1071,8 @@ GPUPass *GPU_generate_pass(GPUMaterial *material,
GSet *used_libraries = gpu_material_used_libraries(material);
char *tmp = gpu_material_library_generate_code(used_libraries, frag_lib);
char *geometrycode = code_generate_geometry(&graph->nodes, geom_code, defines);
char *vertexcode = code_generate_vertex(&graph->nodes, vert_code, (geometrycode != NULL));
char *geometrycode = code_generate_geometry(graph, geom_code, defines);
char *vertexcode = code_generate_vertex(graph, vert_code, (geometrycode != NULL));
char *fragmentcode = BLI_strdupcat(tmp, fragmentgen);
MEM_freeN(fragmentgen);

View File

@ -207,11 +207,6 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
ListBase *GPU_material_get_inputs(GPUMaterial *material)
{
return &material->graph.inputs;
}
/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
@ -579,9 +574,9 @@ void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
}
}
void gpu_material_add_node(GPUMaterial *material, GPUNode *node)
GPUNodeGraph *gpu_material_node_graph(GPUMaterial *material)
{
BLI_addtail(&material->graph.nodes, node);
return &material->graph;
}
GSet *gpu_material_used_libraries(GPUMaterial *material)

View File

@ -109,20 +109,20 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType
input->link = link;
link->users++;
break;
case GPU_NODE_LINK_IMAGE:
case GPU_NODE_LINK_IMAGE_TILED:
case GPU_NODE_LINK_COLORBAND:
input->source = GPU_SOURCE_TEX;
input->colorband = link->colorband;
input->texture = link->texture;
break;
case GPU_NODE_LINK_IMAGE_BLENDER:
case GPU_NODE_LINK_IMAGE_TILEMAP:
input->source = GPU_SOURCE_TEX;
input->ima = link->ima;
input->iuser = link->iuser;
case GPU_NODE_LINK_IMAGE_TILED_MAPPING:
input->source = GPU_SOURCE_TEX_TILED_MAPPING;
input->texture = link->texture;
break;
case GPU_NODE_LINK_ATTR:
input->source = GPU_SOURCE_ATTR;
input->attr_type = link->attr_type;
BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name));
input->attr = link->attr;
input->attr->gputype = type;
break;
case GPU_NODE_LINK_CONSTANT:
input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT;
@ -249,24 +249,97 @@ static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **li
BLI_addtail(&node->outputs, output);
}
/* Creating Inputs */
/* Attributes and Textures */
GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
static GPUMaterialAttribute *gpu_node_graph_add_attribute(GPUNodeGraph *graph,
CustomDataType type,
const char *name)
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_ATTR;
link->attr_name = name;
/* Fall back to the UV layer, which matches old behavior. */
if (type == CD_AUTO_FROM_NAME && name[0] == '\0') {
link->attr_type = CD_MTFACE;
type = CD_MTFACE;
}
else {
link->attr_type = type;
/* Find existing attribute. */
int num_attributes = 0;
GPUMaterialAttribute *attr = graph->attributes.first;
for (; attr; attr = attr->next) {
if (attr->type == type && STREQ(attr->name, name)) {
break;
}
num_attributes++;
}
/* Add new requested attribute if it's within GPU limits. */
if (attr == NULL && num_attributes < GPU_MAX_ATTR) {
attr = MEM_callocN(sizeof(*attr), __func__);
attr->type = type;
STRNCPY(attr->name, name);
attr->id = num_attributes;
BLI_addtail(&graph->attributes, attr);
}
if (attr != NULL) {
attr->users++;
}
return attr;
}
static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
struct GPUTexture **colorband,
GPUNodeLinkType link_type)
{
/* Find existing texture. */
int num_textures = 0;
GPUMaterialTexture *tex = graph->textures.first;
for (; tex; tex = tex->next) {
if (tex->ima == ima && tex->colorband == colorband) {
break;
}
num_textures++;
}
/* Add new requested texture. */
if (tex == NULL) {
tex = MEM_callocN(sizeof(*tex), __func__);
tex->ima = ima;
tex->iuser = iuser;
tex->colorband = colorband;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
BLI_snprintf(
tex->tiled_mapping_name, sizeof(tex->tiled_mapping_name), "tsamp%d", num_textures);
}
BLI_addtail(&graph->textures, tex);
}
tex->users++;
return tex;
}
/* Creating Inputs */
GPUNodeLink *GPU_attribute(GPUMaterial *mat, const CustomDataType type, const char *name)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUMaterialAttribute *attr = gpu_node_graph_add_attribute(graph, type, name);
if (attr == NULL) {
static const float zero_data[GPU_MAX_CONSTANT_DATA] = {0.0f};
return GPU_constant(zero_data);
}
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_ATTR;
link->attr = attr;
return link;
}
GPUNodeLink *GPU_constant(float *num)
GPUNodeLink *GPU_constant(const float *num)
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_CONSTANT;
@ -274,7 +347,7 @@ GPUNodeLink *GPU_constant(float *num)
return link;
}
GPUNodeLink *GPU_uniform(float *num)
GPUNodeLink *GPU_uniform(const float *num)
{
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_UNIFORM;
@ -282,21 +355,42 @@ GPUNodeLink *GPU_uniform(float *num)
return link;
}
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser)
GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_BLENDER;
link->ima = ima;
link->iuser = iuser;
link->link_type = GPU_NODE_LINK_IMAGE;
link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
return link;
}
GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED;
link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
return link;
}
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iuser)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
return link;
}
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row)
{
struct GPUTexture **colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
MEM_freeN(pixels);
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
link->colorband = gpu_material_ramp_texture_row_set(mat, size, pixels, row);
MEM_freeN(pixels);
link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type);
return link;
}
@ -340,7 +434,8 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
}
va_end(params);
gpu_material_add_node(mat, node);
GPUNodeGraph *graph = gpu_material_node_graph(mat);
BLI_addtail(&graph->nodes, node);
return true;
}
@ -415,7 +510,8 @@ bool GPU_stack_link(GPUMaterial *material,
}
va_end(params);
gpu_material_add_node(material, node);
GPUNodeGraph *graph = gpu_material_node_graph(material);
BLI_addtail(&graph->nodes, node);
return true;
}
@ -435,6 +531,13 @@ static void gpu_inputs_free(ListBase *inputs)
GPUInput *input;
for (input = inputs->first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTR) {
input->attr->users--;
}
else if (ELEM(input->source, GPU_SOURCE_TEX, GPU_SOURCE_TEX_TILED_MAPPING)) {
input->texture->users--;
}
if (input->link) {
gpu_node_link_free(input->link);
}
@ -469,7 +572,6 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
gpu_node_free(node);
}
gpu_inputs_free(&graph->inputs);
graph->outlink = NULL;
}
@ -477,8 +579,8 @@ void gpu_node_graph_free_nodes(GPUNodeGraph *graph)
void gpu_node_graph_free(GPUNodeGraph *graph)
{
gpu_node_graph_free_nodes(graph);
BLI_freelistN(&graph->attributes);
BLI_freelistN(&graph->textures);
BLI_freelistN(&graph->attributes);
}
/* Prune Unused Nodes */
@ -507,15 +609,13 @@ static void gpu_nodes_tag(GPUNodeLink *link)
void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
{
GPUNode *node, *next;
for (node = graph->nodes.first; node; node = node->next) {
for (GPUNode *node = graph->nodes.first; node; node = node->next) {
node->tag = false;
}
gpu_nodes_tag(graph->outlink);
for (node = graph->nodes.first; node; node = next) {
for (GPUNode *node = graph->nodes.first, *next = NULL; node; node = next) {
next = node->next;
if (!node->tag) {
@ -523,4 +623,18 @@ void gpu_node_graph_prune_unused(GPUNodeGraph *graph)
gpu_node_free(node);
}
}
for (GPUMaterialAttribute *attr = graph->attributes.first, *next = NULL; attr; attr = next) {
next = attr->next;
if (attr->users == 0) {
BLI_freelinkN(&graph->attributes, attr);
}
}
for (GPUMaterialTexture *tex = graph->textures.first, *next = NULL; tex; tex = next) {
next = tex->next;
if (tex->users == 0) {
BLI_freelinkN(&graph->textures, tex);
}
}
}

View File

@ -19,6 +19,8 @@
/** \file
* \ingroup gpu
*
* Intermediate node graph for generating GLSL shaders.
*/
#ifndef __GPU_NODE_GRAPH_H__
@ -45,6 +47,7 @@ typedef enum eGPUDataSource {
GPU_SOURCE_BUILTIN,
GPU_SOURCE_STRUCT,
GPU_SOURCE_TEX,
GPU_SOURCE_TEX_TILED_MAPPING,
} eGPUDataSource;
typedef enum {
@ -53,8 +56,9 @@ typedef enum {
GPU_NODE_LINK_BUILTIN,
GPU_NODE_LINK_COLORBAND,
GPU_NODE_LINK_CONSTANT,
GPU_NODE_LINK_IMAGE_BLENDER,
GPU_NODE_LINK_IMAGE_TILEMAP,
GPU_NODE_LINK_IMAGE,
GPU_NODE_LINK_IMAGE_TILED,
GPU_NODE_LINK_IMAGE_TILED_MAPPING,
GPU_NODE_LINK_OUTPUT,
GPU_NODE_LINK_UNIFORM,
} GPUNodeLinkType;
@ -79,7 +83,7 @@ struct GPUNodeLink {
union {
/* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */
float *data;
const float *data;
/* GPU_NODE_LINK_BUILTIN */
eGPUBuiltin builtin;
/* GPU_NODE_LINK_COLORBAND */
@ -87,15 +91,9 @@ struct GPUNodeLink {
/* GPU_NODE_LINK_OUTPUT */
struct GPUOutput *output;
/* GPU_NODE_LINK_ATTR */
struct {
const char *attr_name;
CustomDataType attr_type;
};
/* GPU_NODE_LINK_IMAGE_BLENDER | GPU_NODE_LINK_IMAGE_TILEMAP */
struct {
struct Image *ima;
struct ImageUser *iuser;
};
struct GPUMaterialAttribute *attr;
/* GPU_NODE_LINK_IMAGE_BLENDER */
struct GPUMaterialTexture *texture;
};
};
@ -118,35 +116,16 @@ typedef struct GPUInput {
eGPUDataSource source; /* data source */
int shaderloc; /* id from opengl */
char shadername[32]; /* name in shader */
/* Content based on eGPUDataSource */
union {
/* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */
float vec[16]; /* vector data */
/* GPU_SOURCE_BUILTIN */
eGPUBuiltin builtin; /* builtin uniform */
/* GPU_SOURCE_TEX */
struct {
struct GPUTexture **colorband; /* input texture, only set at runtime */
struct Image *ima; /* image */
struct ImageUser *iuser; /* image user */
bool bindtex; /* input is responsible for binding the texture? */
int texid; /* number for multitexture, starting from zero */
eGPUType textype; /* texture type (2D, 1D Array ...) */
};
/* GPU_SOURCE_TEX | GPU_SOURCE_TEX_TILED_MAPPING */
struct GPUMaterialTexture *texture;
/* GPU_SOURCE_ATTR */
struct {
/** Attribute name. */
char attr_name[MAX_CUSTOMDATA_LAYER_NAME];
/** ID for vertex attributes. */
int attr_id;
/** This is the first one that is bound. */
bool attr_first;
/** Attribute type. */
CustomDataType attr_type;
};
struct GPUMaterialAttribute *attr;
};
} GPUInput;
@ -154,8 +133,7 @@ typedef struct GPUNodeGraph {
/* Nodes */
ListBase nodes;
/* Inputs and output. */
ListBase inputs;
/* Output. */
GPUNodeLink *outlink;
/* Requested attributes and textures. */
@ -171,7 +149,7 @@ void gpu_node_graph_free(GPUNodeGraph *graph);
/* Material calls */
void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node);
struct GPUNodeGraph *gpu_material_node_graph(struct GPUMaterial *material);
struct GPUTexture **gpu_material_ramp_texture_row_set(struct GPUMaterial *mat,
int size,
float *pixels,

View File

@ -276,7 +276,7 @@ void node_shader_gpu_bump_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink *
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
{
if (!*link) {
*link = GPU_attribute(CD_ORCO, "");
*link = GPU_attribute(mat, CD_ORCO, "");
GPU_link(mat, "generated_texco", GPU_builtin(GPU_VIEW_POSITION), *link, link);
node_shader_gpu_bump_tex_coord(mat, node, link);
}

View File

@ -66,7 +66,7 @@ static int node_shader_gpu_attribute(GPUMaterial *mat,
GPU_builtin(GPU_VOLUME_TEMPERATURE));
}
else {
GPUNodeLink *cd_attr = GPU_attribute(CD_AUTO_FROM_NAME, attr->name);
GPUNodeLink *cd_attr = GPU_attribute(mat, CD_AUTO_FROM_NAME, attr->name);
GPU_stack_link(mat, node, "node_attribute", in, out, cd_attr);
/* for each output. */

View File

@ -46,7 +46,8 @@ static int node_shader_gpu_geometry(GPUMaterial *mat,
GPUNodeLink *bary_link = (!out[5].hasoutput) ? GPU_constant(val) :
GPU_builtin(GPU_BARYCENTRIC_TEXCO);
/* Opti: don't request orco if not needed. */
GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) : GPU_attribute(CD_ORCO, "");
GPUNodeLink *orco_link = (!out[2].hasoutput) ? GPU_constant(val) :
GPU_attribute(mat, CD_ORCO, "");
const bool success = GPU_stack_link(mat,
node,

View File

@ -92,7 +92,7 @@ static int gpu_shader_normal_map(GPUMaterial *mat,
GPU_link(mat,
"node_normal_map",
GPU_builtin(GPU_OBJECT_INFO),
GPU_attribute(CD_TANGENT, nm->uv_map),
GPU_attribute(mat, CD_TANGENT, nm->uv_map),
GPU_builtin(GPU_WORLD_NORMAL),
newnormal,
&newnormal);

View File

@ -43,10 +43,10 @@ static int node_shader_gpu_tangent(GPUMaterial *mat,
if (attr->direction_type == SHD_TANGENT_UVMAP) {
return GPU_stack_link(
mat, node, "node_tangentmap", in, out, GPU_attribute(CD_TANGENT, attr->uv_map));
mat, node, "node_tangentmap", in, out, GPU_attribute(mat, CD_TANGENT, attr->uv_map));
}
else {
GPUNodeLink *orco = GPU_attribute(CD_ORCO, "");
GPUNodeLink *orco = GPU_attribute(mat, CD_ORCO, "");
if (attr->axis == SHD_TANGENT_AXIS_X) {
GPU_link(mat, "tangent_orco_x", orco, &orco);

View File

@ -47,8 +47,8 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat,
/* Opti: don't request orco if not needed. */
GPUNodeLink *orco = (!out[0].hasoutput) ? GPU_constant((float[4]){0.0f, 0.0f, 0.0f, 0.0f}) :
GPU_attribute(CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, "");
GPU_attribute(mat, CD_ORCO, "");
GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, "");
GPUNodeLink *viewpos = GPU_builtin(GPU_VIEW_POSITION);
GPUNodeLink *worldnor = GPU_builtin(GPU_WORLD_NORMAL);
GPUNodeLink *texcofacs = GPU_builtin(GPU_CAMERA_TEXCO_FACTORS);

View File

@ -88,7 +88,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
"node_tex_environment_equirectangular",
in[0].link,
GPU_constant(&clamp_size),
GPU_image(ima, iuser),
GPU_image(mat, ima, iuser),
&in[0].link);
}
else {
@ -103,7 +103,7 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_linear_no_mip",
in[0].link,
GPU_image(ima, iuser),
GPU_image(mat, ima, iuser),
&out[0].link,
&outalpha);
break;
@ -111,13 +111,17 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
GPU_link(mat,
"node_tex_image_nearest",
in[0].link,
GPU_image(ima, iuser),
GPU_image(mat, ima, iuser),
&out[0].link,
&outalpha);
break;
default:
GPU_link(
mat, "node_tex_image_cubic", in[0].link, GPU_image(ima, iuser), &out[0].link, &outalpha);
GPU_link(mat,
"node_tex_image_cubic",
in[0].link,
GPU_image(mat, ima, iuser),
&out[0].link,
&outalpha);
break;
}

View File

@ -123,26 +123,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
}
if (!*texco) {
*texco = GPU_attribute(CD_MTFACE, "");
*texco = GPU_attribute(mat, CD_MTFACE, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
}
node_shader_gpu_tex_mapping(mat, node, in, out);
if (ima->source == IMA_SRC_TILED) {
/* The tiled shader needs both the tile array itself as well as the mapping from tile to array
* position. Which of these to allocate is automatically decided based on the shader argument
* type, so here the first GPU_image(ima, iuser) will resolve to the array and the second to
* the mapping since the third argument in the shader has type sampler2DArray while
* the fourth is sampler1DArray.
*/
/* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */
GPU_stack_link(mat,
node,
names_tiled[tex->interpolation],
in,
out,
GPU_image(ima, iuser),
GPU_image(ima, iuser));
GPU_image_tiled(mat, ima, iuser),
GPU_image_tiled_mapping(mat, ima, iuser));
}
else {
switch (tex->projection) {
@ -157,20 +152,21 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
case SHD_PROJ_BOX:
vnor = GPU_builtin(GPU_WORLD_NORMAL);
ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
blend = GPU_uniform(&tex->projection_blend);
gpu_image = GPU_image(ima, iuser);
gpu_image = GPU_image(mat, ima, iuser);
/* equivalent to normal_world_to_object */
GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
GPU_link(mat, gpu_node_name, *texco, norm, GPU_image(ima, iuser), &col1, &col2, &col3);
GPU_link(
mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3);
GPU_stack_link(
mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
break;
@ -184,9 +180,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
case SHD_PROJ_TUBE:
@ -198,9 +194,9 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPU_link(mat, "set_rgb", *texco, &input_coords);
}
if (do_texco_extend) {
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(ima, iuser), texco);
GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
}
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser));
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
break;
}
@ -208,7 +204,7 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
if (do_texco_clip) {
gpu_node_name = names_clip[tex->interpolation];
in[0].link = input_coords;
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(ima, iuser), out[0].link);
GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link);
}
}
}

View File

@ -63,7 +63,7 @@ static int node_shader_gpu_tex_sky(GPUMaterial *mat,
GPUNodeStack *out)
{
if (!in[0].link) {
in[0].link = GPU_attribute(CD_ORCO, "");
in[0].link = GPU_attribute(mat, CD_ORCO, "");
}
node_shader_gpu_tex_mapping(mat, node, in, out);

View File

@ -41,7 +41,7 @@ static int node_shader_gpu_uvmap(GPUMaterial *mat,
GPUNodeStack *out)
{
NodeShaderUVMap *attr = node->storage;
GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, attr->uv_map);
GPUNodeLink *mtface = GPU_attribute(mat, CD_MTFACE, attr->uv_map);
GPU_stack_link(mat, node, "node_uvmap", in, out, mtface);

View File

@ -60,7 +60,7 @@ static int gpu_shader_vector_displacement(GPUMaterial *mat,
"node_vector_displacement_tangent",
in,
out,
GPU_attribute(CD_TANGENT, ""),
GPU_attribute(mat, CD_TANGENT, ""),
GPU_builtin(GPU_WORLD_NORMAL),
GPU_builtin(GPU_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_MATRIX));

View File

@ -39,7 +39,7 @@ static int node_shader_gpu_vertex_color(GPUMaterial *mat,
GPUNodeStack *out)
{
NodeShaderVertexColor *vertexColor = (NodeShaderVertexColor *)node->storage;
GPUNodeLink *vertexColorLink = GPU_attribute(CD_MCOL, vertexColor->layer_name);
GPUNodeLink *vertexColorLink = GPU_attribute(mat, CD_MCOL, vertexColor->layer_name);
return GPU_stack_link(mat, node, "node_vertex_color", in, out, vertexColorLink);
}