Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-04-27 23:27:09 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-05-01 19:11:21 +0300
commite868b459bb8efc35012b2364762f3d25d96b8b0d (patch)
treeeb2c0e9909a3a4ea5225f6b537f8b7fbdf51d832 /source/blender
parent2f100c13ee14cc6876423d1ac39ef9c565fb8987 (diff)
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.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_node.h1
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c64
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/probe_geom.glsl2
-rw-r--r--source/blender/draw/intern/DRW_render.h3
-rw-r--r--source/blender/draw/intern/draw_manager.c76
-rw-r--r--source/blender/gpu/GPU_material.h6
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c123
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h6
-rw-r--r--source/blender/gpu/intern/gpu_material.c56
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl11
-rw-r--r--source/blender/makesrna/intern/rna_world.c1
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c4
15 files changed, 333 insertions, 30 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 01d93d98540..219bca0a1a9 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -253,6 +253,7 @@ typedef struct bNodeType {
/* nodetype->compatibility */
#define NODE_OLD_SHADING 1
#define NODE_NEW_SHADING 2
+#define NODE_NEWER_SHADING 3
/* node resize directions */
#define NODE_RESIZE_TOP 1
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 6fa99b37ced..5f7c7787cfc 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -29,6 +29,8 @@
#include "BLI_dynstr.h"
#include "BLI_rand.h"
+
+#include "GPU_material.h"
#include "GPU_glew.h"
#include "eevee_engine.h"
@@ -39,6 +41,8 @@
/* *********** STATIC *********** */
static struct {
+ char *frag_shader_lib;
+
struct GPUShader *default_lit;
struct GPUShader *default_world;
struct GPUShader *depth_sh;
@@ -214,6 +218,16 @@ static void EEVEE_engine_init(void *ved)
(int)viewport_size[0], (int)viewport_size[1],
&tex, 1);
+ if (!e_data.frag_shader_lib) {
+ DynStr *ds_frag = BLI_dynstr_new();
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
+ BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag);
+ BLI_dynstr_free(ds_frag);
+ }
+
if (!e_data.depth_sh) {
e_data.depth_sh = DRW_shader_create_3D_depth_only();
}
@@ -222,10 +236,7 @@ static void EEVEE_engine_init(void *ved)
char *frag_str = NULL;
DynStr *ds_frag = BLI_dynstr_new();
- BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl);
- BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl);
+ BLI_dynstr_append(ds_frag, e_data.frag_shader_lib);
BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl);
frag_str = BLI_dynstr_get_cstring(ds_frag);
BLI_dynstr_free(ds_frag);
@@ -345,6 +356,8 @@ static DRWShadingGroup *eevee_cascade_shadow_shgroup(
static void EEVEE_cache_init(void *vedata)
{
+ static int zero = 0;
+
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl;
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
@@ -373,26 +386,48 @@ static void EEVEE_cache_init(void *vedata)
psl->probe_background = DRW_pass_create("Probe Background Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
- DRWShadingGroup *grp;
+ DRWShadingGroup *grp = NULL;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- if (false) { /* TODO check for world nodetree */
- // GPUMaterial *gpumat = GPU_material_from_nodetree(struct bNodeTree *ntree, ListBase *gpumaterials, void *engine_type, int options)
+ float *col = ts.colorBackground;
+ if (wo) {
+ col = &wo->horr;
}
- else {
- float *col = ts.colorBackground;
- static int zero = 0;
- if (wo) {
- col = &wo->horr;
+ if (wo && wo->use_nodes && wo->nodetree) {
+ struct GPUMaterial *gpumat = GPU_material_from_nodetree(
+ wo->nodetree, &wo->gpumaterial, &DRW_engine_viewport_eevee_type, 0,
+ datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, e_data.frag_shader_lib,
+ "#define PROBE_CAPTURE\n"
+ "#define MAX_LIGHT 128\n"
+ "#define MAX_SHADOW_CUBE 42\n"
+ "#define MAX_SHADOW_MAP 64\n"
+ "#define MAX_SHADOW_CASCADE 8\n"
+ "#define MAX_CASCADE_NUM 4\n");
+
+ grp = DRW_shgroup_material_instance_create(gpumat, psl->probe_background, geom);
+
+ if (grp) {
+ DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
+
+ for (int i = 0; i < 6; ++i)
+ DRW_shgroup_call_dynamic_add_empty(grp);
+ }
+ else {
+ /* Shader failed : pink background */
+ static float pink[3] = {1.0f, 0.0f, 1.0f};
+ col = pink;
}
+ }
+ /* Fallback if shader fails or if not using nodetree. */
+ if (grp == NULL) {
grp = eevee_cube_shgroup(e_data.default_world, psl->probe_background, geom);
- DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_int(grp, "Layer", &zero, 1);
}
}
@@ -591,6 +626,7 @@ static void EEVEE_draw_scene(void *vedata)
static void EEVEE_engine_free(void)
{
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
DRW_SHADER_FREE_SAFE(e_data.default_lit);
DRW_SHADER_FREE_SAFE(e_data.shadow_sh);
DRW_SHADER_FREE_SAFE(e_data.default_world);
@@ -628,7 +664,7 @@ DrawEngineType draw_engine_eevee_type = {
RenderEngineType DRW_engine_viewport_eevee_type = {
NULL, NULL,
- EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
+ EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_OGL_PIPELINE | RE_USE_SHADING_NODES,
NULL, NULL, NULL, NULL, NULL, NULL, &EEVEE_collection_settings_create,
&draw_engine_eevee_type,
{NULL, NULL, NULL}
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index fddc9c54cb2..ef8af646ec1 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -54,7 +54,7 @@ struct ShadowMapData {
#define sh_map_bias near_far_bias.z
#ifndef MAX_CASCADE_NUM
-#define MAX_CASCADE_NUM 1
+#define MAX_CASCADE_NUM 4
#endif
struct ShadowCascadeData {
@@ -94,8 +94,6 @@ vec4 saturate(vec4 a) { return vec4(saturate(a.x), saturate(a.y), saturate(a.z),
float distance_squared(vec2 a, vec2 b) { a -= b; return dot(a, a); }
float distance_squared(vec3 a, vec3 b) { a -= b; return dot(a, a); }
-float hypot(float x, float y) { return sqrt(x*x + y*y); }
-
float inverse_distance(vec3 V) { return max( 1 / length(V), 1e-8); }
float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
index 4cb229e392b..8d4a1e6d523 100644
--- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl
@@ -3,9 +3,11 @@ uniform vec3 diffuse_col;
uniform vec3 specular_col;
uniform int hardness;
+out vec4 FragColor;
+
void main()
{
float roughness = 1.0 - float(hardness) / 511.0;
roughness *= roughness;
- fragColor = vec4(eevee_surface_lit(worldNormal, diffuse_col, specular_col, roughness), 1.0);
+ FragColor = vec4(eevee_surface_lit(worldNormal, diffuse_col, specular_col, roughness), 1.0);
}
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 7a0a7b8da91..10d9ce7c4c0 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -28,8 +28,6 @@ layout(std140) uniform shadow_block {
in vec3 worldPosition;
in vec3 worldNormal;
-out vec4 fragColor;
-
/* type */
#define POINT 0.0
#define SUN 1.0
diff --git a/source/blender/draw/engines/eevee/shaders/probe_geom.glsl b/source/blender/draw/engines/eevee/shaders/probe_geom.glsl
index ad112977e9f..5f79e1c6eb8 100644
--- a/source/blender/draw/engines/eevee/shaders/probe_geom.glsl
+++ b/source/blender/draw/engines/eevee/shaders/probe_geom.glsl
@@ -8,7 +8,7 @@ in vec4 vPos[];
in int face[];
out vec3 worldPosition;
-out vec3 worldNormal;
+out vec3 worldNormal; /* Required. otherwise generate linking error on AMD. */
const vec3 maj_axes[6] = vec3[6](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3( 0.0, 0.0, 1.0), vec3( 0.0, 0.0, -1.0));
const vec3 x_axis[6] = vec3[6](vec3(0.0, 0.0, -1.0), vec3( 0.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), vec3(1.0, 0.0, 0.0), vec3( 1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0));
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index 39b8e23db80..29295e8f06d 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -56,6 +56,7 @@
struct bContext;
struct GPUFrameBuffer;
struct GPUShader;
+struct GPUMaterial;
struct GPUTexture;
struct GPUUniformBuffer;
struct Object;
@@ -245,6 +246,8 @@ typedef enum {
} DRWState;
DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass);
+DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material, DRWPass *pass, struct Batch *geom);
DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, struct Batch *geom);
DRWShadingGroup *DRW_shgroup_point_batch_create(struct GPUShader *shader, DRWPass *pass);
DRWShadingGroup *DRW_shgroup_line_batch_create(struct GPUShader *shader, DRWPass *pass);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 97cd1102406..059ebc6eab3 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -47,11 +47,13 @@
#include "ED_space_api.h"
#include "ED_screen.h"
+#include "intern/gpu_codegen.h"
#include "GPU_batch.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
#include "GPU_framebuffer.h"
#include "GPU_lamp.h"
+#include "GPU_material.h"
#include "GPU_shader.h"
#include "GPU_texture.h"
#include "GPU_uniformbuffer.h"
@@ -614,6 +616,80 @@ DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
return shgroup;
}
+DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPass *pass)
+{
+ double time = 0.0; /* TODO make time variable */
+ const int max_tex = GPU_max_textures() - 1;
+
+ /* TODO : Ideally we should not convert. But since the whole codegen
+ * is relying on GPUPass we keep it as is for now. */
+
+ GPUPass *gpupass = GPU_material_get_pass(material);
+
+ if (!gpupass) {
+ /* Shader compilation error */
+ return NULL;
+ }
+
+ struct GPUShader *shader = GPU_pass_shader(gpupass);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(shader, pass);
+
+ /* Converting dynamic GPUInput to DRWUniform */
+ ListBase *inputs = &gpupass->inputs;
+
+ for (GPUInput *input = inputs->first; input; input = input->next) {
+ /* Textures */
+ if (input->ima) {
+ GPUTexture *tex = GPU_texture_from_blender(input->ima, input->iuser, input->textarget, input->image_isdata, time, 1);
+
+ if (input->bindtex) {
+ /* TODO maybe track texture slot usage to avoid clash with engine textures */
+ DRW_shgroup_uniform_texture(grp, input->shadername, tex, max_tex - input->texid);
+ }
+ }
+ /* Floats */
+ else {
+ switch (input->type) {
+ case 1:
+ DRW_shgroup_uniform_float(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case 2:
+ DRW_shgroup_uniform_vec2(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case 3:
+ DRW_shgroup_uniform_vec3(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case 4:
+ DRW_shgroup_uniform_vec4(grp, input->shadername, (float *)input->dynamicvec, 1);
+ break;
+ case 9:
+ DRW_shgroup_uniform_mat3(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ case 16:
+ DRW_shgroup_uniform_mat4(grp, input->shadername, (float *)input->dynamicvec);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ return grp;
+}
+
+DRWShadingGroup *DRW_shgroup_material_instance_create(struct GPUMaterial *material, DRWPass *pass, Batch *geom)
+{
+ DRWShadingGroup *shgroup = DRW_shgroup_material_create(material, pass);
+
+ if (shgroup) {
+ shgroup->type = DRW_SHG_INSTANCE;
+ shgroup->instance_geom = geom;
+ }
+
+ return shgroup;
+}
+
DRWShadingGroup *DRW_shgroup_instance_create(struct GPUShader *shader, DRWPass *pass, Batch *geom)
{
DRWShadingGroup *shgroup = DRW_shgroup_create(shader, pass);
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 7d08e72bb7b..31785a0121f 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -56,6 +56,7 @@ struct GPUTexture;
struct GPULamp;
struct PreviewImage;
struct World;
+struct bNodeTree;
typedef struct GPUNode GPUNode;
typedef struct GPUNodeLink GPUNodeLink;
@@ -218,7 +219,9 @@ 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,
+ 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);
void GPU_material_free(struct ListBase *gpumaterial);
@@ -235,6 +238,7 @@ void GPU_material_unbind(GPUMaterial *material);
bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
GPUMatType GPU_Material_get_type(GPUMaterial *material);
+struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index de2b94482f4..89c58eb8495 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -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;
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index 7af17f9122d..9263fe3bc3f 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -156,10 +156,7 @@ typedef struct GPUInput {
} GPUInput;
struct GPUPass {
- struct GPUPass *next, *prev;
-
ListBase inputs;
- struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
char *geometrycode;
@@ -170,6 +167,9 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
+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);
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
struct GPUVertexAttribs *attribs, int *builtin,
const GPUMatType type, const char *name,
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index aa7a104ff86..083b0596b1c 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -94,12 +94,15 @@ static struct GPUWorld {
} GPUWorld;
struct GPUMaterial {
- Scene *scene;
+ Scene *scene; /* DEPRECATED was only usefull for lamps */
Material *ma;
/* material for mesh surface, worlds or something else.
* some code generation is done differently depending on the use case */
- int type;
+ int type; /* DEPRECATED */
+
+ void *engine; /* attached engine type */
+ int options; /* to identify shader variations (shadow, probe, world background...) */
/* for creating the material */
ListBase nodes;
@@ -436,6 +439,10 @@ GPUMatType GPU_Material_get_type(GPUMaterial *material)
return material->type;
}
+GPUPass *GPU_material_get_pass(GPUMaterial *material)
+{
+ return material->pass;
+}
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
@@ -470,6 +477,10 @@ 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;
@@ -2096,6 +2107,47 @@ GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
return mat;
}
+/* 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,
+ const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ for (link = gpumaterials->first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial *)link->data;
+ if (current_material->engine == engine_type &&
+ current_material->options == options)
+ {
+ return current_material;
+ }
+ }
+
+ /* allocate material */
+ mat = GPU_material_construct_begin(NULL); /* TODO remove GPU_material_construct_begin */
+ mat->engine = engine_type;
+ mat->options = options;
+
+ ntreeGPUMaterialNodes(ntree, mat, NODE_NEWER_SHADING);
+
+ /* Let Draw manager finish the construction. */
+ if (mat->outlink) {
+ outlink = mat->outlink;
+ mat->pass = GPU_generate_pass_new(&mat->nodes, outlink, vert_code, geom_code, frag_lib, defines);
+ }
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(gpumaterials, link);
+
+ return mat;
+}
GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
{
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 857db4f7f7c..a0c56e9ebf4 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1,6 +1,8 @@
uniform mat4 ModelViewMatrix;
+#ifndef PROBE_CAPTURE
uniform mat4 ProjectionMatrix;
+#endif
uniform mat4 ModelViewMatrixInverse;
uniform mat4 ProjectionMatrixInverse;
uniform mat3 NormalMatrix;
@@ -172,7 +174,7 @@ void color_to_blender_normal_new_shading(vec3 color, out vec3 normal)
}
#define M_PI 3.14159265358979323846
-#define M_1_PI 0.31830988618379069
+#define M_1_PI 0.318309886183790671538
/*********** SHADER NODES ***************/
@@ -2813,6 +2815,13 @@ void background_transform_to_world(vec3 viewvec, out vec3 worldvec)
worldvec = (ModelViewMatrixInverse * co).xyz;
}
+#ifdef PROBE_CAPTURE
+void environment_default_vector(out vec3 worldvec)
+{
+ worldvec = normalize(worldPosition);
+}
+#endif
+
void node_background(vec4 color, float strength, vec3 N, out vec4 result)
{
result = color * strength;
diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c
index 7c1ef6b0d87..202ba63c850 100644
--- a/source/blender/makesrna/intern/rna_world.c
+++ b/source/blender/makesrna/intern/rna_world.c
@@ -119,6 +119,7 @@ static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr)
ED_node_shader_default(C, &wrld->id);
rna_World_update(CTX_data_main(C), CTX_data_scene(C), ptr);
+ rna_World_draw_update(CTX_data_main(C), CTX_data_scene(C), ptr);
}
#else
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index 2f8f95b0675..e090f26ab6b 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -69,8 +69,10 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE
if (type == GPU_MATERIAL_TYPE_MESH)
in[0].link = GPU_builtin(GPU_VIEW_POSITION);
- else
+ else if (type == GPU_MATERIAL_TYPE_WORLD)
GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link);
+ else
+ GPU_link(mat, "environment_default_vector", &in[0].link);
}
node_shader_gpu_tex_mapping(mat, node, in, out);