Clay-Engine (merge clay-engine)
authorClément Foucault <foucault.clem@gmail.com>
Tue, 7 Feb 2017 10:20:15 +0000 (11:20 +0100)
committerDalai Felinto <dfelinto@gmail.com>
Tue, 7 Feb 2017 10:31:22 +0000 (11:31 +0100)
Initial work by Clément Foucault with contributions from Dalai Felinto
(mainly per-collection engine settings logic, and depsgraph iterator placeholder).

This makes Blender require OpenGL 3.3. Which means Intel graphic card
and OSX will break. Disable CLAY_ENGINE in CMake in those cases.

This is a prototype render engine intended to help the design of real
render engines. This is mainly an engine with enphasis in matcap and
ambient occlusion.

Implemented Features
--------------------

* Clay Render Engine, following the new API, to be used as reference for
future engines

* A more complete Matcap customization with more options

* Per-Collection render engine settings

* New Ground Truth AO - not enabled

Missing Features
----------------

* Finish object edit mode
  - Fix shaders to use new matrix
  - Fix artifacts when edge does off screen
  - Fix depth issue
  - Selection sillhouette
  - Mesh wires
  - Use mesh normals (for higher quality matcap)
  - Non-Mesh objects drawing
  - Widget drawing
  - Performance issues

* Finish mesh edit mode
  - Derived-Mesh-less edit mode API (mesh_rende.c)

* General edit mode
  - Per-collection edit mode settings

* General engines
  - Per-collection engine settings
    (they are their, but they still need to be flushed by depsgraph, and
    used by the drawing code)

64 files changed:
CMakeLists.txt
build_files/cmake/macros.cmake
release/scripts/startup/bl_ui/properties_collection.py
release/scripts/startup/bl_ui/properties_render.py
release/scripts/startup/bl_ui/properties_render_layer.py
source/blender/CMakeLists.txt
source/blender/blenkernel/BKE_layer.h
source/blender/blenkernel/intern/layer.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh_render.c
source/blender/blenkernel/intern/scene.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/versioning_280.c
source/blender/blenloader/intern/writefile.c
source/blender/draw/CMakeLists.txt
source/blender/draw/DRW_engine.h [new file with mode: 0644]
source/blender/draw/DRW_engines.h [deleted file]
source/blender/draw/engines/clay/clay.c [new file with mode: 0644]
source/blender/draw/engines/clay/clay.h [moved from source/blender/draw/DRW_defines.h with 71% similarity]
source/blender/draw/engines/clay/shaders/clay_frag.glsl [new file with mode: 0644]
source/blender/draw/engines/clay/shaders/clay_vert.glsl [new file with mode: 0644]
source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl [new file with mode: 0644]
source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl [new file with mode: 0644]
source/blender/draw/intern/DRW_render.h [new file with mode: 0644]
source/blender/draw/intern/draw_cache.c [new file with mode: 0644]
source/blender/draw/intern/draw_cache.h [new file with mode: 0644]
source/blender/draw/intern/draw_manager.c [new file with mode: 0644]
source/blender/draw/intern/draw_mode_pass.c [new file with mode: 0644]
source/blender/draw/intern/draw_mode_pass.h [new file with mode: 0644]
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/gpu/CMakeLists.txt
source/blender/gpu/GPU_extensions.h
source/blender/gpu/GPU_framebuffer.h
source/blender/gpu/GPU_shader.h
source/blender/gpu/GPU_uniformbuffer.h [new file with mode: 0644]
source/blender/gpu/GPU_viewport.h
source/blender/gpu/gawain/batch.c
source/blender/gpu/gawain/batch.h
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_framebuffer.c
source/blender/gpu/intern/gpu_shader.c
source/blender/gpu/intern/gpu_texture.c
source/blender/gpu/intern/gpu_uniformbuffer.c [new file with mode: 0644]
source/blender/gpu/intern/gpu_viewport.c
source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl [new file with mode: 0644]
source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl [new file with mode: 0644]
source/blender/makesdna/DNA_layer_types.h
source/blender/makesdna/DNA_material_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_render.c
source/blender/makesrna/intern/rna_scene.c
source/blender/render/CMakeLists.txt
source/blender/render/extern/include/RE_engine.h
source/blender/render/intern/source/external_engine.c
source/blenderplayer/bad_level_call_stubs/stubs.c

index d52f0c835111deaa2ce94e72e15cabea9d4c65d3..a107dd78fbb6b42550f5c4307a18ab26d92923be 100644 (file)
@@ -242,6 +242,8 @@ endif()
 option(WITH_PLAYER        "Build Player" OFF)
 option(WITH_OPENCOLORIO   "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
 
+option(WITH_CLAY_ENGINE    "Enable New Clay engine (Breaks Mac and Intel compatibility)" ON)
+
 # Compositor
 option(WITH_COMPOSITOR         "Enable the tile based nodal compositor" ON)
 
index 83ae56636b036ef89cdfbe49df6e92c39f1d86c0..fa9c2a28cb50c0691371565716f73d499b7ed314 100644 (file)
@@ -598,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
                bf_modifiers
                bf_bmesh
                bf_gpu
+               bf_draw
                bf_blenloader
                bf_blenkernel
                bf_physics
index d67d694aec9d51106a54b6e37d795f0768d0f123..88d78f98ef28a14c4ee986765a9cb7cf4dd39a76 100644 (file)
@@ -75,5 +75,54 @@ class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
         row.operator("collections.objects_deselect", text="Deselect")
 
 
+def template_engine_settings(col, settings, name, use_icon_view=False):
+    icons = {
+            False: 'ZOOMIN',
+            True: 'X',
+            }
+
+    use_name = "{0}_use".format(name)
+    use = getattr(settings, use_name)
+
+    row = col.row()
+    col = row.column()
+    col.active = use
+
+    if use_icon_view:
+        col.template_icon_view(settings, name)
+    else:
+        col.prop(settings, name)
+
+    row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False)
+
+
+class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
+    bl_label = "Render Settings"
+    COMPAT_ENGINES = {'BLENDER_CLAY'}
+
+    @classmethod
+    def poll(cls, context):
+        scene = context.scene
+        return scene and (scene.render.engine in cls.COMPAT_ENGINES)
+
+    def draw(self, context):
+        layout = self.layout
+
+        collection = context.layer_collection
+        settings = collection.get_engine_settings()
+
+        col = layout.column()
+        template_engine_settings(col, settings, "type")
+        template_engine_settings(col, settings, "matcap_icon", use_icon_view=True)
+        template_engine_settings(col, settings, "matcap_rotation")
+        template_engine_settings(col, settings, "matcap_hue")
+        template_engine_settings(col, settings, "matcap_saturation")
+        template_engine_settings(col, settings, "matcap_value")
+        template_engine_settings(col, settings, "ssao_factor_cavity")
+        template_engine_settings(col, settings, "ssao_factor_edge")
+        template_engine_settings(col, settings, "ssao_distance")
+        template_engine_settings(col, settings, "ssao_attenuation")
+
+
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)
index 6d23c07152e3a39963279f590a8d55d9f2eda847..90d46a6ee47a2b83129efc1f332d98aa5a2fb36b 100644 (file)
@@ -584,5 +584,24 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
             sub.prop(rd, "bake_user_scale", text="User Scale")
 
 
+class RENDER_PT_clay(RenderButtonsPanel, Panel):
+    bl_label = "Default Clay"
+    COMPAT_ENGINES = {'BLENDER_CLAY'}
+
+    def draw(self, context):
+        layout = self.layout;
+        settings = context.scene.active_engine_settings
+        layout.template_icon_view(settings, "matcap_icon")
+        layout.prop(settings, "matcap_rotation")
+        layout.prop(settings, "matcap_hue")
+        layout.prop(settings, "matcap_saturation")
+        layout.prop(settings, "matcap_value")
+        layout.prop(settings, "ssao_factor_cavity")
+        layout.prop(settings, "ssao_factor_edge")
+        layout.prop(settings, "ssao_distance")
+        layout.prop(settings, "ssao_attenuation")
+        layout.prop(settings, "ssao_samples")
+
+
 if __name__ == "__main__":  # only for live edit.
     bpy.utils.register_module(__name__)
index 45c93dd9335d38af3ec1bf37fe269453a595e4bf..2545eadc792db91ce4866ecd57ddd8944e35f79a 100644 (file)
@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
 class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
     bl_label = "Layer List"
     bl_options = {'HIDE_HEADER'}
-    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+    COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
 
     def draw(self, context):
         layout = self.layout
index 6f2b78e084529a69af4bef6dc81f39a06ed00e40..47ebed8f791ad2bbbf872368d3afc92af60b4334 100644 (file)
@@ -100,6 +100,7 @@ add_subdirectory(windowmanager)
 add_subdirectory(blenkernel)
 add_subdirectory(blenlib)
 add_subdirectory(bmesh)
+add_subdirectory(draw)
 add_subdirectory(render)
 add_subdirectory(blenfont)
 add_subdirectory(blentranslation)
index 850c63f535f40baaac20bceb36b5e9dcb7533538..de8a577d272a9fd457d065b2a68e2265edc9fd6c 100644 (file)
@@ -39,13 +39,17 @@ extern "C" {
 #define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
 #define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */
 #define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */
 #define TODO_LAYER /* generic todo */
 
-struct Base;
-struct ID;
+struct CollectionEngineSettings;
 struct LayerCollection;
+struct ID;
+struct ListBase;
 struct Main;
 struct Object;
+struct Base;
+struct RenderEngine;
 struct Scene;
 struct SceneCollection;
 struct SceneLayer;
@@ -66,6 +70,9 @@ void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
 void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
 void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
 
+void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl);
+void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl);
+
 void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
 
 struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
@@ -91,6 +98,24 @@ void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *s
 
 void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
 
+/* engine settings */
+typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
+struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name);
+void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func);
+void BKE_layer_collection_engine_settings_callback_free(void);
+void BKE_layer_collection_engine_settings_create(struct ListBase *lb, const char *engine_name);
+void BKE_layer_collection_engine_settings_free(struct ListBase *lb);
+
+void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value);
+void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value);
+struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name);
+int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name);
+float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name);
+void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value);
+void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value);
+bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name);
+void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value);
+
 /* iterators */
 
 void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
@@ -172,6 +197,9 @@ void BKE_visible_bases_Iterator_end(Iterator *iter);
 /* temporary hacky solution waiting for final depsgraph evaluation */
 #define DEG_OBJECT_ITER(sl_, ob_)                                             \
 {                                                                             \
+       /* temporary solution, waiting for depsgraph update */                    \
+       BKE_scene_layer_engine_settings_update(sl);                               \
+                                                                                 \
        /* flush all the data to objects*/                                        \
        Base *base_;                                                              \
        for (base_ = sl->object_bases.first; base_; base_ = base_->next) {        \
index cec1d70463fc7e8359e80b0296556760af9f2fb1..28c5e9aff5d8cfe57db8afa740144ec1f833def3 100644 (file)
 #include "MEM_guardedalloc.h"
 
 /* prototype */
+struct CollectionEngineSettingsCB_Type;
 static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
 static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
 static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static void collection_engine_settings_create(ListBase *lb, struct CollectionEngineSettingsCB_Type *ces_type);
+static void layer_collection_create_engine_settings(LayerCollection *lc);
 static void object_bases_Iterator_next(Iterator *iter, const int flag);
 
 /* RenderLayer */
@@ -254,6 +257,35 @@ void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
                        base->flag &= ~BASE_SELECTED;
                }
        }
+
+       BKE_scene_layer_engine_settings_recalculate(sl);
+}
+
+/**
+ * Tag Scene Layer to recalculation
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl)
+{
+       sl->flag |= SCENE_LAYER_ENGINE_DIRTY;
+}
+
+/**
+ * Re-calculate the engine settings for all the objects in SceneLayer
+ *
+ * Temporary function, waiting for real depsgraph
+ */
+void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl)
+{
+       if ((sl->flag & SCENE_LAYER_ENGINE_DIRTY) == 0) {
+               return;
+       }
+
+       /* do the complete settings update */
+       TODO_LAYER_DEPSGRAPH;
+
+       sl->flag &= ~SCENE_LAYER_ENGINE_DIRTY;
 }
 
 /**
@@ -292,10 +324,12 @@ static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
 
        BLI_freelistN(&lc->object_bases);
        BLI_freelistN(&lc->overrides);
+       BKE_layer_collection_engine_settings_free(&lc->engine_settings);
 
        for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
                layer_collection_free(sl, nlc);
        }
+
        BLI_freelistN(&lc->layer_collections);
 }
 
@@ -467,6 +501,7 @@ static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, Scene
        lc->scene_collection = sc;
        lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
 
+       layer_collection_create_engine_settings(lc);
        layer_collection_populate(sl, lc, sc);
        return lc;
 }
@@ -578,6 +613,211 @@ void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const ch
        TODO_LAYER_OVERRIDE;
 }
 
+/* ---------------------------------------------------------------------- */
+/* Engine Settings */
+
+ListBase R_engines_settings_callbacks = {NULL, NULL};
+
+typedef struct CollectionEngineSettingsCB_Type {
+       struct CollectionEngineSettingsCB_Type *next, *prev;
+
+       char name[MAX_NAME]; /* engine name */
+
+       CollectionEngineSettingsCB callback;
+
+} CollectionEngineSettingsCB_Type;
+
+static void create_engine_settings_layer_collection(LayerCollection *lc, CollectionEngineSettingsCB_Type *ces_type)
+{
+       if (BKE_layer_collection_engine_get(lc, ces_type->name)) {
+               return;
+       }
+
+       collection_engine_settings_create(&lc->engine_settings, ces_type);
+
+       for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+               create_engine_settings_layer_collection(lcn, ces_type);
+       }
+}
+
+static void create_engines_settings_scene(Scene *scene, CollectionEngineSettingsCB_Type *ces_type)
+{
+       for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+               for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                       create_engine_settings_layer_collection(lc, ces_type);
+               }
+       }
+}
+
+void BKE_layer_collection_engine_settings_callback_register(
+        Main *bmain, const char *engine_name, CollectionEngineSettingsCB func)
+{
+       CollectionEngineSettingsCB_Type *ces_type;
+
+       /* cleanup in case it existed */
+       ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+
+       if (ces_type) {
+               BLI_remlink(&R_engines_settings_callbacks, ces_type);
+               MEM_freeN(ces_type);
+       }
+
+       ces_type = MEM_callocN(sizeof(CollectionEngineSettingsCB_Type), "collection_engine_type");
+       BLI_strncpy_utf8(ces_type->name, engine_name, sizeof(ces_type->name));
+       ces_type->callback = func;
+       BLI_addtail(&R_engines_settings_callbacks, ces_type);
+
+       if (bmain) {
+               /* populate all of the collections of the scene with those settings */
+               for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+                       create_engines_settings_scene(scene, ces_type);
+               }
+       }
+}
+
+void BKE_layer_collection_engine_settings_callback_free(void)
+{
+       BLI_freelistN(&R_engines_settings_callbacks);
+}
+
+static void collection_engine_settings_create(ListBase *lb, CollectionEngineSettingsCB_Type *ces_type)
+{
+       /* create callback data */
+       CollectionEngineSettings *ces = MEM_callocN(sizeof(CollectionEngineSettings), "Collection Engine Settings");
+       BLI_strncpy_utf8(ces->name, ces_type->name, sizeof(ces->name));
+       BLI_addtail(lb, ces);
+
+       /* call callback */
+       ces_type->callback(NULL, ces);
+}
+
+/**
+ * Initialize a CollectionEngineSettings
+ *
+ * Usually we would pass LayerCollection->engine_settings
+ * But depsgraph uses this for Object->collection_settings
+ */
+void BKE_layer_collection_engine_settings_create(ListBase *lb, const char *engine_name)
+{
+       CollectionEngineSettingsCB_Type *ces_type;
+       ces_type = BLI_findstring(&R_engines_settings_callbacks, engine_name, offsetof(CollectionEngineSettingsCB_Type, name));
+       BLI_assert(ces_type);
+       collection_engine_settings_create(lb, ces_type);
+}
+
+/**
+ * Free the CollectionEngineSettings ListBase
+ *
+ * Usually we would pass LayerCollection->engine_settings
+ * But depsgraph uses this for Object->collection_settings
+ */
+void BKE_layer_collection_engine_settings_free(ListBase *lb)
+{
+       for (CollectionEngineSettings *cse = lb->first; cse; cse = cse->next) {
+               BLI_freelistN(&cse->properties);
+       }
+       BLI_freelistN(lb);
+}
+
+/**
+ * Initialize the render settings for a single LayerCollection
+ */
+static void layer_collection_create_engine_settings(LayerCollection *lc)
+{
+       CollectionEngineSettingsCB_Type *ces_type;
+       for (ces_type = R_engines_settings_callbacks.first; ces_type; ces_type = ces_type->next) {
+               create_engine_settings_layer_collection(lc, ces_type);
+       }
+}
+
+/**
+ * Return layer collection engine settings for specified engine
+ */
+CollectionEngineSettings *BKE_layer_collection_engine_get(LayerCollection *lc, const char *engine_name)
+{
+       CollectionEngineSettings *ces;
+       ces = BLI_findstring(&lc->engine_settings, engine_name, offsetof(CollectionEngineSettings, name));
+       return ces;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings Properties */
+
+void BKE_collection_engine_property_add_float(CollectionEngineSettings *ces, const char *name, float value)
+{
+       CollectionEnginePropertyFloat *prop;
+       prop = MEM_callocN(sizeof(CollectionEnginePropertyFloat), "collection engine settings float");
+       prop->data.type = COLLECTION_PROP_TYPE_FLOAT;
+       BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
+       prop->value = value;
+       BLI_addtail(&ces->properties, prop);
+}
+
+void BKE_collection_engine_property_add_int(CollectionEngineSettings *ces, const char *name, int value)
+{
+       CollectionEnginePropertyInt *prop;
+       prop = MEM_callocN(sizeof(CollectionEnginePropertyInt), "collection engine settings int");
+       prop->data.type = COLLECTION_PROP_TYPE_INT;
+       BLI_strncpy_utf8(prop->data.name, name, sizeof(prop->data.name));
+       prop->value = value;
+       BLI_addtail(&ces->properties, prop);
+}
+
+CollectionEngineProperty *BKE_collection_engine_property_get(CollectionEngineSettings *ces, const char *name)
+{
+       return BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+}
+
+int BKE_collection_engine_property_value_get_int(CollectionEngineSettings *ces, const char *name)
+{
+       CollectionEnginePropertyInt *prop;
+       prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+       return prop->value;
+}
+
+float BKE_collection_engine_property_value_get_float(CollectionEngineSettings *ces, const char *name)
+{
+       CollectionEnginePropertyFloat *prop;
+       prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+       return prop->value;
+}
+
+void BKE_collection_engine_property_value_set_int(CollectionEngineSettings *ces, const char *name, int value)
+{
+       CollectionEnginePropertyInt *prop;
+       prop = (CollectionEnginePropertyInt *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+       prop->value = value;
+       prop->data.flag |= COLLECTION_PROP_USE;
+}
+
+void BKE_collection_engine_property_value_set_float(CollectionEngineSettings *ces, const char *name, float value)
+{
+       CollectionEnginePropertyFloat *prop;
+       prop = (CollectionEnginePropertyFloat *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+       prop->value = value;
+       prop->data.flag |= COLLECTION_PROP_USE;
+}
+
+bool BKE_collection_engine_property_use_get(CollectionEngineSettings *ces, const char *name)
+{
+       CollectionEngineProperty *prop;
+       prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+       return ((prop->flag & COLLECTION_PROP_USE) != 0);
+}
+
+void BKE_collection_engine_property_use_set(CollectionEngineSettings *ces, const char *name, bool value)
+{
+       CollectionEngineProperty *prop;
+       prop = (CollectionEngineProperty *)BLI_findstring(&ces->properties, name, offsetof(CollectionEngineProperty, name));
+
+       if (value) {
+               prop->flag |= COLLECTION_PROP_USE;
+       }
+       else {
+               prop->flag &= ~COLLECTION_PROP_USE;
+       }
+}
+
 /* ---------------------------------------------------------------------- */
 /* Iterators */
 
index 54945242fe4064742f128d448af0003f53fe2e4d..435504859a43562f8d31abb35d9f294f35659457 100644 (file)
@@ -111,6 +111,12 @@ void BKE_material_free(Material *ma)
 
        BKE_icon_id_delete((ID *)ma);
        BKE_previewimg_free(&ma->preview);
+
+       for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) {
+               if (mes->data)
+                       MEM_SAFE_FREE(mes->data);
+       }
+       BLI_freelistN(&ma->engines_settings);
 }
 
 void BKE_material_init(Material *ma)
@@ -248,6 +254,8 @@ Material *BKE_material_copy(Main *bmain, Material *ma)
 
        BLI_listbase_clear(&man->gpumaterial);
 
+       /* TODO Duplicate Engine Settings and set runtime to NULL */
+
        BKE_id_copy_ensure_local(bmain, &ma->id, &man->id);
 
        return man;
@@ -279,6 +287,8 @@ Material *localize_material(Material *ma)
                man->nodetree = ntreeLocalize(ma->nodetree);
        
        BLI_listbase_clear(&man->gpumaterial);
+
+       /* TODO Duplicate Engine Settings and set runtime to NULL */
        
        return man;
 }
@@ -1698,6 +1708,7 @@ void copy_matcopybuf(Material *ma)
        matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
        matcopybuf.preview = NULL;
        BLI_listbase_clear(&matcopybuf.gpumaterial);
+       /* TODO Duplicate Engine Settings and set runtime to NULL */
        matcopied = 1;
 }
 
index 4118208d32f4a18afce7c158b2b9c93c43a24870..fd0f49810fb775d589ba32924e7d0d01e71b7c5f 100644 (file)
@@ -47,7 +47,7 @@
 /* Mesh Interface */
 
 #define MESH_RENDER_FUNCTION(func_name)     \
-       if (me->edit_btmesh) {                  \
+       if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \
            return mesh_bmesh_##func_name(me);  \
        }                                       \
        else {                                  \
index d47982f96eb86dcf03220cdb74a0dec8e540ec5d..1ce4bf8f9eb720addd7017ce576a7f518db7dae7 100644 (file)
 
 const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
 const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
+const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY";
 const char *RE_engine_id_CYCLES = "CYCLES";
 
 void free_avicodecdata(AviCodecData *acd)
@@ -566,6 +567,13 @@ void BKE_scene_free(Scene *sce)
        BKE_collection_master_free(sce);
        MEM_freeN(sce->collection);
        sce->collection = NULL;
+
+       /* Runtime Engine Data */
+       for (RenderEngineSettings *res = sce->engines_settings.first; res; res = res->next) {
+               if (res->data)
+                       MEM_freeN(res->data);
+       }
+       BLI_freelistN(&sce->engines_settings);
 }
 
 void BKE_scene_init(Scene *sce)
index e669bf3b4a6ba3536cec94fe59536b44681c896c..da0650d02f57b55d2454a2acef872f0200ce0bf6 100644 (file)
@@ -3970,6 +3970,7 @@ static void lib_link_material(FileData *fd, Main *main)
 static void direct_link_material(FileData *fd, Material *ma)
 {
        int a;
+       MaterialEngineSettings *mes;
        
        ma->adt = newdataadr(fd, ma->adt);
        direct_link_animdata(fd, ma->adt);
@@ -3990,6 +3991,11 @@ static void direct_link_material(FileData *fd, Material *ma)
        
        ma->preview = direct_link_preview_image(fd, ma->preview);
        BLI_listbase_clear(&ma->gpumaterial);
+
+       link_list(fd, &ma->engines_settings);
+       for (mes = ma->engines_settings.first; mes; mes = mes->next) {
+               mes->data = newdataadr(fd, mes->data);
+       }
 }
 
 /* ************ READ PARTICLE SETTINGS ***************** */
@@ -5552,6 +5558,7 @@ static void direct_link_object(FileData *fd, Object *ob)
        ob->bb = NULL;
        ob->derivedDeform = NULL;
        ob->derivedFinal = NULL;
+       ob->collection_settings = NULL;
        BLI_listbase_clear(&ob->gpulamp);
        link_list(fd, &ob->pc_ids);
 
@@ -5924,6 +5931,14 @@ static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
        }
 }
 
+static void direct_link_engine_settings(FileData *fd, ListBase *lb)
+{
+       link_list(fd, lb);
+       for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
+               link_list(fd, &ces->properties);
+       }
+}
+
 static void direct_link_layer_collections(FileData *fd, ListBase *lb)
 {
        link_list(fd, lb);
@@ -5938,6 +5953,8 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb)
 
                link_list(fd, &lc->overrides);
 
+               direct_link_engine_settings(fd, &lc->engine_settings);
+
                direct_link_layer_collections(fd, &lc->layer_collections);
        }
 }
@@ -5950,6 +5967,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        RigidBodyWorld *rbw;
        SceneLayer *sl;
        SceneRenderLayer *srl;
+       RenderEngineSettings *res;
        
        sce->theDag = NULL;
        sce->depsgraph = NULL;
@@ -6212,6 +6230,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                sl->basact = newdataadr(fd, sl->basact);
                direct_link_layer_collections(fd, &sl->layer_collections);
        }
+
+       link_list(fd, &sce->engines_settings);
+       for (res = sce->engines_settings.first; res; res = res->next) {
+               res->data = newdataadr(fd, res->data);
+       }
 }
 
 /* ************ READ WM ***************** */
index a4e69c9d51477017e6959fe869dda75014d501e3..89ee05ee3e7f9d97d36cddd56b9b23b9712fb16d 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "DNA_object_types.h"
 #include "DNA_layer_types.h"
+#include "DNA_material_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_genfile.h"
 
index 4ddf83d306bf249100b7cd6ae78a13161a0439fb..0ad879b9aa6e28ddbe9bbb9cb9ab939f55872525 100644 (file)
@@ -1894,6 +1894,8 @@ static void write_objects(WriteData *wd, ListBase *idbase)
 
                        writelist(wd, DATA, LinkData, &ob->pc_ids);
                        writelist(wd, DATA, LodLevel, &ob->lodlevels);
+
+                       ob->collection_settings = NULL;
                }
 
                write_previews(wd, ob->preview);
@@ -2469,6 +2471,21 @@ static void write_textures(WriteData *wd, ListBase *idbase)
        mywrite_flush(wd);
 }
 
+static void write_material_engines_settings(WriteData *wd, ListBase *lb)
+{
+       for (MaterialEngineSettings *res = lb->first; res; res = res->next) {
+               writestruct(wd, DATA, MaterialEngineSettings, 1, res);
+
+               if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+                       writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data);
+               }
+               else {
+                       /* No engine matched */
+                       /* error: don't know how to write this file */
+               }
+       }
+}
+
 static void write_materials(WriteData *wd, ListBase *idbase)
 {
        Material *ma;
@@ -2505,6 +2522,8 @@ static void write_materials(WriteData *wd, ListBase *idbase)
                        }
 
                        write_previews(wd, ma->preview);
+
+                       write_material_engines_settings(wd, &ma->engines_settings);
                }
                ma = ma->id.next;
        }
@@ -2639,6 +2658,26 @@ static void write_scene_collection(WriteData *wd, SceneCollection *sc)
        }
 }
 
+static void write_collection_engine_settings(WriteData *wd, ListBase *lb)
+{
+       for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
+               writestruct(wd, DATA, CollectionEngineSettings, 1, ces);
+
+               for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) {
+                       switch (prop->type) {
+                           case COLLECTION_PROP_TYPE_FLOAT:
+                                   writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop);
+                                   break;
+                           case COLLECTION_PROP_TYPE_INT:
+                                   writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop);
+                                   break;
+                           default:
+                                   ; /* error: don't know how to write this file */
+                       }
+               }
+       }
+}
+
 static void write_layer_collections(WriteData *wd, ListBase *lb)
 {
        for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
@@ -2647,10 +2686,27 @@ static void write_layer_collections(WriteData *wd, ListBase *lb)
                writelist(wd, DATA, LinkData, &lc->object_bases);
                writelist(wd, DATA, CollectionOverride, &lc->overrides);
 
+               write_collection_engine_settings(wd, &lc->engine_settings);
+
                write_layer_collections(wd, &lc->layer_collections);
        }
 }
 
