Eevee: World nodetree gpumaterial compatibility.

- Unify GPUMaterial creation (world/mesh).
- Support for multiple shader variations (not used for now).
- Convert GPUInputs to DRWUniforms to be used with the draw manager.
- Nodetree Update is not supported. The only way to refresh the shaders is to change render engine.
- Cleanup in GPUPass.
- Add new temporary Node Compatibility type. Compatibility types should be removed in the future.
This commit is contained in:
2017-04-27 22:27:09 +02:00
parent 2f100c13ee
commit e868b459bb
15 changed files with 333 additions and 30 deletions

View File

@@ -928,6 +928,67 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
static void gpu_nodes_extract_dynamic_inputs_new(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
GPUNode *node;
GPUInput *next, *input;
ListBase *inputs = &pass->inputs;
int extract, z;
memset(inputs, 0, sizeof(*inputs));
if (!shader)
return;
GPU_shader_bind(shader);
for (node = nodes->first; node; node = node->next) {
z = 0;
for (input = node->inputs.first; input; input = next, z++) {
next = input->next;
/* attributes don't need to be bound, they already have
* an id that the drawing functions will use */
if (input->source == GPU_SOURCE_ATTRIB) {
continue;
}
if (input->source == GPU_SOURCE_BUILTIN ||
input->source == GPU_SOURCE_OPENGL_BUILTIN)
{
continue;
}
if (input->ima || input->tex || input->prv)
BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid);
else
BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id);
/* pass non-dynamic uniforms to opengl */
extract = 0;
if (input->ima || input->tex || input->prv) {
if (input->bindtex)
extract = 1;
}
else if (input->dynamicvec)
extract = 1;
if (extract)
input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
/* extract nodes */
if (extract) {
BLI_remlink(&node->inputs, input);
BLI_addtail(inputs, input);
}
}
}
GPU_shader_unbind();
}
static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
@@ -1647,6 +1708,67 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
}
}
GPUPass *GPU_generate_pass_new(ListBase *nodes, struct GPUNodeLink *frag_outlink,
const char *vert_code, const char *geom_code,
const char *frag_lib, const char *defines)
{
GPUShader *shader;
GPUPass *pass;
char *vertexgen, *geometrygen, *fragmentgen, *tmp;
char *vertexcode, *geometrycode, *fragmentcode;
/* prune unused nodes */
gpu_nodes_prune(nodes, frag_outlink);
/* generate code and compile with opengl */
fragmentgen = code_generate_fragment(nodes, frag_outlink->output);
// vertexgen = code_generate_vertex(nodes, GPU_MATERIAL_TYPE_MESH);
// geometrygen = code_generate_geometry(nodes, false);
UNUSED_VARS(vertexgen, geometrygen);
tmp = BLI_strdupcat(frag_lib, glsl_material_library);
fragmentcode = BLI_strdupcat(tmp, fragmentgen);
vertexcode = BLI_strdup(vert_code);
geometrycode = BLI_strdup(geom_code);
shader = GPU_shader_create(vertexcode,
fragmentcode,
geometrycode,
NULL,
defines);
MEM_freeN(tmp);
/* failed? */
if (!shader) {
if (fragmentcode)
MEM_freeN(fragmentcode);
if (vertexcode)
MEM_freeN(vertexcode);
if (geometrycode)
MEM_freeN(geometrycode);
MEM_freeN(fragmentgen);
gpu_nodes_free(nodes);
return NULL;
}
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;
pass->vertexcode = vertexcode;
pass->libcode = glsl_material_library;
/* extract dynamic inputs and throw away nodes */
gpu_nodes_extract_dynamic_inputs_new(pass, nodes);
gpu_nodes_free(nodes);
MEM_freeN(fragmentgen);
return pass;
}
GPUPass *GPU_generate_pass(
ListBase *nodes, GPUNodeLink *outlink,
GPUVertexAttribs *attribs, int *builtins,
@@ -1705,7 +1827,6 @@ GPUPass *GPU_generate_pass(
/* create pass */
pass = MEM_callocN(sizeof(GPUPass), "GPUPass");
pass->output = outlink->output;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
pass->geometrycode = geometrycode;