diff options
23 files changed, 324 insertions, 94 deletions
diff --git a/SConstruct b/SConstruct index 45c9ae3b84d..4c2097f8879 100644 --- a/SConstruct +++ b/SConstruct @@ -757,6 +757,7 @@ if B.targets != ['cudakernels']: data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex.glsl") + data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vertex_world.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl") data_to_c_simple("source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl") data_to_c_simple("intern/opencolorio/gpu_shader_display_transform.glsl") diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index ea1b9a3f13d..af2080c1b61 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -116,7 +116,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) MEM_freeN(ma->texpaintslot); if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); } void init_material(Material *ma) @@ -1724,7 +1724,7 @@ void paste_matcopybuf(Material *ma) MEM_freeN(ma->nodetree); } - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); id = (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 8e3c92314e6..29a345e111b 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -49,6 +49,8 @@ #include "BKE_node.h" #include "BKE_world.h" +#include "GPU_material.h" + void BKE_world_free_ex(World *wrld, bool do_id_user) { MTex *mtex; @@ -69,6 +71,9 @@ void BKE_world_free_ex(World *wrld, bool do_id_user) MEM_freeN(wrld->nodetree); } + if (wrld->gpumaterial.first) + GPU_material_free(&wrld->gpumaterial); + BKE_icon_delete((struct ID *)wrld); wrld->id.icon_id = 0; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 9b043c6dbda..05af147eb86 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3260,6 +3260,7 @@ static void direct_link_world(FileData *fd, World *wrld) } wrld->preview = direct_link_preview_image(fd, wrld->preview); + BLI_listbase_clear(&wrld->gpumaterial); } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 1320fedbfa7..e4e16dd03fc 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -281,7 +281,7 @@ static void material_changed(Main *bmain, Material *ma) /* glsl */ if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); /* find node materials using this */ for (parent = bmain->mat.first; parent; parent = parent->id.next) { @@ -295,7 +295,7 @@ static void material_changed(Main *bmain, Material *ma) BKE_icon_changed(BKE_icon_getid(&parent->id)); if (parent->gpumaterial.first) - GPU_material_free(parent); + GPU_material_free(&parent->gpumaterial); } /* find if we have a scene with textured display */ @@ -341,10 +341,10 @@ static void lamp_changed(Main *bmain, Lamp *la) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial); + GPU_material_free(&defmaterial.gpumaterial); } static int material_uses_texture(Material *ma, Tex *tex) @@ -382,7 +382,7 @@ static void texture_changed(Main *bmain, Tex *tex) BKE_icon_changed(BKE_icon_getid(&ma->id)); if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); } /* find lamps */ @@ -411,6 +411,9 @@ static void texture_changed(Main *bmain, Tex *tex) } BKE_icon_changed(BKE_icon_getid(&wo->id)); + + if (wo->gpumaterial.first) + GPU_material_free(&wo->gpumaterial); } /* find compositing nodes */ @@ -456,14 +459,17 @@ static void world_changed(Main *bmain, World *wo) /* icons */ BKE_icon_changed(BKE_icon_getid(&wo->id)); - + /* glsl */ for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial); + GPU_material_free(&defmaterial.gpumaterial); + + if (wo->gpumaterial.first) + GPU_material_free(&wo->gpumaterial); } static void image_changed(Main *bmain, Image *ima) @@ -483,6 +489,7 @@ static void scene_changed(Main *bmain, Scene *scene) { Object *ob; Material *ma; + World *wo; /* glsl */ for (ob = bmain->object.first; ob; ob = ob->id.next) { @@ -498,10 +505,14 @@ static void scene_changed(Main *bmain, Scene *scene) for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); + for (wo = bmain->world.first; wo; wo = wo->id.next) + if (wo->gpumaterial.first) + GPU_material_free(&wo->gpumaterial); + if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial); + GPU_material_free(&defmaterial.gpumaterial); } void ED_render_id_flush_update(Main *bmain, ID *id) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index d52a351ffc2..1b82e89a364 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -342,14 +342,22 @@ void snode_dag_update(bContext *C, SpaceNode *snode) void snode_notify(bContext *C, SpaceNode *snode) { + ID *id = snode->id; + WM_event_add_notifier(C, NC_NODE | NA_EDITED, NULL); - if (ED_node_is_shader(snode)) - WM_event_add_notifier(C, NC_MATERIAL | ND_NODES, snode->id); + if (ED_node_is_shader(snode)) { + if (GS(id->name) == ID_MA) + WM_main_add_notifier(NC_MATERIAL | ND_SHADING, id); + else if (GS(id->name) == ID_LA) + WM_main_add_notifier(NC_LAMP | ND_LIGHTING, id); + else if (GS(id->name) == ID_WO) + WM_main_add_notifier(NC_WORLD | ND_WORLD, id); + } else if (ED_node_is_compositor(snode)) - WM_event_add_notifier(C, NC_SCENE | ND_NODES, snode->id); + WM_event_add_notifier(C, NC_SCENE | ND_NODES, id); else if (ED_node_is_texture(snode)) - WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, snode->id); + WM_event_add_notifier(C, NC_TEXTURE | ND_NODES, id); } void ED_node_set_tree_type(SpaceNode *snode, bNodeTreeType *typeinfo) @@ -662,11 +670,16 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node) /* if active texture changed, free glsl materials */ if ((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) { Material *ma; + World *wo; for (ma = bmain->mat.first; ma; ma = ma->id.next) if (ma->nodetree && ma->use_nodes && ntreeHasTree(ma->nodetree, ntree)) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); + for (wo = bmain->world.first; wo; wo = wo->id.next) + if (wo->nodetree && wo->use_nodes && ntreeHasTree(wo->nodetree, ntree)) + GPU_material_free(&wo->gpumaterial); + WM_main_add_notifier(NC_IMAGE, NULL); } diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 81f926e5048..95b11d1731f 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -414,7 +414,7 @@ static void view3d_free(SpaceLink *sl) /* matcap material, its preview rect gets freed via icons */ if (vd->defmaterial) { if (vd->defmaterial->gpumaterial.first) - GPU_material_free(vd->defmaterial); + GPU_material_free(&vd->defmaterial->gpumaterial); BKE_previewimg_free(&vd->defmaterial->preview); MEM_freeN(vd->defmaterial); } @@ -1168,6 +1168,7 @@ static void space_view3d_listener(bScreen *UNUSED(sc), ScrArea *sa, struct wmNot case NC_WORLD: switch (wmn->data) { case ND_WORLD_DRAW: + case ND_WORLD: if (v3d->flag3 & V3D_SHOW_WORLD) ED_area_tag_redraw_regiontype(sa, RGN_TYPE_WINDOW); break; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d4a0c01518b..26ce64fd8ca 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2807,10 +2807,34 @@ void ED_view3d_draw_offscreen_init(Scene *scene, View3D *v3d) static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar, bool force) { /* clear background */ - if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) { /* clear with solid color */ + if (scene->world && ((v3d->flag3 & V3D_SHOW_WORLD) || force)) { float alpha = (force) ? 1.0f : 0.0; + bool glsl = GPU_glsl_support() && BKE_scene_use_new_shading_nodes(scene) && scene->world->nodetree && scene->world->use_nodes; - if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */ + if (glsl) { + RegionView3D *rv3d = ar->regiondata; + GPUMaterial *gpumat = GPU_material_world(scene, scene->world); + + /* calculate full shader for background */ + GPU_material_bind(gpumat, 1, 1, 1.0, true, rv3d->viewmat, rv3d->viewinv, (v3d->scenelock != 0)); + + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glShadeModel(GL_SMOOTH); + glBegin(GL_QUADS); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(1.0, -1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); + glVertex3f(-1.0, 1.0, 1.0); + glEnd(); + glShadeModel(GL_FLAT); + + GPU_material_unbind(gpumat); + + glDepthFunc(GL_LEQUAL); + glDisable(GL_DEPTH_TEST); + } + else if (scene->world->skytype & WO_SKYBLEND) { /* blend sky */ int x, y; float col_hor[3]; float col_zen[3]; @@ -3009,7 +3033,9 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, * warning! can be slow so only free animated images - campbell */ GPU_free_images_anim(); } - + /* setup view matrices */ + view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); + /* clear opengl buffers */ if (do_sky) { view3d_main_area_clear(scene, v3d, ar, true); @@ -3019,11 +3045,6 @@ void ED_view3d_draw_offscreen(Scene *scene, View3D *v3d, ARegion *ar, int winx, glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - - /* setup view matrices */ - view3d_main_area_setup_view(scene, v3d, ar, viewmat, winmat); - - /* main drawing call */ view3d_draw_objects(NULL, scene, v3d, ar, NULL, do_bgpic, true); diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 63eea9486ed..361c247767f 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -73,6 +73,7 @@ data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC) +data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index fab9c28cb61..09a5653b1ec 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -58,6 +58,7 @@ struct GPUMaterial; struct GPUTexture; struct GPULamp; struct PreviewImage; +struct World; typedef struct GPUNode GPUNode; typedef struct GPUNodeLink GPUNodeLink; @@ -95,6 +96,12 @@ typedef enum GPUOpenGLBuiltin { GPU_COLOR = 2, } GPUOpenGLBuiltin; +typedef enum GPUMatType { + GPU_MATERIAL_TYPE_MESH = 1, + GPU_MATERIAL_TYPE_WORLD = 2, +} GPUMatType; + + typedef enum GPUBlendMode { GPU_BLEND_SOLID = 0, GPU_BLEND_ADD = 1, @@ -131,10 +138,11 @@ void GPU_material_enable_alpha(GPUMaterial *material); 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_blender(struct Scene *scene, struct Material *ma); GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma); -void GPU_material_free(struct Material *ma); +void GPU_material_free(struct ListBase *gpumaterial); void GPU_materials_free(void); @@ -144,6 +152,7 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float void GPU_material_unbind(GPUMaterial *material); int GPU_material_bound(GPUMaterial *material); struct Scene *GPU_material_scene(GPUMaterial *material); +GPUMatType GPU_Material_get_type(GPUMaterial *material); void GPU_material_vertex_attributes(GPUMaterial *material, struct GPUVertexAttribs *attrib); diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index f11ecafc986..e44a99286a8 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -69,6 +69,7 @@ sources.extend(( os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex_world.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), )) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 4182f51561b..1b99c6ee49a 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -58,6 +58,7 @@ extern char datatoc_gpu_shader_material_glsl[]; extern char datatoc_gpu_shader_vertex_glsl[]; +extern char datatoc_gpu_shader_vertex_world_glsl[]; static char *glsl_material_library = NULL; @@ -252,7 +253,7 @@ void gpu_codegen_exit(void) extern Material defmaterial; // render module abuse... if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial); + GPU_material_free(&defmaterial.gpumaterial); if (FUNCTION_HASH) { BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN); @@ -624,8 +625,7 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch if (builtins & GPU_VIEW_NORMAL) BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n"); - - + codegen_declare_tmps(ds, nodes); codegen_call_functions(ds, nodes, output); @@ -640,12 +640,13 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch return code; } -static char *code_generate_vertex(ListBase *nodes) +static char *code_generate_vertex(ListBase *nodes, int type) { DynStr *ds = BLI_dynstr_new(); GPUNode *node; GPUInput *input; char *code; + char *vertcode; for (node=nodes->first; node; node=node->next) { for (input=node->inputs.first; input; input=input->next) { @@ -659,8 +660,21 @@ static char *code_generate_vertex(ListBase *nodes) } BLI_dynstr_append(ds, "\n"); - BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl); + switch (type) { + case GPU_MATERIAL_TYPE_MESH: + vertcode = datatoc_gpu_shader_vertex_glsl; + break; + case GPU_MATERIAL_TYPE_WORLD: + vertcode = datatoc_gpu_shader_vertex_world_glsl; + break; + default: + fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n"); + break; + } + + BLI_dynstr_append(ds, vertcode); + 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) { @@ -1386,7 +1400,7 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) } } -GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name) +GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, int type, const char *name) { GPUShader *shader; GPUPass *pass; @@ -1405,7 +1419,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri /* generate code and compile with opengl */ fragmentcode = code_generate_fragment(nodes, outlink->output, name); - vertexcode = code_generate_vertex(nodes); + vertexcode = code_generate_vertex(nodes, type); shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL); /* failed? */ diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 69213925931..a0698235db6 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -175,7 +175,7 @@ struct GPUPass { typedef struct GPUPass GPUPass; GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink, - struct GPUVertexAttribs *attribs, int *builtin, const char *name); + struct GPUVertexAttribs *attribs, int *builtin, int type, const char *name); struct GPUShader *GPU_pass_shader(GPUPass *pass); diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index e4228bedf9d..31b499d54ab 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -76,10 +76,15 @@ typedef enum DynMatProperty { DYN_LAMP_PERSMAT = 8, } DynMatProperty; + struct GPUMaterial { Scene *scene; Material *ma; + /* material for mesh surface, worlds or something else. + * some code generation is done differently depending on the use case */ + int type; + /* for creating the material */ ListBase nodes; GPUNodeLink *outlink; @@ -194,7 +199,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material) attribs->totlayer = b; } -static int GPU_material_construct_end(GPUMaterial *material) +static int GPU_material_construct_end(GPUMaterial *material, const char *passname) { if (material->outlink) { GPUNodeLink *outlink; @@ -202,7 +207,7 @@ static int GPU_material_construct_end(GPUMaterial *material) outlink = material->outlink; material->pass = GPU_generate_pass(&material->nodes, outlink, - &material->attribs, &material->builtins, material->ma->id.name); + &material->attribs, &material->builtins, material->type, passname); if (!material->pass) return 0; @@ -229,12 +234,12 @@ static int GPU_material_construct_end(GPUMaterial *material) return 0; } -void GPU_material_free(Material *ma) +void GPU_material_free(ListBase *gpumaterial) { LinkData *link; LinkData *nlink, *mlink, *next; - for (link=ma->gpumaterial.first; link; link=link->next) { + for (link=gpumaterial->first; link; link=link->next) { GPUMaterial *material = link->data; if (material->pass) @@ -243,19 +248,23 @@ void GPU_material_free(Material *ma) for (nlink=material->lamps.first; nlink; nlink=nlink->next) { GPULamp *lamp = nlink->data; - for (mlink=lamp->materials.first; mlink; mlink=next) { - next = mlink->next; - if (mlink->data == ma) - BLI_freelinkN(&lamp->materials, mlink); + if (material->ma) { + Material *ma = material->ma; + + for (mlink=lamp->materials.first; mlink; mlink=next) { + next = mlink->next; + if (mlink->data == ma) + BLI_freelinkN(&lamp->materials, mlink); + } } } - + BLI_freelistN(&material->lamps); MEM_freeN(material); } - BLI_freelistN(&ma->gpumaterial); + BLI_freelistN(gpumaterial); } bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma) @@ -280,42 +289,44 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim viewlay &= srl->lay; /* handle layer lamps */ - for (nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; - - if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) - && GPU_lamp_override_visible(lamp, srl, material->ma)) { - lamp->dynenergy = lamp->energy; - copy_v3_v3(lamp->dyncol, lamp->col); - } - else { - lamp->dynenergy = 0.0f; - lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; - } - - if (material->dynproperty & DYN_LAMP_VEC) { - copy_v3_v3(lamp->dynvec, lamp->vec); - normalize_v3(lamp->dynvec); - negate_v3(lamp->dynvec); - mul_mat3_m4_v3(viewmat, lamp->dynvec); - } - - if (material->dynproperty & DYN_LAMP_CO) { - copy_v3_v3(lamp->dynco, lamp->co); - mul_m4_v3(viewmat, lamp->dynco); - } - - if (material->dynproperty & DYN_LAMP_IMAT) { - mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); - } - - if (material->dynproperty & DYN_LAMP_PERSMAT) { - if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */ - GPU_lamp_update_buffer_mats(lamp); - mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); + if (material->type == GPU_MATERIAL_TYPE_MESH) { + for (nlink=material->lamps.first; nlink; nlink=nlink->next) { + lamp= nlink->data; + + if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay)) + && GPU_lamp_override_visible(lamp, srl, material->ma)) { + lamp->dynenergy = lamp->energy; + copy_v3_v3(lamp->dyncol, lamp->col); + } + else { + lamp->dynenergy = 0.0f; + lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; + } + + if (material->dynproperty & DYN_LAMP_VEC) { + copy_v3_v3(lamp->dynvec, lamp->vec); + normalize_v3(lamp->dynvec); + negate_v3(lamp->dynvec); + mul_mat3_m4_v3(viewmat, lamp->dynvec); + } + + if (material->dynproperty & DYN_LAMP_CO) { + copy_v3_v3(lamp->dynco, lamp->co); + mul_m4_v3(viewmat, lamp->dynco); + } + + if (material->dynproperty & DYN_LAMP_IMAT) { + mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); + } + + if (material->dynproperty & DYN_LAMP_PERSMAT) { + if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */ + GPU_lamp_update_buffer_mats(lamp); + mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); + } } } - + /* note material must be bound before setting uniforms */ GPU_pass_bind(material->pass, time, mipmap); @@ -376,6 +387,12 @@ Scene *GPU_material_scene(GPUMaterial *material) return material->scene; } +GPUMatType GPU_Material_get_type(GPUMaterial *material) +{ + return material->type; +} + + void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs) { *attribs = material->attribs; @@ -1589,6 +1606,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) /* allocate material */ mat = GPU_material_construct_begin(ma); mat->scene = scene; + mat->type = GPU_MATERIAL_TYPE_MESH; if (ma->preview && ma->preview->rect[0]) { outlink = gpu_material_preview_matcap(mat, ma); @@ -1599,7 +1617,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) GPU_material_output_link(mat, outlink); - GPU_material_construct_end(mat); + GPU_material_construct_end(mat, "matcap_pass"); /* 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 @@ -1612,6 +1630,45 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma) return mat; } +GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo) +{ + LinkData *link; + GPUMaterial *mat; + + for (link=wo->gpumaterial.first; link; link=link->next) + if (((GPUMaterial*)link->data)->scene == scene) + return link->data; + + /* allocate material */ + mat = GPU_material_construct_begin(NULL); + mat->scene = scene; + mat->type = GPU_MATERIAL_TYPE_WORLD; + + /* create nodes */ + if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes) + ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING); + else { + /* old fixed function world */ + } + + if (GPU_material_do_color_management(mat)) + if (mat->outlink) + GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); + + GPU_material_construct_end(mat, wo->id.name); + + /* 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(&wo->gpumaterial, link); + + return mat; +} + + GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) { GPUMaterial *mat; @@ -1625,6 +1682,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) /* allocate material */ mat = GPU_material_construct_begin(ma); mat->scene = scene; + mat->type = GPU_MATERIAL_TYPE_MESH; /* render pipeline option */ if (ma->mode & MA_TRANSP) @@ -1654,7 +1712,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) if (mat->outlink) GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); - GPU_material_construct_end(mat); + GPU_material_construct_end(mat, ma->id.name); /* 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 @@ -1671,12 +1729,16 @@ void GPU_materials_free(void) { Object *ob; Material *ma; + World *wo; extern Material defmaterial; for (ma=G.main->mat.first; ma; ma=ma->id.next) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); - GPU_material_free(&defmaterial); + for (wo=G.main->world.first; wo; wo=wo->id.next) + GPU_material_free(&ma->gpumaterial); + + GPU_material_free(&defmaterial.gpumaterial); for (ob=G.main->object.first; ob; ob=ob->id.next) GPU_lamp_free(ob); @@ -1945,7 +2007,7 @@ void GPU_lamp_free(Object *ob) BLI_freelinkN(&lamp->materials, nlink); if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); } gpu_lamp_shadow_free(lamp); diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 867270a6d7a..c463fb25ded 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2256,6 +2256,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result) result = color*strength; } +/* background */ + +void background_transform_to_world(vec3 viewvec, out vec3 worldvec) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + worldvec = (gl_ModelViewMatrixInverse * co).xyz; +} + +void node_background(vec4 color, float strength, vec3 N, out vec4 result) +{ + result = color*strength; +} + /* closures */ void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader) @@ -2364,6 +2380,30 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz; } +void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, + vec3 attr_orco, vec3 attr_uv, + out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, + out vec3 camera, out vec3 window, out vec3 reflection) +{ + vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); + vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; + + generated = coords; + normal = -coords; + uv = attr_uv; + object = coords; + + camera = co.xyz; + window = mtex_2d_mapping(I); + + reflection = -coords; +} + /* textures */ void node_tex_gradient(vec3 co, out vec4 color, out float fac) @@ -2525,6 +2565,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec result = surface; } +void node_output_world(vec4 surface, vec4 volume, out vec4 result) +{ + result = surface; +} + /* ********************** matcap style render ******************** */ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result) diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl new file mode 100644 index 00000000000..9dbcaeb7a32 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl @@ -0,0 +1,13 @@ + +varying vec3 varposition; +varying vec3 varnormal; + +void main() +{ + /* position does not need to be transformed, we already have it */ + gl_Position = gl_Vertex; + + varposition = gl_Vertex.xyz; + + varnormal = normalize(-varposition); + diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 50542797f0b..2a9bcc20a9f 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -128,6 +128,7 @@ typedef struct World { /* nodes */ struct bNodeTree *nodetree; + ListBase gpumaterial; /* runtime */ } World; /* **************** WORLD ********************* */ diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index a191cc32bb2..e3d44cb1349 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -485,7 +485,7 @@ static void rna_SpaceView3D_matcap_update(Main *UNUSED(bmain), Scene *UNUSED(sce BKE_previewimg_free(&ma->preview); if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); WM_main_add_notifier(NC_MATERIAL | ND_SHADING_DRAW, ma); } diff --git a/source/blender/makesrna/intern/rna_world.c b/source/blender/makesrna/intern/rna_world.c index f63350ea0ae..721cbaf21c7 100644 --- a/source/blender/makesrna/intern/rna_world.c +++ b/source/blender/makesrna/intern/rna_world.c @@ -89,7 +89,7 @@ static void rna_World_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerR World *wo = ptr->id.data; DAG_id_tag_update(&wo->id, 0); - WM_main_add_notifier(NC_WORLD, wo); + WM_main_add_notifier(NC_WORLD | ND_WORLD, wo); } static void rna_World_draw_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) diff --git a/source/blender/nodes/shader/nodes/node_shader_background.c b/source/blender/nodes/shader/nodes/node_shader_background.c index 2478fb4d38c..b387529e456 100644 --- a/source/blender/nodes/shader/nodes/node_shader_background.c +++ b/source/blender/nodes/shader/nodes/node_shader_background.c @@ -40,6 +40,11 @@ static bNodeSocketTemplate sh_node_background_out[] = { { -1, 0, "" } }; +static int node_shader_gpu_background(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + return GPU_stack_link(mat, "node_background", in, out, GPU_builtin(GPU_VIEW_NORMAL)); +} + /* node type definition */ void register_node_type_sh_background(void) { @@ -50,6 +55,7 @@ void register_node_type_sh_background(void) node_type_socket_templates(&ntype, sh_node_background_in, sh_node_background_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_background); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_output_world.c b/source/blender/nodes/shader/nodes/node_shader_output_world.c index c8e47c47c5f..ad7389fd56e 100644 --- a/source/blender/nodes/shader/nodes/node_shader_output_world.c +++ b/source/blender/nodes/shader/nodes/node_shader_output_world.c @@ -35,6 +35,16 @@ static bNodeSocketTemplate sh_node_output_world_in[] = { { -1, 0, "" } }; +static int node_shader_gpu_output_world(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + GPUNodeLink *outlink; + + GPU_stack_link(mat, "node_output_world", in, out, &outlink); + GPU_material_output_link(mat, outlink); + + return 1; +} + /* node type definition */ void register_node_type_sh_output_world(void) { @@ -45,7 +55,8 @@ void register_node_type_sh_output_world(void) node_type_socket_templates(&ntype, sh_node_output_world_in, NULL); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); - + node_type_gpu(&ntype, node_shader_gpu_output_world); + /* Do not allow muting output node. */ node_type_internal_links(&ntype, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c index 781b1bb5a93..85eca6ae990 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_coord.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_coord.c @@ -46,10 +46,18 @@ static int node_shader_gpu_tex_coord(GPUMaterial *mat, bNode *UNUSED(node), bNod { GPUNodeLink *orco = GPU_attribute(CD_ORCO, ""); GPUNodeLink *mtface = GPU_attribute(CD_MTFACE, ""); - - 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), orco, mtface); + GPUMatType type = GPU_Material_get_type(mat); + + if (type == GPU_MATERIAL_TYPE_MESH) { + 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), orco, mtface); + } + else { + 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), orco, mtface); + } } /* node type definition */ 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 56db9dd3b44..f6361331741 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c @@ -67,9 +67,15 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat, bNode *node, bNodeE if (!ima) return GPU_stack_link(mat, "node_tex_environment_empty", in, out); - if (!in[0].link) - in[0].link = GPU_builtin(GPU_VIEW_POSITION); - + if (!in[0].link) { + GPUMatType type = GPU_Material_get_type(mat); + + if (type == GPU_MATERIAL_TYPE_MESH) + in[0].link = GPU_builtin(GPU_VIEW_POSITION); + else + GPU_link(mat, "background_transform_to_world", GPU_builtin(GPU_VIEW_POSITION), &in[0].link); + } + node_shader_gpu_tex_mapping(mat, node, in, out); if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) |