+static void write_render_engines_settings(WriteData *wd, ListBase *lb)
+{
+       for (RenderEngineSettings *res = lb->first; res; res = res->next) {
+               writestruct(wd, DATA, RenderEngineSettings, 1, res);
+
+               if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+                       writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data);
+               }
+               else {
+                       /* No engine matched */
+                       /* error: don't know how to write this file */
+               }
+       }
+}
+
 static void write_scenes(WriteData *wd, ListBase *scebase)
 {
        Scene *sce;
@@ -2880,6 +2936,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
                        write_layer_collections(wd, &sl->layer_collections);
                }
 
+               write_render_engines_settings(wd, &sce->engines_settings);
+
                sce = sce->id.next;
        }
 
index 60449ebc6008ed003cab741a47b740ad3a43b8e5..d5b54e8a74612c7132dcb0cde452a2649e8eb838 100644 (file)
 set(INC
        .
        intern
-       nodes
-       operations
+       engines/clay
+
        ../blenkernel
        ../blenlib
        ../blentranslation
        ../imbuf
+       ../depsgraph
        ../makesdna
        ../makesrna
-       ../windowmanager
-       ../nodes
-       ../nodes/composite
-       ../nodes/intern
+       ../gpu
+       ../editors/include
+       ../editors/space_view3d
        ../render/extern/include
        ../render/intern/include
-       ../../../extern/clew/include
+
+       ../../../intern/glew-mx
        ../../../intern/guardedalloc
-       ../../../intern/atomic
 )
 
 set(INC_SYS
-
+       ${GLEW_INCLUDE_PATH}
 )
 
 set(SRC
-       DRW_defines.h
+       intern/draw_manager.c
+       intern/draw_mode_pass.c
+       intern/draw_cache.c
+       engines/clay/clay.c
 
-)
+       intern/DRW_render.h
+       intern/draw_mode_pass.h
+       intern/draw_cache.h
+       engines/clay/clay.h
 
-list(APPEND INC
+       ./DRW_engine.h
 )
 
+if(WITH_CLAY_ENGINE)
+       add_definitions(-DWITH_CLAY_ENGINE)
 endif()
 
+data_to_c_simple(engines/clay/shaders/clay_frag.glsl SRC)
+data_to_c_simple(engines/clay/shaders/clay_vert.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_alchemy.glsl SRC)
+data_to_c_simple(engines/clay/shaders/ssao_groundtruth.glsl SRC)
+
+list(APPEND INC
+)
+
 blender_add_lib(bf_draw "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
new file mode 100644 (file)
index 0000000..4f86e3f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file DRW_engine.h
+ *  \ingroup draw
+ */
+
+#ifndef __DRW_ENGINE_H__
+#define __DRW_ENGINE_H__
+
+//#define WITH_VIEWPORT_CACHE_TEST
+
+struct DRWPass;
+struct Material;
+struct Scene;
+
+void DRW_engines_init(void);
+void DRW_engines_free(void);
+
+/* This is here because GPUViewport needs it */
+void DRW_pass_free(struct DRWPass *pass);
+
+/* Settings */
+void *DRW_material_settings_get(struct Material *ma, const char *engine_name);
+void *DRW_render_settings_get(struct Scene *scene, const char *engine_name);
+
+#endif /* __DRW_ENGINE_H__ */
\ No newline at end of file
diff --git a/source/blender/draw/DRW_engines.h b/source/blender/draw/DRW_engines.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c
new file mode 100644 (file)
index 0000000..f443606
--- /dev/null
@@ -0,0 +1,722 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+#include "DRW_render.h"
+
+#include "BKE_icons.h"
+#include "BKE_main.h"
+
+#include "BLI_dynstr.h"
+#include "BLI_rand.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+#include "UI_resources.h"
+#include "UI_interface_icons.h"
+
+#include "clay.h"
+#ifdef WITH_CLAY_ENGINE
+/* Shaders */
+
+extern char datatoc_clay_frag_glsl[];
+extern char datatoc_clay_vert_glsl[];
+extern char datatoc_ssao_alchemy_glsl[];
+extern char datatoc_ssao_groundtruth_glsl[];
+
+/* Storage */
+
+/* UBOs data needs to be 16 byte aligned (size of vec4) */
+/* Reminder : float, int, bool are 4 bytes */
+typedef struct CLAY_UBO_Material {
+       float ssao_params_var[4];
+       /* - 16 -*/
+       float matcap_hsv[3];
+       float matcap_id; /* even float encoding have enough precision */
+       /* - 16 -*/
+       float matcap_rot[2];
+       float pad[2]; /* ensure 16 bytes alignement */
+} CLAY_UBO_Material; /* 48 bytes */
+
+typedef struct CLAY_UBO_Storage {
+       CLAY_UBO_Material materials[512]; /* 512 = 9 bit material id */
+} CLAY_UBO_Storage;
+
+static struct CLAY_data {
+       /* Depth Pre Pass */
+       struct GPUShader *depth_sh;
+       /* Shading Pass */
+       struct GPUShader *clay_sh;
+
+       /* Materials Parameter UBO */
+       struct GPUUniformBuffer *mat_ubo;
+       CLAY_UBO_Storage mat_storage;
+       short ubo_flag;
+
+       /* Matcap textures */
+       struct GPUTexture *matcap_array;
+       float matcap_colors[24][3];
+
+       /* Ssao */
+       float winmat[4][4];
+       float viewvecs[3][4];
+       float ssao_params[4];
+       struct GPUTexture *jitter_tx;
+       struct GPUTexture *sampling_tx;
+} data = {NULL};
+
+/* CLAY_data.ubo_flag */
+enum {
+       CLAY_UBO_CLEAR    = (1 << 0),
+       CLAY_UBO_REFRESH  = (1 << 1),
+};
+
+/* keep it under MAX_BUFFERS */
+typedef struct CLAY_FramebufferList{
+       /* default */
+       struct GPUFrameBuffer *default_fb;
+       /* engine specific */
+       struct GPUFrameBuffer *downsample_depth;
+} CLAY_FramebufferList;
+
+/* keep it under MAX_TEXTURES */
+typedef struct CLAY_TextureList{
+       /* default */
+       struct GPUTexture *color;
+       struct GPUTexture *depth;
+       /* engine specific */
+       struct GPUTexture *depth_low;
+} CLAY_TextureList;
+
+/* for clarity follow the same layout as CLAY_TextureList */
+enum {
+       SCENE_COLOR,
+       SCENE_DEPTH,
+       SCENE_DEPTH_LOW,
+};
+
+/* keep it under MAX_PASSES */
+typedef struct CLAY_PassList{
+       /* default */
+       struct DRWPass *non_meshes_pass;
+       struct DRWPass *ob_center_pass;
+       /* engine specific */
+       struct DRWPass *depth_pass;
+       struct DRWPass *clay_pass;
+       struct DRWPass *wire_overlay_pass;
+       struct DRWPass *wire_outline_pass;
+} CLAY_PassList;
+
+//#define GTAO
+
+/* Functions */
+
+static void add_icon_to_rect(PreviewImage *prv, float *final_rect, int layer)
+{
+       int image_size = prv->w[0] * prv->h[0];
+       float *new_rect = &final_rect[image_size * 4 * layer];
+
+       IMB_buffer_float_from_byte(new_rect, (unsigned char *)prv->rect[0], IB_PROFILE_SRGB, IB_PROFILE_SRGB,
+                                  false, prv->w[0], prv->h[0], prv->w[0], prv->w[0]);
+
+       /* Find overall color */
+       for (int y = 0; y < 4; ++y)     {
+               for (int x = 0; x < 4; ++x) {
+                       data.matcap_colors[layer][0] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 0];
+                       data.matcap_colors[layer][1] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 1];
+                       data.matcap_colors[layer][2] += new_rect[y * 512 * 128 * 4 + x * 128 * 4 + 2];
+               }
+       }
+
+       data.matcap_colors[layer][0] /= 16.0f * 2.0f; /* the * 2 is to darken for shadows */
+       data.matcap_colors[layer][1] /= 16.0f * 2.0f;
+       data.matcap_colors[layer][2] /= 16.0f * 2.0f;
+}
+
+static struct GPUTexture *load_matcaps(PreviewImage *prv[24], int nbr)
+{
+       struct GPUTexture *tex;
+       int w = prv[0]->w[0];
+       int h = prv[0]->h[0];
+       float *final_rect = MEM_callocN(sizeof(float) * 4 * w * h * nbr, "Clay Matcap array rect");
+
+       for (int i = 0; i < nbr; ++i) {
+               add_icon_to_rect(prv[i], final_rect, i);
+               BKE_previewimg_free(&prv[i]);
+       }
+
+       tex = DRW_texture_create_2D_array(w, h, nbr, DRW_TEX_RGBA_8, DRW_TEX_FILTER, final_rect);
+       MEM_freeN(final_rect);
+
+       return tex;
+}
+
+static int matcap_to_index(int matcap)
+{
+       if (matcap == ICON_MATCAP_02) return 1;
+       else if (matcap == ICON_MATCAP_03) return 2;
+       else if (matcap == ICON_MATCAP_04) return 3;
+       else if (matcap == ICON_MATCAP_05) return 4;
+       else if (matcap == ICON_MATCAP_06) return 5;
+       else if (matcap == ICON_MATCAP_07) return 6;
+       else if (matcap == ICON_MATCAP_08) return 7;
+       else if (matcap == ICON_MATCAP_09) return 8;
+       else if (matcap == ICON_MATCAP_10) return 9;
+       else if (matcap == ICON_MATCAP_11) return 10;
+       else if (matcap == ICON_MATCAP_12) return 11;
+       else if (matcap == ICON_MATCAP_13) return 12;
+       else if (matcap == ICON_MATCAP_14) return 13;
+       else if (matcap == ICON_MATCAP_15) return 14;
+       else if (matcap == ICON_MATCAP_16) return 15;
+       else if (matcap == ICON_MATCAP_17) return 16;
+       else if (matcap == ICON_MATCAP_18) return 17;
+       else if (matcap == ICON_MATCAP_19) return 18;
+       else if (matcap == ICON_MATCAP_20) return 19;
+       else if (matcap == ICON_MATCAP_21) return 20;
+       else if (matcap == ICON_MATCAP_22) return 21;
+       else if (matcap == ICON_MATCAP_23) return 22;
+       else if (matcap == ICON_MATCAP_24) return 23;
+       return 0;
+}
+
+static struct GPUTexture *create_spiral_sample_texture(int numsaples)
+{
+       struct GPUTexture *tex;
+       float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
+       const float numsaples_inv = 1.0f / numsaples;
+       int i;
+       /* arbitrary number to ensure we don't get conciding samples every circle */
+       const float spirals = 7.357;
+
+       for (i = 0; i < numsaples; i++) {
+               float r = (i + 0.5f) * numsaples_inv;
+               float phi = r * spirals * (float)(2.0 * M_PI);
+               texels[i][0] = r * cosf(phi);
+               texels[i][1] = r * sinf(phi);
+       }
+
+       tex = DRW_texture_create_1D(numsaples, DRW_TEX_RG_16, 0, (float *)texels);
+
+       MEM_freeN(texels);
+       return tex;
+}
+
+static struct GPUTexture *create_jitter_texture(void)
+{
+       float jitter[64 * 64][2];
+       int i;
+
+       /* TODO replace by something more evenly distributed like blue noise */
+       for (i = 0; i < 64 * 64; i++) {
+#ifdef GTAO
+               jitter[i][0] = BLI_frand();
+               jitter[i][1] = BLI_frand();
+#else
+               jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
+               jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
+               normalize_v2(jitter[i]);
+#endif
+       }
+
+       return DRW_texture_create_2D(64, 64, DRW_TEX_RG_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
+}
+
+static void clay_material_settings_init(MaterialEngineSettingsClay *ma)
+{
+       ma->matcap_icon = ICON_MATCAP_01;
+       ma->matcap_rot = 0.0f;
+       ma->matcap_hue = 0.5f;
+       ma->matcap_sat = 0.5f;
+       ma->matcap_val = 0.5f;
+       ma->ssao_distance = 0.2;
+       ma->ssao_attenuation = 1.0f;
+       ma->ssao_factor_cavity = 1.0f;
+       ma->ssao_factor_edge = 1.0f;
+}
+
+RenderEngineSettings *CLAY_render_settings_create(void)
+{
+       RenderEngineSettingsClay *settings = MEM_callocN(sizeof(RenderEngineSettingsClay), "RenderEngineSettingsClay");
+
+       clay_material_settings_init((MaterialEngineSettingsClay *)settings);
+
+       settings->ssao_samples = 32;
+
+       return (RenderEngineSettings *)settings;
+}
+
+MaterialEngineSettings *CLAY_material_settings_create(void)
+{
+       MaterialEngineSettingsClay *settings = MEM_callocN(sizeof(MaterialEngineSettingsClay), "MaterialEngineSettingsClay");
+
+       clay_material_settings_init(settings);
+
+       return (MaterialEngineSettings *)settings;
+}
+
+static void CLAY_engine_init(const bContext *C)
+{
+       Main *bmain = CTX_data_main(C);
+
+       /* Create Texture Array */
+       if (!data.matcap_array) {
+               PreviewImage *prv[24]; /* For now use all of the 24 internal matcaps */
+
+               /* TODO only load used matcaps */
+               prv[0]  = UI_icon_to_preview(ICON_MATCAP_01);
+               prv[1]  = UI_icon_to_preview(ICON_MATCAP_02);
+               prv[2]  = UI_icon_to_preview(ICON_MATCAP_03);
+               prv[3]  = UI_icon_to_preview(ICON_MATCAP_04);
+               prv[4]  = UI_icon_to_preview(ICON_MATCAP_05);
+               prv[5]  = UI_icon_to_preview(ICON_MATCAP_06);
+               prv[6]  = UI_icon_to_preview(ICON_MATCAP_07);
+               prv[7]  = UI_icon_to_preview(ICON_MATCAP_08);
+               prv[8]  = UI_icon_to_preview(ICON_MATCAP_09);
+               prv[9]  = UI_icon_to_preview(ICON_MATCAP_10);
+               prv[10] = UI_icon_to_preview(ICON_MATCAP_11);
+               prv[11] = UI_icon_to_preview(ICON_MATCAP_12);
+               prv[12] = UI_icon_to_preview(ICON_MATCAP_13);
+               prv[13] = UI_icon_to_preview(ICON_MATCAP_14);
+               prv[14] = UI_icon_to_preview(ICON_MATCAP_15);
+               prv[15] = UI_icon_to_preview(ICON_MATCAP_16);
+               prv[16] = UI_icon_to_preview(ICON_MATCAP_17);
+               prv[17] = UI_icon_to_preview(ICON_MATCAP_18);
+               prv[18] = UI_icon_to_preview(ICON_MATCAP_19);
+               prv[19] = UI_icon_to_preview(ICON_MATCAP_20);
+               prv[20] = UI_icon_to_preview(ICON_MATCAP_21);
+               prv[21] = UI_icon_to_preview(ICON_MATCAP_22);
+               prv[22] = UI_icon_to_preview(ICON_MATCAP_23);
+               prv[23] = UI_icon_to_preview(ICON_MATCAP_24);
+
+               data.matcap_array = load_matcaps(prv, 24);
+       }
+
+       /* AO Jitter */
+       if (!data.jitter_tx) {
+               data.jitter_tx = create_jitter_texture();
+       }
+
+       /* AO Samples */
+       /* TODO use hammersley sequence */
+       if (!data.sampling_tx) {
+               data.sampling_tx = create_spiral_sample_texture(500);
+       }
+
+       /* Depth prepass */
+       if (!data.depth_sh) {
+               data.depth_sh = DRW_shader_create_3D_depth_only();
+       }
+
+       if (!data.mat_ubo) {
+               data.mat_ubo = DRW_uniformbuffer_create(sizeof(CLAY_UBO_Storage), NULL);
+       }
+
+       /* Shading pass */
+       if (!data.clay_sh) {
+               DynStr *ds = BLI_dynstr_new();
+               const char *max_mat =
+                       "#define MAX_MATERIAL 512\n"
+                       "#define USE_ROTATION\n"
+                       "#define USE_AO\n"
+                       "#define USE_HSV\n";
+               char *matcap_with_ao;
+
+               BLI_dynstr_append(ds, datatoc_clay_frag_glsl);
+#ifdef GTAO
+               BLI_dynstr_append(ds, datatoc_ssao_groundtruth_glsl);
+#else
+               BLI_dynstr_append(ds, datatoc_ssao_alchemy_glsl);
+#endif
+
+               matcap_with_ao = BLI_dynstr_get_cstring(ds);
+
+               data.clay_sh = DRW_shader_create(datatoc_clay_vert_glsl, NULL, matcap_with_ao, max_mat);
+
+               BLI_dynstr_free(ds);
+               MEM_freeN(matcap_with_ao);
+       }
+
+       /* Cleanup all runtime data loaded from file */
+       for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+               /* Using render settings as material settings */
+               MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
+               res->flag = CLAY_OUTDATED;
+               res->ubo_index = -1;
+
+               /* Update Collections Materials */
+               for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+                       for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                               CollectionEngineSettings *ces;
+                               ces = BKE_layer_collection_engine_get(lc, RE_engine_id_BLENDER_CLAY);
+                               if (ces) { /* May not exists */
+                                       BKE_collection_engine_property_value_set_int(ces, "flag", CLAY_OUTDATED);
+                                       BKE_collection_engine_property_value_set_int(ces, "ubo_index", -1);
+                               }
+                       }
+               }
+       }
+
+       data.ubo_flag |= CLAY_UBO_REFRESH;
+}
+
+static void CLAY_ssao_setup(void)
+{
+       float invproj[4][4];
+       float dfdyfacs[2];
+       bool is_persp = DRW_viewport_is_persp_get();
+       /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+       float viewvecs[3][4] = {
+           {-1.0f, -1.0f, -1.0f, 1.0f},
+           {1.0f, -1.0f, -1.0f, 1.0f},
+           {-1.0f, 1.0f, -1.0f, 1.0f}
+       };
+       int i;
+       float *size = DRW_viewport_size_get();
+       RenderEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
+
+       DRW_get_dfdy_factors(dfdyfacs);
+
+       data.ssao_params[0] = settings->ssao_samples;
+       data.ssao_params[1] = size[0] / 64.0;
+       data.ssao_params[2] = size[1] / 64.0;
+       data.ssao_params[3] = dfdyfacs[1]; /* dfdy sign for offscreen */
+
+       /* invert the view matrix */
+       DRW_viewport_matrix_get(data.winmat, DRW_MAT_WIN);
+       invert_m4_m4(invproj, data.winmat);
+
+       /* convert the view vectors to view space */
+       for (i = 0; i < 3; i++) {
+               mul_m4_v4(invproj, viewvecs[i]);
+               /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+               mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+               if (is_persp)
+                       mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+               viewvecs[i][3] = 1.0;
+
+               copy_v4_v4(data.viewvecs[i], viewvecs[i]);
+       }
+
+       /* we need to store the differences */
+       data.viewvecs[1][0] -= data.viewvecs[0][0];
+       data.viewvecs[1][1] = data.viewvecs[2][1] - data.viewvecs[0][1];
+
+       /* calculate a depth offset as well */
+       if (!is_persp) {
+               float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+               mul_m4_v4(invproj, vec_far);
+               mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+               data.viewvecs[1][2] = vec_far[2] - data.viewvecs[0][2];
+       }
+}
+
+static DRWShadingGroup *CLAY_shgroup_create(DRWPass *pass, int *UNUSED(material_id))
+{
+       const int depthloc = 0, matcaploc = 1, jitterloc = 2, sampleloc = 3;
+
+       //CLAY_UBO_Material *mat = &data.mat_storage.materials[0];
+       DRWShadingGroup *grp = DRW_shgroup_create(data.clay_sh, pass);
+
+       DRW_shgroup_uniform_vec2(grp, "screenres", DRW_viewport_size_get(), 1);
+       DRW_shgroup_uniform_buffer(grp, "depthtex", SCENE_DEPTH, depthloc);
+       DRW_shgroup_uniform_texture(grp, "matcaps", data.matcap_array, matcaploc);
+       DRW_shgroup_uniform_mat4(grp, "WinMatrix", (float *)data.winmat);
+       DRW_shgroup_uniform_vec4(grp, "viewvecs", (float *)data.viewvecs, 3);
+       DRW_shgroup_uniform_vec4(grp, "ssao_params", data.ssao_params, 1);
+       DRW_shgroup_uniform_vec3(grp, "matcaps_color", (float *)data.matcap_colors, 24);
+
+       //DRW_shgroup_uniform_int(grp, "material_id", material_id, 1);
+
+#ifndef GTAO
+       DRW_shgroup_uniform_texture(grp, "ssao_jitter", data.jitter_tx, jitterloc);
+       DRW_shgroup_uniform_texture(grp, "ssao_samples", data.sampling_tx, sampleloc);
+#endif
+
+       return grp;
+}
+
+static void update_ubo_storage(float matcap_rot, float matcap_hue, float matcap_sat, float matcap_val,
+                               float ssao_distance, float ssao_factor_cavity, float ssao_factor_edge,
+                               float ssao_attenuation, int matcap_icon, unsigned int current_id)
+{
+       CLAY_UBO_Material *ubo = &data.mat_storage.materials[current_id];
+
+       ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f);
+       ubo->matcap_rot[1] = sinf(matcap_rot * 3.14159f * 2.0f);
+
+       ubo->matcap_hsv[0] = matcap_hue + 0.5f;
+       ubo->matcap_hsv[1] = matcap_sat * 2.0f;
+       ubo->matcap_hsv[2] = matcap_val * 2.0f;
+
+       ubo->ssao_params_var[0] = ssao_distance;
+       ubo->ssao_params_var[1] = ssao_factor_cavity;
+       ubo->ssao_params_var[2] = ssao_factor_edge;
+       ubo->ssao_params_var[3] = ssao_attenuation;
+
+
+       ubo->matcap_id = matcap_to_index(matcap_icon);
+}
+
+static void CLAY_update_material_ubo(const struct bContext *C)
+{
+       Main *bmain = CTX_data_main(C);
+
+       /* Update Default materials */
+       for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+               /* Using render settings as material settings */
+               MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
+
+               if (res->flag & CLAY_OUTDATED)
+                       data.ubo_flag |= CLAY_UBO_REFRESH;
+
+               if (res->matcap_icon < ICON_MATCAP_01 ||
+                   res->matcap_icon > ICON_MATCAP_24)
+               {
+                       res->matcap_icon = ICON_MATCAP_01;
+               }
+
+               res->flag &= ~CLAY_OUTDATED;
+
+
+               /* Update Collections Materials */
+               for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+                       for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                               CollectionEngineSettings *ces;
+                               ces = BKE_layer_collection_engine_get(lc, RE_engine_id_BLENDER_CLAY);
+
+                               BKE_collection_engine_property_value_set_int(ces, "flag", 0);
+                               BKE_collection_engine_property_value_set_int(ces, "ubo_index", 0);
+                       }
+               }
+       }
+
+       if (data.ubo_flag & CLAY_UBO_REFRESH) {
+               int current_id = 0;
+
+
+               /* Default materials */
+               for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+                       MaterialEngineSettingsClay *res = DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY);
+
+                       update_ubo_storage(res->matcap_rot, res->matcap_hue, res->matcap_sat, res->matcap_val,
+                                          res->ssao_distance, res->ssao_factor_cavity, res->ssao_factor_edge,
+                                          res->ssao_attenuation, res->matcap_icon, current_id);
+                       current_id++;
+
+                       for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+                               for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+                                       /* TODO */
+                                       current_id++;
+                               }
+                       }
+                       current_id++;
+               }
+
+
+               DRW_uniformbuffer_update(data.mat_ubo, &data.mat_storage);
+       }
+
+       data.ubo_flag = 0;
+}
+
+static void CLAY_create_cache(CLAY_PassList *passes, const struct bContext *C)
+{
+       SceneLayer *sl = CTX_data_scene_layer(C);
+       DRWShadingGroup *default_shgrp, *depthbatch;
+
+       /* Depth Pass */
+       {
+               passes->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+               depthbatch = DRW_shgroup_create(data.depth_sh, passes->depth_pass);
+       }
+
+       /* Clay Pass */
+       {
+               MaterialEngineSettingsClay *settings = DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY);
+
+               passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+
+               default_shgrp = CLAY_shgroup_create(passes->clay_pass, &settings->ubo_index);
+               DRW_shgroup_uniform_block(default_shgrp, "material_block", data.mat_ubo, 0);
+       }
+
+       /* Object Mode */
+       {
+               DRW_pass_setup_common(&passes->wire_overlay_pass,
+                                         &passes->wire_outline_pass,
+                                         &passes->non_meshes_pass,
+                                         &passes->ob_center_pass);
+       }
+
+       /* TODO Create hash table of batch based on material id*/
+       Object *ob;
+       DEG_OBJECT_ITER(sl, ob)
+       {
+               if ((ob->base_flag & BASE_VISIBLED) == 0) {
+                       continue;
+               }
+
+               struct Batch *geom;
+               //bool do_outlines;
+
+               switch (ob->type) {
+                       case OB_MESH:
+                               geom = DRW_cache_surface_get(ob);
+
+                               /* Add everything for now */
+                               DRW_shgroup_call_add(depthbatch, geom, ob->obmat);
+                               DRW_shgroup_call_add(default_shgrp, geom, ob->obmat);
+
+                               //DRW_shgroup_wire_overlay(passes->wire_overlay_pass, ob);
+
+                               //do_outlines  = ((ob->base_flag & BASE_SELECTED) != 0);
+                               //DRW_shgroup_wire_outline(passes->wire_outline_pass, ob, false, false, do_outlines);
+
+                               /* When encountering a new material :
+                                * - Create new Batch
+                                * - Initialize Batch
+                                * - Push it to the hash table
+                                * - The pass takes care of inserting it
+                                * next to the same shader calls */
+
+                               /* Free hash table */
+                               break;
+                       case OB_LAMP:
+                       case OB_CAMERA:
+                       case OB_EMPTY:
+                       default:
+                               DRW_shgroup_non_meshes(passes->non_meshes_pass, ob);
+                               break;
+               }
+
+               DRW_shgroup_object_center(passes->ob_center_pass, ob);
+               DRW_shgroup_relationship_lines(passes->non_meshes_pass, ob);
+       }
+       DEG_OBJECT_ITER_END
+}
+
+static void CLAY_view_draw(RenderEngine *UNUSED(engine), const bContext *context)
+{
+       /* This function may run for multiple viewports
+        * so get the current viewport buffers */
+       CLAY_FramebufferList *buffers = NULL;
+       CLAY_TextureList *textures = NULL;
+       CLAY_PassList *passes = NULL;
+
+       DRW_viewport_init(context, (void **)&buffers, (void **)&textures, (void **)&passes);
+
+       CLAY_engine_init(context);
+
+       CLAY_update_material_ubo(context);
+
+       /* TODO : tag to refresh by the deps graph */
+       /* ideally only refresh when objects are added/removed */
+       /* or render properties / materials change */
+#ifdef WITH_VIEWPORT_CACHE_TEST
+       static bool once = false;
+#endif
+       if (DRW_viewport_cache_is_dirty()
+#ifdef WITH_VIEWPORT_CACHE_TEST
+               && !once
+#endif
+               ) {
+#ifdef WITH_VIEWPORT_CACHE_TEST
+               once = true;
+#endif
+               CLAY_create_cache(passes, context);
+       }
+
+       /* Start Drawing */
+       DRW_draw_background();
+
+       /* Pass 1 : Depth pre-pass */
+       DRW_draw_pass(passes->depth_pass);
+
+       /* Pass 2 (Optionnal) : Separated Downsampled AO */
+       DRW_framebuffer_texture_detach(textures->depth);
+       /* TODO */
+
+       /* Pass 3 : Shading */
+       CLAY_ssao_setup();
+       DRW_draw_pass(passes->clay_pass);
+
+       /* Pass 4 : Overlays */
+       DRW_framebuffer_texture_attach(buffers->default_fb, textures->depth, 0);
+       //DRW_draw_pass(passes->wire_overlay_pass);
+       //DRW_draw_pass(passes->wire_outline_pass);
+       DRW_draw_pass(passes->non_meshes_pass);
+       DRW_draw_pass(passes->ob_center_pass);
+
+       /* Always finish by this */
+       DRW_state_reset();
+}
+
+static void CLAY_collection_settings_create(RenderEngine *UNUSED(engine), CollectionEngineSettings *ces)
+{
+       BLI_assert(ces);
+       BKE_collection_engine_property_add_int(ces, "matcap_icon", ICON_MATCAP_01);
+       BKE_collection_engine_property_add_int(ces, "type", CLAY_MATCAP_NONE);
+       BKE_collection_engine_property_add_float(ces, "matcap_rotation", 0.0f);
+       BKE_collection_engine_property_add_float(ces, "matcap_hue", 0.5f);
+       BKE_collection_engine_property_add_float(ces, "matcap_saturation", 0.5f);
+       BKE_collection_engine_property_add_float(ces, "matcap_value", 0.5f);
+       BKE_collection_engine_property_add_float(ces, "ssao_distance", 0.2f);
+       BKE_collection_engine_property_add_float(ces, "ssao_attenuation", 1.0f);
+       BKE_collection_engine_property_add_float(ces, "ssao_factor_cavity", 1.0f);
+       BKE_collection_engine_property_add_float(ces, "ssao_factor_edge", 1.0f);
+
+       /* Runtime data (not display in settings) */
+       BKE_collection_engine_property_add_int(ces, "ubo_index", -1);
+       BKE_collection_engine_property_add_int(ces, "flag", CLAY_OUTDATED);
+}
+
+void clay_engine_free(void)
+{
+       /* data.depth_sh Is builtin so it's automaticaly freed */
+       if (data.clay_sh) {
+               DRW_shader_free(data.clay_sh);
+       }
+
+       if (data.matcap_array) {
+               DRW_texture_free(data.matcap_array);
+       }
+
+       if (data.jitter_tx) {
+               DRW_texture_free(data.jitter_tx);
+       }
+
+       if (data.sampling_tx) {
+               DRW_texture_free(data.sampling_tx);
+       }
+
+       if (data.mat_ubo) {
+               DRW_uniformbuffer_free(data.mat_ubo);
+       }
+}
+
+RenderEngineType viewport_clay_type = {
+       NULL, NULL,
+       "BLENDER_CLAY", N_("Clay"), RE_INTERNAL | RE_USE_OGL_PIPELINE,
+       NULL, NULL, NULL, NULL, &CLAY_view_draw, NULL, &CLAY_collection_settings_create,
+       {NULL, NULL, NULL}
+};
+#endif
\ No newline at end of file
similarity index 71%
rename from source/blender/draw/DRW_defines.h
rename to source/blender/draw/engines/clay/clay.h
index 212c39e203b5cc9f7fe34900f85bcfb9957dcfe5..404924be2a1e3030d36f4fe3016c0ee3a3d4a4da 100644 (file)
  *
  */
 
