World background working on cycle nodes.
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 24 Nov 2014 16:18:56 +0000 (17:18 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Wed, 26 Nov 2014 14:07:26 +0000 (15:07 +0100)
This is added in the spirit of the general cycles GLSL system
which is pretty much WIP still.

This will only work on cycles at the moment but generating for blender
internal is possible too of course though it will be done in a separate
commit.

This hasn't been tested with all and every node in cycles, but
environment and regular textures with texture coordinates work.

There is some difference between the way cycles treats some coordinates,
which is in world space and the way GLSL treats them, which is in view
space.
We might want to explore and improve this further in the future.

...also </drumroll>

23 files changed:
SConstruct
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/world.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/render/render_update.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_material.h
source/blender/gpu/SConscript
source/blender/gpu/intern/gpu_codegen.c
source/blender/gpu/intern/gpu_codegen.h
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/gpu/shaders/gpu_shader_vertex_world.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_world_types.h
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_world.c
source/blender/nodes/shader/nodes/node_shader_background.c
source/blender/nodes/shader/nodes/node_shader_output_world.c
source/blender/nodes/shader/nodes/node_shader_tex_coord.c
source/blender/nodes/shader/nodes/node_shader_tex_environment.c

index 45c9ae3b84d3b857f801a1934d83ebcd9b76fd41..4c2097f88798f154fa045f3af7ba72650029dfd8 100644 (file)
@@ -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")
index ea1b9a3f13ddbab8a212260f5ecb2c488f6a8ec3..af2080c1b618a79163a6c7ae36734c23071088c0 100644 (file)
@@ -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));
index 8e3c92314e61c57522d30aef8508e88319d9b1ce..29a345e111bfee1c415b61b70128eecc8cb07588 100644 (file)
@@ -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;
 }
index 9b043c6dbda8c9ec92010ab4054240735cfe0d1a..05af147eb865a9bca658ba97d8d29f5b7289976f 100644 (file)
@@ -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);
 }
 
 
index 1320fedbfa7aee812d318c6d12bbac0533dfe0cf..e4e16dd03fc232f8facf6188208caf60c8b8ab2e 100644 (file)
@@ -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)
index d52a351ffc25a4d67a089892bc4e4787bb6d6b35..1b82e89a364b853518b8feb2166d8333d485e623 100644 (file)
@@ -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);
                        }
 
index 81f926e50489c01dd46dcad4a63b8232828538a5..95b11d1731f97f9194ca1d54059f149523b702b1 100644 (file)
@@ -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;
index d4a0c01518b53d415dfc770c10f651545ea907b8..26ce64fd8ca18c04dcb036f008372178e284c171 100644 (file)
@@ -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);
 
index 63eea9486ed8c6c2fabd10bb621b999493ffd081..361c247767fbbe3028bacf06b57755a4dd8ef93a 100644 (file)
@@ -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)
 
index fab9c28cb61548e7037b4c2a08a9d7e7dd1f2cc2..09a5653b1ec21da86ddac2f22010487a38ba94c9 100644 (file)
@@ -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);
index f11ecafc986d48c77281b869e6b0f13a07b3ab7a..e44a99286a898c0161c98a3854de124b1a29ae98 100644 (file)
@@ -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"),
     ))
index 4182f51561b4304ce16b7fe875c33f2097692cd5..1b99c6ee49a273c499f7755f21053c5098309ea7 100644 (file)
@@ -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? */
index 692139259315c658765651a0e7afd37b60127691..a0698235db620bce9b48c6218f176f282ae5b6f7 100644 (file)
@@ -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);
 
index e4228bedf9df06f4dec91b6a86676dae0387fec6..31b499d54abdc2cd09319c73e73ba2567cfb48af 100644 (file)
@@ -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);
index 867270a6d7af258f4cfccd6f49340dc32e44ef0d..c463fb25dedd0994ec22f7d8a1b71305b4294588 100644 (file)
@@ -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 (file)
index 0000000..9dbcaeb
--- /dev/null
@@ -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);
+
index 50542797f0bb7c3696d582e0a2b6b215b26acb05..2a9bcc20a9fca3271d32bf645f67f92edca833b6 100644 (file)
@@ -128,6 +128,7 @@ typedef struct World {
        /* nodes */
        struct bNodeTree *nodetree;
 
+       ListBase gpumaterial;           /* runtime */
 } World;
 
 /* **************** WORLD ********************* */
index a191cc32bb27c3261290f797b6e5badf781298ed..e3d44cb1349d68e87e8204a81cbdcb21bf033879 100644 (file)
@@ -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);
        }
index f63350ea0ae43c3a7ff9399e909deb91f75e6947..721cbaf21c75a7f0f7193a8d9285b143092380a2 100644 (file)
@@ -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)
index 2478fb4d38cd5129618f0a5ff77e0c94bbe5e991..b387529e456c587bdeae76aadc39ecaa45171303 100644 (file)
@@ -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);
 }
index c8e47c47c5fe3d85ec17c67c5bcbc64c1b37485a..ad7389fd56ea7897ff7d8d252ba17cdce8c0e61d 100644 (file)
@@ -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);
 
index 781b1bb5a93aa9ab42b5fa75cd0de4a2d34121d8..85eca6ae9900672bbf51e433912f67a46086e083 100644 (file)
@@ -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 */
index 56db9dd3b44ac86a96882b4def34623647dc6a98..f63613317411d1c30f62b31fd2a7d3f9b429b4e9 100644 (file)
@@ -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)