-#ifndef __DRW_DEFINES_H__
-#define __DRW_DEFINES_H__
+/** \file clay.h
+ *  \ingroup DNA
+ */
+
+#ifndef __ENGINE_CLAY_H__
+#define __ENGINE_CLAY_H__
+
+extern RenderEngineType viewport_clay_type;
+
+struct RenderEngineSettings *CLAY_render_settings_create(void);
+struct MaterialEngineSettings *CLAY_material_settings_create(void);
+
+void clay_engine_free(void);
 
-#endif  /* __DRW_DEFINES_H__ */
+#endif /* __ENGINE_CLAY_H__ */
\ No newline at end of file
diff --git a/source/blender/draw/engines/clay/shaders/clay_frag.glsl b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
new file mode 100644 (file)
index 0000000..d9b372b
--- /dev/null
@@ -0,0 +1,207 @@
+uniform vec2 screenres;
+uniform sampler2D depthtex;
+uniform mat4 WinMatrix;
+
+/* Matcap */
+uniform sampler2DArray matcaps;
+uniform vec3 matcaps_color[24];
+
+/* Screen Space Occlusion */
+/* store the view space vectors for the corners of the view frustum here.
+ * It helps to quickly reconstruct view space vectors by using uv coordinates,
+ * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+uniform vec4 viewvecs[3];
+uniform vec4 ssao_params;
+
+uniform sampler2D ssao_jitter;
+uniform sampler1D ssao_samples;
+
+/* Material Parameters packed in an UBO */
+struct Material {
+       vec4 ssao_params_var;
+       vec4 matcap_hsv_id;
+       vec4 matcap_rot; /* vec4 to ensure 16 bytes alignement (don't trust compiler) */
+};
+
+layout(std140) uniform material_block {
+       Material matcaps_param[MAX_MATERIAL];
+};
+
+int mat_id;
+
+/* Aliases */
+#define ssao_samples_num       ssao_params.x
+#define jitter_tilling         ssao_params.yz
+#define dfdy_sign                      ssao_params.w
+
+#define matcap_hsv                     matcaps_param[mat_id].matcap_hsv_id.xyz
+#define matcap_index           matcaps_param[mat_id].matcap_hsv_id.w
+#define matcap_rotation                matcaps_param[mat_id].matcap_rot.xy
+
+in vec3 normal;
+out vec4 fragColor;
+
+/* TODO Move this to SSAO modules */
+/* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer
+ * we change the factors from the article to fit the OpennGL model.  */
+vec3 get_view_space_from_depth(in vec2 uvcoords, in float depth)
+{
+       if (WinMatrix[3][3] == 0.0) {
+               /* Perspective */
+               float d = 2.0 * depth - 1.0;
+
+               float zview = -WinMatrix[3][2] / (d + WinMatrix[2][2]);
+
+               return zview * (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz);
+       }
+       else {
+               /* Orthographic */
+               vec3 offset = vec3(uvcoords, depth);
+
+               return viewvecs[0].xyz + offset * viewvecs[1].xyz;
+       }
+}
+
+/* TODO remove this when switching to geometric normals */
+vec3 calculate_view_space_normal(in vec3 viewposition)
+{
+       vec3 normal = cross(normalize(dFdx(viewposition)), dfdy_sign * normalize(dFdy(viewposition)));
+       return normalize(normal);
+}
+
+#ifdef USE_HSV
+void rgb_to_hsv(vec3 rgb, out vec3 outcol)
+{
+       float cmax, cmin, h, s, v, cdelta;
+       vec3 c;
+
+       cmax = max(rgb[0], max(rgb[1], rgb[2]));
+       cmin = min(rgb[0], min(rgb[1], rgb[2]));
+       cdelta = cmax - cmin;
+
+       v = cmax;
+       if (cmax != 0.0)
+               s = cdelta / cmax;
+       else {
+               s = 0.0;
+               h = 0.0;
+       }
+
+       if (s == 0.0) {
+               h = 0.0;
+       }
+       else {
+               c = (vec3(cmax, cmax, cmax) - rgb.xyz) / cdelta;
+
+               if (rgb.x == cmax) h = c[2] - c[1];
+               else if (rgb.y == cmax) h = 2.0 + c[0] -  c[2];
+               else h = 4.0 + c[1] - c[0];
+
+               h /= 6.0;
+
+               if (h < 0.0)
+                       h += 1.0;
+       }
+
+       outcol = vec3(h, s, v);
+}
+
+void hsv_to_rgb(vec3 hsv, out vec3 outcol)
+{
+       float i, f, p, q, t, h, s, v;
+       vec3 rgb;
+
+       h = hsv[0];
+       s = hsv[1];
+       v = hsv[2];
+
+       if (s == 0.0) {
+               rgb = vec3(v, v, v);
+       }
+       else {
+               if (h == 1.0)
+                       h = 0.0;
+
+               h *= 6.0;
+               i = floor(h);
+               f = h - i;
+               rgb = vec3(f, f, f);
+               p = v * (1.0 - s);
+               q = v * (1.0 - (s * f));
+               t = v * (1.0 - (s * (1.0 - f)));
+
+               if (i == 0.0) rgb = vec3(v, t, p);
+               else if (i == 1.0) rgb = vec3(q, v, p);
+               else if (i == 2.0) rgb = vec3(p, v, t);
+               else if (i == 3.0) rgb = vec3(p, q, v);
+               else if (i == 4.0) rgb = vec3(t, p, v);
+               else rgb = vec3(v, p, q);
+       }
+
+       outcol = rgb;
+}
+
+void hue_sat(float hue, float sat, float value, inout vec3 col)
+{
+       vec3 hsv;
+
+       rgb_to_hsv(col, hsv);
+
+       hsv.x += hue;
+       hsv.x -= floor(hsv.x);
+       hsv.y *= sat;
+       hsv.y = clamp(hsv.y, 0.0, 1.0);
+       hsv.z *= value;
+       hsv.z = clamp(hsv.z, 0.0, 1.0);
+
+       hsv_to_rgb(hsv, col);
+}
+#endif
+
+#ifdef USE_AO
+/* Prototype */
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges);
+#endif
+
+void main() {
+       vec2 screenco = vec2(gl_FragCoord.xy) / screenres;
+       float depth = texture(depthtex, screenco).r;
+
+       vec3 position = get_view_space_from_depth(screenco, depth);
+       vec3 normal = calculate_view_space_normal(position);
+
+       //mat_id = int(screenco.x*3.0);
+
+       /* Manual Depth test */
+       /* Doing this test earlier gives problem with dfdx calculations
+        * TODO move this before when we have proper geometric normals */
+       if (gl_FragCoord.z > depth + 1e-5)
+               discard;
+
+#ifdef USE_ROTATION
+       /* Rotate texture coordinates */
+       vec2 rotY = vec2(-matcap_rotation.y, matcap_rotation.x);
+       vec2 texco = abs(vec2(dot(normal.xy, matcap_rotation), dot(normal.xy, rotY)) * .49 + 0.5);
+#else
+       vec2 texco = abs(normal.xy * .49 + 0.5);
+#endif
+       vec3 col = texture(matcaps, vec3(texco, matcap_index)).rgb;
+
+#ifdef USE_AO
+       float cavity, edges;
+       ssao_factors(depth, normal, position, screenco, cavity, edges);
+
+       col *= mix(vec3(1.0), matcaps_color[int(matcap_index)], cavity);
+#endif
+
+#ifdef USE_HSV
+       hue_sat(matcap_hsv.x, matcap_hsv.y, matcap_hsv.z, col);
+#endif
+
+#ifdef USE_AO
+       /* Apply highlights after hue shift */
+       col *= edges + 1.0;
+#endif
+
+       fragColor = vec4(col, 1.0);
+}
diff --git a/source/blender/draw/engines/clay/shaders/clay_vert.glsl b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
new file mode 100644 (file)
index 0000000..0b598ea
--- /dev/null
@@ -0,0 +1,20 @@
+uniform mat4 ModelViewProjectionMatrix;
+uniform mat3 NormalMatrix;
+
+#if __VERSION__ == 120
+attribute vec3 pos;
+attribute vec3 nor;
+varying vec3 normal;
+#else
+in vec3 pos;
+in vec3 nor;
+out vec3 normal;
+#endif
+
+
+void main()
+{
+       normal = normalize(NormalMatrix * nor);
+       gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
+}
+
diff --git a/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
new file mode 100644 (file)
index 0000000..d032fb9
--- /dev/null
@@ -0,0 +1,73 @@
+#define ssao_distance          matcaps_param[mat_id].ssao_params_var.x
+#define ssao_factor_cavity     matcaps_param[mat_id].ssao_params_var.y
+#define ssao_factor_edge       matcaps_param[mat_id].ssao_params_var.z
+#define ssao_attenuation       matcaps_param[mat_id].ssao_params_var.w
+
+/*  from The Alchemy screen-space ambient obscurance algorithm
+ * http://graphics.cs.williams.edu/papers/AlchemyHPG11/VV11AlchemyAO.pdf */
+
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
+{
+       /* take the normalized ray direction here */
+       vec2 rotX = texture2D(ssao_jitter, screenco.xy * jitter_tilling).rg;
+       vec2 rotY = vec2(-rotX.y, rotX.x);
+
+       /* find the offset in screen space by multiplying a point
+        * in camera space at the depth of the point by the projection matrix. */
+       vec2 offset;
+       float homcoord = WinMatrix[2][3] * position.z + WinMatrix[3][3];
+       offset.x = WinMatrix[0][0] * ssao_distance / homcoord;
+       offset.y = WinMatrix[1][1] * ssao_distance / homcoord;
+       /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
+       offset *= 0.5;
+
+       cavities = edges = 0.0;
+       int x;
+       int num_samples = int(ssao_samples_num);
+
+       for (x = 0; x < num_samples; x++) {
+               /* TODO : optimisation replace by constant */
+               vec2 dir_sample = texture1D(ssao_samples, (float(x) + 0.5) / ssao_samples_num).rg;
+
+               /* rotate with random direction to get jittered result */
+               vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
+
+               vec2 uvcoords = screenco.xy + dir_jittered * offset;
+
+               if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
+                       continue;
+
+               float depth_new = texture2D(depthtex, uvcoords).r;
+
+               /* Handle Background case */
+               bool is_background = (depth_new == 1.0);
+
+               /* This trick provide good edge effect even if no neighboor is found. */
+               vec3 pos_new = get_view_space_from_depth(uvcoords, (is_background) ? depth : depth_new);
+
+               if (is_background)
+                       pos_new.z -= ssao_distance;
+
+               vec3 dir = pos_new - position;
+               float len = length(dir);
+               float f_cavities = dot(dir, normal);
+               float f_edge = -f_cavities;
+               float f_bias = 0.05 * len + 0.0001;
+
+               float attenuation = 1.0 / (len * (1.0 + len * len * ssao_attenuation));
+
+               /* use minor bias here to avoid self shadowing */
+               if (f_cavities > -f_bias)
+                       cavities += f_cavities * attenuation;
+
+               if (f_edge > f_bias)
+                       edges += f_edge * attenuation;
+       }
+
+       cavities /= ssao_samples_num;
+       edges /= ssao_samples_num;
+
+       /* don't let cavity wash out the surface appearance */
+       cavities = clamp(cavities * ssao_factor_cavity, 0.0, 1.0);
+       edges = edges * ssao_factor_edge;
+}
diff --git a/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl
new file mode 100644 (file)
index 0000000..2f29624
--- /dev/null
@@ -0,0 +1,120 @@
+#define ssao_distance          matcaps_param[mat_id].ssao_params_var.x
+#define ssao_factor_cavity     matcaps_param[mat_id].ssao_params_var.y
+#define ssao_factor_edge       matcaps_param[mat_id].ssao_params_var.z
+#define ssao_attenuation       matcaps_param[mat_id].ssao_params_var.w
+
+/* Based on Practical Realtime Strategies for Accurate Indirect Occlusion
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pdf
+ * http://blog.selfshadow.com/publications/s2016-shading-course/activision/s2016_pbs_activision_occlusion.pptx */
+
+#define COSINE_WEIGHTING
+
+float integrate_arc(in float h1, in float h2, in float gamma, in float n_proj_len)
+{
+       float a = 0.0;
+#ifdef COSINE_WEIGHTING
+       float cos_gamma = cos(gamma);
+       float sin_gamma_2 = 2.0 * sin(gamma);
+       a += -cos(2.0 * h1 - gamma) + cos_gamma + h1 * sin_gamma_2;
+       a += -cos(2.0 * h2 - gamma) + cos_gamma + h2 * sin_gamma_2;
+       a *= 0.25; /* 1/4 */
+       a *= n_proj_len;
+#else
+       /* Uniform weighting (slide 59) */
+       a += 1 - cos(h1);
+       a += 1 - cos(h2);
+#endif
+       return a;
+}
+
+float get_max_horizon(in vec2 co, in vec3 x, in vec3 omega_o, in float h)
+{
+       if (co.x > 1.0 || co.x < 0.0 || co.y > 1.0 || co.y < 0.0)
+               return h;
+
+       float depth = texture2D(depthtex, co).r;
+
+       /* Background case */
+       if (depth == 1.0)
+               return h;
+
+       vec3 s = get_view_space_from_depth(co, depth); /* s View coordinate */
+       vec3 omega_s = s - x;
+       float len = length(omega_s);
+
+       if (len < ssao_distance) {
+               omega_s /= len;
+               h = max(h, dot(omega_s, omega_o));
+       }
+       return h;
+}
+
+void ssao_factors(in float depth, in vec3 normal, in vec3 position, in vec2 screenco, out float cavities, out float edges)
+{
+       /* Renaming */
+       vec3 omega_o = -normalize(position); /* viewvec */
+       vec2 x_ = screenco; /* x^ Screen coordinate */
+       vec3 x = position; /* x view space coordinate */
+
+#ifdef SPATIAL_DENOISE
+       float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+       float noise_offset = (1.0 / 4.0) * float(int(gl_FragCoord.y - gl_FragCoord.x) & 0x3);
+#else
+       float noise_dir = (1.0 / 16.0) * float(((int(gl_FragCoord.x + gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+       float noise_offset = (0.5 / 16.0) + (1.0 / 16.0) * float(((int(gl_FragCoord.x - gl_FragCoord.y) & 0x3) << 2) + (int(gl_FragCoord.x) & 0x3));
+#endif
+
+       const float phi_step = 16.0;
+       const float theta_step = 16.0;
+       const float m_pi = 3.14159265358979323846;
+       vec2 pixel_ratio = vec2(screenres.y / screenres.x, 1.0);
+       vec2 pixel_size = vec2(1.0) / screenres.xy;
+       float min_stride = length(pixel_size);
+       float homcco = WinMatrix[2][3] * position.z + WinMatrix[3][3];
+       float n = max(min_stride * theta_step, ssao_distance / homcco); /* Search distance */
+
+       /* Integral over PI */
+       float A = 0.0;
+       for (float i = 0.0; i < phi_step; i++) {
+               float phi = m_pi * ((noise_dir + i) / phi_step);
+
+               vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */
+
+               /* Search maximum horizon angles Theta1 and Theta2 */
+               float theta1 = -1.0, theta2 = -1.0; /* init at cos(pi) */
+               for (float j = 0.0; j < theta_step; j++) {
+                       vec2 s_ = t_phi * pixel_ratio * n * ((j + noise_offset)/ theta_step); /* s^ Screen coordinate */
+                       vec2 co;
+
+                       co = x_ + s_;
+                       theta1 = get_max_horizon(co, x, omega_o, theta1);
+
+                       co = x_ - s_;
+                       theta2 = get_max_horizon(co, x, omega_o, theta2);
+               }
+
+               /* (Slide 54) */
+               theta1 = -acos(theta1);
+               theta2 = acos(theta2);
+
+               /* Projecting Normal to Plane P defined by t_phi and omega_o */
+               vec3 h = normalize(cross(vec3(t_phi, 0.0), omega_o)); /* Normal vector to Integration plane */
+               vec3 t = cross(h, omega_o); /* Normal vector to plane */
+               vec3 n_proj = normal - h * dot(normal, h);
+               float n_proj_len = length(n_proj);
+               vec3 n_proj_norm = normalize(n_proj);
+
+               /* Clamping thetas (slide 58) */
+               float gamma = sign(dot(n_proj_norm, t)) * acos(dot(normal, omega_o)); /* Angle between view vec and normal */
+               theta1 = gamma + max(theta1 - gamma, -m_pi * 0.5);
+               theta2 = gamma + min(theta2 - gamma, m_pi * 0.5);
+
+               /* Solving inner integral */
+               A += integrate_arc(theta1, theta2, gamma, n_proj_len);
+       }
+
+       A /= phi_step;
+
+       cavities = 1.0 - A;
+       edges = 0.0;
+}
\ No newline at end of file
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
new file mode 100644 (file)
index 0000000..90412e6
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file DRW_render.h
+ *  \ingroup draw
+ */
+
+/* This is the Render Functions used by Realtime engines to draw with OpenGL */
+
+#ifndef __DRW_RENDER_H__
+#define __DRW_RENDER_H__
+
+#include "BKE_context.h"
+#include "BKE_layer.h"
+#include "BKE_scene.h"
+
+#include "BLI_listbase.h"
+#include "BLI_math_matrix.h"
+#include "BLI_math_vector.h"
+#include "BLI_string.h"
+
+#include "BLT_translation.h"
+
+#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_material_types.h"
+#include "DNA_scene_types.h"
+
+#include "draw_mode_pass.h"
+#include "draw_cache.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RE_engine.h"
+
+//#define WITH_VIEWPORT_CACHE_TEST
+
+struct GPUFrameBuffer;
+struct GPUShader;
+struct GPUTexture;
+struct GPUUniformBuffer;
+struct Object;
+struct Batch;
+
+typedef struct DRWUniform DRWUniform;
+typedef struct DRWInterface DRWInterface;
+typedef struct DRWPass DRWPass;
+typedef struct DRWShadingGroup DRWShadingGroup;
+
+/* Textures */
+
+typedef enum {
+       DRW_TEX_RGBA_8,
+       DRW_TEX_RGBA_16,
+       DRW_TEX_RGBA_32,
+       DRW_TEX_RGB_8,
+       DRW_TEX_RGB_16,
+       DRW_TEX_RGB_32,
+       DRW_TEX_RG_8,
+       DRW_TEX_RG_16,
+       DRW_TEX_RG_32,
+       DRW_TEX_R_8,
+       DRW_TEX_R_16,
+       DRW_TEX_R_32,
+       DRW_TEX_DEPTH_16,
+       DRW_TEX_DEPTH_24,
+       DRW_TEX_DEPTH_32,
+} DRWTextureFormat;
+
+typedef enum {
+       DRW_TEX_FILTER = (1 << 0),
+       DRW_TEX_WRAP = (1 << 1),
+       DRW_TEX_COMPARE = (1 << 2),
+} DRWTextureFlag;
+
+struct GPUTexture *DRW_texture_create_1D(
+               int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_2D(
+               int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels);
+struct GPUTexture *DRW_texture_create_2D_array(
+               int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels);
+void DRW_texture_free(struct GPUTexture *tex);
+
+/* UBOs */
+struct GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data);
+void DRW_uniformbuffer_update(struct GPUUniformBuffer *ubo, const void *data);
+void DRW_uniformbuffer_free(struct GPUUniformBuffer *ubo);
+
+/* Buffers */
+
+/* DRWFboTexture->format */
+#define DRW_BUF_DEPTH_16               1
+#define DRW_BUF_DEPTH_24               2
+#define DRW_BUF_R_8                            3
+#define DRW_BUF_R_16                   4
+#define DRW_BUF_R_32                   5
+#define DRW_BUF_RG_8                   6
+#define DRW_BUF_RG_16                  7
+#define DRW_BUF_RG_32                  8
+#define DRW_BUF_RGB_8                  9
+#define DRW_BUF_RGB_16                 10
+#define DRW_BUF_RGB_32                 11
+#define DRW_BUF_RGBA_8                 12
+#define DRW_BUF_RGBA_16                        13
+#define DRW_BUF_RGBA_32                        14
+
+#define MAX_FBO_TEX                    5
+
+typedef struct DRWFboTexture {
+       struct GPUTexture **tex;
+       int format;
+} DRWFboTexture;
+
+void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX], int texnbr);
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb);
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
+void DRW_framebuffer_texture_detach(struct GPUTexture *tex);
+/* Shaders */
+struct GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_2D(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_3D(const char *frag, const char *defines);
+struct GPUShader *DRW_shader_create_3D_depth_only(void);
+void DRW_shader_free(struct GPUShader *shader);
+
+/* Batches */
+
+typedef enum {
+       DRW_STATE_WRITE_DEPTH = (1 << 0),
+       DRW_STATE_WRITE_COLOR = (1 << 1),
+       DRW_STATE_DEPTH_LESS  = (1 << 2),
+       DRW_STATE_DEPTH_EQUAL = (1 << 3),
+       DRW_STATE_CULL_BACK   = (1 << 4),
+       DRW_STATE_CULL_FRONT  = (1 << 5),
+       DRW_STATE_WIRE        = (1 << 6),
+       DRW_STATE_WIRE_LARGE  = (1 << 7),
+       DRW_STATE_POINT       = (1 << 8),
+       DRW_STATE_STIPPLE_2   = (1 << 9),
+       DRW_STATE_STIPPLE_3   = (1 << 10),
+       DRW_STATE_STIPPLE_4   = (1 << 11),
+       DRW_STATE_BLEND       = (1 << 12),
+} DRWState;
+
+/* Used by DRWShadingGroup.dyntype */
+#define DRW_DYN_POINTS 1
+#define DRW_DYN_LINES 2
+#define DRW_DYN_INSTANCE 3
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass);
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup);
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, struct Batch *geom, float (*obmat)[4]);
+void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state);
+void DRW_shgroup_dyntype_set(DRWShadingGroup *shgroup, int type);
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const struct GPUTexture *tex, int loc);
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const struct GPUUniformBuffer *ubo, int loc);
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc);
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize);
+void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize);
+void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize);
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value);
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value);
+
+/* Passes */
+DRWPass *DRW_pass_create(const char *name, DRWState state);
+DRWShadingGroup *DRW_pass_nth_shgroup_get(DRWPass *pass, int n);
+
+/* Viewport */
+typedef enum {
+       DRW_MAT_PERS,
+       DRW_MAT_WIEW,
+       DRW_MAT_WIN,
+} DRWViewportMatrixType;
+
+void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes);
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type);
+float *DRW_viewport_size_get(void);
+float *DRW_viewport_screenvecs_get(void);
+float *DRW_viewport_pixelsize_get(void);
+bool DRW_viewport_is_persp_get(void);
+bool DRW_viewport_cache_is_dirty(void);
+
+/* Settings */
+#ifndef __DRW_ENGINE_H__
+void *DRW_material_settings_get(Material *ma, const char *engine_name);
+void *DRW_render_settings_get(Scene *scene, const char *engine_name);
+#endif /* __DRW_ENGINE_H__ */
+
+/* Draw commands */
+void DRW_draw_background(void);
+void DRW_centercircle(const float co[3]);
+void DRW_draw_pass(DRWPass *pass);
+
+void DRW_state_reset(void);
+
+/* Other */
+void DRW_get_dfdy_factors(float dfdyfac[2]);
+
+#endif /* __DRW_RENDER_H__ */
\ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
new file mode 100644 (file)
index 0000000..1255a08
--- /dev/null
@@ -0,0 +1,543 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_cache.c
+ *  \ingroup draw
+ */
+
+
+#include "DNA_scene_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "BKE_mesh_render.h"
+
+#include "GPU_batch.h"
+
+#include "draw_cache.h"
+
+static struct DRWShapeCache{
+       Batch *drw_single_vertice;
+       Batch *drw_fullscreen_quad;
+       Batch *drw_plain_axes;
+       Batch *drw_single_arrow;
+       Batch *drw_single_arrow_line;
+       Batch *drw_cube;
+       Batch *drw_circle;
+       Batch *drw_empty_sphere;
+       Batch *drw_empty_cone;
+       Batch *drw_arrows;
+       Batch *drw_lamp;
+       Batch *drw_lamp_sunrays;
+} SHC = {NULL};
+
+void DRW_shape_cache_free(void)
+{
+       if (SHC.drw_single_vertice)
+               Batch_discard_all(SHC.drw_single_vertice);
+       if (SHC.drw_fullscreen_quad)
+               Batch_discard_all(SHC.drw_fullscreen_quad);
+       if (SHC.drw_plain_axes)
+               Batch_discard_all(SHC.drw_plain_axes);
+       if (SHC.drw_single_arrow)
+               Batch_discard_all(SHC.drw_single_arrow);
+       if (SHC.drw_single_arrow_line)
+               Batch_discard_all(SHC.drw_single_arrow_line);
+       if (SHC.drw_cube)
+               Batch_discard_all(SHC.drw_cube);
+       if (SHC.drw_circle)
+               Batch_discard_all(SHC.drw_circle);
+       if (SHC.drw_empty_sphere)
+               Batch_discard_all(SHC.drw_empty_sphere);
+       if (SHC.drw_empty_cone)
+               Batch_discard_all(SHC.drw_empty_cone);
+       if (SHC.drw_arrows)
+               Batch_discard_all(SHC.drw_arrows);
+       if (SHC.drw_lamp)
+               Batch_discard_all(SHC.drw_lamp);
+       if (SHC.drw_lamp_sunrays)
+               Batch_discard_all(SHC.drw_lamp_sunrays);
+}
+
+/* Quads */
+Batch *DRW_cache_fullscreen_quad_get(void)
+{
+       if (!SHC.drw_fullscreen_quad) {
+               float v1[2] = {-1.0f, -1.0f};
+               float v2[2] = { 1.0f, -1.0f};
+               float v3[2] = {-1.0f,  1.0f};
+               float v4[2] = { 1.0f,  1.0f};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 6);
+
+               setAttrib(vbo, pos_id, 0, v1);
+               setAttrib(vbo, pos_id, 1, v2);
+               setAttrib(vbo, pos_id, 2, v3);
+
+               setAttrib(vbo, pos_id, 3, v2);
+               setAttrib(vbo, pos_id, 4, v3);
+               setAttrib(vbo, pos_id, 5, v4);
+
+               SHC.drw_fullscreen_quad = Batch_create(GL_TRIANGLES, vbo, NULL);
+       }
+       return SHC.drw_fullscreen_quad;
+}
+
+/* Common */
+
+Batch *DRW_cache_cube_get(void)
+{
+       if (!SHC.drw_cube) {
+               const GLfloat verts[8][3] = {
+                       {-1.0f, -1.0f, -1.0f},
+                       {-1.0f, -1.0f,  1.0f},
+                       {-1.0f,  1.0f, -1.0f},
+                       {-1.0f,  1.0f,  1.0f},
+                       { 1.0f, -1.0f, -1.0f},
+                       { 1.0f, -1.0f,  1.0f},
+                       { 1.0f,  1.0f, -1.0f},
+                       { 1.0f,  1.0f,  1.0f}
+               };
+
+               const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 24);
+
+               for (int i = 0; i < 24; ++i) {
+                       setAttrib(vbo, pos_id, i, verts[indices[i]]);
+               }
+
+               SHC.drw_cube = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_cube;
+}
+
+
+Batch *DRW_cache_circle_get(void)
+{
+#define CIRCLE_RESOL 32
+       if (!SHC.drw_circle) {
+               float v[3] = {0.0f, 0.0f, 0.0f};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, CIRCLE_RESOL * 2);
+
+               for (int a = 0; a < CIRCLE_RESOL; a++) {
+                       v[0] = sinf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+                       v[1] = cosf((2.0f * M_PI * a) / ((float)CIRCLE_RESOL));
+                       v[2] = 0.0f;
+                       setAttrib(vbo, pos_id, a * 2, v);
+
+                       v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+                       v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)CIRCLE_RESOL));
+                       v[2] = 0.0f;
+                       setAttrib(vbo, pos_id, a * 2 + 1, v);
+               }
+
+               SHC.drw_circle = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_circle;
+#undef CIRCLE_RESOL
+}
+
+/* Empties */
+Batch *DRW_cache_plain_axes_get(void)
+{
+       if (!SHC.drw_plain_axes) {
+               int axis;
+               float v1[3] = {0.0f, 0.0f, 0.0f};
+               float v2[3] = {0.0f, 0.0f, 0.0f};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 6);
+
+               for (axis = 0; axis < 3; axis++) {
+                       v1[axis] = 1.0f;
+                       v2[axis] = -1.0f;
+
+                       setAttrib(vbo, pos_id, axis * 2, v1);
+                       setAttrib(vbo, pos_id, axis * 2 + 1, v2);
+
+                       /* reset v1 & v2 to zero for next axis */
+                       v1[axis] = v2[axis] = 0.0f;
+               }
+
+               SHC.drw_plain_axes = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_plain_axes;
+}
+
+Batch *DRW_cache_single_arrow_get(Batch **line)
+{
+       if (!SHC.drw_single_arrow_line || !SHC.drw_single_arrow) {
+               float v1[3] = {0.0f, 0.0f, 0.0f}, v2[3], v3[3];
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               /* Line */
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 2);
+
+               setAttrib(vbo, pos_id, 0, v1);
+               v1[2] = 1.0f;
+               setAttrib(vbo, pos_id, 1, v1);
+
+               SHC.drw_single_arrow_line = Batch_create(GL_LINES, vbo, NULL);
+
+               /* Square Pyramid */
+               vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 12);
+
+               v2[0] = 0.035f; v2[1] = 0.035f;
+               v3[0] = -0.035f; v3[1] = 0.035f;
+               v2[2] = v3[2] = 0.75f;
+
+               for (int sides = 0; sides < 4; sides++) {
+                       if (sides % 2 == 1) {
+                               v2[0] = -v2[0];
+                               v3[1] = -v3[1];
+                       }
+                       else {
+                               v2[1] = -v2[1];
+                               v3[0] = -v3[0];
+                       }
+
+                       setAttrib(vbo, pos_id, sides * 3 + 0, v1);
+                       setAttrib(vbo, pos_id, sides * 3 + 1, v2);
+                       setAttrib(vbo, pos_id, sides * 3 + 2, v3);
+               }
+
+               SHC.drw_single_arrow = Batch_create(GL_TRIANGLES, vbo, NULL);
+       }
+       *line = SHC.drw_single_arrow_line;
+       return SHC.drw_single_arrow;
+}
+
+Batch *DRW_cache_empty_sphere_get(void)
+{
+#define NSEGMENTS 16
+       if (!SHC.drw_empty_sphere) {
+               /* a single ring of vertices */
+               float p[NSEGMENTS][2];
+               for (int i = 0; i < NSEGMENTS; ++i) {
+                       float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+                       p[i][0] = cosf(angle);
+                       p[i][1] = sinf(angle);
+               }
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, NSEGMENTS * 2 * 3);
+
+               for (int axis = 0; axis < 3; ++axis) {
+                       for (int i = 0; i < NSEGMENTS; ++i) {
+                               for (int j = 0; j < 2; ++j) {
+                                       float cv[2], v[3];
+
+                                       cv[0] = p[(i+j) % NSEGMENTS][0];
+                                       cv[1] = p[(i+j) % NSEGMENTS][1];
+
+                                       if (axis == 0)
+                                               v[0] = cv[0], v[1] = cv[1], v[2] = 0.0f;
+                                       else if (axis == 1)
+                                               v[0] = cv[0], v[1] = 0.0f,  v[2] = cv[1];
+                                       else
+                                               v[0] = 0.0f,  v[1] = cv[0], v[2] = cv[1];
+
+                                       setAttrib(vbo, pos_id, i*2 + j + (NSEGMENTS * 2 * axis), v);
+                               }
+                       }
+               }
+
+               SHC.drw_empty_sphere = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_empty_sphere;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_empty_cone_get(void)
+{
+#define NSEGMENTS 8
+       if (!SHC.drw_empty_cone) {
+               /* a single ring of vertices */
+               float p[NSEGMENTS][2];
+               for (int i = 0; i < NSEGMENTS; ++i) {
+                       float angle = 2 * M_PI * ((float)i / (float)NSEGMENTS);
+                       p[i][0] = cosf(angle);
+                       p[i][1] = sinf(angle);
+               }
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, NSEGMENTS * 4);
+
+               for (int i = 0; i < NSEGMENTS; ++i) {
+                       float cv[2], v[3];
+                       cv[0] = p[(i) % NSEGMENTS][0];
+                       cv[1] = p[(i) % NSEGMENTS][1];
+
+                       /* cone sides */
+                       v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+                       setAttrib(vbo, pos_id, i*4, v);
+                       v[0] = 0.0f, v[1] = 2.0f, v[2] = 0.0f;
+                       setAttrib(vbo, pos_id, i*4 + 1, v);
+
+                       /* end ring */
+                       v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+                       setAttrib(vbo, pos_id, i*4 + 2, v);
+                       cv[0] = p[(i+1) % NSEGMENTS][0];
+                       cv[1] = p[(i+1) % NSEGMENTS][1];
+                       v[0] = cv[0], v[1] = 0.0f, v[2] = cv[1];
+                       setAttrib(vbo, pos_id, i*4 + 3, v);
+               }
+
+               SHC.drw_empty_cone = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_empty_cone;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_arrows_get(void)
+{
+       if (!SHC.drw_arrows) {
+               float v1[3] = {0.0, 0.0, 0.0};
+               float v2[3] = {0.0, 0.0, 0.0};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               /* Line */
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 6 * 3);
+
+               for (int axis = 0; axis < 3; axis++) {
+                       const int arrow_axis = (axis == 0) ? 1 : 0;
+
+                       v2[axis] = 1.0f;
+                       setAttrib(vbo, pos_id, axis * 6 + 0, v1);
+                       setAttrib(vbo, pos_id, axis * 6 + 1, v2);
+
+                       v1[axis] = 0.85f;
+                       v1[arrow_axis] = -0.08f;
+                       setAttrib(vbo, pos_id, axis * 6 + 2, v1);
+                       setAttrib(vbo, pos_id, axis * 6 + 3, v2);
+
+                       v1[arrow_axis] = 0.08f;
+                       setAttrib(vbo, pos_id, axis * 6 + 4, v1);
+                       setAttrib(vbo, pos_id, axis * 6 + 5, v2);
+
+                       /* reset v1 & v2 to zero */
+                       v1[arrow_axis] = v1[axis] = v2[axis] = 0.0f;
+               }
+
+               SHC.drw_arrows = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_arrows;
+}
+
+/* Lamps */
+Batch *DRW_cache_lamp_get(void)
+{
+#define NSEGMENTS 8
+       if (!SHC.drw_lamp) {
+               float v[2];
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, NSEGMENTS * 2);
+
+               for (int a = 0; a < NSEGMENTS; a++) {
+                       v[0] = sinf((2.0f * M_PI * a) / ((float)NSEGMENTS));
+                       v[1] = cosf((2.0f * M_PI * a) / ((float)NSEGMENTS));
+                       setAttrib(vbo, pos_id, a * 2, v);
+
+                       v[0] = sinf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
+                       v[1] = cosf((2.0f * M_PI * (a + 1)) / ((float)NSEGMENTS));
+                       setAttrib(vbo, pos_id, a * 2 + 1, v);
+               }
+
+               SHC.drw_lamp = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_lamp;
+#undef NSEGMENTS
+}
+
+Batch *DRW_cache_lamp_sunrays_get(void)
+{
+       if (!SHC.drw_lamp_sunrays) {
+               float v[2], v1[2], v2[2];
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 16);
+
+               for (int a = 0; a < 8; a++) {
+                       v[0] = sinf((2.0f * M_PI * a) / 8.0f);
+                       v[1] = cosf((2.0f * M_PI * a) / 8.0f);
+
+                       mul_v2_v2fl(v1, v, 1.2f);
+                       mul_v2_v2fl(v2, v, 2.5f);
+
+                       setAttrib(vbo, pos_id, a * 2, v1);
+                       setAttrib(vbo, pos_id, a * 2 + 1, v2);
+               }
+
+               SHC.drw_lamp_sunrays = Batch_create(GL_LINES, vbo, NULL);
+       }
+       return SHC.drw_lamp_sunrays;
+}
+
+
+/* Object Center */
+Batch *DRW_cache_single_vert_get(void)
+{
+       if (!SHC.drw_single_vertice) {
+               float v1[3] = {0.0f, 0.0f, 0.0f};
+
+               /* Position Only 3D format */
+               static VertexFormat format = { 0 };
+               static unsigned pos_id;
+               if (format.attrib_ct == 0) {
+                       pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+               }
+
+               VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+               VertexBuffer_allocate_data(vbo, 1);
+
+               setAttrib(vbo, pos_id, 0, v1);
+
+               SHC.drw_single_vertice = Batch_create(GL_POINTS, vbo, NULL);
+       }
+       return SHC.drw_single_vertice;
+}
+
+/* Meshes */
+Batch *DRW_cache_wire_overlay_get(Object *ob)
+{
+       Batch *overlay_wire = NULL;
+
+       BLI_assert(ob->type == OB_MESH);
+
+       Mesh *me = ob->data;
+#if 1 /* new version not working */
+       overlay_wire = BKE_mesh_batch_cache_get_overlay_edges(me);
+#else
+       overlay_wire = BKE_mesh_batch_cache_get_all_edges(me);
+#endif
+       return overlay_wire;
+}
+
+Batch *DRW_cache_wire_outline_get(Object *ob)
+{
+       Batch *fancy_wire = NULL;
+
+       BLI_assert(ob->type == OB_MESH);
+
+       Mesh *me = ob->data;
+       fancy_wire = BKE_mesh_batch_cache_get_fancy_edges(me);
+
+       return fancy_wire;
+}
+
+Batch *DRW_cache_surface_get(Object *ob)
+{
+       Batch *surface = NULL;
+
+       BLI_assert(ob->type == OB_MESH);
+
+       Mesh *me = ob->data;
+       surface = BKE_mesh_batch_cache_get_all_triangles(me);
+
+       return surface;
+}
+
+#if 0 /* TODO */
+struct Batch *DRW_cache_surface_material_get(Object *ob, int nr) {
+       /* TODO */
+       return NULL;
+}
+#endif
\ No newline at end of file
diff --git a/source/blender/draw/intern/draw_cache.h b/source/blender/draw/intern/draw_cache.h
new file mode 100644 (file)
index 0000000..c53f3d8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_cache.h
+ *  \ingroup draw
+ */
+
+#ifndef __DRAW_CACHE_H__
+#define __DRAW_CACHE_H__
+
+struct Batch;
+struct Object;
+
+void DRW_shape_cache_free(void);
+
+/* Common Shapes */
+struct Batch *DRW_cache_fullscreen_quad_get(void);
+struct Batch *DRW_cache_single_vert_get(void);
+
+/* Empties */
+struct Batch *DRW_cache_plain_axes_get(void);
+struct Batch *DRW_cache_single_arrow_get(struct Batch **line);
+struct Batch *DRW_cache_cube_get(void);
+struct Batch *DRW_cache_circle_get(void);
+struct Batch *DRW_cache_empty_sphere_get(void);
+struct Batch *DRW_cache_empty_cone_get(void);
+struct Batch *DRW_cache_arrows_get(void);
+
+/* Lamps */
+struct Batch *DRW_cache_lamp_get(void);
+struct Batch *DRW_cache_lamp_sunrays_get(void);
+
+/* Meshes */
+struct Batch *DRW_cache_wire_overlay_get(struct Object *ob);
+struct Batch *DRW_cache_wire_outline_get(struct Object *ob);
+struct Batch *DRW_cache_surface_get(struct Object *ob);
+
+#endif /* __DRAW_CACHE_H__ */
\ No newline at end of file
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
new file mode 100644 (file)
index 0000000..a7ce650
--- /dev/null
@@ -0,0 +1,1148 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/draw_manager.c
+ *  \ingroup draw
+ */
+
+#include <stdio.h>
+
+#include "BLI_listbase.h"
+#include "BLI_rect.h"
+#include "BLI_string.h"
+
+#include "BIF_glutil.h"
+
+#include "BKE_global.h"
+
+#include "BLT_translation.h"
+
+#include "DRW_engine.h"
+#include "DRW_render.h"
+
+#include "DNA_view3d_types.h"
+
+#include "GPU_basic_shader.h"
+#include "GPU_batch.h"
+#include "GPU_draw.h"
+#include "GPU_extensions.h"
+#include "GPU_framebuffer.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_shader.h"
+#include "GPU_texture.h"
+#include "GPU_uniformbuffer.h"
+#include "GPU_viewport.h"
+
+#include "RE_engine.h"
+
+#include "UI_resources.h"
+
+#include "clay.h"
+
+extern char datatoc_gpu_shader_2D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_basic_vert_glsl[];
+
+/* Structures */
+typedef enum {
+       DRW_UNIFORM_BOOL,
+       DRW_UNIFORM_INT,
+       DRW_UNIFORM_FLOAT,
+       DRW_UNIFORM_TEXTURE,
+       DRW_UNIFORM_BUFFER,
+       DRW_UNIFORM_MAT3,
+       DRW_UNIFORM_MAT4,
+       DRW_UNIFORM_BLOCK
+} DRWUniformType;
+
+struct DRWUniform {
+       struct DRWUniform *next, *prev;
+       DRWUniformType type;
+       int location;
+       int length;
+       int arraysize;
+       int bindloc;
+       const void *value;
+};
+
+struct DRWInterface {
+       ListBase uniforms;
+       /* matrices locations */
+       int modelview;
+       int projection;
+       int modelviewprojection;
+       int viewprojection;
+       int normal;
+       int eye;
+};
+
+struct DRWPass {
+       ListBase shgroups;
+       DRWState state;
+       float state_param; /* Line / Point width */
+};
+
+typedef struct DRWCall {
+       struct DRWCall *next, *prev;
+       Batch *geometry;
+       float(*obmat)[4];
+} DRWCall;
+
+struct DRWShadingGroup {
+       struct DRWShadingGroup *next, *prev;
+       struct GPUShader *shader;        /* Shader to bind */
+       struct DRWInterface *interface;  /* Uniforms pointers */
+       ListBase calls;                  /* List with all geometry and transforms */
+       int state;                       /* State changes for this batch only */
+       short dyntype;                   /* Dynamic Batch type, 0 is normal */
+       Batch *dyngeom;                  /* Dynamic batch */
+       GLuint instance_vbo;             /* Dynamic batch VBO storing Model Matrices */
+       int instance_count;                /* Dynamic batch Number of instance to render */
+};
+
+/* Render State */
+static struct DRWGlobalState{
+       GPUShader *shader;
+       struct GPUFrameBuffer *default_framebuffer;
+       FramebufferList *current_fbl;
+       TextureList *current_txl;
+       PassList *current_psl;
+       ListBase bound_texs;
+       int tex_bind_id;
+       float size[2];
+       float screenvecs[2][3];
+       float pixsize;
+       /* Current rendering context set by DRW_viewport_init */
+       const struct bContext *context;
+} DST = {NULL};
+
+/* ***************************************** TEXTURES ******************************************/
+static void drw_texture_get_format(DRWTextureFormat format, GPUTextureFormat *data_type, int *channels)
+{
+       switch (format) {
+               case DRW_TEX_RGBA_8: *data_type = GPU_RGBA8; break;
+               case DRW_TEX_RGBA_16: *data_type = GPU_RGBA16F; break;
+               case DRW_TEX_RG_16: *data_type = GPU_RG16F; break;
+               case DRW_TEX_RG_32: *data_type = GPU_RG32F; break;
+               case DRW_TEX_R_8: *data_type = GPU_R8; break;
+#if 0
+               case DRW_TEX_RGBA_32: *data_type = GPU_RGBA32F; break;
+               case DRW_TEX_RGB_8: *data_type = GPU_RGB8; break;
+               case DRW_TEX_RGB_16: *data_type = GPU_RGB16F; break;
+               case DRW_TEX_RGB_32: *data_type = GPU_RGB32F; break;
+               case DRW_TEX_RG_8: *data_type = GPU_RG8; break;
+               case DRW_TEX_R_16: *data_type = GPU_R16F; break;
+               case DRW_TEX_R_32: *data_type = GPU_R32F; break;
+#endif
+               case DRW_TEX_DEPTH_16: *data_type = GPU_DEPTH_COMPONENT16; break;
+               case DRW_TEX_DEPTH_24: *data_type = GPU_DEPTH_COMPONENT24; break;
+               case DRW_TEX_DEPTH_32: *data_type = GPU_DEPTH_COMPONENT32F; break;
+               default :
+                       /* file type not supported you must uncomment it from above */
+                       BLI_assert(false);
+                       break;
+       }
+
+       switch (format) {
+               case DRW_TEX_RGBA_8:
+               case DRW_TEX_RGBA_16:
+               case DRW_TEX_RGBA_32:
+                       *channels = 4;
+                       break;
+               case DRW_TEX_RGB_8:
+               case DRW_TEX_RGB_16:
+               case DRW_TEX_RGB_32:
+                       *channels = 3;
+                       break;
+               case DRW_TEX_RG_8:
+               case DRW_TEX_RG_16:
+               case DRW_TEX_RG_32:
+                       *channels = 2;
+                       break;
+               default:
+                       *channels = 1;
+                       break;
+       }
+}
+
+static void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
+{
+       GPU_texture_bind(tex, 0);
+       GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
+       GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP);
+       GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
+       GPU_texture_unbind(tex);
+}
+
+GPUTexture *DRW_texture_create_1D(int w, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+       GPUTexture *tex;
+       GPUTextureFormat data_type;
+       int channels;
+
+       drw_texture_get_format(format, &data_type, &channels);
+       tex = GPU_texture_create_1D_custom(w, channels, data_type, fpixels, NULL);
+       drw_texture_set_parameters(tex, flags);
+
+       return tex;
+}
+
+GPUTexture *DRW_texture_create_2D(int w, int h, DRWTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+       GPUTexture *tex;
+       GPUTextureFormat data_type;
+       int channels;
+
+       drw_texture_get_format(format, &data_type, &channels);
+       tex = GPU_texture_create_2D_custom(w, h, channels, data_type, fpixels, NULL);
+       drw_texture_set_parameters(tex, flags);
+
+       return tex;
+}
+
+/* TODO make use of format */
+GPUTexture *DRW_texture_create_2D_array(int w, int h, int d, DRWTextureFormat UNUSED(format), DRWTextureFlag flags, const float *fpixels)
+{
+       GPUTexture *tex;
+
+       tex = GPU_texture_create_2D_array(w, h, d, fpixels, NULL);
+       drw_texture_set_parameters(tex, flags);
+
+       return tex;
+}
+
+void DRW_texture_free(GPUTexture *tex)
+{
+       GPU_texture_free(tex);
+}
+
+
+/* ************************************ UNIFORM BUFFER OBJECT **********************************/
+
+GPUUniformBuffer *DRW_uniformbuffer_create(int size, const void *data)
+{
+       return GPU_uniformbuffer_create(size, data, NULL);
+}
+
+void DRW_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+       GPU_uniformbuffer_update(ubo, data);
+}
+
+void DRW_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+       GPU_uniformbuffer_free(ubo);
+}
+
+/* ****************************************** SHADERS ******************************************/
+
+GPUShader *DRW_shader_create(const char *vert, const char *geom, const char *frag, const char *defines)
+{
+       return GPU_shader_create(vert, frag, geom, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_2D(const char *frag, const char *defines)
+{
+       return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_3D(const char *frag, const char *defines)
+{
+       return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, 0, 0, 0);
+}
+
+GPUShader *DRW_shader_create_3D_depth_only(void)
+{
+       return GPU_shader_get_builtin_shader(GPU_SHADER_3D_DEPTH_ONLY);
+}
+
+void DRW_shader_free(GPUShader *shader)
+{
+       GPU_shader_free(shader);
+}
+
+/* ***************************************** INTERFACE ******************************************/
+
+static DRWInterface *DRW_interface_create(GPUShader *shader)
+{
+       DRWInterface *interface = MEM_mallocN(sizeof(DRWInterface), "DRWInterface");
+
+       interface->modelview = GPU_shader_get_uniform(shader, "ModelViewMatrix");
+       interface->projection = GPU_shader_get_uniform(shader, "ProjectionMatrix");
+       interface->viewprojection = GPU_shader_get_uniform(shader, "ViewProjectionMatrix");
+       interface->modelviewprojection = GPU_shader_get_uniform(shader, "ModelViewProjectionMatrix");
+       interface->normal = GPU_shader_get_uniform(shader, "NormalMatrix");
+       interface->eye = GPU_shader_get_uniform(shader, "eye");
+
+       BLI_listbase_clear(&interface->uniforms);
+
+       return interface;
+}
+
+static void DRW_interface_uniform(DRWShadingGroup *shgroup, const char *name,
+                                  DRWUniformType type, const void *value, int length, int arraysize, int bindloc)
+{
+       DRWUniform *uni = MEM_mallocN(sizeof(DRWUniform), "DRWUniform");
+
+       if (type == DRW_UNIFORM_BLOCK) {
+               uni->location = GPU_shader_get_uniform_block(shgroup->shader, name);
+       }
+       else {
+               uni->location = GPU_shader_get_uniform(shgroup->shader, name);
+       }
+
+       uni->type = type;
+       uni->value = value;
+       uni->length = length;
+       uni->arraysize = arraysize;
+       uni->bindloc = bindloc; /* for textures */
+
+       if (uni->location == -1) {
+               if (G.debug & G_DEBUG)
+                       fprintf(stderr, "Uniform '%s' not found!\n", name);
+
+               MEM_freeN(uni);
+               return;
+       }
+
+       BLI_addtail(&shgroup->interface->uniforms, uni);
+}
+
+void DRW_get_dfdy_factors(float dfdyfac[2])
+{
+       GPU_get_dfdy_factors(dfdyfac);
+}
+
+/* ***************************************** SHADING GROUP ******************************************/
+
+DRWShadingGroup *DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
+{
+       DRWShadingGroup *shgroup = MEM_callocN(sizeof(DRWShadingGroup), "DRWShadingGroup");
+
+       shgroup->shader = shader;
+       shgroup->interface = DRW_interface_create(shader);
+       shgroup->state = 0;
+       shgroup->dyntype = 0;
+       shgroup->dyngeom = NULL;
+
+       BLI_addtail(&pass->shgroups, shgroup);
+
+       return shgroup;
+}
+
+void DRW_shgroup_free(struct DRWShadingGroup *shgroup)
+{
+       BLI_freelistN(&shgroup->calls);
+       BLI_freelistN(&shgroup->interface->uniforms);
+       MEM_freeN(shgroup->interface);
+
+       if (shgroup->dyngeom)
+               Batch_discard_all(shgroup->dyngeom);
+}
+
+/* Later use VBO */
+void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[4])
+{
+       if (geom) {
+               DRWCall *call = MEM_callocN(sizeof(DRWCall), "DRWCall");
+
+               call->obmat = obmat;
+               call->geometry = geom;
+
+               BLI_addtail(&shgroup->calls, call);
+       }
+}
+
+/* Make sure you know what you do when using this,
+ * State is not revert back at the end of the shgroup */
+void DRW_shgroup_state_set(DRWShadingGroup *shgroup, DRWState state)
+{
+       shgroup->state = state;
+}
+
+void DRW_shgroup_dyntype_set(DRWShadingGroup *shgroup, int type)
+{
+       shgroup->dyntype = type;
+}
+
+void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex, int loc)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 0, loc);
+}
+
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup, const char *name, const GPUUniformBuffer *ubo, int loc)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 0, loc);
+}
+
+void DRW_shgroup_uniform_buffer(DRWShadingGroup *shgroup, const char *name, const int value, int loc)
+{
+       /* we abuse the lenght attrib to store the buffer index */
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BUFFER, NULL, value, 0, loc);
+}
+
+void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup, const char *name, const bool *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_BOOL, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec2(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 2, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec3(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 3, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_vec4(DRWShadingGroup *shgroup, const char *name, const float *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_FLOAT, value, 4, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_int(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 1, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_ivec2(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 2, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_ivec3(DRWShadingGroup *shgroup, const char *name, const int *value, int arraysize)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_INT, value, 3, arraysize, 0);
+}
+
+void DRW_shgroup_uniform_mat3(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT3, value, 9, 1, 0);
+}
+
+void DRW_shgroup_uniform_mat4(DRWShadingGroup *shgroup, const char *name, const float *value)
+{
+       DRW_interface_uniform(shgroup, name, DRW_UNIFORM_MAT4, value, 16, 1, 0);
+}
+
+/* Creates OGL primitives based on DRWCall.obmat position list */
+static void shgroup_dynamic_batch_primitives(DRWShadingGroup *shgroup)
+{
+       int i = 0;
+       int nbr = BLI_listbase_count(&shgroup->calls);
+       GLenum type;
+
+       if (nbr == 0) {
+               if (shgroup->dyngeom) {
+                       Batch_discard(shgroup->dyngeom);
+                       shgroup->dyngeom = NULL;
+               }
+               return;
+       }
+
+       /* Gather Data */
+       float *data = MEM_mallocN(sizeof(float) * 3 * nbr , "Object Center Batch data");
+
+       for (DRWCall *call = shgroup->calls.first; call; call = call->next, i++) {
+               copy_v3_v3(&data[i*3], call->obmat[3]);
+       }
+
+       /* Upload Data */
+       static VertexFormat format = { 0 };
+       static unsigned pos_id;
+       if (format.attrib_ct == 0) {
+               pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT);
+       }
+
+       VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+       VertexBuffer_allocate_data(vbo, nbr);
+
+       fillAttrib(vbo, pos_id, data);
+
+       if (shgroup->dyntype == DRW_DYN_POINTS)
+               type = GL_POINTS;
+       else
+               type = GL_LINES;
+
+       /* TODO make the batch dynamic instead of freeing it every times */
+       if (shgroup->dyngeom)
+               Batch_discard_all(shgroup->dyngeom);
+
+       shgroup->dyngeom = Batch_create(type, vbo, NULL);
+
+       MEM_freeN(data);
+}
+
+static void shgroup_dynamic_batch_instance(DRWShadingGroup *shgroup)
+{
+       int i = 0;
+       int nbr = BLI_listbase_count(&shgroup->calls);
+
+       shgroup->instance_count = nbr;
+
+       if (nbr == 0) {
+               if (shgroup->instance_vbo) {
+                       glDeleteBuffers(1, &shgroup->instance_vbo);
+                       shgroup->instance_vbo = 0;
+               }
+               return;
+       }
+
+       /* Gather Data */
+       float *data = MEM_mallocN(sizeof(float) * 4 * 4 * nbr , "Instance Model Matrix");
+
+       for (DRWCall *call = shgroup->calls.first; call; call = call->next, i++) {
+               copy_m4_m4((float (*)[4])&data[i*16], call->obmat);
+       }
+
+       /* TODO poke mike to add this to gawain */
+       if (shgroup->instance_vbo) {
+               glDeleteBuffers(1, &shgroup->instance_vbo);
+               shgroup->instance_vbo = 0;
+       }
+
+       glGenBuffers(1, &shgroup->instance_vbo);
+       glBindBuffer(GL_ARRAY_BUFFER, shgroup->instance_vbo);
+       glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 4 * 4 * nbr, data, GL_STATIC_DRAW);
+
+       MEM_freeN(data);
+}
+
+static void shgroup_dynamic_batch_from_calls(DRWShadingGroup *shgroup)
+{
+#ifdef WITH_VIEWPORT_CACHE_TEST
+       if (shgroup->dyngeom) return;
+#endif
+       if (shgroup->dyntype == DRW_DYN_INSTANCE) {
+               shgroup_dynamic_batch_instance(shgroup);
+       }
+       else {
+               shgroup_dynamic_batch_primitives(shgroup);
+       }
+}
+
+/* ***************************************** PASSES ******************************************/
+
+DRWPass *DRW_pass_create(const char *name, DRWState state)
+{
+       DRWPass *pass = MEM_callocN(sizeof(DRWPass), name);
+       pass->state = state;
+
+       BLI_listbase_clear(&pass->shgroups);
+
+       return pass;
+}
+
+void DRW_pass_free(DRWPass *pass)
+{
+       for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+               DRW_shgroup_free(shgroup);
+       }
+       BLI_freelistN(&pass->shgroups);
+}
+
+/* TODO this is slow we should not have to use this (better store shgroup pointer somewhere) */
+DRWShadingGroup *DRW_pass_nth_shgroup_get(DRWPass *pass, int n)
+{
+       int i = 0;
+       for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+               if (i == n)
+                       return shgroup;
+               i++;
+       }
+
+       return NULL;
+}
+
+/* ****************************************** DRAW ******************************************/
+
+void DRW_draw_background(void)
+{
+       /* Just to make sure */
+       glDepthMask(GL_TRUE);
+       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+       if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
+               /* Gradient background Color */
+               gpuMatrixBegin3D(); /* TODO: finish 2D API */
+
+               glClear(GL_DEPTH_BUFFER_BIT);
+
+               VertexFormat *format = immVertexFormat();
+               unsigned pos = add_attrib(format, "pos", COMP_F32, 2, KEEP_FLOAT);
+               unsigned color = add_attrib(format, "color", COMP_U8, 3, NORMALIZE_INT_TO_FLOAT);
+               unsigned char col_hi[3], col_lo[3];
+
+               immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+
+               UI_GetThemeColor3ubv(TH_LOW_GRAD, col_lo);
+               UI_GetThemeColor3ubv(TH_HIGH_GRAD, col_hi);
+
+               immBegin(GL_QUADS, 4);
+               immAttrib3ubv(color, col_lo);
+               immVertex2f(pos, -1.0f, -1.0f);
+               immVertex2f(pos, 1.0f, -1.0f);
+
+               immAttrib3ubv(color, col_hi);
+               immVertex2f(pos, 1.0f, 1.0f);
+               immVertex2f(pos, -1.0f, 1.0f);
+               immEnd();
+
+               immUnbindProgram();
+
+               gpuMatrixEnd();
+       }
+       else {
+               /* Solid background Color */
+               UI_ThemeClearColorAlpha(TH_HIGH_GRAD, 1.0f);
+               glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+       }
+}
+#ifdef WITH_CLAY_ENGINE
+/* Only alter the state (does not reset it like set_state() ) */
+static void shgroup_set_state(DRWShadingGroup *shgroup)
+{
+       if (shgroup->state) {
+               /* Blend */
+               if (shgroup->state & DRW_STATE_BLEND) {
+                       glEnable(GL_BLEND);
+               }
+
+               /* Wire width */
+               if (shgroup->state & DRW_STATE_WIRE) {
+                       glLineWidth(1.0f);
+               }
+               else if (shgroup->state & DRW_STATE_WIRE_LARGE) {
+                       glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+               }
+
+               /* Line Stipple */
+               if (shgroup->state & DRW_STATE_STIPPLE_2) {
+                       setlinestyle(2);
+               }
+               else if (shgroup->state & DRW_STATE_STIPPLE_3) {
+                       setlinestyle(3);
+               }
+               else if (shgroup->state & DRW_STATE_STIPPLE_4) {
+                       setlinestyle(4);
+               }
+
+               if (shgroup->state & DRW_STATE_POINT) {
+                       GPU_enable_program_point_size();
+                       glPointSize(5.0f);
+               }
+       }
+}
+
+typedef struct DRWBoundTexture {
+       struct DRWBoundTexture *next, *prev;
+       GPUTexture *tex;
+} DRWBoundTexture;
+
+static void draw_geometry(DRWShadingGroup *shgroup, DRWInterface *interface, Batch *geom,
+                          unsigned int instance_vbo, int instance_count, const float (*obmat)[4])
+{
+       RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+       
+       float mvp[4][4], mv[4][4], n[3][3];
+       float eye[3] = { 0.0f, 0.0f, 1.0f }; /* looking into the screen */
+
+       bool do_mvp = (interface->modelviewprojection != -1);
+       bool do_mv = (interface->modelview != -1);
+       bool do_n = (interface->normal != -1);
+       bool do_eye = (interface->eye != -1);
+
+       if (do_mvp) {
+               mul_m4_m4m4(mvp, rv3d->persmat, obmat);
+       }
+       if (do_mv || do_n || do_eye) {
+               mul_m4_m4m4(mv, rv3d->viewmat, obmat);
+       }
+       if (do_n || do_eye) {
+               copy_m3_m4(n, mv);
+               invert_m3(n);
+               transpose_m3(n);
+       }
+       if (do_eye) {
+               /* Used by orthographic wires */
+               float tmp[3][3];
+               invert_m3_m3(tmp, n);
+               /* set eye vector, transformed to object coords */
+               mul_m3_v3(tmp, eye);
+       }
+
+       /* Should be really simple */
+       /* step 1 : bind object dependent matrices */
+       if (interface->modelviewprojection != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->modelviewprojection, 16, 1, (float *)mvp);
+       }
+       if (interface->viewprojection != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->viewprojection, 16, 1, (float *)rv3d->persmat);
+       }
+       if (interface->projection != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->projection, 16, 1, (float *)rv3d->winmat);
+       }
+       if (interface->modelview != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->modelview, 16, 1, (float *)mv);
+       }
+       if (interface->normal != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->normal, 9, 1, (float *)n);
+       }
+       if (interface->eye != -1) {
+               GPU_shader_uniform_vector(shgroup->shader, interface->eye, 3, 1, (float *)eye);
+       }
+
+       /* step 2 : bind vertex array & draw */
+       Batch_set_program(geom, GPU_shader_get_program(shgroup->shader));
+       if (instance_vbo) {
+               Batch_draw_stupid_instanced(geom, instance_vbo, instance_count);
+       }
+       else {
+               Batch_draw_stupid(geom);
+       }
+}
+
+static void draw_shgroup(DRWShadingGroup *shgroup)
+{
+       BLI_assert(shgroup->shader);
+       BLI_assert(shgroup->interface);
+
+       DRWInterface *interface = shgroup->interface;
+
+       if (DST.shader != shgroup->shader) {
+               if (DST.shader) GPU_shader_unbind();
+               GPU_shader_bind(shgroup->shader);
+               DST.shader = shgroup->shader;
+       }
+
+       if (shgroup->dyntype != 0) {
+               shgroup_dynamic_batch_from_calls(shgroup);
+       }
+
+       shgroup_set_state(shgroup);
+
+       /* Binding Uniform */
+       /* Don't check anything, Interface should already contain the least uniform as possible */
+       for (DRWUniform *uni = interface->uniforms.first; uni; uni = uni->next) {
+               DRWBoundTexture *bound_tex;
+
+               switch (uni->type) {
+                       case DRW_UNIFORM_BOOL:
+                       case DRW_UNIFORM_INT:
+                               GPU_shader_uniform_vector_int(shgroup->shader, uni->location, uni->length, uni->arraysize, (int *)uni->value);
+                               break;
+                       case DRW_UNIFORM_FLOAT:
+                       case DRW_UNIFORM_MAT3:
+                       case DRW_UNIFORM_MAT4:
+                               GPU_shader_uniform_vector(shgroup->shader, uni->location, uni->length, uni->arraysize, (float *)uni->value);
+                               break;
+                       case DRW_UNIFORM_TEXTURE:
+                               GPU_texture_bind((GPUTexture *)uni->value, uni->bindloc);
+
+                               bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
+                               bound_tex->tex = (GPUTexture *)uni->value;
+                               BLI_addtail(&DST.bound_texs, bound_tex);
+
+                               GPU_shader_uniform_texture(shgroup->shader, uni->location, (GPUTexture *)uni->value);
+                               break;
+                       case DRW_UNIFORM_BUFFER:
+                               /* restore index from lenght we abused */
+                               GPU_texture_bind(DST.current_txl->textures[uni->length], uni->bindloc);
+                               GPU_texture_compare_mode(DST.current_txl->textures[uni->length], false);
+                               GPU_texture_filter_mode(DST.current_txl->textures[uni->length], false);
+                               
+                               bound_tex = MEM_callocN(sizeof(DRWBoundTexture), "DRWBoundTexture");
+                               bound_tex->tex = DST.current_txl->textures[uni->length];
+                               BLI_addtail(&DST.bound_texs, bound_tex);
+
+                               GPU_shader_uniform_texture(shgroup->shader, uni->location, DST.current_txl->textures[uni->length]);
+                               break;
+                       case DRW_UNIFORM_BLOCK:
+                               GPU_uniformbuffer_bind((GPUUniformBuffer *)uni->value, uni->bindloc);
+                               GPU_shader_uniform_buffer(shgroup->shader, uni->location, (GPUUniformBuffer *)uni->value);
+                               break;
+               }
+       }
+
+       /* Rendering Calls */
+       if (shgroup->dyntype != 0) {
+               /* Replacing multiple calls with only one */
+               float obmat[4][4];
+               unit_m4(obmat);
+
+               if (shgroup->dyntype == DRW_DYN_INSTANCE && shgroup->instance_count > 0) {
+                       DRWCall *call = shgroup->calls.first;
+                       draw_geometry(shgroup, interface, call->geometry, shgroup->instance_vbo, shgroup->instance_count, obmat);
+               }
+               else {
+                       /* Some dynamic batch can have no geom (no call to aggregate) */
+                       if (shgroup->dyngeom) {
+                               draw_geometry(shgroup, interface, shgroup->dyngeom, 0, 1, obmat);
+                       }
+               }
+       }
+       else {
+               for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
+                       draw_geometry(shgroup, interface, call->geometry, 0, 1, call->obmat);
+               }
+       }
+}
+
+static void set_state(short flag)
+{
+       /* TODO Keep track of the state and only revert what is needed */
+
+       /* Depth Write */
+       if (flag & DRW_STATE_WRITE_DEPTH)
+               glDepthMask(GL_TRUE);
+       else
+               glDepthMask(GL_FALSE);
+
+       /* Color Write */
+       if (flag & DRW_STATE_WRITE_COLOR)
+               glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+       else
+               glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+       /* Backface Culling */
+       if (flag & DRW_STATE_CULL_BACK ||
+           flag & DRW_STATE_CULL_FRONT) {
+
+               glEnable(GL_CULL_FACE);
+
+               if (flag & DRW_STATE_CULL_BACK)
+                       glCullFace(GL_BACK);
+               else if (flag & DRW_STATE_CULL_FRONT)
+                       glCullFace(GL_FRONT);
+       }
+       else {
+               glDisable(GL_CULL_FACE);
+       }
+
+       /* Depht Test */
+       if (flag & DRW_STATE_DEPTH_LESS ||
+           flag & DRW_STATE_DEPTH_EQUAL) {
+
+               glEnable(GL_DEPTH_TEST);
+
+               if (flag & DRW_STATE_DEPTH_LESS)
+                       glDepthFunc(GL_LEQUAL);
+               else if (flag & DRW_STATE_DEPTH_EQUAL)
+                       glDepthFunc(GL_EQUAL);
+       }
+       else {
+               glDisable(GL_DEPTH_TEST);
+       }
+
+       /* Wire Width */
+       if (flag & DRW_STATE_WIRE) {
+               glLineWidth(1.0f);
+       }
+       else if (flag & DRW_STATE_WIRE_LARGE) {
+               glLineWidth(UI_GetThemeValuef(TH_OUTLINE_WIDTH) * 2.0f);
+       }
+
+       /* Points Size */
+       if (flag & DRW_STATE_POINT) {
+               GPU_enable_program_point_size();
+               glPointSize(5.0f);
+       }
+       else {
+               GPU_disable_program_point_size();
+       }
+
+       /* Blending (all buffer) */
+       if (flag & DRW_STATE_BLEND) {
+               glEnable(GL_BLEND);
+       }
+       else {
+               glDisable(GL_BLEND);
+       }
+
+       /* Line Stipple */
+       if (flag & DRW_STATE_STIPPLE_2) {
+               setlinestyle(2);
+       }
+       else if (flag & DRW_STATE_STIPPLE_3) {
+               setlinestyle(3);
+       }
+       else if (flag & DRW_STATE_STIPPLE_4) {
+               setlinestyle(4);
+       }
+       else {
+               setlinestyle(0);
+       }
+}
+
+void DRW_draw_pass(DRWPass *pass)
+{
+       /* Start fresh */
+       DST.shader = NULL;
+       DST.tex_bind_id = 0;
+
+       set_state(pass->state);
+       BLI_listbase_clear(&DST.bound_texs);
+
+       for (DRWShadingGroup *shgroup = pass->shgroups.first; shgroup; shgroup = shgroup->next) {
+               draw_shgroup(shgroup);
+       }
+
+       /* Clear Bound textures */
+       for (DRWBoundTexture *bound_tex = DST.bound_texs.first; bound_tex; bound_tex = bound_tex->next) {
+               GPU_texture_unbind(bound_tex->tex);
+       }
+       DST.tex_bind_id = 0;
+       BLI_freelistN(&DST.bound_texs);
+
+       if (DST.shader) {
+               GPU_shader_unbind();
+               DST.shader = NULL;
+       }
+}
+
+/* Reset state to not interfer with other UI drawcall */
+void DRW_state_reset(void)
+{
+       DRWState state = 0;
+       state |= DRW_STATE_WRITE_DEPTH;
+       state |= DRW_STATE_WRITE_COLOR;
+       state |= DRW_STATE_DEPTH_LESS;
+       set_state(state);
+}
+#endif
+/* ****************************************** Settings ******************************************/
+void *DRW_material_settings_get(Material *ma, const char *engine_name)
+{
+       MaterialEngineSettings *ms = NULL;
+
+       ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name));
+
+#ifdef WITH_CLAY_ENGINE
+       /* If the settings does not exists yet, create it */
+       if (ms == NULL) {
+               ms = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+
+               BLI_strncpy(ms->name, engine_name, 32);
+
+               /* TODO make render_settings_create a polymorphic function */
+               if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
+                       ms->data = CLAY_material_settings_create();
+               }
+               else {
+                       /* No engine matched */
+                       BLI_assert(false);
+               }
+
+               BLI_addtail(&ma->engines_settings, ms);
+       }
+#else
+       return NULL;
+#endif
+
+       return ms->data;
+}
+
+/* If scene is NULL, use context scene */
+void *DRW_render_settings_get(Scene *scene, const char *engine_name)
+{
+       RenderEngineSettings *rs = NULL;
+
+       if (scene == NULL)
+               scene = CTX_data_scene(DST.context);
+
+       rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name));
+
+#ifdef WITH_CLAY_ENGINE
+       /* If the settings does not exists yet, create it */
+       if (rs == NULL) {
+               rs = MEM_callocN(sizeof(RenderEngineSettings), "RenderEngineSettings");
+
+               BLI_strncpy(rs->name, engine_name, 32);
+
+               /* TODO make render_settings_create a polymorphic function */
+               if (STREQ(engine_name, RE_engine_id_BLENDER_CLAY)) {
+                       rs->data = CLAY_render_settings_create();
+               }
+               else {
+                       /* No engine matched */
+                       BLI_assert(false);
+               }
+
+               BLI_addtail(&scene->engines_settings, rs);
+       }
+#else
+       return NULL;
+#endif
+
+       return rs->data;
+}
+/* ****************************************** Framebuffers ******************************************/
+
+void DRW_framebuffer_init(struct GPUFrameBuffer **fb, int width, int height, DRWFboTexture textures[MAX_FBO_TEX],
+                          int texnbr)
+{
+       if (!*fb) {
+               int color_attachment = -1;
+               *fb = GPU_framebuffer_create();
+
+               for (int i = 0; i < texnbr; ++i)
+               {
+                       DRWFboTexture fbotex = textures[i];
+                       
+                       if (!*fbotex.tex) {
+                               /* TODO refine to opengl formats */
+                               if (fbotex.format == DRW_BUF_DEPTH_16 ||
+                                       fbotex.format == DRW_BUF_DEPTH_24) {
+                                       *fbotex.tex = GPU_texture_create_depth(width, height, NULL);
+                                       GPU_texture_compare_mode(*fbotex.tex, false);
+                                       GPU_texture_filter_mode(*fbotex.tex, false);
+                               }
+                               else {
+                                       *fbotex.tex = GPU_texture_create_2D(width, height, NULL, NULL);
+                                       ++color_attachment;
+                               }
+                       }
+                       
+                       GPU_framebuffer_texture_attach(*fb, *fbotex.tex, color_attachment);
+               }
+
+               if (!GPU_framebuffer_check_valid(*fb, NULL)) {
+                       printf("Error invalid framebuffer\n");
+               }
+
+               GPU_framebuffer_bind(DST.default_framebuffer);
+       }
+}
+
+void DRW_framebuffer_bind(struct GPUFrameBuffer *fb)
+{
+       GPU_framebuffer_bind(fb);
+}
+
+void DRW_framebuffer_texture_attach(struct GPUFrameBuffer *fb, GPUTexture *tex, int slot)
+{
+       GPU_framebuffer_texture_attach(fb, tex, slot);
+}
+
+void DRW_framebuffer_texture_detach(GPUTexture *tex)
+{
+       GPU_framebuffer_texture_detach(tex);
+}
+
+/* ****************************************** Viewport ******************************************/
+
+float *DRW_viewport_size_get(void)
+{
+       return &DST.size[0];
+}
+
+float *DRW_viewport_screenvecs_get(void)
+{
+       return &DST.screenvecs[0][0];
+}
+
+float *DRW_viewport_pixelsize_get(void)
+{
+       return &DST.pixsize;
+}
+
+void DRW_viewport_init(const bContext *C, void **buffers, void **textures, void **passes)
+{
+       RegionView3D *rv3d = CTX_wm_region_view3d(C);
+       GPUViewport *viewport = rv3d->viewport;
+
+       GPU_viewport_get_engine_data(viewport, buffers, textures, passes);
+
+       /* Refresh DST.size */
+       DefaultTextureList *txl = (DefaultTextureList *)*textures;
+       DST.size[0] = (float)GPU_texture_width(txl->color);
+       DST.size[1] = (float)GPU_texture_height(txl->color);
+
+       DefaultFramebufferList *fbl = (DefaultFramebufferList *)*buffers;
+       DST.default_framebuffer = fbl->default_fb;
+
+       DST.current_txl = (TextureList *)*textures;
+       DST.current_fbl = (FramebufferList *)*buffers;
+       DST.current_psl = (PassList *)*passes;
+
+       /* Refresh DST.screenvecs */
+       copy_v3_v3(DST.screenvecs[0], rv3d->viewinv[0]);
+       copy_v3_v3(DST.screenvecs[1], rv3d->viewinv[1]);
+       normalize_v3(DST.screenvecs[0]);
+       normalize_v3(DST.screenvecs[1]);
+
+       /* Refresh DST.pixelsize */
+       DST.pixsize = rv3d->pixsize;
+
+       /* Save context for all later needs */
+       DST.context = C;
+}
+
+void DRW_viewport_matrix_get(float mat[4][4], DRWViewportMatrixType type)
+{
+       RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+
+       if (type == DRW_MAT_PERS)
+               copy_m4_m4(mat, rv3d->persmat);
+       else if (type == DRW_MAT_WIEW)
+               copy_m4_m4(mat, rv3d->viewmat);
+       else if (type == DRW_MAT_WIN)
+               copy_m4_m4(mat, rv3d->winmat);
+}
+
+bool DRW_viewport_is_persp_get(void)
+{
+       RegionView3D *rv3d = CTX_wm_region_view3d(DST.context);
+       return rv3d->is_persp;
+}
+
+bool DRW_viewport_cache_is_dirty(void)
+{
+       /* TODO Use a dirty flag */
+       return (DST.current_psl->passes[0] == NULL);
+}
+
+/* ****************************************** INIT ******************************************/
+
+void DRW_engines_init(void)
+{
+#ifdef WITH_CLAY_ENGINE
+       RE_engines_register(NULL, &viewport_clay_type);
+#endif
+}
+
+void DRW_engines_free(void)
+{
+#ifdef WITH_CLAY_ENGINE
+       clay_engine_free();
+
+       DRW_shape_cache_free();
+
+       BLI_remlink(&R_engines, &viewport_clay_type);
+#endif
+}
\ No newline at end of file
diff --git a/source/blender/draw/intern/draw_mode_pass.c b/source/blender/draw/intern/draw_mode_pass.c
new file mode 100644 (file)
index 0000000..507872a
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file blender/draw/draw_mode_pass.c
+ *  \ingroup draw
+ */
+
+#include "DNA_userdef_types.h"
+
+#include "GPU_shader.h"
+
+#include "UI_resources.h"
+
+#include "BKE_global.h"
+
+#include "draw_mode_pass.h"
+
+/* ************************** OBJECT MODE ******************************* */
+
+/* Store list of shading group for easy access*/
+
+/* Empties */
+static DRWShadingGroup *plain_axes_wire;
+static DRWShadingGroup *plain_axes_active;
+static DRWShadingGroup *plain_axes_select;
+static DRWShadingGroup *plain_axes_transform;
+static DRWShadingGroup *plain_axes_group;
+static DRWShadingGroup *plain_axes_group_active;
+
+static DRWShadingGroup *cube_wire;
+static DRWShadingGroup *cube_active;
+static DRWShadingGroup *cube_select;
+static DRWShadingGroup *cube_transform;
+static DRWShadingGroup *cube_group;
+static DRWShadingGroup *cube_group_active;
+
+static DRWShadingGroup *circle_wire;
+static DRWShadingGroup *circle_active;
+static DRWShadingGroup *circle_select;
+static DRWShadingGroup *circle_transform;
+static DRWShadingGroup *circle_group;
+static DRWShadingGroup *circle_group_active;
+
+static DRWShadingGroup *sphere_wire;
+static DRWShadingGroup *sphere_active;
+static DRWShadingGroup *sphere_select;
+static DRWShadingGroup *sphere_transform;
+static DRWShadingGroup *sphere_group;
+static DRWShadingGroup *sphere_group_active;
+
+static DRWShadingGroup *cone_wire;
+static DRWShadingGroup *cone_active;
+static DRWShadingGroup *cone_select;
+static DRWShadingGroup *cone_transform;
+static DRWShadingGroup *cone_group;
+static DRWShadingGroup *cone_group_active;
+
+static DRWShadingGroup *single_arrow_wire;
+static DRWShadingGroup *single_arrow_active;
+static DRWShadingGroup *single_arrow_select;
+static DRWShadingGroup *single_arrow_transform;
+static DRWShadingGroup *single_arrow_group;
+static DRWShadingGroup *single_arrow_group_active;
+
+static DRWShadingGroup *single_arrow_line_wire;
+static DRWShadingGroup *single_arrow_line_active;
+static DRWShadingGroup *single_arrow_line_select;
+static DRWShadingGroup *single_arrow_line_transform;
+static DRWShadingGroup *single_arrow_line_group;
+static DRWShadingGroup *single_arrow_line_group_active;
+
+static DRWShadingGroup *arrows_wire;
+static DRWShadingGroup *arrows_active;
+static DRWShadingGroup *arrows_select;
+static DRWShadingGroup *arrows_transform;
+static DRWShadingGroup *arrows_group;
+static DRWShadingGroup *arrows_group_active;
+
+/* Lamps */
+static DRWShadingGroup *lamp_center;
+static DRWShadingGroup *lamp_center_group;
+static DRWShadingGroup *lamp_groundpoint;
+static DRWShadingGroup *lamp_groundline;
+static DRWShadingGroup *lamp_circle;
+static DRWShadingGroup *lamp_circle_active;
+static DRWShadingGroup *lamp_circle_select;
+static DRWShadingGroup *lamp_circle_transform;
+static DRWShadingGroup *lamp_circle_group;
+static DRWShadingGroup *lamp_circle_group_active;
+static DRWShadingGroup *lamp_circle_shadow;
+static DRWShadingGroup *lamp_circle_shadow_active;
+static DRWShadingGroup *lamp_circle_shadow_select;
+static DRWShadingGroup *lamp_circle_shadow_transform;
+static DRWShadingGroup *lamp_circle_shadow_group;
+static DRWShadingGroup *lamp_circle_shadow_group_active;
+static DRWShadingGroup *lamp_sunrays;
+static DRWShadingGroup *lamp_sunrays_active;
+static DRWShadingGroup *lamp_sunrays_select;
+static DRWShadingGroup *lamp_sunrays_transform;
+static DRWShadingGroup *lamp_sunrays_group;
+static DRWShadingGroup *lamp_sunrays_group_active;
+
+/* Helpers */
+static DRWShadingGroup *relationship_lines;
+
+/* Objects Centers */
+static DRWShadingGroup *center_active;
+static DRWShadingGroup *center_selected;
+static DRWShadingGroup *center_deselected;
+
+static DRWShadingGroup *shgroup_instance_uniform_color(DRWPass *pass, float color[4])
+{
+       GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh_inst, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+
+       return grp;
+}
+
+static DRWShadingGroup *shgroup_dynlines_uniform_color(DRWPass *pass, float color[4])
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_LINES);
+
+       return grp;
+}
+
+static DRWShadingGroup *shgroup_dynpoints_uniform_color(DRWPass *pass, float color[4], float *size)
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_uniform_float(grp, "size", size, 1);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+       DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+
+       return grp;
+}
+
+static DRWShadingGroup *shgroup_groundlines_uniform_color(DRWPass *pass, float color[4])
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDLINE);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+
+       return grp;
+}
+
+static DRWShadingGroup *shgroup_groundpoints_uniform_color(DRWPass *pass, float color[4])
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_GROUNDPOINT);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+       DRW_shgroup_state_set(grp, DRW_STATE_POINT);
+       return grp;
+}
+
+static DRWShadingGroup *shgroup_lamp(DRWPass *pass, float color[4], float *size)
+{
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_LAMP_COMMON);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+       DRW_shgroup_uniform_vec4(grp, "color", color, 1);
+       DRW_shgroup_uniform_float(grp, "size", size, 1);
+       DRW_shgroup_uniform_float(grp, "pixel_size", DRW_viewport_pixelsize_get(), 1);
+       DRW_shgroup_uniform_vec3(grp, "screen_vecs", DRW_viewport_screenvecs_get(), 2);
+       DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+       DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+       return grp;
+}
+
+/* This Function setup the passes needed for the mode rendering.
+ * The passes are populated by the rendering engine using the DRW_shgroup_* functions. */
+void DRW_pass_setup_common(DRWPass **wire_overlay, DRWPass **wire_outline, DRWPass **non_meshes, DRWPass **ob_center)
+{
+       /* Theses are defined for the whole application so make sure they rely on global settings */
+       static float colorWire[4], colorWireEdit[4];
+       static float colorActive[4], colorSelect[4], colorTransform[4], colorGroup[4], colorGroupActive[4];
+       static float colorEmpty[4], colorLamp[4], colorCamera[4], colorSpeaker[4];
+       static float lampCenterSize, lampCircleRad, lampCircleShadowRad, colorLampNoAlpha[4];
+
+       UI_GetThemeColor4fv(TH_WIRE, colorWire);
+       UI_GetThemeColor4fv(TH_WIRE_EDIT, colorWireEdit);
+       UI_GetThemeColor4fv(TH_ACTIVE, colorActive);
+       UI_GetThemeColor4fv(TH_SELECT, colorSelect);
+       UI_GetThemeColor4fv(TH_TRANSFORM, colorTransform);
+       UI_GetThemeColor4fv(TH_GROUP_ACTIVE, colorGroupActive);
+       UI_GetThemeColor4fv(TH_GROUP, colorGroup);
+       UI_GetThemeColor4fv(TH_LAMP, colorLamp);
+       UI_GetThemeColor4fv(TH_LAMP, colorLampNoAlpha);
+       UI_GetThemeColor4fv(TH_SPEAKER, colorSpeaker);
+       UI_GetThemeColor4fv(TH_CAMERA, colorCamera);
+       UI_GetThemeColor4fv(TH_EMPTY, colorEmpty);
+
+       colorLampNoAlpha[3] = 1.0f;
+
+       if (wire_overlay) {
+               /* This pass can draw mesh edges top of Shaded Meshes without any Z fighting */
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_BLEND;
+               *wire_overlay = DRW_pass_create("Wire Overlays Pass", state);
+       }
+
+       if (wire_outline) {
+               /* This pass can draw mesh outlines and/or fancy wireframe */
+               /* Fancy wireframes are not meant to be occluded (without Z offset) */
+               /* Outlines and Fancy Wires use the same VBO */
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+               *wire_outline = DRW_pass_create("Wire + Outlines Pass", state);
+       }
+
+       if (non_meshes) {
+               /* Non Meshes Pass (Camera, empties, lamps ...) */
+               DRWShadingGroup *grp;
+
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS | DRW_STATE_BLEND;
+               state |= DRW_STATE_WIRE;
+               *non_meshes = DRW_pass_create("Non Meshes Pass", state);
+
+               GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+               /* Empties */
+               plain_axes_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               plain_axes_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               plain_axes_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               plain_axes_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               plain_axes_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               plain_axes_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               cube_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               cube_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               cube_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               cube_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               cube_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               cube_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               circle_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               circle_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               circle_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               circle_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               circle_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               circle_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               sphere_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               sphere_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               sphere_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               sphere_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               sphere_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               sphere_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               cone_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               cone_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               cone_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               cone_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               cone_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               cone_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               single_arrow_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               single_arrow_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               single_arrow_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               single_arrow_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               single_arrow_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               single_arrow_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               single_arrow_line_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               single_arrow_line_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               single_arrow_line_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               single_arrow_line_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               single_arrow_line_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               single_arrow_line_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               arrows_wire = shgroup_instance_uniform_color(*non_meshes, colorEmpty);
+               arrows_active = shgroup_instance_uniform_color(*non_meshes, colorActive);
+               arrows_select = shgroup_instance_uniform_color(*non_meshes, colorSelect);
+               arrows_transform = shgroup_instance_uniform_color(*non_meshes, colorTransform);
+               arrows_group = shgroup_instance_uniform_color(*non_meshes, colorGroup);
+               arrows_group_active = shgroup_instance_uniform_color(*non_meshes, colorGroupActive);
+
+               /* Lamps */
+               lampCenterSize = (U.obcenter_dia + 1.5f) * U.pixelsize;
+               lampCircleRad = U.pixelsize * 9.0f;
+               lampCircleShadowRad = lampCircleRad + U.pixelsize * 3.0f;
+               /* TODO
+                * for now we create 3 times the same VBO with only lamp center coordinates
+                * but ideally we would only create it once */
+               lamp_center = shgroup_dynpoints_uniform_color(*non_meshes, colorLampNoAlpha, &lampCenterSize);
+               lamp_center_group = shgroup_dynpoints_uniform_color(*non_meshes, colorGroup, &lampCenterSize);
+               lamp_circle = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleRad);
+               lamp_circle_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleRad);
+               lamp_circle_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleRad);
+               lamp_circle_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleRad);
+               lamp_circle_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleRad);
+               lamp_circle_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleRad);
+               lamp_circle_shadow = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleShadowRad);
+               lamp_circle_shadow_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleShadowRad);
+               lamp_circle_shadow_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleShadowRad);
+               lamp_circle_shadow_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleShadowRad);
+               lamp_circle_shadow_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleShadowRad);
+               lamp_circle_shadow_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleShadowRad);
+               lamp_sunrays = shgroup_lamp(*non_meshes, colorLampNoAlpha, &lampCircleRad);
+               lamp_sunrays_active = shgroup_lamp(*non_meshes, colorActive, &lampCircleRad);
+               lamp_sunrays_select = shgroup_lamp(*non_meshes, colorSelect, &lampCircleRad);
+               lamp_sunrays_transform = shgroup_lamp(*non_meshes, colorTransform, &lampCircleRad);
+               lamp_sunrays_group = shgroup_lamp(*non_meshes, colorGroup, &lampCircleRad);
+               lamp_sunrays_group_active = shgroup_lamp(*non_meshes, colorGroupActive, &lampCircleRad);
+               lamp_groundline = shgroup_groundlines_uniform_color(*non_meshes, colorLamp);
+               lamp_groundpoint = shgroup_groundpoints_uniform_color(*non_meshes, colorLamp);
+
+               /* Stipple Wires */
+               grp = DRW_shgroup_create(sh, *non_meshes);
+               DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_2);
+
+               grp = DRW_shgroup_create(sh, *non_meshes);
+               DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+
+               grp = DRW_shgroup_create(sh, *non_meshes);
+               DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_4);
+
+               /* Relationship Lines */
+               relationship_lines = shgroup_dynlines_uniform_color(*non_meshes, colorWire);
+               DRW_shgroup_state_set(relationship_lines, DRW_STATE_STIPPLE_3);
+       }
+
+       if (ob_center) {
+               /* Object Center pass grouped by State */
+               DRWShadingGroup *grp;
+               static float colorDeselect[4], outlineColor[4];
+               static float outlineWidth, size;
+
+               DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND | DRW_STATE_POINT;
+               *ob_center = DRW_pass_create("Obj Center Pass", state);
+
+               outlineWidth = 1.0f * U.pixelsize;
+               size = U.obcenter_dia * U.pixelsize + outlineWidth;
+               //UI_GetThemeColorShadeAlpha4fv(TH_ACTIVE, 0, -80, colorActive);
+               //UI_GetThemeColorShadeAlpha4fv(TH_SELECT, 0, -80, colorSelect);
+               UI_GetThemeColorShadeAlpha4fv(TH_TRANSFORM, 0, -80, colorDeselect);
+               UI_GetThemeColorShadeAlpha4fv(TH_WIRE, 0, -30, outlineColor);
+
+               GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH);
+
+               /* Active */
+               grp = DRW_shgroup_create(sh, *ob_center);
+               DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+               DRW_shgroup_uniform_float(grp, "size", &size, 1);
+               DRW_shgroup_uniform_float(grp, "outlineWidth", &outlineWidth, 1);
+               DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1);
+               DRW_shgroup_uniform_vec4(grp, "outlineColor", outlineColor, 1);
+               center_active = grp;
+
+               /* Select */
+               grp = DRW_shgroup_create(sh, *ob_center);
+               DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+               DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1);
+               center_selected = grp;
+
+               /* Deselect */
+               grp = DRW_shgroup_create(sh, *ob_center);
+               DRW_shgroup_dyntype_set(grp, DRW_DYN_POINTS);
+               DRW_shgroup_uniform_vec4(grp, "color", colorDeselect, 1);
+               center_deselected = grp;
+       }
+}
+
+/* ******************************************** WIRES *********************************************** */
+
+/* TODO FINISH */
+static int draw_object_wire_theme(Object *ob)
+{
+       const bool is_edit = (ob->mode & OB_MODE_EDIT) != 0;
+       /* confusing logic here, there are 2 methods of setting the color
+        * 'colortab[colindex]' and 'theme_id', colindex overrides theme_id.
+        *
+        * note: no theme yet for 'colindex' */
+       int theme_id = is_edit ? TH_WIRE_EDIT : TH_WIRE;
+
+       if (//(scene->obedit == NULL) &&
+           ((G.moving & G_TRANSFORM_OBJ) != 0) &&
+           ((ob->base_flag & BASE_SELECTED) != 0))
+       {
+               theme_id = TH_TRANSFORM;
+       }
+       else {
+               /* Sets the 'theme_id' or fallback to wire */
+               if ((ob->flag & OB_FROMGROUP) != 0) {
+                       if ((ob->base_flag & BASE_SELECTED) != 0) {
+                               /* uses darker active color for non-active + selected */
+                               theme_id = TH_GROUP_ACTIVE;
+
+                               // if (scene->basact != base) {
+                               //      theme_shade = -16;
+                               // }
+                       }
+                       else {
+                               theme_id = TH_GROUP;
+                       }
+               }
+               else {
+                       if ((ob->base_flag & BASE_SELECTED) != 0) {
+                               theme_id = //scene->basact == base ? TH_ACTIVE :
+                               TH_SELECT;
+                       }
+                       else {
+                               if (ob->type == OB_LAMP) theme_id = TH_LAMP;
+                               else if (ob->type == OB_SPEAKER) theme_id = TH_SPEAKER;
+                               else if (ob->type == OB_CAMERA) theme_id = TH_CAMERA;
+                               else if (ob->type == OB_EMPTY) theme_id = TH_EMPTY;
+                               /* fallback to TH_WIRE */
+                       }
+               }
+       }
+
+       return theme_id;
+}
+
+void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob)
+{
+#if 1
+       struct Batch *geom = DRW_cache_wire_overlay_get(ob);
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_OVERLAY);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
+       DRW_shgroup_uniform_vec2(grp, "viewportSize", DRW_viewport_size_get(), 1);
+
+       DRW_shgroup_call_add(grp, geom, ob->obmat);
+#else
+       static float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+       struct Batch *geom = DRW_cache_wire_overlay_get(ob);
+       GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_overlay);
+       DRW_shgroup_uniform_vec4(grp, "color", col, 1);
+
+       DRW_shgroup_call_add(grp, geom, ob->obmat);
+#endif
+}
+
+void DRW_shgroup_wire_outline(DRWPass *wire_outline, Object *ob,
+                              const bool do_front, const bool do_back, const bool do_outline)
+{
+       GPUShader *sh;
+       struct Batch *geom = DRW_cache_wire_outline_get(ob);
+
+       /* Get color */
+       /* TODO get the right color depending on ob state (Groups, overides etc..) */
+       static float frontcol[4], backcol[4], color[4];
+       UI_GetThemeColor4fv(TH_ACTIVE, color);
+       copy_v4_v4(frontcol, color);
+       copy_v4_v4(backcol, color);
+       backcol[3] = 0.333f;
+       frontcol[3] = 0.667f;
+
+#if 1 /* New wire */
+
+       bool is_perps = DRW_viewport_is_persp_get();
+       static bool bTrue = true;
+       static bool bFalse = false;
+
+       /* Note (TODO) : this requires cache to be discarded on ortho/perp switch
+        * It may be preferable (or not depending on performance implication)
+        * to introduce a shader uniform switch */
+       if (is_perps) {
+               sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_PERSP);
+       }
+       else {
+               sh = GPU_shader_get_builtin_shader(GPU_SHADER_EDGES_FRONT_BACK_ORTHO);
+       }
+
+       if (do_front || do_back) {
+               bool *bFront = (do_front) ? &bTrue : &bFalse;
+               bool *bBack = (do_back) ? &bTrue : &bFalse;
+
+               DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+               DRW_shgroup_state_set(grp, DRW_STATE_WIRE);
+               DRW_shgroup_uniform_vec4(grp, "frontColor", frontcol, 1);
+               DRW_shgroup_uniform_vec4(grp, "backColor", backcol, 1);
+               DRW_shgroup_uniform_bool(grp, "drawFront", bFront, 1);
+               DRW_shgroup_uniform_bool(grp, "drawBack", bBack, 1);
+               DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bFalse, 1);
+               DRW_shgroup_call_add(grp, geom, ob->obmat);
+       }
+
+       if (do_outline) {
+               DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+               DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
+               DRW_shgroup_uniform_vec4(grp, "silhouetteColor", color, 1);
+               DRW_shgroup_uniform_bool(grp, "drawFront", &bFalse, 1);
+               DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 1);
+               DRW_shgroup_uniform_bool(grp, "drawSilhouette", &bTrue, 1);
+
+               DRW_shgroup_call_add(grp, geom, ob->obmat);
+       }
+
+#else /* Old (flat) wire */
+
+       sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+       DRWShadingGroup *grp = DRW_shgroup_create(sh, wire_outline);
+       DRW_shgroup_state_set(grp, DRW_STATE_WIRE_LARGE);
+       DRW_shgroup_uniform_vec4(grp, "color", frontcol, 1);
+
+       DRW_shgroup_call_add(grp, geom, ob->obmat);
+#endif
+
+}
+
+/* ***************************** NON MESHES ********************** */
+
+static void DRW_draw_lamp(Object *ob)
+{
+       struct Batch *center = DRW_cache_single_vert_get();
+       struct Batch *lamp = DRW_cache_lamp_get();
+       struct Batch *sunrays = DRW_cache_lamp_sunrays_get();
+       Lamp *la = ob->data;
+       int theme_id = draw_object_wire_theme(ob);
+
+       /* Don't draw the center if it's selected or active */
+       if (theme_id == TH_GROUP)
+               DRW_shgroup_call_add(lamp_center_group, center, ob->obmat);
+       else if (theme_id == TH_LAMP)
+               DRW_shgroup_call_add(lamp_center, center, ob->obmat);
+
+       /* First circle */
+       if (theme_id == TH_ACTIVE)
+               DRW_shgroup_call_add(lamp_circle_active, lamp, ob->obmat);
+       else if (theme_id == TH_SELECT)
+               DRW_shgroup_call_add(lamp_circle_select, lamp, ob->obmat);
+       else if (theme_id == TH_GROUP)
+               DRW_shgroup_call_add(lamp_circle_group, lamp, ob->obmat);
+       else if (theme_id == TH_GROUP_ACTIVE)
+               DRW_shgroup_call_add(lamp_circle_group_active, lamp, ob->obmat);
+       else if (theme_id == TH_TRANSFORM)
+               DRW_shgroup_call_add(lamp_circle_transform, lamp, ob->obmat);
+       else
+               DRW_shgroup_call_add(lamp_circle, lamp, ob->obmat);
+
+       /* draw dashed outer circle if shadow is on. remember some lamps can't have certain shadows! */
+       if (la->type != LA_HEMI) {
+               if ((la->mode & LA_SHAD_RAY) || ((la->mode & LA_SHAD_BUF) && (la->type == LA_SPOT))) {
+                       if (theme_id == TH_ACTIVE)
+                               DRW_shgroup_call_add(lamp_circle_shadow_active, lamp, ob->obmat);
+                       else if (theme_id == TH_SELECT)
+                               DRW_shgroup_call_add(lamp_circle_shadow_select, lamp, ob->obmat);
+                       else if (theme_id == TH_GROUP)
+                               DRW_shgroup_call_add(lamp_circle_shadow_group, lamp, ob->obmat);
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               DRW_shgroup_call_add(lamp_circle_shadow_group_active, lamp, ob->obmat);
+                       else if (theme_id == TH_TRANSFORM)
+                               DRW_shgroup_call_add(lamp_circle_shadow_transform, lamp, ob->obmat);
+                       else
+                               DRW_shgroup_call_add(lamp_circle_shadow, lamp, ob->obmat);
+               }
+       }
+
+       /* Sunrays */
+       if (la->type == LA_SUN) {
+               if (theme_id == TH_ACTIVE)
+                       DRW_shgroup_call_add(lamp_sunrays_active, sunrays, ob->obmat);
+               else if (theme_id == TH_SELECT)
+                       DRW_shgroup_call_add(lamp_sunrays_select, sunrays, ob->obmat);
+               else if (theme_id == TH_GROUP)
+                       DRW_shgroup_call_add(lamp_sunrays_group, sunrays, ob->obmat);
+               else if (theme_id == TH_GROUP_ACTIVE)
+                       DRW_shgroup_call_add(lamp_sunrays_group_active, sunrays, ob->obmat);
+               else if (theme_id == TH_TRANSFORM)
+                       DRW_shgroup_call_add(lamp_sunrays_transform, sunrays, ob->obmat);
+               else
+                       DRW_shgroup_call_add(lamp_sunrays, sunrays, ob->obmat);
+       }
+
+       /* Line and point going to the ground */
+       DRW_shgroup_call_add(lamp_groundline, center, ob->obmat);
+       DRW_shgroup_call_add(lamp_groundpoint, center, ob->obmat);
+}
+
+static void DRW_draw_empty(Object *ob)
+{
+       struct Batch *geom, *geom2;
+       DRWShadingGroup *grp, *grp2;
+       int theme_id = draw_object_wire_theme(ob);
+
+       switch (ob->empty_drawtype) {
+               case OB_PLAINAXES:
+                       if (theme_id == TH_ACTIVE)
+                               grp = plain_axes_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = plain_axes_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = plain_axes_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = plain_axes_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = plain_axes_transform;
+                       else
+                               grp = plain_axes_wire;
+
+                       geom = DRW_cache_plain_axes_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       break;
+
+               case OB_SINGLE_ARROW:
+                       if (theme_id == TH_ACTIVE) {
+                               grp = single_arrow_active;
+                               grp2 = single_arrow_line_active;
+                       }
+                       else if (theme_id == TH_SELECT) {
+                               grp = single_arrow_select;
+                               grp2 = single_arrow_line_select;
+                       }
+                       else if (theme_id == TH_GROUP_ACTIVE) {
+                               grp = single_arrow_group_active;
+                               grp2 = single_arrow_line_group_active;
+                       }
+                       else if (theme_id == TH_GROUP) {
+                               grp = single_arrow_group;
+                               grp2 = single_arrow_line_group;
+                       }
+                       else if (theme_id == TH_TRANSFORM) {
+                               grp = single_arrow_transform;
+                               grp2 = single_arrow_line_transform;
+                       }
+                       else {
+                               grp = single_arrow_wire;
+                               grp2 = single_arrow_line_wire;
+                       }
+
+                       geom = DRW_cache_single_arrow_get(&geom2);
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       DRW_shgroup_call_add(grp2, geom2, ob->obmat);
+                       break;
+
+               case OB_CUBE:
+                       if (theme_id == TH_ACTIVE)
+                               grp = cube_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = cube_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = cube_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = cube_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = cube_transform;
+                       else
+                               grp = cube_wire;
+
+                       geom = DRW_cache_cube_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       break;
+
+               case OB_CIRCLE:
+                       if (theme_id == TH_ACTIVE)
+                               grp = circle_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = circle_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = circle_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = circle_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = circle_transform;
+                       else
+                               grp = circle_wire;
+
+                       geom = DRW_cache_circle_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       break;
+
+               case OB_EMPTY_SPHERE:
+                       if (theme_id == TH_ACTIVE)
+                               grp = sphere_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = sphere_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = sphere_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = sphere_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = sphere_transform;
+                       else
+                               grp = sphere_wire;
+
+                       geom = DRW_cache_empty_sphere_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       break;
+
+               case OB_EMPTY_CONE:
+                       if (theme_id == TH_ACTIVE)
+                               grp = cone_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = cone_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = cone_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = cone_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = cone_transform;
+                       else
+                               grp = cone_wire;
+
+                       geom = DRW_cache_empty_cone_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       break;
+
+               case OB_ARROWS:
+               default:
+                       if (theme_id == TH_ACTIVE)
+                               grp = arrows_active;
+                       else if (theme_id == TH_SELECT)
+                               grp = arrows_select;
+                       else if (theme_id == TH_GROUP_ACTIVE)
+                               grp = arrows_group_active;
+                       else if (theme_id == TH_GROUP)
+                               grp = arrows_group;
+                       else if (theme_id == TH_TRANSFORM)
+                               grp = arrows_transform;
+                       else
+                               grp = arrows_wire;
+
+                       geom = DRW_cache_arrows_get();
+                       DRW_shgroup_call_add(grp, geom, ob->obmat);
+                       /* TODO Missing axes names */
+                       break;
+       }
+}
+
+void DRW_shgroup_non_meshes(DRWPass *UNUSED(non_meshes), Object *ob)
+{
+       switch (ob->type) {
+               case OB_LAMP:
+                       DRW_draw_lamp(ob);
+                       break;
+               case OB_CAMERA:
+               case OB_EMPTY:
+                       DRW_draw_empty(ob);
+               default:
+                       break;
+       }
+}
+
+void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), Object *ob)
+{
+       if (ob->parent) {
+               struct Batch *geom = DRW_cache_single_vert_get();
+               DRW_shgroup_call_add(relationship_lines, geom, ob->obmat);
+               DRW_shgroup_call_add(relationship_lines, geom, ob->parent->obmat);
+       }
+}
+
+/* ***************************** COMMON **************************** */
+
+void DRW_shgroup_object_center(DRWPass *UNUSED(ob_center), Object *ob)
+{
+       struct Batch *geom = DRW_cache_single_vert_get();
+
+       if ((ob->base_flag & BASE_SELECTED) != 0) {
+               DRW_shgroup_call_add(center_selected, geom, ob->obmat);
+       }
+       else if (0) {
+               DRW_shgroup_call_add(center_deselected, geom, ob->obmat);
+       }
+}
diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_mode_pass.h
new file mode 100644 (file)
index 0000000..d11213e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Blender Institute
+ *
+ */
+
+/** \file draw_mode_pass.h
+ *  \ingroup draw
+ */
+
+#ifndef __DRAW_MODE_PASS_H__
+#define __DRAW_MODE_PASS_H__
+
+#include "DRW_render.h"
+
+struct DRWPass;
+struct Batch;
+struct Object;
+
+void DRW_pass_setup_common(struct DRWPass **wire_overlay, struct DRWPass **wire_outline, struct DRWPass **non_meshes, struct DRWPass **ob_center);
+
+void DRW_shgroup_wire_overlay(struct DRWPass *wire_overlay, struct Object *ob);
+void DRW_shgroup_wire_outline(
+        struct DRWPass *wire_outline, struct Object *ob, const bool do_front, const bool do_back, const bool do_outline);
+
+void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, struct Object *ob);
+void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, struct Object *ob);
+void DRW_shgroup_object_center(struct DRWPass *ob_center, struct Object *ob);
+
+#endif /* __DRAW_MODE_PASS_H__ */
\ No newline at end of file
index a3d4f6ef031d85815444da1c0b79030a89414bfb..a48208b55f72169a5514c31ad1c9c40945ea4efa 100644 (file)
@@ -586,6 +586,7 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
 
        if (rv3d->viewport) {
                GPU_viewport_free(rv3d->viewport);
+               MEM_freeN(rv3d->viewport);
                rv3d->viewport = NULL;
        }
 }
@@ -747,6 +748,7 @@ static void view3d_main_region_free(ARegion *ar)
                }
                if (rv3d->viewport) {
                        GPU_viewport_free(rv3d->viewport);
+                       MEM_freeN(rv3d->viewport);
                }
 
                MEM_freeN(rv3d);
index b0faffcab3bdfc0d490eed22a2cf16e067d5401f..65966a67da80374f022700a28bbaf6ea5fa43f63 100644 (file)
@@ -2098,12 +2098,42 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data
 #endif
 }
 
+static void view3d_render_pass(const bContext *C, ARegion *ar)
+{
+       Scene *scene = CTX_data_scene(C);
+       RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */
+
+       if (type->flag & RE_USE_OGL_PIPELINE) {
+               type->view_draw(NULL, C);
+       }
+       else {
+               // Offline Render engine
+       }
+}
+
+static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data))
+{
+
+       view3d_draw_setup_view(C, ar);
+
+       /* Only 100% compliant on new spec goes bellow */
+       view3d_render_pass(C, ar);
+
+       view3d_draw_grid(C, ar);
+       view3d_draw_manipulator(C);
+       view3d_draw_region_info(C, ar);
+}
+
+
 void view3d_main_region_draw(const bContext *C, ARegion *ar)
 {
+       Scene *scene = CTX_data_scene(C);
        View3D *v3d = CTX_wm_view3d(C);
        RegionView3D *rv3d = ar->regiondata;
+       /* TODO layers - In the future we should get RE from Layers */
+       RenderEngineType *type = RE_engines_find(scene->r.engine);
 
-       if (IS_VIEWPORT_LEGACY(v3d)) {
+       if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_OGL_PIPELINE) == 0)) {
                view3d_main_region_draw_legacy(C, ar);
                return;
        }
@@ -2111,12 +2141,20 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
        if (!rv3d->viewport)
                rv3d->viewport = GPU_viewport_create();
 
+       GPU_viewport_bind(rv3d->viewport, &ar->winrct);
+
        /* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
         * before we even call the drawing routine, but let's move on for now (dfelinto)
         * but this is a provisory way to start seeing things in the viewport */
        DrawData draw_data;
        view3d_draw_data_init(C, ar, rv3d, &draw_data);
-       view3d_draw_view(C, ar, &draw_data);
+
+       if (type->flag & RE_USE_OGL_PIPELINE)
+               view3d_draw_view_new(C, ar, &draw_data);
+       else
+               view3d_draw_view(C, ar, &draw_data);
+
+       GPU_viewport_unbind(rv3d->viewport);
 
        v3d->flag |= V3D_INVALID_BACKBUF;
 }
index bed47354d8909654ded2f115373e847cd7c05e68..f7346a378dc253e011ca91251e684ec2afe2179f 100644 (file)
@@ -38,6 +38,7 @@
 struct ARegion;
 struct ARegionType;
 struct BoundBox;
+struct Batch;
 struct DerivedMesh;
 struct Object;
 struct SmokeDomainSettings;
index c5531b8542eff5f3a78351b391a08fb4fbf5dda4..364e77123d95d13f1784b082339709152c2f2f66 100644 (file)
@@ -31,6 +31,7 @@ set(INC
        ../imbuf
        ../makesdna
        ../makesrna
+       ../draw
 
        ../editors/include
 
@@ -64,6 +65,7 @@ set(SRC
        intern/gpu_select.c
        intern/gpu_shader.c
        intern/gpu_texture.c
+       intern/gpu_uniformbuffer.c
        intern/gpu_viewport.c
 
        gawain/attrib_binding.c
@@ -122,6 +124,7 @@ set(SRC
        GPU_select.h
        GPU_shader.h
        GPU_texture.h
+       GPU_uniformbuffer.h
        GPU_viewport.h
 
        intern/gpu_codegen.h
@@ -145,10 +148,16 @@ data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_instance_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
 
+data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_groundline_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_3D_lamp_vert.glsl SRC)
+
 data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC)
 data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC)
index 31ad8243c4bafb57749740d7cea8bb0d77dda2bb..ff00a83d00b68b7cab9eed3df5573eacac047028 100644 (file)
@@ -53,6 +53,8 @@ int GPU_max_textures(void);
 float GPU_max_texture_anisotropy(void);
 int GPU_max_color_texture_samples(void);
 int GPU_max_cube_map_size(void);
+int GPU_max_ubo_binds(void);
+int GPU_max_ubo_size(void);
 int GPU_color_depth(void);
 void GPU_get_dfdy_factors(float fac[2]);
 
index 989b874fd389a863035b6fba631cca1ed351ded9..9611a6f0577b7f8f6d0aa0a7b440d8bd3c2a1bb5 100644 (file)
@@ -52,6 +52,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
 GPUFrameBuffer *GPU_framebuffer_create(void);
 bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
 void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
+void GPU_framebuffer_bind(GPUFrameBuffer *fb);
 void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
 void GPU_framebuffer_free(GPUFrameBuffer *fb);
index 394e751ed9b36f8a6cbdf5bb83cde1c8bcfda505..b36954dd010b0ba3822843ce082efe5d014e29f9 100644 (file)
@@ -38,6 +38,7 @@ extern "C" {
 
 typedef struct GPUShader GPUShader;
 struct GPUTexture;
+struct GPUUniformBuffer;
 
 /* GPU Shader
  * - only for fragment shaders now
@@ -69,14 +70,17 @@ void GPU_shader_free(GPUShader *shader);
 void GPU_shader_bind(GPUShader *shader);
 void GPU_shader_unbind(void);
 
+int GPU_shader_get_program(GPUShader *shader);
 void *GPU_shader_get_interface(GPUShader *shader);
 void GPU_shader_set_interface(GPUShader *shader, void *interface);
 int GPU_shader_get_uniform(GPUShader *shader, const char *name);
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
 void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
        int arraysize, const float *value);
 void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
        int arraysize, const int *value);
 
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
 void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
 void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
 void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
@@ -104,6 +108,7 @@ typedef enum GPUBuiltinShader {
        GPU_SHADER_2D_IMAGE_COLOR,
        /* for simple 3D drawing */
        GPU_SHADER_3D_UNIFORM_COLOR,
+       GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
        GPU_SHADER_3D_FLAT_COLOR,
        GPU_SHADER_3D_SMOOTH_COLOR,
        GPU_SHADER_3D_DEPTH_ONLY,
@@ -126,6 +131,10 @@ typedef enum GPUBuiltinShader {
        GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
        GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
        GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
+       /* lamp drawing */
+       GPU_SHADER_3D_GROUNDPOINT,
+       GPU_SHADER_3D_GROUNDLINE,
+       GPU_SHADER_3D_LAMP_COMMON,
 
        GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
 } GPUBuiltinShader;
diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h
new file mode 100644 (file)
index 0000000..bcb6e10
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Clement Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_uniformbuffer.h
+ *  \ingroup gpu
+ */
+
+typedef struct GPUUniformBuffer GPUUniformBuffer;
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]);
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo);
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data);
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number);
+#if 0 
+void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo);
+#endif
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo);
index fce509377abeb95fb5dd2943dc47529e96408d6b..e44657a46479ea648add762df79c856969869d5f 100644 (file)
 
 #include <stdbool.h>
 
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
+#include "GPU_texture.h"
+
 typedef struct GPUViewport GPUViewport;
 
-GPUViewport *GPU_viewport_create(void);
+#define MAX_BUFFERS 8
+#define MAX_TEXTURES 16
+#define MAX_PASSES 16
+
+/* All FramebufferLists are just the same pointers with different names */
+typedef struct FramebufferList {
+       struct GPUFrameBuffer *framebuffers[MAX_BUFFERS];
+} FramebufferList;
+
+typedef struct TextureList {
+       struct GPUTexture *textures[MAX_TEXTURES];
+} TextureList;
+
+typedef struct PassList {
+       struct DRWPass *passes[MAX_TEXTURES];
+} PassList;
 
+/* Buffer and textures used by the viewport by default */
+typedef struct DefaultFramebufferList {
+       struct GPUFrameBuffer *default_fb;
+} DefaultFramebufferList;
+
+typedef struct DefaultTextureList {
+       struct GPUTexture *color;
+       struct GPUTexture *depth;
+} DefaultTextureList;
+
+typedef struct DefaultPassList {
+       struct DRWPass *non_meshes_pass;
+       struct DRWPass *ob_center_pass;
+} DefaultPassList;
+
+GPUViewport *GPU_viewport_create(void);
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
+void GPU_viewport_unbind(GPUViewport *viewport);
 void GPU_viewport_free(GPUViewport *viewport);
 
+void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss);
+
 /* debug */
 bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]);
 void GPU_viewport_debug_depth_free(GPUViewport *viewport);
index a60865d41d2fbcc45da48ca96d979f326cc9b494..99c133011777999b88aaa1c12fe1425957a7c7c0 100644 (file)
@@ -247,3 +247,89 @@ void Batch_draw(Batch* batch)
        Batch_done_using_program(batch);
        glBindVertexArray(0);
        }
+
+/* clement : temp stuff */
+void Batch_draw_stupid(Batch* batch)
+{
+       if (batch->vao_id)
+               glBindVertexArray(batch->vao_id);
+       else
+               Batch_prime(batch);
+
+       if (batch->program_dirty)
+               Batch_update_program_bindings(batch);
+
+       // Batch_use_program(batch);
+
+       //gpuBindMatrices(batch->program);
+
+       if (batch->elem)
+               {
+               const ElementList* el = batch->elem;
+
+#if TRACK_INDEX_RANGE
+               if (el->base_index)
+                       glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index);
+               else
+                       glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0);
+#else
+               glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0);
+#endif
+               }
+       else
+               glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct);
+
+       // Batch_done_using_program(batch);
+       glBindVertexArray(0);
+}
+
+/* clement : temp stuff */
+void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count)
+{
+       if (batch->vao_id)
+               glBindVertexArray(batch->vao_id);
+       else
+               Batch_prime(batch);
+
+       if (batch->program_dirty)
+               Batch_update_program_bindings(batch);
+
+       const GLint loc = glGetAttribLocation(batch->program, "InstanceModelMatrix");
+
+#if TRUST_NO_ONE
+       assert(loc != -1);
+#endif
+
+       glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
+       glEnableVertexAttribArray(loc);
+       glVertexAttribPointer(loc + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)0);
+       glEnableVertexAttribArray(loc + 1);
+       glVertexAttribPointer(loc + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(sizeof(float)*4));
+       glEnableVertexAttribArray(loc + 2);
+       glVertexAttribPointer(loc + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(2 * sizeof(float)*4));
+       glEnableVertexAttribArray(loc + 3);
+       glVertexAttribPointer(loc + 3, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(3 * sizeof(float)*4));
+       glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+       glVertexAttribDivisor(loc + 0, 1);
+       glVertexAttribDivisor(loc + 1, 1);
+       glVertexAttribDivisor(loc + 2, 1);
+       glVertexAttribDivisor(loc + 3, 1);
+
+       // Batch_use_program(batch);
+
+       //gpuBindMatrices(batch->program);
+
+       if (batch->elem)
+               {
+               const ElementList* el = batch->elem;
+
+               glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
+               }
+       else
+               glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count);
+
+       // Batch_done_using_program(batch);
+       glBindVertexArray(0);
+}
+
index 932ee18270321c52427b2b6622fe16884f4f52a9..8b5c48cca792202fd9702c3f0a141d41cb3a6b1e 100644 (file)
@@ -57,6 +57,8 @@ void Batch_Uniform3fv(Batch*, const char* name, const float data[3]);
 void Batch_Uniform4fv(Batch*, const char* name, const float data[4]);
 
 void Batch_draw(Batch*);
+void Batch_draw_stupid(Batch* batch);
+void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count);
 
 
 
index e8fd4b8b8b13344206889b633f4c17fa5a46dde9..d7ed65e853ebb5f305824f48322c728a8b22120f 100644 (file)
@@ -69,6 +69,8 @@ static struct GPUGlobal {
        GLint maxtexsize;
        GLint maxcubemapsize;
        GLint maxtextures;
+       GLint maxubosize;
+       GLint maxubobinds;
        bool extdisabled;
        int colordepth;
        int samples_color_texture_max;
@@ -121,6 +123,16 @@ int GPU_max_cube_map_size(void)
        return GG.maxcubemapsize;
 }
 
+int GPU_max_ubo_binds(void)
+{
+       return GG.maxubobinds;
+}
+
+int GPU_max_ubo_size(void)
+{
+       return GG.maxubosize;
+}
+
 void GPU_get_dfdy_factors(float fac[2])
 {
        copy_v2_v2(fac, GG.dfdyfactors);
@@ -154,6 +166,9 @@ void gpu_extensions_init(void)
        else
                GG.max_anisotropy = 1.0f;
 
+       glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds);
+       glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
+
        GLint r, g, b;
        glGetIntegerv(GL_RED_BITS, &r);
        glGetIntegerv(GL_GREEN_BITS, &g);
index 2ef8018e5e97adf932d054cb5605690646fc4f3f..1efc451f4a8af12a7bc7a5706aa253a71926c62c 100644 (file)
@@ -260,6 +260,43 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
        glPushMatrix();
 }
 
+void GPU_framebuffer_bind(GPUFrameBuffer *fb)
+{
+       int numslots = 0, i;
+       GLenum attachments[4];
+       GLenum readattachement = 0;
+       GPUTexture *tex;
+
+       for (i = 0; i < 4; i++) {
+               if (fb->colortex[i]) {
+                       attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
+                       tex = fb->colortex[i];
+
+                       if (!readattachement)
+                               readattachement = GL_COLOR_ATTACHMENT0 + i;
+
+                       numslots++;
+               }
+       }
+
+       /* bind framebuffer */
+       glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
+
+       if (numslots == 0) {
+               glDrawBuffer(GL_NONE);
+               glReadBuffer(GL_NONE);
+               tex = fb->depthtex;
+       }
+       else {
+               /* last bound prevails here, better allow explicit control here too */
+               glDrawBuffers(numslots, attachments);
+               glReadBuffer(readattachement);
+       }
+
+       glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
+       GG.currentfb = fb->object;
+}
+
 
 void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
 {
@@ -283,7 +320,6 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
        /* push matrices and set default viewport and matrix */
        glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
        GG.currentfb = fb->object;
-       GG.currentfb = fb->object;
 }
 
 bool GPU_framebuffer_bound(GPUFrameBuffer *fb)
index b81c19d5c706dcb5f15cd0e0c6c68b8862b0ea13..0d6fd5f7b997072e74dab7bc55269f8be8bc325d 100644 (file)
@@ -37,6 +37,7 @@
 #include "GPU_debug.h"
 #include "GPU_extensions.h"
 #include "GPU_shader.h"
+#include "GPU_uniformbuffer.h"
 #include "GPU_texture.h"
 
 #include "gpu_shader_private.h"
@@ -64,10 +65,16 @@ extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
 extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
 extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
 extern char datatoc_gpu_shader_3D_vert_glsl[];
+extern char datatoc_gpu_shader_3D_instance_vert_glsl[];
 extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
 extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
 extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
 
+extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
+extern char datatoc_gpu_shader_3D_groundline_vert_glsl[];
+extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
+extern char datatoc_gpu_shader_3D_lamp_vert_glsl[];
+
 extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
 extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[];
 extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[];
@@ -511,11 +518,24 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
        return glGetUniformLocation(shader->program, name);
 }
 
+int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
+{
+       BLI_assert(shader && shader->program);
+
+       return glGetUniformBlockIndex(shader->program, name);
+}
+
 void *GPU_shader_get_interface(GPUShader *shader)
 {
        return shader->uniform_interface;
 }
 
+/* Clement : Temp */
+int GPU_shader_get_program(GPUShader *shader)
+{
+       return (int)shader->program;
+}
+
 void GPU_shader_set_interface(GPUShader *shader, void *interface)
 {
        shader->uniform_interface = interface;
@@ -563,6 +583,17 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou
        }
 }
 
+void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
+{
+       int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
+
+       if (location == -1) {
+               return;
+       }
+
+       glUniformBlockBinding(shader->program, location, bindpoint);
+}
+
 void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
 {
        int number = GPU_texture_bound_number(tex);
@@ -645,12 +676,21 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
                [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
                                                datatoc_gpu_shader_image_color_frag_glsl },
                [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
+               [GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE] = { datatoc_gpu_shader_3D_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
                [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
                                               datatoc_gpu_shader_flat_color_frag_glsl },
                [GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
                                                 datatoc_gpu_shader_3D_smooth_color_frag_glsl },
                [GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl },
 
+               [GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
+               [GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_groundline_vert_glsl,
+                                              datatoc_gpu_shader_uniform_color_frag_glsl,
+                                              datatoc_gpu_shader_3D_groundline_geom_glsl },
+
+               [GPU_SHADER_3D_LAMP_COMMON] = { datatoc_gpu_shader_3D_lamp_vert_glsl,
+                                               datatoc_gpu_shader_uniform_color_frag_glsl},
+
                [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
                        { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
                [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =
index 6fb658e20ebb05f7531958a6adf7543f35c357c6..3513250993eb25ada56f968a245568c455ecfae4 100644 (file)
@@ -91,6 +91,7 @@ static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type,
                /* Formats texture & renderbuffer */
                case GPU_RGBA16F: return GL_RGBA16F;
                case GPU_RG32F: return GL_RG32F;
+               case GPU_RG16F: return GL_RG16F;
                case GPU_RGBA8: return GL_RGBA8;
                case GPU_R8: return GL_R8;
                /* Special formats texture & renderbuffer */
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
new file mode 100644 (file)
index 0000000..76aa1a8
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2005 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Clement Foucault.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_uniformbuffer.c
+ *  \ingroup gpu
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+
+#include "GPU_extensions.h"
+#include "GPU_glew.h"
+#include "GPU_uniformbuffer.h"
+
+struct GPUUniformBuffer {
+       int size;           /* in bytes */
+       GLuint bindcode;    /* opengl identifier for UBO */
+       int bindpoint;      /* current binding point */
+};
+
+GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256])
+{
+       GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBuffer), "GPUUniformBuffer");
+       ubo->size = size;
+
+       /* Generate Buffer object */
+       glGenBuffers(1, &ubo->bindcode);
+       
+       if (!ubo->bindcode) {
+               if (err_out)
+                       BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO create failed");
+               GPU_uniformbuffer_free(ubo);
+               return NULL;
+       }
+
+       if (ubo->size > GPU_max_ubo_size()) {
+               if (err_out)
+                       BLI_snprintf(err_out, 256, "GPUUniformBuffer: UBO too big");
+               GPU_uniformbuffer_free(ubo);
+               return NULL;
+       }
+
+       glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+       glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW);
+       glBindBuffer(GL_UNIFORM_BUFFER, 0);
+
+       return ubo;
+}
+
+void GPU_uniformbuffer_free(GPUUniformBuffer *ubo)
+{
+       glDeleteBuffers(1, &ubo->bindcode);
+       MEM_freeN(ubo);
+}
+
+void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data)
+{
+       glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode);
+       glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data);
+       glBindBuffer(GL_UNIFORM_BUFFER, 0);
+}
+
+void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number)
+{
+       if (number >= GPU_max_ubo_binds()) {
+               fprintf(stderr, "Not enough UBO slots.\n");
+               return;
+       }
+
+       if (ubo->bindcode != 0) {
+               glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode);
+       }
+
+       ubo->bindpoint = number;
+}
+
+int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo)
+{
+       return ubo->bindpoint;
+}
\ No newline at end of file
index a4fb3494639692044a45a1df9a1fe75bf643cc96..b1964857ab104af360d5e19bda4057a4a08625b8 100644 (file)
  * System that manages viewport drawing.
  */
 
+#include <string.h>
+
+#include "BLI_rect.h"
+
+#include "DNA_vec_types.h"
+
+#include "GPU_framebuffer.h"
 #include "GPU_glew.h"
 #include "GPU_immediate.h"
-#include "GPU_viewport.h"
 #include "GPU_texture.h"
+#include "GPU_viewport.h"
+
+#include "DRW_engine.h"
 
 #include "MEM_guardedalloc.h"
 
@@ -43,19 +52,200 @@ struct GPUViewport {
 
        /* debug */
        GPUTexture *debug_depth;
-       int debug_width, debug_height;
+       int size[2];
+
+       /* Viewport Buffer Storage */
+       /* TODO indentify to what engine conf are theses buffers */
+       DefaultFramebufferList *fbl;
+       DefaultTextureList *txl;
+       DefaultPassList *psl;
 };
 
+static void GPU_viewport_buffers_free(GPUViewport *viewport);
+static void GPU_viewport_passes_free(GPUViewport *viewport);
+
 GPUViewport *GPU_viewport_create(void)
 {
        GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport");
+       viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList");
+       viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList");
+       viewport->psl = MEM_callocN(sizeof(PassList), "PassList");
+       viewport->size[0] = viewport->size[1] = -1;
+
        return viewport;
 }
 
+void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss)
+{
+       *fbs = viewport->fbl;
+       *txs = viewport->txl;
+       *pss = viewport->psl;
+}
+
+void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+{
+       /* add one pixel because of scissor test */
+       int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1;
+
+#ifndef WITH_VIEWPORT_CACHE_TEST
+       /* TODO for testing only, we need proper cache invalidation */
+       GPU_viewport_passes_free(viewport);
+#endif
+
+       if (viewport->fbl->default_fb) {
+               if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) {
+                       GPU_viewport_buffers_free(viewport);
+               }
+       }
+
+       if (!viewport->fbl->default_fb) {
+               bool ok = true;
+               viewport->size[0] = rect_w;
+               viewport->size[1] = rect_h;
+
+               viewport->fbl->default_fb = GPU_framebuffer_create();
+               if (!viewport->fbl->default_fb) {
+                       ok = false;
+                       goto cleanup;
+               }
+
+               /* Color */
+               /* No multi samples for now */
+               viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL);
+               if (!viewport->txl->color) {
+                       ok = false;
+                       goto cleanup;
+               }
+
+               if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) {
+                       ok = false;
+                       goto cleanup;
+               }
+
+               /* Depth */
+               viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL);
+               if (!viewport->txl->depth) {
+                       ok = false;
+                       goto cleanup;
+               }
+               else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) {
+                       ok = false;
+                       goto cleanup;
+               }
+               else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) {
+                       ok = false;
+                       goto cleanup;
+               }
+
+cleanup:
+               if (!ok) {
+                       GPU_viewport_free(viewport);
+                       MEM_freeN(viewport);
+                       return;
+               }
+
+               GPU_framebuffer_restore();
+       }
+
+       GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0);
+}
+
+static void draw_ofs_to_screen(GPUViewport *viewport)
+{
+       GPUTexture *color = viewport->txl->color;
+
+       const float w = (float)GPU_texture_width(color);
+       const float h = (float)GPU_texture_height(color);
+
+       VertexFormat *format = immVertexFormat();
+       unsigned texcoord = add_attrib(format, "texCoord", GL_FLOAT, 2, KEEP_FLOAT);
+       unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT);
+
+       immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA);
+
+       GPU_texture_bind(color, 0);
+
+       immUniform1i("image", 0); /* default GL_TEXTURE0 unit */
+
+       immBegin(GL_QUADS, 4);
+
+       immAttrib2f(texcoord, 0.0f, 0.0f);
+       immVertex2f(pos, 0.0f, 0.0f);
+
+       immAttrib2f(texcoord, 1.0f, 0.0f);
+       immVertex2f(pos, w, 0.0f);
+
+       immAttrib2f(texcoord, 1.0f, 1.0f);
+       immVertex2f(pos, w, h);
+
+       immAttrib2f(texcoord, 0.0f, 1.0f);
+       immVertex2f(pos, 0.0f, h);
+
+       immEnd();
+
+       GPU_texture_unbind(color);
+
+       immUnbindProgram();
+}
+
+void GPU_viewport_unbind(GPUViewport *viewport)
+{
+       if (viewport->fbl->default_fb) {
+               GPU_framebuffer_texture_unbind(NULL, NULL);
+               GPU_framebuffer_restore();
+
+               glEnable(GL_SCISSOR_TEST);
+
+               /* This might be bandwidth limiting */
+               draw_ofs_to_screen(viewport);
+       }
+}
+
+static void GPU_viewport_buffers_free(GPUViewport *viewport)
+{
+       FramebufferList *fbl = (FramebufferList *)viewport->fbl;
+       TextureList *txl = (TextureList *)viewport->txl;
+       int i;
+       for (i = MAX_BUFFERS - 1; i > -1; --i) {
+               GPUFrameBuffer *fb = fbl->framebuffers[i];
+               if (fb) {
+                       GPU_framebuffer_free(fb);
+                       fbl->framebuffers[i] = NULL;
+               }
+       }
+       for (i = MAX_TEXTURES - 1; i > -1; --i) {
+               GPUTexture *tex = txl->textures[i];
+               if (tex) {
+                       GPU_texture_free(tex);
+                       txl->textures[i] = NULL;
+               }
+       }
+}
+
+static void GPU_viewport_passes_free(GPUViewport *viewport)
+{
+       PassList *psl = (PassList *)viewport->psl;
+       int i;
+
+       for (i = MAX_PASSES - 1; i > -1; --i) {
+               struct DRWPass *pass = psl->passes[i];
+               if (pass) {
+                       DRW_pass_free(pass);
+                       MEM_freeN(pass);
+                       psl->passes[i] = NULL;
+               }
+       }
+}
+
 void GPU_viewport_free(GPUViewport *viewport)
 {
        GPU_viewport_debug_depth_free(viewport);
-       MEM_freeN(viewport);
+       GPU_viewport_buffers_free(viewport);
+       GPU_viewport_passes_free(viewport);
+
+       MEM_freeN(viewport->fbl);
+       MEM_freeN(viewport->txl);
+       MEM_freeN(viewport->psl);
 }
 
 /****************** debug ********************/
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl
new file mode 100644 (file)
index 0000000..f16fa21
--- /dev/null
@@ -0,0 +1,16 @@
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+layout(points) in;
+layout(line_strip, max_vertices = 2) out;
+
+void main()
+{
+       vec3 vert = gl_in[0].gl_Position.xyz;
+       gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0);
+       EmitVertex();
+       gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0);
+       EmitVertex();
+       EndPrimitive();
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_vert.glsl
new file mode 100644 (file)
index 0000000..60793bf
--- /dev/null
@@ -0,0 +1,8 @@
+
+/* Does Nothing */
+in vec3 pos;
+
+void main()
+{
+       gl_Position = vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl
new file mode 100644 (file)
index 0000000..be6b601
--- /dev/null
@@ -0,0 +1,11 @@
+
+/* Make to be used with dynamic batching so no Model Matrix needed */
+uniform mat4 ViewProjectionMatrix;
+
+in vec3 pos;
+
+void main()
+{
+       gl_Position = ViewProjectionMatrix * vec4(pos.xy, 0.0, 1.0);
+       gl_PointSize = 2.0;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl
new file mode 100644 (file)
index 0000000..7eb321f
--- /dev/null
@@ -0,0 +1,10 @@
+
+uniform mat4 ViewProjectionMatrix;
+
+in vec3 pos;
+in mat4 InstanceModelMatrix;
+
+void main()
+{
+       gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_lamp_vert.glsl
new file mode 100644 (file)
index 0000000..dbc683e
--- /dev/null
@@ -0,0 +1,24 @@
+
+uniform mat4 ViewProjectionMatrix;
+uniform vec3 screen_vecs[2];
+uniform float size;
+uniform float pixel_size;
+
+in vec2 pos;
+in mat4 InstanceModelMatrix;
+
+#define lamp_pos InstanceModelMatrix[3].xyz
+
+float mul_project_m4_v3_zfac(in vec3 co)
+{
+       return (ViewProjectionMatrix[0][3] * co.x) +
+              (ViewProjectionMatrix[1][3] * co.y) +
+              (ViewProjectionMatrix[2][3] * co.z) + ViewProjectionMatrix[3][3];
+}
+
+void main()
+{
+       float pix_size = mul_project_m4_v3_zfac(lamp_pos) * pixel_size;
+       vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y;
+       gl_Position = ViewProjectionMatrix * vec4(lamp_pos + screen_pos * size * pix_size, 1.0);
+}
index 6f6c6d7d14564aa4babe43bac4b94447f09085c0..3a4293c8ad8200f3d387bac4814c66537ec5dba3 100644 (file)
@@ -59,6 +59,7 @@ typedef struct LayerCollection {
        ListBase object_bases;      /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
        ListBase overrides;
        ListBase layer_collections; /* synced with collection->collections */
+       ListBase engine_settings; /* CollectionEngineSettings */
 } LayerCollection;
 
 typedef struct SceneLayer {
@@ -102,8 +103,54 @@ enum {
 /* SceneLayer->flag */
 enum {
        SCENE_LAYER_RENDER = (1 << 0),
+       SCENE_LAYER_ENGINE_DIRTY  = (1 << 1),
 };
 
+
+/* *************************************************************** */
+/* Engine Settings */
+
+typedef struct CollectionEngineProperty {
+       struct CollectionEngineProperty *next, *prev;
+       char name[64]; /* MAX_NAME */
+       short type;
+       short pad;
+       char flag;
+       char pad2[3];
+} CollectionEngineProperty;
+
+typedef struct CollectionEnginePropertyInt {
+  struct CollectionEngineProperty data;
+  int value;
+  int pad;
+} CollectionEnginePropertyInt;
+
+typedef struct CollectionEnginePropertyFloat {
+  struct CollectionEngineProperty data;
+  float value;
+  float pad;
+} CollectionEnginePropertyFloat;
+
+typedef struct CollectionEngineSettings {
+       struct CollectionEngineSettings *next, *prev;
+       char name[32]; /* engine name - MAX_NAME */
+       ListBase properties; /* CollectionProperty */
+} CollectionEngineSettings;
+
+/* CollectionEngineProperty->flag */
+enum {
+       COLLECTION_PROP_USE = (1 << 0),
+};
+
+/* CollectionEntineProperty.type */
+typedef enum CollectionEnginePropertyType {
+       COLLECTION_PROP_TYPE_FLOAT = 0,
+       COLLECTION_PROP_TYPE_INT = 1,
+} CollectionEnginePropertyType;
+
+/* *************************************************************** */
+
+
 #ifdef __cplusplus
 }
 #endif
index 0c500e366a7b7b89fc794fc94698536929b742d7..bd8278f897ab53d4c7669f3ffbc5ab7d7701f331 100644 (file)
@@ -90,6 +90,43 @@ typedef struct TexPaintSlot {
        int pad;
 } TexPaintSlot;
 
+/* Material Engine Settings */
+typedef struct MaterialEngineSettings {
+       struct MaterialEngineSettings *next, *prev;
+       char name[32]; /* engine name - MAX_NAME */
+       void *data;
+} MaterialEngineSettings;
+
+/* Clay engine */
+
+/* MaterialRuntimeClay.flag */
+#define CLAY_OUTDATED          1
+
+typedef struct MaterialEngineSettingsClay {
+       short type;
+       short matcap_icon; /* Icon ID */
+
+       float matcap_rot;
+       float matcap_hue;
+       float matcap_sat;
+       float matcap_val;
+
+       float ssao_distance;
+       float ssao_attenuation;
+       float ssao_factor_cavity;
+       float ssao_factor_edge;
+
+       /* Runtime */
+       short flag;
+       short pad;
+       int ubo_index;
+} MaterialEngineSettingsClay;
+
+/* MaterialEngineSettingsClay.type */
+#define CLAY_MATCAP_NONE               0
+#define CLAY_MATCAP_SIMPLE             1
+#define CLAY_MATCAP_COMPLETE   2
+
 typedef struct Material {
        ID id;
        struct AnimData *adt;   /* animation data (must be immediately after id for utilities to use it) */ 
@@ -203,6 +240,9 @@ typedef struct Material {
 
        struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
                                            * with refresh_texpaint_image_cache */
+       /* Engine Settings */
+       ListBase engines_settings; /* MaterialEngineSettings */
+
        ListBase gpumaterial;           /* runtime */
 } Material;
 
index 60aaa4ace20c4adeeb5cf8d17963f279776a6634..080ade57c0dbfada145a9016a82c9fe05d13bd63 100644 (file)
@@ -46,6 +46,7 @@ struct Object;
 struct AnimData;
 struct Ipo;
 struct BoundBox;
+struct CollectionSettings;
 struct Path;
 struct Material;
 struct PartDeflect;
@@ -302,6 +303,8 @@ typedef struct Object {
        LodLevel *currentlod;
 
        struct PreviewImage *preview;
+
+       struct ListBase *collection_settings; /* used by depsgraph, flushed from collection-tree */
 } Object;
 
 /* Warning, this is not used anymore because hooks are now modifiers */
index ba5e50ec44196443e743e853127c8e9052ad4bf1..6e56824b1769038c22f262bbee865e0e722be890 100644 (file)
@@ -48,6 +48,7 @@ extern "C" {
 #include "DNA_freestyle_types.h"
 #include "DNA_gpu_types.h"
 #include "DNA_layer_types.h"
+#include "DNA_material_types.h"
 #include "DNA_userdef_types.h"
 
 struct CurveMapping;
@@ -538,6 +539,50 @@ typedef enum BakePassFilter {
 
 #define R_BAKE_PASS_FILTER_ALL (~0)
 
+/* *************************************************************** */
+/* Engine Settings */
+
+typedef struct RenderEngineSettings {
+       struct RenderEngineSettings *next, *prev;
+       char name[32]; /* engine name */
+       void *data;
+} RenderEngineSettings;
+
+/* Render Data */
+typedef struct RenderEngineSettingsClay {
+       /* Use same layout as MaterialEngineSettingsClay so this struct
+        * can be used as Material Settings. */
+       short type;
+       short matcap_icon; /* Icon ID */
+
+       float matcap_rot;
+       float matcap_hue;
+       float matcap_sat;
+       float matcap_val;
+
+       float ssao_distance;
+       float ssao_attenuation;
+       float ssao_factor_cavity;
+       float ssao_factor_edge;
+
+       short flag;
+       short pad;
+       int ubo_index;
+       /* end of MaterialEngineSettingsClay */
+
+       /* Global Settings */
+       short options;
+       short pad1;
+       int ssao_samples;
+       int pad2[2];
+} RenderEngineSettingsClay;
+
+/* RenderEngineSettingsClay.options */
+typedef enum ClayFlagSettings {
+       CLAY_USE_AO     = (1 << 0),
+       CLAY_USE_HSV    = (1 << 1),
+} ClayFlagSettings;
+
 /* *************************************************************** */
 /* Render Data */
 
@@ -1707,6 +1752,9 @@ typedef struct Scene {
        struct SceneCollection *collection;
        int active_layer;
        int pad4;
+
+       ListBase engines_settings; /* RenderEngineSettings */
+       int pad5[2];
 } Scene;
 
 /* **************** RENDERDATA ********************* */
@@ -1895,6 +1943,7 @@ enum {
 /* scene->r.engine (scene.c) */
 extern const char *RE_engine_id_BLENDER_RENDER;
 extern const char *RE_engine_id_BLENDER_GAME;
+extern const char *RE_engine_id_BLENDER_CLAY;
 extern const char *RE_engine_id_CYCLES;
 
 /* **************** SCENE ********************* */
index 9c45e34f211909622ff370af9f0c2ffa87abca0a..2221526fa8bef6b9373f1c852eef85e8f25fb641 100644 (file)
@@ -106,6 +106,7 @@ extern StructRNA RNA_ClothCollisionSettings;
 extern StructRNA RNA_ClothModifier;
 extern StructRNA RNA_ClothSettings;
 extern StructRNA RNA_CloudsTexture;
+extern StructRNA RNA_CollectionEngineSettings;
 extern StructRNA RNA_CollectionProperty;
 extern StructRNA RNA_CollisionModifier;
 extern StructRNA RNA_CollisionSensor;
@@ -385,6 +386,8 @@ extern StructRNA RNA_MaterialStrand;
 extern StructRNA RNA_MaterialSubsurfaceScattering;
 extern StructRNA RNA_MaterialTextureSlot;
 extern StructRNA RNA_MaterialVolume;
+extern StructRNA RNA_MaterialEngineSettings;
+extern StructRNA RNA_MaterialEngineSettingsClay;
 extern StructRNA RNA_Mask;
 extern StructRNA RNA_MaskLayer;
 extern StructRNA RNA_Menu;
@@ -500,6 +503,8 @@ extern StructRNA RNA_RenderLayer;
 extern StructRNA RNA_RenderPass;
 extern StructRNA RNA_RenderResult;
 extern StructRNA RNA_RenderSettings;
+extern StructRNA RNA_RenderEngineSettings;
+extern StructRNA RNA_RenderEngineSettingsClay;
 extern StructRNA RNA_RigidBodyWorld;
 extern StructRNA RNA_RigidBodyObject;
 extern StructRNA RNA_RigidBodyJointConstraint;
index 0f3ea27a7f9d2aefc70a6391c7062f8134c8846c..0bf2bbb61094b3a741feb0abe3e6bbb3bd843398 100644 (file)
@@ -192,6 +192,10 @@ if(WITH_GAMEENGINE)
        add_definitions(-DWITH_GAMEENGINE)
 endif()
 
+if(WITH_CLAY_ENGINE)
+       add_definitions(-DWITH_CLAY_ENGINE)
+endif()
+
 if(WITH_IMAGE_OPENEXR)
        add_definitions(-DWITH_OPENEXR)
 endif()
@@ -341,6 +345,7 @@ blender_include_dirs(
        ../../bmesh
        ../../blentranslation
        ../../depsgraph
+       ../../draw
        ../../gpu
        ../../imbuf
        ../../ikplugin
index b293f20dd95d927b06747e4a9ce53648846e06af..4d3e3ffca26c2c04b5db74e6eac7527cc3eab9ef 100644 (file)
@@ -313,6 +313,31 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value)
        }
 }
 
+static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr)
+{
+#ifdef WITH_CLAY_ENGINE
+       MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data;
+       if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) {
+               return  &RNA_MaterialEngineSettingsClay;
+       }
+#endif
+       return &RNA_MaterialEngineSettings;
+}
+
+static void rna_Material_update_engine_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
+{
+#if 0
+       Material *ma = (Material *)ptr->data;
+       RenderEngineSettings *ed = DRW_material_settings_get(ma, sce->r.engine, NULL);
+
+       if (ed->runtime) {
+               MEM_freeN(ed->runtime);
+               ed->runtime = NULL;
+       }
+#endif
+       WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
 static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value)
 {
        Material *ma = (Material *)ptr->data;
@@ -824,6 +849,118 @@ static void rna_def_material_mtex(BlenderRNA *brna)
        RNA_def_property_update(prop, 0, "rna_Material_update");
 }
 
+static void rna_def_material_settings_clay(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       static EnumPropertyItem clay_matcap_items[] = {
+               {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+               {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+               {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+               {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+               {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+               {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+               {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+               {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+               {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+               {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+               {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+               {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+               {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+               {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+               {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+               {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+               {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+               {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+               {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+               {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+               {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+               {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+               {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+               {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       static EnumPropertyItem clay_matcap_type[] = {
+               {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
+               {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
+               {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       srna = RNA_def_struct(brna, "MaterialEngineSettingsClay", "MaterialEngineSettings");
+       RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
+       RNA_def_struct_sdna_from(srna, "MaterialEngineSettingsClay", "data");
+
+       prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, clay_matcap_type);
+       RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, clay_matcap_items);
+       RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_val");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+
+       prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+       RNA_def_property_range(prop, 1.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
+}
+
+static void rna_def_material_engine_settings(BlenderRNA *brna)
+{
+       StructRNA *srna;
+
+       srna = RNA_def_struct(brna, "MaterialEngineSettings", NULL);
+       RNA_def_struct_ui_text(srna, "Engine Settings", "Engine specific settings");
+       RNA_def_struct_sdna(srna, "MaterialEngineSettings");
+       RNA_def_struct_refine_func(srna, "rna_MaterialEngineSettings_refine");
+
+       rna_def_material_settings_clay(brna);
+}
+
 static void rna_def_material_gamesettings(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -2087,6 +2224,11 @@ void RNA_def_material(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "MaterialGameSettings");
        RNA_def_property_ui_text(prop, "Game Settings", "Game material settings");
 
+       /* Engine settings */
+       prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_struct_type(prop, "MaterialEngineSettings");
+       RNA_def_property_ui_text(prop, "Material Engine Settings", "Engine specific settings");
+
        /* nodetree */
        prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
@@ -2136,6 +2278,7 @@ void RNA_def_material(BlenderRNA *brna)
        rna_def_material_strand(brna);
        rna_def_material_physics(brna);
        rna_def_material_gamesettings(brna);
+       rna_def_material_engine_settings(brna);
 
        RNA_api_material(srna);
 }
index 518c7efd9157f3e21d1c0675cc08e1dc473cd4fa..5f796261c731920b46377aac5ad6d0428563d322 100644 (file)
@@ -261,6 +261,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
        RNA_parameter_list_free(&list);
 }
 
+static void engine_collection_settings_create(RenderEngine *engine, struct CollectionEngineSettings *ces)
+{
+       extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
+       PointerRNA ptr,cesptr;
+       ParameterList list;
+       FunctionRNA *func;
+
+       RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
+       RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &cesptr);
+       func = &rna_RenderEngine_collection_settings_create_func;
+
+       RNA_parameter_list_create(&list, &ptr, func);
+       RNA_parameter_set_lookup(&list, "collection_settings", &cesptr);
+       engine->type->ext.call(NULL, &ptr, func, &list);
+
+       RNA_parameter_list_free(&list);
+}
+
 /* RenderEngine registration */
 
 static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -281,7 +299,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
        RenderEngineType *et, dummyet = {NULL};
        RenderEngine dummyengine = {NULL};
        PointerRNA dummyptr;
-       int have_function[6];
+       int have_function[7];
 
        /* setup dummy engine & engine type to store static properties in */
        dummyengine.type = &dummyet;
@@ -323,8 +341,9 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
        et->view_update = (have_function[3]) ? engine_view_update : NULL;
        et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
        et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
+       et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL;
 
-       BLI_addtail(&R_engines, et);
+       RE_engines_register(bmain, et);
 
        return et->ext.srna;
 }
@@ -489,6 +508,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
        parm = RNA_def_pointer(func, "node", "Node", "", "");
        RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
 
+       /* per-collection engine settings initialization */
+       func = RNA_def_function(srna, "collection_settings_create", NULL);
+       RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
+       RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
+       parm = RNA_def_pointer(func, "collection_settings", "CollectionEngineSettings", "", "");
+       RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+
        /* tag for redraw */
        func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
        RNA_def_function_ui_description(func, "Request redraw for viewport rendering");
index 8f36af96cf42b098fee15462076b982e245a17f6..ec9a08af287a25a3a75e283da6c57b467622a288 100644 (file)
@@ -52,6 +52,8 @@
 
 #include "GPU_extensions.h"
 
+#include "DRW_engine.h"
+
 #include "RNA_define.h"
 #include "RNA_enum_types.h"
 
@@ -80,6 +82,8 @@
 
 #include "BLI_threads.h"
 
+#define NO_ENGINE "NO_ENGINE"
+
 #ifdef WITH_OPENEXR
 EnumPropertyItem rna_enum_exr_codec_items[] = {
        {R_IMF_EXR_CODEC_NONE, "NONE", 0, "None", ""},
@@ -1872,6 +1876,43 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value)
                gm->exitkey = value;
 }
 
+static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr)
+{
+#ifdef WITH_CLAY_ENGINE
+       RenderEngineSettings *res = (RenderEngineSettings *)ptr->data;
+
+       if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+               return  &RNA_RenderEngineSettingsClay;
+       }
+#endif
+       return &RNA_RenderEngineSettings;
+}
+
+static PointerRNA rna_RenderEngineSettings_active_get(PointerRNA *ptr)
+{
+       Scene *scene = (Scene *)ptr->data;
+       RenderEngineSettings *res;
+
+       /* Ensure settings exists */
+       DRW_render_settings_get(scene, scene->r.engine);
+
+       res = BLI_findstring(&scene->engines_settings, scene->r.engine, offsetof(RenderEngineSettings, name));
+
+       return rna_pointer_inherit_refine(ptr, &RNA_RenderEngineSettings, res);
+}
+
+static void rna_RenderEngineSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+       Scene *sce = (Scene *)ptr->id.data;
+       MaterialEngineSettingsClay *res;
+
+       res = (MaterialEngineSettingsClay *)DRW_render_settings_get(sce, sce->r.engine);
+
+       res->flag = CLAY_OUTDATED;
+
+       WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+
 static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame)
 {
        TimeMarker *marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
@@ -2311,6 +2352,83 @@ static void rna_SceneCollection_object_unlink(
        WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
 }
 
+/****** layer collection engine settings *******/
+
+static StructRNA *rna_CollectionEngineSettings_refine(struct PointerRNA *ptr)
+{
+       CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;
+
+       if (STREQ(ces->name, "BLENDER_CLAY")) {
+               return &RNA_CollectionEngineSettingsClay;
+       }
+
+       /* TODO - handle other engines */
+       TODO_LAYER;
+       (void) ces;
+
+       return &RNA_CollectionEngineSettings;
+}
+
+/****** clay engine settings *******/
+
+#define RNA_LAYER_ENGINE_USE_GET_SET(_NAME_)                                           \
+       static int rna_LayerEngineSettings_##_NAME_##_use_get(PointerRNA *ptr)             \
+    {                                                                                  \
+           CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;         \
+           return BKE_collection_engine_property_use_get(ces, #_NAME_) ? 1 : 0;           \
+       }                                                                                  \
+                                                                                          \
+       static void rna_LayerEngineSettings_##_NAME_##_use_set(PointerRNA *ptr, int value) \
+    {                                                                                  \
+           CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;         \
+           BKE_collection_engine_property_use_set(ces, #_NAME_, value? true : false);     \
+       }
+
+#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _NAME_)                                   \
+static _TYPE_ rna_LayerEngineSettings_##_NAME_##_get(PointerRNA *ptr)              \
+{                                                                                  \
+       CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;         \
+       return BKE_collection_engine_property_value_get_##_TYPE_(ces, #_NAME_);        \
+}                                                                                  \
+                                                                                      \
+static void rna_LayerEngineSettings_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value)  \
+{                                                                                  \
+       CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;         \
+       BKE_collection_engine_property_value_set_##_TYPE_(ces, #_NAME_, value);        \
+}                                                                                  \
+       RNA_LAYER_ENGINE_USE_GET_SET(_NAME_)
+
+#define RNA_LAYER_ENGINE_GET_SET_FLOAT(_NAME_) \
+       RNA_LAYER_ENGINE_GET_SET(float, _NAME_)
+
+#define RNA_LAYER_ENGINE_GET_SET_INT(_NAME_) \
+       RNA_LAYER_ENGINE_GET_SET(int, _NAME_)
+
+
+RNA_LAYER_ENGINE_GET_SET_INT(type)
+RNA_LAYER_ENGINE_GET_SET_INT(matcap_icon)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_rotation)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_hue)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_saturation)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_value)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_cavity)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_edge)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_distance)
+RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_attenuation)
+
+#undef RNA_LAYER_ENGINE_GET_SET_INT
+#undef RNA_LAYER_ENGINE_GET_SET_FLOAT
+#undef RNA_LAYER_ENGINE_GET_SET
+#undef RNA_LAYER_ENGINE_USE_GET_SET
+
+static void rna_CollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
+{
+       SceneLayer *sl = CTX_data_scene_layer(C);
+       BKE_scene_layer_engine_settings_recalculate(sl);
+}
+
+/***********************************/
+
 static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value)
 {
        SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
@@ -2340,6 +2458,25 @@ static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *it
        return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
 }
 
+static PointerRNA rna_LayerCollection_engine_settings_get(ID *UNUSED(id), LayerCollection *lc, bContext *C, const char *engine)
+{
+       Scene *scene = CTX_data_scene(C);
+       const char *engine_name;
+
+       if (STREQ(engine, NO_ENGINE)) {
+               RenderData *rd = &scene->r;
+               engine_name = rd->engine;
+       }
+       else {
+               engine_name = engine;
+       }
+
+       PointerRNA ptr;
+       CollectionEngineSettings *ces = BKE_layer_collection_engine_get(lc, engine_name);
+       RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &ptr);
+       return rna_pointer_inherit_refine(&ptr, &RNA_CollectionEngineSettings, ces);
+}
+
 static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr)
 {
        Scene *scene = CTX_data_scene(C);
@@ -5602,11 +5739,176 @@ static void rna_def_layer_collection_override(BlenderRNA *brna)
        RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
 }
 
+#define RNA_LAYER_ENGINE_USE(_NAME_)                                          \
+       prop = RNA_def_property(srna, #_NAME_"_use", PROP_BOOLEAN, PROP_NONE);    \
+       RNA_def_property_boolean_funcs(prop,                                      \
+           "rna_LayerEngineSettings_"#_NAME_"_use_get",                          \
+           "rna_LayerEngineSettings_"#_NAME_"_use_set");                         \
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);                         \
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+
+static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       static EnumPropertyItem clay_matcap_items[] = {
+           {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+           {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+           {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+           {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+           {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+           {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+           {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+           {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+           {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+           {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+           {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+           {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+           {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+           {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+           {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+           {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+           {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+           {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+           {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+           {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+           {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+           {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+           {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+           {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+           {0, NULL, 0, NULL, NULL}
+       };
+
+       static EnumPropertyItem clay_matcap_type[] = {
+           {CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
+           {CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
+           {CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
+           {0, NULL, 0, NULL, NULL}
+       };
+
+       srna = RNA_def_struct(brna, "CollectionEngineSettingsClay", NULL);
+       RNA_def_struct_sdna(srna, "CollectionEngineSettings");
+       RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection");
+
+       prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Name", "Engine name");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_struct_name_property(srna, prop);
+
+       /* see RNA_LAYER_ENGINE_GET_SET macro */
+
+       prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_type_get", "rna_LayerEngineSettings_type_set", NULL);
+       RNA_def_property_enum_items(prop, clay_matcap_type);
+       RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(type)
+
+       prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_matcap_icon_get", "rna_LayerEngineSettings_matcap_icon_set", NULL);
+       RNA_def_property_enum_items(prop, clay_matcap_items);
+       RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(matcap_icon)
+
+       prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_rotation_get", "rna_LayerEngineSettings_matcap_rotation_set", NULL);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(matcap_rotation)
+
+       prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_hue_get", "rna_LayerEngineSettings_matcap_hue_set", NULL);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(matcap_hue)
+
+       prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_saturation_get", "rna_LayerEngineSettings_matcap_saturation_set", NULL);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(matcap_saturation)
+
+       prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_value_get", "rna_LayerEngineSettings_matcap_value_set", NULL);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(matcap_value)
+
+       prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_cavity_get", "rna_LayerEngineSettings_ssao_factor_cavity_set", NULL);
+       RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(ssao_factor_cavity)
+
+       prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_edge_get", "rna_LayerEngineSettings_ssao_factor_edge_set", NULL);
+       RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(ssao_factor_edge)
+
+       prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_distance_get", "rna_LayerEngineSettings_ssao_distance_set", NULL);
+       RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(ssao_distance)
+
+       prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_attenuation_get", "rna_LayerEngineSettings_ssao_attenuation_set", NULL);
+       RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+       RNA_def_property_range(prop, 1.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+       RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
+       RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
+       RNA_LAYER_ENGINE_USE(ssao_attenuation)
+}
+
+static void rna_def_layer_collection_engine_settings(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+
+       srna = RNA_def_struct(brna, "CollectionEngineSettings", NULL);
+       RNA_def_struct_ui_text(srna, "Collections Engine Settings", "Engine specific settings for this collection");
+       RNA_def_struct_refine_func(srna, "rna_CollectionEngineSettings_refine");
+
+       prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Name", "Engine name");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+       RNA_def_struct_name_property(srna, prop);
+
+       /* the engine specific structs */
+       rna_def_layer_collection_engine_settings_clay(brna);
+}
+
+#undef RNA_LAYER_ENGINE_USE
+
 static void rna_def_layer_collection(BlenderRNA *brna)
 {
        StructRNA *srna;
        PropertyRNA *prop;
 
+       FunctionRNA *func;
+       PropertyRNA *parm;
+
        srna = RNA_def_struct(brna, "LayerCollection", NULL);
        RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection");
 
@@ -5638,6 +5940,15 @@ static void rna_def_layer_collection(BlenderRNA *brna)
        RNA_def_property_struct_type(prop, "LayerCollectionOverride");
        RNA_def_property_ui_text(prop, "Collection Overrides", "");
 
+       func = RNA_def_function(srna, "get_engine_settings", "rna_LayerCollection_engine_settings_get");
+       RNA_def_function_ui_description(func, "Return the engine settings for this collection");
+       RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
+       parm = RNA_def_string(func, "engine", NO_ENGINE, MAX_NAME, "Engine", "use context one by default");
+       RNA_def_parameter_clear_flags(parm, 0, PARM_REQUIRED);
+       parm = RNA_def_pointer(func, "result", "CollectionEngineSettings", "", "");
+       RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
+       RNA_def_function_return(func, parm);
+
        /* Flags */
        prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE);
@@ -6580,6 +6891,115 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna)
 }
 #endif
 
+#ifdef WITH_CLAY_ENGINE
+static void rna_def_render_engine_settings_clay(BlenderRNA *brna)
+{
+       StructRNA *srna;
+       PropertyRNA *prop;
+       static EnumPropertyItem clay_matcap_items[] = {
+               {ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
+               {ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
+               {ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
+               {ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
+               {ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
+               {ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
+               {ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
+               {ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
+               {ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
+               {ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
+               {ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
+               {ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
+               {ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
+               {ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
+               {ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
+               {ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
+               {ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
+               {ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
+               {ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
+               {ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
+               {ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
+               {ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
+               {ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
+               {ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
+               {0, NULL, 0, NULL, NULL}
+       };
+
+       srna = RNA_def_struct(brna, "RenderEngineSettingsClay", "RenderEngineSettings");
+       RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
+       RNA_def_struct_sdna_from(srna, "RenderEngineSettingsClay", "data");
+
+       prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_items(prop, clay_matcap_items);
+       RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
+       RNA_def_property_float_sdna(prop, NULL, "matcap_val");
+       RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
+       RNA_def_property_range(prop, 0.0f, 250.0f);
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
+       RNA_def_property_range(prop, 0.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
+       RNA_def_property_range(prop, 1.0f, 100000.0f);
+       RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
+       RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
+
+       /* Clay settings */
+       prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE);
+       RNA_def_property_ui_text(prop, "Samples", "Number of samples");
+       RNA_def_property_range(prop, 1, 500);
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+}
+#endif
+
+static void rna_def_scene_render_engine(BlenderRNA *brna)
+{
+       StructRNA *srna;
+
+       srna = RNA_def_struct(brna, "RenderEngineSettings", NULL);
+       RNA_def_struct_ui_text(srna, "Render Engine Settings", "Engine specific render settings");
+       RNA_def_struct_sdna(srna, "RenderEngineSettings");
+       RNA_def_struct_refine_func(srna, "rna_RenderEngineSettings_refine");
+
+#ifdef WITH_CLAY_ENGINE
+       rna_def_render_engine_settings_clay(brna);
+#endif
+}
+
 static void rna_def_scene_render_data(BlenderRNA *brna)
 {
        StructRNA *srna;
@@ -8075,7 +8495,17 @@ void RNA_def_scene(BlenderRNA *brna)
        RNA_def_property_pointer_sdna(prop, NULL, "r");
        RNA_def_property_struct_type(prop, "RenderSettings");
        RNA_def_property_ui_text(prop, "Render Data", "");
-       
+
+       /* Render Engine Data */
+       prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
+       RNA_def_property_struct_type(prop, "RenderEngineSettings");
+       RNA_def_property_ui_text(prop, "Render Engine Settings", "Engine specific render settings");
+
+       prop = RNA_def_property(srna, "active_engine_settings", PROP_POINTER, PROP_NONE);
+       RNA_def_property_struct_type(prop, "RenderEngineSettings");
+       RNA_def_property_pointer_funcs(prop, "rna_RenderEngineSettings_active_get", NULL, NULL, NULL);
+       RNA_def_property_ui_text(prop, "Active Render Engine Settings", "Active Engine specific render settings for this scene");
+
        /* Safe Areas */
        prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
        RNA_def_property_pointer_sdna(prop, NULL, "safe_areas");
@@ -8222,11 +8652,13 @@ void RNA_def_scene(BlenderRNA *brna)
        rna_def_scene_collection(brna);
        rna_def_layer_collection(brna);
        rna_def_layer_collection_override(brna);
+       rna_def_layer_collection_engine_settings(brna);
        rna_def_scene_layer(brna);
        rna_def_object_base(brna);
        RNA_define_animate_sdna(true);
        /* *** Animated *** */
        rna_def_scene_render_data(brna);
+       rna_def_scene_render_engine(brna);
        rna_def_scene_render_layer(brna);
        rna_def_gpu_fx(brna);
        rna_def_scene_render_view(brna);
@@ -8236,3 +8668,5 @@ void RNA_def_scene(BlenderRNA *brna)
 }
 
 #endif
+
+#undef NO_ENGINE
index 9e40ab02ee417ceaf089c49e574cf7c63e153004..27fa119bc882c155d5e1b691a8a2859d2c6fc364 100644 (file)
@@ -35,6 +35,7 @@ set(INC
        ../makesdna
        ../makesrna
        ../physics
+       ../draw
        ../../../intern/guardedalloc
        ../../../intern/mikktspace
        ../../../intern/smoke/extern
index f83a210275f810033ab81ff618faa683355679f5..f1b3534b40a78a41ec90d9e1d013fbccb1fdfeea 100644 (file)
@@ -39,6 +39,8 @@
 
 struct bNode;
 struct bNodeTree;
+struct CollectionEngineSettings;
+struct Main;
 struct Object;
 struct Render;
 struct RenderData;
@@ -63,6 +65,7 @@ struct BakePixel;
 #define RE_USE_TEXTURE_PREVIEW         128
 #define RE_USE_SHADING_NODES_CUSTOM    256
 #define RE_USE_SPHERICAL_STEREO 512
+#define RE_USE_OGL_PIPELINE            1024
 
 /* RenderEngine.flag */
 #define RE_ENGINE_ANIMATION            1
@@ -97,6 +100,8 @@ typedef struct RenderEngineType {
 
        void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
 
+       void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
+
        /* RNA integration */
        ExtensionRNA ext;
 } RenderEngineType;
@@ -164,6 +169,7 @@ void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe)
 
 void RE_engines_init(void);
 void RE_engines_exit(void);
+void RE_engines_register(struct Main *bmain, RenderEngineType *render_type);
 
 RenderEngineType *RE_engines_find(const char *idname);
 
index fd9d95c63b6bef5077cc8eb10f62d8a864efb113..1744d88a14f915afdc7d88c69295367c2067bc15 100644 (file)
@@ -45,6 +45,7 @@
 #include "BKE_camera.h"
 #include "BKE_global.h"
 #include "BKE_colortools.h"
+#include "BKE_layer.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
 
@@ -58,6 +59,8 @@
 #include "RE_pipeline.h"
 #include "RE_bake.h"
 
+#include "DRW_engine.h"
+
 #include "initrender.h"
 #include "renderpipeline.h"
 #include "render_types.h"
@@ -68,7 +71,7 @@
 static RenderEngineType internal_render_type = {
        NULL, NULL,
        "BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
-       NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        {NULL, NULL, NULL}
 };
 
@@ -77,7 +80,7 @@ static RenderEngineType internal_render_type = {
 static RenderEngineType internal_game_type = {
        NULL, NULL,
        "BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
-       NULL, NULL, NULL, NULL, NULL, NULL,
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL,
        {NULL, NULL, NULL}
 };
 
@@ -87,16 +90,21 @@ ListBase R_engines = {NULL, NULL};
 
 void RE_engines_init(void)
 {
-       BLI_addtail(&R_engines, &internal_render_type);
+       RE_engines_register(NULL, &internal_render_type);
 #ifdef WITH_GAMEENGINE
-       BLI_addtail(&R_engines, &internal_game_type);
+       RE_engines_register(NULL, &internal_game_type);
 #endif
+       DRW_engines_init();
 }
 
 void RE_engines_exit(void)
 {
        RenderEngineType *type, *next;
 
+       DRW_engines_free();
+
+       BKE_layer_collection_engine_settings_callback_free();
+
        for (type = R_engines.first; type; type = next) {
                next = type->next;
 
@@ -111,6 +119,14 @@ void RE_engines_exit(void)
        }
 }
 
+void RE_engines_register(Main *bmain, RenderEngineType *render_type)
+{
+       if (render_type->collection_settings_create) {
+               BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create);
+       }
+       BLI_addtail(&R_engines, render_type);
+}
+
 RenderEngineType *RE_engines_find(const char *idname)
 {
        RenderEngineType *type;
index e74f6f3208c50bb12723d7868489649d7e93fc93..a9cf76adae3e512a15bb9db5f4543428ccbe0038 100644 (file)
@@ -186,6 +186,7 @@ struct wmWindowManager;
 #include "../blender/render/extern/include/RE_pipeline.h"
 #include "../blender/render/extern/include/RE_render_ext.h"
 #include "../blender/render/extern/include/RE_shader_ext.h"
+#include "../blender/draw/DRW_engine.h"
 #include "../blender/windowmanager/WM_api.h"
 
 
@@ -663,6 +664,7 @@ void RE_ReleaseResultImage(struct Render *re) RET_NONE
 int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO
 void RE_engines_init() RET_NONE
 void RE_engines_exit() RET_NONE
+void RE_engines_register(struct Main *bmain, RenderEngineType *render_type) RET_NONE
 void RE_engine_report(struct RenderEngine *engine, int type, const char *msg) RET_NONE
 ListBase R_engines = {NULL, NULL};
 void RE_engine_free(struct RenderEngine *engine) RET_NONE
@@ -679,6 +681,9 @@ void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index,
 void RE_FreeAllPersistentData(void) RET_NONE
 float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
 
+/* Draw */
+void *DRW_render_settings_get(struct Scene *scene, const char *engine_name) RET_NULL
+
 /* python */
 struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
 void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE