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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build_files/cmake/macros.cmake1
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_render_layer.py2
-rw-r--r--source/blender/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/BKE_layer.h9
-rw-r--r--source/blender/blenkernel/intern/material.c13
-rw-r--r--source/blender/blenkernel/intern/mesh_render.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c10
-rw-r--r--source/blender/blenloader/intern/readfile.c15
-rw-r--r--source/blender/blenloader/intern/versioning_280.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c35
-rw-r--r--source/blender/draw/CMakeLists.txt36
-rw-r--r--source/blender/draw/DRW_engine.h45
-rw-r--r--source/blender/draw/DRW_engines.h0
-rw-r--r--source/blender/draw/engines/clay/clay.c680
-rw-r--r--source/blender/draw/engines/clay/clay.h (renamed from source/blender/draw/DRW_defines.h)17
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_frag.glsl207
-rw-r--r--source/blender/draw/engines/clay/shaders/clay_vert.glsl20
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl73
-rw-r--r--source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl120
-rw-r--r--source/blender/draw/intern/DRW_render.h218
-rw-r--r--source/blender/draw/intern/draw_cache.c201
-rw-r--r--source/blender/draw/intern/draw_cache.h41
-rw-r--r--source/blender/draw/intern/draw_manager.c1115
-rw-r--r--source/blender/draw/intern/draw_mode_pass.c393
-rw-r--r--source/blender/draw/intern/draw_mode_pass.h44
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c2
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c42
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h1
-rw-r--r--source/blender/gpu/CMakeLists.txt4
-rw-r--r--source/blender/gpu/GPU_extensions.h2
-rw-r--r--source/blender/gpu/GPU_framebuffer.h1
-rw-r--r--source/blender/gpu/GPU_shader.h5
-rw-r--r--source/blender/gpu/GPU_texture.h105
-rw-r--r--source/blender/gpu/GPU_uniformbuffer.h44
-rw-r--r--source/blender/gpu/GPU_viewport.h42
-rw-r--r--source/blender/gpu/gawain/batch.c86
-rw-r--r--source/blender/gpu/gawain/batch.h2
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c2
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c112
-rw-r--r--source/blender/gpu/intern/gpu_draw.c23
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c15
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c42
-rw-r--r--source/blender/gpu/intern/gpu_material.c4
-rw-r--r--source/blender/gpu/intern/gpu_shader.c27
-rw-r--r--source/blender/gpu/intern/gpu_texture.c645
-rw-r--r--source/blender/gpu/intern/gpu_uniformbuffer.c105
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c198
-rw-r--r--source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl10
-rw-r--r--source/blender/makesdna/DNA_material_types.h49
-rw-r--r--source/blender/makesdna/DNA_scene_types.h48
-rw-r--r--source/blender/makesrna/RNA_access.h4
-rw-r--r--source/blender/makesrna/intern/CMakeLists.txt1
-rw-r--r--source/blender/makesrna/intern/rna_material.c143
-rw-r--r--source/blender/makesrna/intern/rna_scene.c159
-rw-r--r--source/blender/render/CMakeLists.txt1
-rw-r--r--source/blender/render/extern/include/RE_engine.h1
-rw-r--r--source/blender/render/intern/source/external_engine.c5
60 files changed, 4865 insertions, 407 deletions
diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake
index 83ae56636b0..fa9c2a28cb5 100644
--- a/build_files/cmake/macros.cmake
+++ b/build_files/cmake/macros.cmake
@@ -598,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_modifiers
bf_bmesh
bf_gpu
+ bf_draw
bf_blenloader
bf_blenkernel
bf_physics
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index d916007ea41..e8ba7cc8033 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -106,7 +106,7 @@ class MaterialButtonsPanel:
class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
- COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
@@ -1052,5 +1052,25 @@ class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
_context_path = "material"
_property_type = bpy.types.Material
+
+class MATERIAL_PT_clay_settings(MaterialButtonsPanel, Panel):
+ bl_label = "Matcap"
+ COMPAT_ENGINES = {'BLENDER_CLAY'}
+
+ def draw(self, context):
+ layout = self.layout;
+ settings = context.material.clay_settings
+ # layout.template_icon_view(settings, "matcap_icon")
+ # layout.prop(settings, "type")
+ # 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")
+
+
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 850606eb80b..5f2c9939dc9 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -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__)
diff --git a/release/scripts/startup/bl_ui/properties_render_layer.py b/release/scripts/startup/bl_ui/properties_render_layer.py
index 45c93dd9335..2545eadc792 100644
--- a/release/scripts/startup/bl_ui/properties_render_layer.py
+++ b/release/scripts/startup/bl_ui/properties_render_layer.py
@@ -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
diff --git a/source/blender/CMakeLists.txt b/source/blender/CMakeLists.txt
index 6f2b78e0845..47ebed8f791 100644
--- a/source/blender/CMakeLists.txt
+++ b/source/blender/CMakeLists.txt
@@ -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)
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index e74cfbe9a11..6373593f199 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -144,6 +144,15 @@ void BKE_visible_bases_Iterator_end(Iterator *iter);
} \
}
+#define FOREACH_BASE(sl, _object_base) \
+{ \
+ for (base = sl->object_bases.first; base; base = base->next) { \
+ _object_base = base;
+
+#define FOREACH_BASE_END \
+ } \
+}
+
#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \
{ \
IteratorBeginCb func_begin; \
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 54945242fe4..89af048f73d 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -111,6 +111,14 @@ 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->runtime)
+ MEM_SAFE_FREE(mes->runtime);
+ if (mes->data)
+ MEM_SAFE_FREE(mes->data);
+ }
+ BLI_freelistN(&ma->engines_settings);
}
void BKE_material_init(Material *ma)
@@ -248,6 +256,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 +289,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 +1710,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;
}
diff --git a/source/blender/blenkernel/intern/mesh_render.c b/source/blender/blenkernel/intern/mesh_render.c
index 4118208d32f..fd0f49810fb 100644
--- a/source/blender/blenkernel/intern/mesh_render.c
+++ b/source/blender/blenkernel/intern/mesh_render.c
@@ -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 { \
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index c1316373b2a..807496d88e1 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -109,6 +109,7 @@
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,15 @@ 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->runtime)
+ MEM_freeN(res->runtime);
+ if (res->data)
+ MEM_freeN(res->data);
+ }
+ BLI_freelistN(&sce->engines_settings);
}
void BKE_scene_init(Scene *sce)
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 90f7ddc5f6d..134ce910dcf 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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,12 @@ 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->runtime = NULL;
+ mes->data = newdataadr(fd, mes->data);
+ }
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -4610,6 +4617,7 @@ static void direct_link_mesh(FileData *fd, Mesh *mesh)
mesh->bb = NULL;
mesh->edit_btmesh = NULL;
+ mesh->batch_cache = NULL;
/* happens with old files */
if (mesh->mselect == NULL) {
@@ -5949,6 +5957,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
RigidBodyWorld *rbw;
SceneLayer *sl;
SceneRenderLayer *srl;
+ RenderEngineSettings *res;
sce->theDag = NULL;
sce->depsgraph = NULL;
@@ -6211,6 +6220,12 @@ 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->runtime = NULL;
+ res->data = newdataadr(fd, res->data);
+ }
}
/* ************ READ WM ***************** */
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 2f3251fb702..92592e9fc62 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -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"
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index c22acf2f758..e20e6a1f94f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2271,6 +2271,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase)
CustomData_reset(&mesh->pdata);
CustomData_reset(&mesh->ldata);
mesh->edit_btmesh = NULL;
+ mesh->batch_cache = NULL;
/* now fill in polys to mfaces */
/* XXX This breaks writing design, by using temp allocated memory, which will likely generate
@@ -2468,6 +2469,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;
@@ -2504,6 +2520,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;
}
@@ -2650,6 +2668,21 @@ static void write_layer_collections(WriteData *wd, ListBase *lb)
}
}
+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;
@@ -2879,6 +2912,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;
}
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index 60449ebc600..6cf358e8c11 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -26,37 +26,49 @@
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
+
+ ./DRW_engine.h
)
+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
)
-endif()
-
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
index 00000000000..05222574ae9
--- /dev/null
+++ b/source/blender/draw/DRW_engine.h
@@ -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 ***runtime);
+void *DRW_render_settings_get(struct Scene *scene, const char *engine_name, void ***runtime);
+
+#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
index e69de29bb2d..00000000000
--- a/source/blender/draw/DRW_engines.h
+++ /dev/null
diff --git a/source/blender/draw/engines/clay/clay.c b/source/blender/draw/engines/clay/clay.c
new file mode 100644
index 00000000000..dabb500936b
--- /dev/null
+++ b/source/blender/draw/engines/clay/clay.c
@@ -0,0 +1,680 @@
+/*
+ * 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"
+
+/* 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 */
+#define CLAY_UBO_CLEAR (1 << 0)
+#define 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 */
+#define SCENE_COLOR 0
+#define SCENE_DEPTH 1
+#define SCENE_DEPTH_LOW 2
+
+/* 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(void)
+{
+ /* 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);
+ }
+}
+
+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, NULL);
+
+ 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 CLAY_update_material_runtime(MaterialEngineSettingsClay *settings, MaterialRuntimeClay **runtime)
+{
+ MaterialRuntimeClay *rt;
+
+ if (*runtime == NULL) {
+ rt = MEM_mallocN(sizeof(MaterialRuntimeClay), "MaterialRuntimeClay");
+ rt->flag = CLAY_OUTDATED;
+ data.ubo_flag |= CLAY_UBO_CLEAR;
+ *runtime = rt;
+ }
+
+ rt = *runtime;
+
+ if (rt->flag & CLAY_OUTDATED) {
+
+ /* Update default material */
+ rt->matcap_rot[0] = cosf(settings->matcap_rot * 3.14159f * 2.0f);
+ rt->matcap_rot[1] = sinf(settings->matcap_rot * 3.14159f * 2.0f);
+
+ rt->matcap_hsv[0] = settings->matcap_hue + 0.5f;
+ rt->matcap_hsv[1] = settings->matcap_sat * 2.0f;
+ rt->matcap_hsv[2] = settings->matcap_val * 2.0f;
+
+ rt->ssao_params_var[0] = settings->ssao_distance;
+ rt->ssao_params_var[1] = settings->ssao_factor_cavity;
+ rt->ssao_params_var[2] = settings->ssao_factor_edge;
+ rt->ssao_params_var[3] = settings->ssao_attenuation;
+
+ if (settings->matcap_icon < ICON_MATCAP_01 ||
+ settings->matcap_icon > ICON_MATCAP_24)
+ {
+ settings->matcap_icon = ICON_MATCAP_01;
+ }
+
+ rt->matcap_id = matcap_to_index(settings->matcap_icon);
+
+ if ((rt->type != settings->type)) {
+ data.ubo_flag |= CLAY_UBO_CLEAR;
+ }
+
+ rt->type = settings->type;
+
+ data.ubo_flag |= CLAY_UBO_REFRESH;
+ rt->flag &= ~CLAY_OUTDATED;
+ }
+}
+
+static void update_ubo_storage(MaterialRuntimeClay *runtime, unsigned int current_id)
+{
+ CLAY_UBO_Material *ubo = &data.mat_storage.materials[current_id];
+
+ ubo->matcap_id = runtime->matcap_id;
+ copy_v3_v3(ubo->matcap_hsv, runtime->matcap_hsv);
+ copy_v2_v2(ubo->matcap_rot, runtime->matcap_rot);
+ copy_v4_v4(ubo->ssao_params_var, runtime->ssao_params_var);
+
+ runtime->material_id = current_id;
+}
+
+static void CLAY_update_material_ubo(const struct bContext *C)
+{
+ Main *bmain = CTX_data_main(C);
+ MaterialRuntimeClay **runtime;
+
+ /* 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, (void ***)&runtime);
+ CLAY_update_material_runtime(res, runtime);
+ }
+
+ /* Update Scene Materials */
+ for (Material *mat = bmain->mat.first; mat; mat = mat->id.next) {
+ MaterialEngineSettingsClay *mesc = DRW_material_settings_get(mat, RE_engine_id_BLENDER_CLAY, (void ***)&runtime);
+ CLAY_update_material_runtime(mesc, runtime);
+ }
+
+ if (data.ubo_flag & CLAY_UBO_REFRESH) {
+ int current_id = 0;
+
+ /* Default materials */
+ for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+ DRW_render_settings_get(sce, RE_engine_id_BLENDER_CLAY, (void ***)&runtime);
+ update_ubo_storage(*runtime, current_id);
+ current_id++;
+ }
+
+ /* TODO only add materials linked to geometry */
+ for (Material *mat = bmain->mat.first; mat; mat = mat->id.next) {
+ DRW_material_settings_get(mat, RE_engine_id_BLENDER_CLAY, (void ***)&runtime);
+ update_ubo_storage(*runtime, 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;
+ ObjectBase *base;
+
+ /* 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 */
+ {
+ MaterialRuntimeClay **runtime;
+ DRW_render_settings_get(NULL, RE_engine_id_BLENDER_CLAY, (void ***)&runtime);
+
+ passes->clay_pass = DRW_pass_create("Clay Pass", DRW_STATE_WRITE_COLOR);
+
+ default_shgrp = CLAY_shgroup_create(passes->clay_pass, &(*runtime)->material_id);
+ 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*/
+ FOREACH_BASE(sl, base)
+ {
+ struct Batch *geom;
+ Object *ob = base->object;
+
+ 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);
+
+ /* 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, base);
+ break;
+ }
+
+ DRW_shgroup_object_center(passes->ob_center_pass, base);
+ DRW_shgroup_relationship_lines(passes->non_meshes_pass, base);
+ }
+ FOREACH_BASE_END
+}
+
+static void CLAY_view_draw(RenderEngine *UNUSED(engine), const struct 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();
+
+ 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->non_meshes_pass);
+ DRW_draw_pass(passes->ob_center_pass);
+
+ /* Always finish by this */
+ DRW_state_reset();
+}
+
+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,
+ {NULL, NULL, NULL}
+}; \ No newline at end of file
diff --git a/source/blender/draw/DRW_defines.h b/source/blender/draw/engines/clay/clay.h
index 212c39e203b..404924be2a1 100644
--- a/source/blender/draw/DRW_defines.h
+++ b/source/blender/draw/engines/clay/clay.h
@@ -19,7 +19,18 @@
*
*/
-#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
index 00000000000..d9b372b652a
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_frag.glsl
@@ -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
index 00000000000..0b598ea0291
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/clay_vert.glsl
@@ -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
index 00000000000..d032fb91c01
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_alchemy.glsl
@@ -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
index 00000000000..2f29624824e
--- /dev/null
+++ b/source/blender/draw/engines/clay/shaders/ssao_groundtruth.glsl
@@ -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
index 00000000000..8bd3cabf8de
--- /dev/null
+++ b/source/blender/draw/intern/DRW_render.h
@@ -0,0 +1,218 @@
+/*
+ * 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_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);
+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 ***runtime);
+void *DRW_render_settings_get(Scene *scene, const char *engine_name, void ***runtime);
+#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
index 00000000000..a5a465a145e
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.c
@@ -0,0 +1,201 @@
+/*
+ * 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_circle_ball;
+ // Batch drw_cube;
+ // Batch drw_circle;
+ // Batch drw_sphere;
+ // Batch drw_cone;
+ // Batch drw_arrows;
+} SHC = {NULL};
+
+/* 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 */
+#define CIRCLE_RESOL 32
+
+Batch *DRW_cache_circle_ball_get(void)
+{
+ if (!SHC.drw_circle_ball) {
+ 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);
+
+ 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, 0, v);
+ }
+
+ SHC.drw_circle_ball = Batch_create(GL_LINE_LOOP, vbo, NULL);
+ }
+ return SHC.drw_circle_ball;
+}
+
+/* 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;
+}
+
+/* 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_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
index 00000000000..13b33931b76
--- /dev/null
+++ b/source/blender/draw/intern/draw_cache.h
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+/* Common Shapes */
+struct Batch *DRW_cache_fullscreen_quad_get(void);
+struct Batch *DRW_cache_circle_ball_get(void);
+struct Batch *DRW_cache_single_vert_get(void);
+struct Batch *DRW_cache_plain_axes_get(void);
+/* Meshes */
+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
index 00000000000..3fff977bc97
--- /dev/null
+++ b/source/blender/draw/intern/draw_manager.c
@@ -0,0 +1,1115 @@
+/*
+ * 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];
+ /* Current rendering context set by DRW_viewport_init */
+ bContext *context;
+} DST = {NULL};
+
+/* ***************************************** TEXTURES ******************************************/
+static void drw_texture_get_format(DRWTextureFormat format, GPUFormat *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_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_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;
+ case DRW_TEX_R_16: *data_type = GPU_R16F; break;
+ case DRW_TEX_R_32: *data_type = GPU_R32F; break;
+ 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;
+ }
+
+ 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;
+ GPUFormat 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;
+ GPUFormat 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_listbase_clear(&shgroup->interface->uniforms);
+
+ 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(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(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(&data[i*16], call->obmat);
+ }
+
+ /* Upload Data */
+ static VertexFormat format = { 0 };
+ static unsigned mat_id;
+ if (format.attrib_ct == 0) {
+ mat_id = add_attrib(&format, "InstanceModelMatrix", GL_FLOAT, 4, KEEP_FLOAT);
+ }
+
+ VertexBuffer *vbo = VertexBuffer_create_with_format(&format);
+ VertexBuffer_allocate_data(vbo, nbr);
+
+ fillAttrib(vbo, mat_id, data);
+
+ /* 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;
+
+ 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)
+{
+ 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);
+ }
+}
+
+/* Only alter the state (does not reset it like set_state() ) */
+static void shgroup_set_state(DRWShadingGroup *shgroup)
+{
+ if (shgroup->state) {
+ /* 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);
+ }
+ }
+}
+
+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);
+}
+
+/* ****************************************** Settings ******************************************/
+
+void *DRW_material_settings_get(Material *ma, const char *engine_name, void ***runtime)
+{
+ MaterialEngineSettings *ms = NULL;
+
+ ms = BLI_findstring(&ma->engines_settings, engine_name, offsetof(MaterialEngineSettings, name));
+
+ /* 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);
+ }
+
+ if (runtime) {
+ *runtime = &ms->runtime;
+ }
+
+ return ms->data;
+}
+
+/* If scene is NULL, use context scene */
+void *DRW_render_settings_get(Scene *scene, const char *engine_name, void ***runtime)
+{
+ RenderEngineSettings *rs = NULL;
+
+ if (scene == NULL)
+ scene = CTX_data_scene(DST.context);
+
+ rs = BLI_findstring(&scene->engines_settings, engine_name, offsetof(RenderEngineSettings, name));
+
+ /* 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);
+ }
+
+ if (runtime) {
+ *runtime = &rs->runtime;
+ }
+
+ 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];
+}
+
+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;
+
+ /* 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)
+{
+ BLI_addtail(&R_engines, &viewport_clay_type);
+}
+
+void DRW_engines_free(void)
+{
+ clay_engine_free();
+
+ BLI_remlink(&R_engines, &viewport_clay_type);
+} \ 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
index 00000000000..c93c9a16109
--- /dev/null
+++ b/source/blender/draw/intern/draw_mode_pass.c
@@ -0,0 +1,393 @@
+/*
+ * 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 *empty_wire;
+static DRWShadingGroup *empty_active;
+static DRWShadingGroup *empty_select;
+static DRWShadingGroup *empty_transform;
+static DRWShadingGroup *empty_group;
+static DRWShadingGroup *empty_group_active;
+
+/* Helpers */
+static DRWShadingGroup *relationship_lines;
+
+/* Objects Centers */
+static DRWShadingGroup *center_active;
+static DRWShadingGroup *center_selected;
+static DRWShadingGroup *center_deselected;
+
+/* 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)
+{
+ 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_DEPTH_EQUAL | 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) {
+ 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];
+
+ 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(OB_LAMP, colorLamp);
+ UI_GetThemeColor4fv(OB_SPEAKER, colorSpeaker);
+ UI_GetThemeColor4fv(OB_CAMERA, colorCamera);
+ UI_GetThemeColor4fv(OB_EMPTY, colorEmpty);
+
+ /* 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 ;//| DRW_STATE_LINE_SMOOTH;
+ *non_meshes = DRW_pass_create("Non Meshes Pass", state);
+
+ GPUShader *sh = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR);
+ GPUShader *sh_inst = GPU_shader_get_builtin_shader(GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE);
+
+ /* Solid Wires */
+ grp = DRW_shgroup_create(sh, *non_meshes);
+
+ /* Points */
+ grp = DRW_shgroup_create(sh, *non_meshes);
+
+ /* Empties */
+ {
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorEmpty, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_wire = grp;
+
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorActive, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_active = grp;
+
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorSelect, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_select = grp;
+
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorTransform, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_transform = grp;
+
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorGroup, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_group = grp;
+
+ grp = DRW_shgroup_create(sh_inst, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorGroupActive, 1);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_INSTANCE);
+ empty_group_active = grp;
+ }
+
+ /* 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 */
+ {
+ grp = DRW_shgroup_create(sh, *non_meshes);
+ DRW_shgroup_uniform_vec4(grp, "color", colorWire, 1);
+ DRW_shgroup_state_set(grp, DRW_STATE_STIPPLE_3);
+ DRW_shgroup_dyntype_set(grp, DRW_DYN_LINES);
+ relationship_lines = grp;
+ }
+ }
+
+ if (ob_center) {
+ /* Object Center pass grouped by State */
+ DRWShadingGroup *grp;
+ static float colorActive[4], colorSelect[4], 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 *********************************************** */
+
+void DRW_shgroup_wire_overlay(DRWPass *wire_overlay, Object *ob)
+{
+ struct Batch *geom = DRW_cache_wire_outline_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);
+}
+
+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, "drawFront", bBack, 1);
+ DRW_shgroup_uniform_bool(grp, "drawBack", &bFalse, 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 ********************** */
+
+void DRW_draw_lamp(DRWPass *non_meshes, Object *ob)
+{
+ /* TODO */
+}
+
+/* TODO FINISH */
+static int draw_object_wire_theme(ObjectBase *base)
+{
+ Object *ob = base->object;
+ 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) &&
+ (base->flag & BASE_SELECTED))
+ {
+ theme_id = TH_TRANSFORM;
+ }
+ else {
+ /* Sets the 'theme_id' or fallback to wire */
+ if ((ob->flag & OB_FROMGROUP) != 0) {
+ if (base->flag & BASE_SELECTED) {
+ /* 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 (base->flag & BASE_SELECTED) {
+ 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_non_meshes(DRWPass *UNUSED(non_meshes), ObjectBase *base)
+{
+ struct Batch *geom;
+ DRWShadingGroup *grp;
+ Object *ob = base->object;
+ int theme_id = draw_object_wire_theme(base);
+
+ switch (ob->type) {
+ case OB_LAMP:
+ case OB_CAMERA:
+ case OB_EMPTY:
+ default:
+ if (theme_id == TH_ACTIVE)
+ grp = empty_active;
+ else if (theme_id == TH_SELECT)
+ grp = empty_select;
+ else if (theme_id == TH_GROUP_ACTIVE)
+ grp = empty_group_active;
+ else if (theme_id == TH_GROUP)
+ grp = empty_group;
+ else if (theme_id == TH_TRANSFORM)
+ grp = empty_transform;
+ else
+ grp = empty_wire;
+
+ geom = DRW_cache_plain_axes_get();
+ DRW_shgroup_call_add(grp, geom, ob->obmat);
+ break;
+ }
+}
+
+void DRW_shgroup_relationship_lines(DRWPass *UNUSED(non_meshes), ObjectBase *base)
+{
+ Object *ob = base->object;
+ 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), ObjectBase *base)
+{
+ Object *ob = base->object;
+ struct Batch *geom = DRW_cache_single_vert_get();
+
+ if (base->flag & BASE_SELECTED)
+ DRW_shgroup_call_add(center_selected, geom, ob->obmat);
+ else
+ DRW_shgroup_call_add(center_deselected, geom, ob->obmat);
+} \ No newline at end of file
diff --git a/source/blender/draw/intern/draw_mode_pass.h b/source/blender/draw/intern/draw_mode_pass.h
new file mode 100644
index 00000000000..3468fdaa6f0
--- /dev/null
+++ b/source/blender/draw/intern/draw_mode_pass.h
@@ -0,0 +1,44 @@
+/*
+ * 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;
+
+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, Object *ob);
+void DRW_shgroup_wire_outline(
+ struct DRWPass *wire_outline, Object *ob, const bool do_front, const bool do_back, const bool do_outline);
+
+void DRW_shgroup_non_meshes(struct DRWPass *non_meshes, ObjectBase *base);
+void DRW_shgroup_relationship_lines(struct DRWPass *non_meshes, ObjectBase *base);
+void DRW_shgroup_object_center(struct DRWPass *ob_center, ObjectBase *base);
+
+#endif /* __DRAW_MODE_PASS_H__ */ \ No newline at end of file
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 27ecbf83db5..debdcb58d71 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -160,7 +160,7 @@ static GPUTexture *create_field_texture(SmokeDomainSettings *sds)
default: return NULL;
}
- return GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, field);
+ return GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1, GPU_R8, field, NULL);
}
typedef struct VolumeSlicer {
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index ddaba639fbc..6021f705035 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -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);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 21a7e26998e..f428b2cec47 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -2096,12 +2096,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;
}
@@ -2109,12 +2139,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;
}
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 504a8383a41..71d6a47c41c 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -38,6 +38,7 @@
struct ARegion;
struct ARegionType;
struct BoundBox;
+struct Batch;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index c5531b8542e..7aeb67a224d 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -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,6 +148,7 @@ 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)
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 31ad8243c4b..ff00a83d00b 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -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]);
diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h
index 989b874fd38..9611a6f0577 100644
--- a/source/blender/gpu/GPU_framebuffer.h
+++ b/source/blender/gpu/GPU_framebuffer.h
@@ -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);
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 394e751ed9b..8cc9433c6ab 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -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,
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 756fe79151b..3ddeb9c1f44 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -55,25 +55,101 @@ typedef struct GPUTexture GPUTexture;
* - if created with from_blender, will not free the texture
*/
-typedef enum GPUHDRType {
- GPU_HDR_NONE = 0,
- GPU_HDR_HALF_FLOAT = 1,
- GPU_HDR_FULL_FLOAT = (1 << 1),
-} GPUHDRType;
+/* From OpenGl 3.3 specification */
+typedef enum GPUFormat {
+ /* Formats texture & renderbuffer */
+ GPU_RGBA32F,
+ GPU_RGBA32I,
+ GPU_RGBA32UI,
+ GPU_RGBA16,
+ GPU_RGBA16F,
+ GPU_RGBA16I,
+ GPU_RGBA16UI,
+ GPU_RGBA8,
+ GPU_RGBA8I,
+ GPU_RGBA8UI,
+ GPU_RG32F,
+ GPU_RG32I,
+ GPU_RG32UI,
+ GPU_RG16,
+ GPU_RG16F,
+ GPU_RG16I,
+ GPU_RG16UI,
+ GPU_RG8,
+ GPU_RG8I,
+ GPU_RG8UI,
+ GPU_R32F,
+ GPU_R32I,
+ GPU_R32UI,
+ GPU_R16F,
+ GPU_R16I,
+ GPU_R16UI,
+ GPU_R16,
+ GPU_R8,
+ GPU_R8I,
+ GPU_R8UI,
+
+ /* Special formats texture & renderbuffer */
+ GPU_R11F_G11F_B10F,
+ GPU_RGB10_A2,
+ GPU_RGB10_A2UI,
+ GPU_DEPTH32F_STENCIL8,
+ GPU_DEPTH24_STENCIL8,
+
+ /* Texture only format */
+ GPU_RGBA16_SNORM,
+ GPU_RGBA8_SNORM,
+ GPU_RGB32F,
+ GPU_RGB32I,
+ GPU_RGB32UI,
+ GPU_RGB16_SNORM,
+ GPU_RGB16F,
+ GPU_RGB16I,
+ GPU_RGB16UI,
+ GPU_RGB16,
+ GPU_RGB8_SNORM,
+ GPU_RGB8,
+ GPU_RGB8I,
+ GPU_RGB8UI,
+ GPU_RG16_SNORM,
+ GPU_RG8_SNORM,
+ GPU_R16_SNORM,
+ GPU_R8_SNORM,
+
+ /* Special formats texture only */
+ GPU_SRGB8_A8,
+ GPU_SRGB8,
+ GPU_RGB9_E5,
+ GPU_COMPRESSED_RG_RGTC2,
+ GPU_COMPRESSED_SIGNED_RG_RGTC2,
+ GPU_COMPRESSED_RED_RGTC1,
+ GPU_COMPRESSED_SIGNED_RED_RGTC1,
+
+ /* Depth Formats */
+ GPU_DEPTH_COMPONENT32F,
+ GPU_DEPTH_COMPONENT24,
+ GPU_DEPTH_COMPONENT16,
+} GPUFormat;
GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
+GPUTexture *GPU_texture_create_1D_custom(
+ int w, int channels, GPUFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_custom(
+ int w, int h, int channels, GPUFormat data_type, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_3D_custom(
+ int w, int h, int d, int channels, GPUFormat data_type, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D_multisample(
- int w, int h, const float *pixels, GPUHDRType hdr, int samples, char err_out[256]);
GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]);
+GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+
GPUTexture *GPU_texture_from_blender(
struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
+
void GPU_invalid_tex_init(void);
void GPU_invalid_tex_bind(int mode);
void GPU_invalid_tex_free(void);
@@ -81,12 +157,13 @@ void GPU_invalid_tex_free(void);
void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
-
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
int GPU_texture_bound_number(GPUTexture *tex);
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare);
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter);
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat);
struct GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
int GPU_texture_framebuffer_attachment(GPUTexture *tex);
diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h
new file mode 100644
index 00000000000..bcb6e1077b7
--- /dev/null
+++ b/source/blender/gpu/GPU_uniformbuffer.h
@@ -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);
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index fce509377ab..e44657a4647 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -34,12 +34,52 @@
#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);
diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c
index a60865d41d2..99c13301177 100644
--- a/source/blender/gpu/gawain/batch.c
+++ b/source/blender/gpu/gawain/batch.c
@@ -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);
+}
+
diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h
index 932ee182703..8b5c48cca79 100644
--- a/source/blender/gpu/gawain/batch.h
+++ b/source/blender/gpu/gawain/batch.h
@@ -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);
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 211394e7932..4223ec54f74 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1192,7 +1192,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType
#if 0
input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
#endif
- input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
+ input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
input->textarget = GL_TEXTURE_2D;
MEM_freeN(link->ptr1);
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
index 13596f2a0de..528bdefc209 100644
--- a/source/blender/gpu/intern/gpu_compositing.c
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -225,7 +225,13 @@ static GPUTexture * create_concentric_sample_texture(int side)
}
}
- tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
+ tex = GPU_texture_create_1D_custom(side * side, 2, GPU_RG16F, (float *)texels, NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_unbind(tex);
+
MEM_freeN(texels);
return tex;
}
@@ -247,7 +253,13 @@ static GPUTexture *create_spiral_sample_texture(int numsaples)
texels[i][1] = r * sinf(phi);
}
- tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
+ tex = GPU_texture_create_1D_custom(numsaples, 2, GPU_RG16F, (float *)texels, NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_unbind(tex);
+
MEM_freeN(texels);
return tex;
}
@@ -358,6 +370,7 @@ void GPU_fx_compositor_destroy(GPUFX *fx)
static GPUTexture * create_jitter_texture(void)
{
+ GPUTexture *tex;
float jitter[64 * 64][2];
int i;
@@ -367,7 +380,15 @@ static GPUTexture * create_jitter_texture(void)
normalize_v2(jitter[i]);
}
- return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL);
+ tex = GPU_texture_create_2D_custom(64, 64, 2, GPU_RG16F, &jitter[0][0], NULL);
+
+ /* Set parameters */
+ GPU_texture_bind(tex, 0);
+ GPU_texture_filter_mode(tex, false);
+ GPU_texture_wrap_mode(tex, true);
+ GPU_texture_unbind(tex);
+
+ return tex;
}
@@ -433,7 +454,7 @@ bool GPU_fx_compositor_initialize_passes(
if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
cleanup_fx_gl_data(fx, false);
- if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, err_out))) {
printf(".256%s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
@@ -485,38 +506,42 @@ bool GPU_fx_compositor_initialize_passes(
{
if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
- if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
+
+ if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RG16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
+ GPU_texture_bind(fx->dof_nearfar_coc, 0);
+ GPU_texture_filter_mode(fx->dof_nearfar_coc, false);
+ GPU_texture_wrap_mode(fx->dof_nearfar_coc, false);
+ GPU_texture_unbind(fx->dof_nearfar_coc);
-
- if (!(fx->dof_near_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ if (!(fx->dof_near_blur = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
- if (!(fx->dof_far_blur = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ if (!(fx->dof_far_blur = GPU_texture_create_2D_custom(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, 2, GPU_RGBA16F, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
@@ -531,21 +556,21 @@ bool GPU_fx_compositor_initialize_passes(
if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
}
if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
- fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, err_out)))
{
printf("%.256s\n", err_out);
cleanup_fx_gl_data(fx, true);
@@ -564,7 +589,7 @@ bool GPU_fx_compositor_initialize_passes(
/* we need to pass data between shader stages, allocate an extra color buffer */
if (num_passes > 1) {
if (!fx->color_buffer_sec) {
- if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, err_out))) {
printf(".256%s\n", err_out);
cleanup_fx_gl_data(fx, true);
return false;
@@ -692,14 +717,16 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
GPU_shader_bind(depth_resolve_shader);
GPU_texture_bind(fx->depth_buffer_xray, 0);
- GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer_xray, false);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, true);
GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray);
/* draw */
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
- GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer_xray, true);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, false);
GPU_texture_unbind(fx->depth_buffer_xray);
GPU_shader_unbind();
@@ -814,7 +841,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(ssao_shader, interface->color_uniform, src);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(ssao_shader, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(fx->jitter_buffer, numslots++);
@@ -830,7 +858,8 @@ bool GPU_fx_do_composite_pass(
/* disable bindings */
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_texture_unbind(fx->jitter_buffer);
GPU_texture_unbind(fx->ssao_spiral_samples_tex);
@@ -906,12 +935,13 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(src, numslots++);
/* disable filtering for the texture so custom downsample can do the right thing */
- GPU_texture_filter_mode(src, false, false);
+ GPU_texture_filter_mode(src, false);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, src);
/* target is the downsampled coc buffer */
@@ -925,9 +955,10 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
- GPU_texture_filter_mode(src, false, true);
+ GPU_texture_filter_mode(src, true);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
@@ -958,7 +989,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_half_downsampled_far, numslots++);
GPU_texture_bind(fx->dof_half_downsampled_near, numslots++);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far);
- GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_far, false);
/* target is the downsampled coc buffer */
GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0);
@@ -978,7 +1009,7 @@ bool GPU_fx_do_composite_pass(
GPU_framebuffer_texture_detach(fx->dof_far_blur);
GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near);
- GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_near, false);
selection[0] = 1.0f;
selection[1] = 0.0f;
@@ -1018,14 +1049,15 @@ bool GPU_fx_do_composite_pass(
GPU_texture_bind(fx->dof_near_blur, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->near_uniform, fx->dof_near_blur);
- GPU_texture_filter_mode(fx->dof_near_blur, false, true);
+ GPU_texture_filter_mode(fx->dof_near_blur, true);
GPU_texture_bind(fx->dof_far_blur, numslots++);
GPU_shader_uniform_texture(dof_shader_pass3, interface->far_uniform, fx->dof_far_blur);
- GPU_texture_filter_mode(fx->dof_far_blur, false, true);
+ GPU_texture_filter_mode(fx->dof_far_blur, true);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_shader_uniform_texture(dof_shader_pass3, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(src, numslots++);
@@ -1040,7 +1072,7 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_near_blur);
GPU_texture_unbind(fx->dof_far_blur);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
GPU_texture_unbind(fx->depth_buffer);
/* may not be attached, in that case this just returns */
@@ -1100,7 +1132,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass1, interface->color_uniform, src);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass1, interface->depth_uniform, fx->depth_buffer);
/* target is the downsampled coc buffer */
@@ -1111,7 +1144,8 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* disable bindings */
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
@@ -1137,7 +1171,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_vector(dof_shader_pass2, interface->viewvecs_uniform, 4, 3, viewvecs[0]);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass2, interface->depth_uniform, fx->depth_buffer);
GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
@@ -1165,7 +1200,8 @@ bool GPU_fx_do_composite_pass(
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* *unbind/detach */
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
GPU_texture_unbind(fx->dof_near_coc_final_buffer);
@@ -1249,7 +1285,8 @@ bool GPU_fx_do_composite_pass(
GPU_shader_uniform_texture(dof_shader_pass5, interface->medium_blurred_uniform, fx->dof_near_coc_buffer);
GPU_texture_bind(fx->depth_buffer, numslots++);
- GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_texture_compare_mode(fx->depth_buffer, false);
+ GPU_texture_filter_mode(fx->depth_buffer, true);
GPU_shader_uniform_texture(dof_shader_pass5, interface->depth_uniform, fx->depth_buffer);
/* if this is the last pass, prepare for rendering on the frambuffer */
@@ -1260,7 +1297,8 @@ bool GPU_fx_do_composite_pass(
GPU_texture_unbind(fx->dof_near_coc_buffer);
GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
GPU_texture_unbind(src);
- GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_compare_mode(fx->depth_buffer, true);
+ GPU_texture_filter_mode(fx->depth_buffer, false);
GPU_texture_unbind(fx->depth_buffer);
/* may not be attached, in that case this just returns */
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index c8d5d92b66b..36c61fde36c 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -1438,31 +1438,40 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
if (smoke_has_colors(sds->fluid)) {
float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
smoke_get_rgba(sds->fluid, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_density(sds->fluid));
+ sds->tex = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, smoke_get_density(sds->fluid), NULL);
}
- sds->tex_flame = (smoke_has_fuel(sds->fluid)) ? GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, smoke_get_flame(sds->fluid)) : NULL;
+ sds->tex_flame = (smoke_has_fuel(sds->fluid)) ?
+ GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, smoke_get_flame(sds->fluid), NULL) :
+ NULL;
}
else if (!sds->tex && highres) {
/* rgba texture for color + density */
if (smoke_turbulence_has_colors(sds->wt)) {
float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
smoke_turbulence_get_rgba(sds->wt, data, 0);
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
+ sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], data, NULL);
MEM_freeN(data);
}
/* density only */
else {
- sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_density(sds->wt));
+ sds->tex = GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1,
+ GPU_R8, smoke_turbulence_get_density(sds->wt), NULL);
}
- sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ? GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1, smoke_turbulence_get_flame(sds->wt)) : NULL;
+ sds->tex_flame = (smoke_turbulence_has_fuel(sds->wt)) ?
+ GPU_texture_create_3D_custom(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 1,
+ GPU_R8, smoke_turbulence_get_flame(sds->wt), NULL):
+ NULL;
}
- sds->tex_shadow = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 1, sds->shadow);
+ sds->tex_shadow = GPU_texture_create_3D_custom(sds->res[0], sds->res[1], sds->res[2], 1,
+ GPU_R8, sds->shadow, NULL);
}
#else // WITH_SMOKE
(void)highres;
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index e8fd4b8b8b1..d7ed65e853e 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -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);
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index ec1471744fa..1efc451f4a8 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -54,7 +54,7 @@ struct GPUFrameBuffer {
static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
{
- const char *format = "GPUFrameBuffer: framebuffer status %s";
+ const char *format = "GPUFrameBuffer: framebuffer status %s\n";
const char *err = "unknown";
#define format_status(X) \
@@ -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)
@@ -453,7 +489,7 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_
return NULL;
}
- ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out);
+ ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, samples, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 56b7af787e7..90e78af48c1 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -2415,7 +2415,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
}
/* Shadow color map */
- lamp->tex = GPU_texture_create_vsm_shadow_map(lamp->size, NULL);
+ lamp->tex = GPU_texture_create_2D_custom(lamp->size, lamp->size, 2, GPU_RG32F, NULL, NULL);
if (!lamp->tex) {
gpu_lamp_shadow_free(lamp);
return lamp;
@@ -2438,7 +2438,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
+ lamp->blurtex = GPU_texture_create_2D_custom(lamp->size * 0.5, lamp->size * 0.5, 2, GPU_RG32F, NULL, NULL);
if (!lamp->blurtex) {
gpu_lamp_shadow_free(lamp);
return lamp;
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index b81c19d5c70..6370e4f7f8c 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -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,6 +65,7 @@ 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[];
@@ -511,11 +513,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 +578,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,6 +671,7 @@ 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,
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 6956a815ac5..91159227069 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -49,9 +49,8 @@ static struct GPUTextureGlobal {
} GG = {NULL, NULL, NULL};
/* GPUTexture */
-
struct GPUTexture {
- int w, h; /* width/height */
+ int w, h, d; /* width/height/depth */
int number; /* number for multitexture binding */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
@@ -62,42 +61,211 @@ struct GPUTexture {
GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
int fb_attachment; /* slot the texture is attached to */
- int depth; /* is a depth texture? if 3D how deep? */
+ bool depth; /* is a depth texture? */
};
-static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
+static GLenum GPU_texture_get_format(int components, GPUFormat data_type, GLenum *format, bool *is_depth)
+{
+ if (data_type == GPU_DEPTH_COMPONENT24 ||
+ data_type == GPU_DEPTH_COMPONENT16 ||
+ data_type == GPU_DEPTH_COMPONENT32F)
+ {
+ *is_depth = true;
+ *format = GL_DEPTH_COMPONENT;
+ }
+ else {
+ *is_depth = false;
+
+ switch (components) {
+ case 1: *format = GL_RED; break;
+ case 2: *format = GL_RG; break;
+ case 3: *format = GL_RGB; break;
+ case 4: *format = GL_RGBA; break;
+ default: break;
+ }
+ }
+
+ switch (data_type) {
+ /* Formats texture & renderbuffer */
+ case GPU_RGBA32F: return GL_RGBA32F;
+ case GPU_RGBA32I: return GL_RGBA32I;
+ case GPU_RGBA32UI: return GL_RGBA32UI;
+ case GPU_RGBA16: return GL_RGBA16;
+ case GPU_RGBA16F: return GL_RGBA16F;
+ case GPU_RGBA16I: return GL_RGBA16I;
+ case GPU_RGBA16UI: return GL_RGBA16UI;
+ case GPU_RGBA8: return GL_RGBA8;
+ case GPU_RGBA8I: return GL_RGBA8I;
+ case GPU_RGBA8UI: return GL_RGBA8UI;
+ case GPU_RG32F: return GL_RG32F;
+ case GPU_RG32I: return GL_RG32I;
+ case GPU_RG32UI: return GL_RG32UI;
+ case GPU_RG16: return GL_RG16;
+ case GPU_RG16F: return GL_RG16F;
+ case GPU_RG16I: return GL_RG16I;
+ case GPU_RG16UI: return GL_RG16UI;
+ case GPU_RG8: return GL_RG8;
+ case GPU_RG8I: return GL_RG8I;
+ case GPU_RG8UI: return GL_RG8UI;
+ case GPU_R32F: return GL_R32F;
+ case GPU_R32I: return GL_R32I;
+ case GPU_R32UI: return GL_R32UI;
+ case GPU_R16F: return GL_R16F;
+ case GPU_R16I: return GL_R16I;
+ case GPU_R16UI: return GL_R16UI;
+ case GPU_R16: return GL_R16;
+ case GPU_R8: return GL_R8;
+ case GPU_R8I: return GL_R8I;
+ case GPU_R8UI: return GL_R8UI;
+ /* Special formats texture & renderbuffer */
+ case GPU_R11F_G11F_B10F: return GL_R11F_G11F_B10F;
+ case GPU_RGB10_A2: return GL_RGB10_A2;
+ case GPU_RGB10_A2UI: return GL_RGB10_A2UI;
+ case GPU_DEPTH32F_STENCIL8: return GL_DEPTH32F_STENCIL8;
+ case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8;
+ /* Texture only format */
+ case GPU_RGBA16_SNORM: return GL_RGBA16_SNORM;
+ case GPU_RGBA8_SNORM: return GL_RGBA8_SNORM;
+ case GPU_RGB32F: return GL_RGB32F;
+ case GPU_RGB32I: return GL_RGB32I;
+ case GPU_RGB32UI: return GL_RGB32UI;
+ case GPU_RGB16_SNORM: return GL_RGB16_SNORM;
+ case GPU_RGB16F: return GL_RGB16F;
+ case GPU_RGB16I: return GL_RGB16I;
+ case GPU_RGB16UI: return GL_RGB16UI;
+ case GPU_RGB16: return GL_RGB16;
+ case GPU_RGB8_SNORM: return GL_RGB8_SNORM;
+ case GPU_RGB8: return GL_RGB8;
+ case GPU_RGB8I: return GL_RGB8I;
+ case GPU_RGB8UI: return GL_RGB8UI;
+ case GPU_RG16_SNORM: return GL_RG16_SNORM;
+ case GPU_RG8_SNORM: return GL_RG8_SNORM;
+ case GPU_R16_SNORM: return GL_R16_SNORM;
+ case GPU_R8_SNORM: return GL_R8_SNORM;
+ /* Special formats texture only */
+#if 0 /* Absent ? */
+ case GPU_SRGB8_A8: return GL_SRGB8_A8;
+#endif
+ case GPU_SRGB8: return GL_SRGB8;
+ case GPU_RGB9_E5: return GL_RGB9_E5;
+ case GPU_COMPRESSED_RG_RGTC2: return GL_COMPRESSED_RG_RGTC2;
+ case GPU_COMPRESSED_SIGNED_RG_RGTC2: return GL_COMPRESSED_SIGNED_RG_RGTC2;
+ case GPU_COMPRESSED_RED_RGTC1: return GL_COMPRESSED_RED_RGTC1;
+ case GPU_COMPRESSED_SIGNED_RED_RGTC1: return GL_COMPRESSED_SIGNED_RED_RGTC1;
+ /* Depth Formats */
+ case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F;
+ case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24;
+ case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16;
+ default:
+ fprintf(stderr, "Texture format incorrect or unsupported\n");
+ return 0;
+ }
+}
+
+static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels)
{
- unsigned char *pixels, *p;
- const float *fp = fpixels;
- const int len = 4 * length;
+ const unsigned int xf = w / tex->w, yf = h / tex->h, zf = d / tex->d;
+ float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex");
- p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
+ if (nfpixels) {
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (unsigned k = 0; k < tex->d; k++) {
+ for (unsigned j = 0; j < tex->h; j++) {
+ for (unsigned i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here,
+ * it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
- for (int a = 0; a < len; a++, p++, fp++)
- *p = FTOCHAR((*fp));
+ if (channels == 4) {
+ nfpixels[offset * 4] = fpixels[offset_orig * 4];
+ nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ nfpixels[offset] = fpixels[offset_orig];
+ }
+ }
+ }
+ }
- return pixels;
+ return nfpixels;
}
-static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
+/* This tries to allocate video memory for a given texture
+ * If alloc fails, lower the resolution until it fits. */
+static bool GPU_texture_try_alloc(
+ GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, int channels,
+ bool try_rescale, const float *fpixels, float **rescaled_fpixels)
{
- void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
+ int r_width;
- if (target == GL_TEXTURE_1D)
- glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
- else
- glTexSubImage2D(target, 0, x, y, w, h, format, GL_UNSIGNED_BYTE, pixels);
-
- MEM_freeN(pixels);
+ if (proxy == GL_PROXY_TEXTURE_1D)
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_2D)
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_3D)
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+
+ glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &r_width);
+
+ if (r_width == 0 && try_rescale) {
+ const int w = tex->w, h = tex->h, d = tex->d;
+
+ /* Find largest texture possible */
+ while (r_width == 0) {
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->d /= 2;
+
+ /* really unlikely to happen but keep this just in case */
+ if (tex->w == 0) break;
+ if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break;
+ if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break;
+
+ if (proxy == GL_PROXY_TEXTURE_1D)
+ glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_2D)
+ glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL);
+ else if (proxy == GL_PROXY_TEXTURE_3D)
+ glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL);
+
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* Rescale */
+ if (r_width > 0) {
+ if (proxy == GL_PROXY_TEXTURE_1D) {
+ /* Do nothing for now */
+ return false;
+ }
+ else if (proxy == GL_PROXY_TEXTURE_2D) {
+ /* Do nothing for now */
+ return false;
+ }
+ else if (proxy == GL_PROXY_TEXTURE_3D) {
+ *rescaled_fpixels = GPU_texture_3D_rescale(tex, w, h, d, channels, fpixels);
+ return (bool)*rescaled_fpixels;
+ }
+ }
+ }
+
+ return (r_width > 0);
}
static GPUTexture *GPU_texture_create_nD(
- int w, int h, int n, const float *fpixels, int depth,
- GPUHDRType hdr_type, int components, int samples,
- char err_out[256])
+ int w, int h, int d, int n, const float *fpixels,
+ GPUFormat data_type, int components, int samples,
+ const bool can_rescale, char err_out[256])
{
- GLenum type, format, internalformat;
- void *pixels = NULL;
+ GLenum format, internalformat, proxy;
+ float *rescaled_fpixels = NULL, *pix;
+ bool valid;
if (samples) {
CLAMP_MAX(samples, GPU_max_color_texture_samples());
@@ -106,121 +274,94 @@ static GPUTexture *GPU_texture_create_nD(
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->w = w;
tex->h = h;
+ tex->d = d;
tex->number = -1;
tex->refcount = 1;
- tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
- tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D;
- tex->depth = depth;
+
+ if (n == 1) {
+ if (h == 0)
+ tex->target_base = tex->target = GL_TEXTURE_1D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY;
+ }
+ else if (n == 2) {
+ if (d == 0)
+ tex->target_base = tex->target = GL_TEXTURE_2D;
+ else
+ tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY;
+ }
+ else if (n == 3) {
+ tex->target_base = tex->target = GL_TEXTURE_3D;
+ }
+
tex->fb_attachment = -1;
+ if (samples && n == 2 && d == 0)
+ tex->target = GL_TEXTURE_2D_MULTISAMPLE;
+
+ internalformat = GPU_texture_get_format(components, data_type, &format, &tex->depth);
+
+ /* Generate Texture object */
glGenTextures(1, &tex->bindcode);
if (!tex->bindcode) {
- if (err_out) {
+ if (err_out)
BLI_snprintf(err_out, 256, "GPUTexture: texture create failed");
- }
- else {
+ else
fprintf(stderr, "GPUTexture: texture create failed");
- }
GPU_texture_free(tex);
return NULL;
}
-#if 0 /* this should be a compile-time check */
- if (!GPU_full_non_power_of_two_support()) {
- tex->w = power_of_2_max_i(tex->w);
- tex->h = power_of_2_max_i(tex->h);
- }
-#endif
-
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- if (depth) {
- type = GL_UNSIGNED_BYTE;
- format = GL_DEPTH_COMPONENT;
- internalformat = GL_DEPTH_COMPONENT;
- }
- else {
- type = GL_FLOAT;
-
- if (components == 4) {
- format = GL_RGBA;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RGBA8;
- break;
- /* the following formats rely on ARB_texture_float or OpenGL 3.0 */
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RGBA16F_ARB;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RGBA32F_ARB;
- break;
- default:
- break;
- }
- }
- else if (components == 2) {
- /* these formats rely on ARB_texture_rg or OpenGL 3.0 */
- format = GL_RG;
- switch (hdr_type) {
- case GPU_HDR_NONE:
- internalformat = GL_RG8;
- break;
- case GPU_HDR_HALF_FLOAT:
- internalformat = GL_RG16F;
- break;
- case GPU_HDR_FULL_FLOAT:
- internalformat = GL_RG32F;
- break;
- default:
- break;
- }
- }
+ /* Check if texture fit in VRAM */
+ if (d > 0)
+ proxy = GL_PROXY_TEXTURE_3D;
+ else if (h > 0)
+ proxy = GL_PROXY_TEXTURE_2D;
+ else
+ proxy = GL_PROXY_TEXTURE_1D;
- if (fpixels && hdr_type == GPU_HDR_NONE) {
- type = GL_UNSIGNED_BYTE;
- pixels = GPU_texture_convert_pixels(w * h, fpixels);
- }
- }
+ valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, components, can_rescale, fpixels,
+ &rescaled_fpixels);
- if (tex->target == GL_TEXTURE_1D) {
- glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL);
+ if (!valid) {
+ if (err_out)
+ BLI_snprintf(err_out, 256, "GPUTexture: texture alloc failed");
+ else
+ fprintf(stderr, "GPUTexture: texture alloc failed. Not enough Video Memory.");
+ GPU_texture_free(tex);
+ return NULL;
+ }
- if (fpixels) {
- glTexSubImage1D(tex->target, 0, 0, w, format, type,
- pixels ? pixels : fpixels);
+ /* Upload Texture */
+ pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels;
- if (tex->w > w) {
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1);
- }
- }
+ if (tex->target == GL_TEXTURE_1D) {
+ glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, GL_FLOAT, pix);
}
- else {
+ else if (tex->target == GL_TEXTURE_1D_ARRAY ||
+ tex->target == GL_TEXTURE_2D)
+ {
if (samples) {
glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true);
+ glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, GL_FLOAT, pix);
}
else {
- glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0,
- format, type, NULL);
- }
-
- if (fpixels) {
- glTexSubImage2D(tex->target, 0, 0, 0, w, h,
- format, type, pixels ? pixels : fpixels);
-
- if (tex->w > w)
- GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h);
- if (tex->h > h)
- GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h);
+ glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, pix);
}
}
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, pix);
+ }
- if (pixels)
- MEM_freeN(pixels);
+ if (rescaled_fpixels)
+ MEM_freeN(rescaled_fpixels);
- if (depth) {
+ /* Texture Parameters */
+ if (tex->depth) {
glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
@@ -232,127 +373,9 @@ static GPUTexture *GPU_texture_create_nD(
glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- else
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
- return tex;
-}
-
-
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
-{
- GLenum type, format, internalformat;
- void *pixels = NULL;
-
- GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
- tex->number = -1;
- tex->refcount = 1;
- tex->target = GL_TEXTURE_3D;
- tex->target_base = GL_TEXTURE_3D;
-
- glGenTextures(1, &tex->bindcode);
-
- if (!tex->bindcode) {
- fprintf(stderr, "GPUTexture: texture create failed");
- GPU_texture_free(tex);
- return NULL;
- }
-
- tex->number = 0;
- glBindTexture(tex->target, tex->bindcode);
-
- type = GL_FLOAT;
- if (channels == 4) {
- format = GL_RGBA;
- internalformat = GL_RGBA8;
- }
- else {
- format = GL_RED;
- internalformat = GL_INTENSITY8;
- }
-
- /* 3D textures are quite heavy, test if it's possible to create them first */
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
-
- bool rescale = false;
- int r_width;
-
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
-
- while (r_width == 0) {
- rescale = true;
- tex->w /= 2;
- tex->h /= 2;
- tex->depth /= 2;
- glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
- glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
- }
-
- /* really unlikely to happen but keep this just in case */
- tex->w = max_ii(tex->w, 1);
- tex->h = max_ii(tex->h, 1);
- tex->depth = max_ii(tex->depth, 1);
-
-#if 0
- if (fpixels)
- pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
-#endif
-
- /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
- * for gooseberry */
- if (rescale && fpixels) {
- /* FIXME: should these be floating point? */
- const unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
- float *tex3d = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->depth, "tex3d");
-
- GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
-
- for (unsigned k = 0; k < tex->depth; k++) {
- for (unsigned j = 0; j < tex->h; j++) {
- for (unsigned i = 0; i < tex->w; i++) {
- /* obviously doing nearest filtering here,
- * it's going to be slow in any case, let's not make it worse */
- float xb = i * xf;
- float yb = j * yf;
- float zb = k * zf;
- unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
- unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
-
- if (channels == 4) {
- tex3d[offset * 4] = fpixels[offset_orig * 4];
- tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
- tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
- tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
- }
- else
- tex3d[offset] = fpixels[offset_orig];
- }
- }
- }
-
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
-
- MEM_freeN(tex3d);
- }
- else if (fpixels) {
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
- }
-
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-
- if (pixels)
- MEM_freeN(pixels);
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ if (n != 1) glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (n == 3) glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
GPU_texture_unbind(tex);
@@ -464,114 +487,64 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
}
-GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, 0, 0, 1, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
+GPUTexture *GPU_texture_create_1D_custom(
+ int w, int channels, GPUFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, 0, 0, 1, pixels, data_type, channels, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_multisample(
- int w, int h, const float *fpixels, GPUHDRType hdr, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
- return tex;
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+GPUTexture *GPU_texture_create_2D_custom(
+ int w, int h, int channels, GPUFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, 0, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
-
- return tex;
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, data_type, channels, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
-{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, samples, err_out);
-
- if (tex)
- GPU_texture_unbind(tex);
- return tex;
+GPUTexture *GPU_texture_create_2D_multisample(int w, int h, const float *pixels, int samples, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, pixels, GPU_RGBA8, 4, samples, false, err_out);
}
-/**
- * A shadow map for VSM needs two components (depth and depth^2)
- */
-GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
+GPUTexture *GPU_texture_create_2D_array(int w, int h, int d, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
+ return GPU_texture_create_nD(w, h, d, 2, pixels, GPU_RGBA8, 4, 0, false, err_out);
}
-GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- if (repeat) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
- }
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
- GPU_texture_unbind(tex);
- }
-
- return tex;
+ return GPU_texture_create_nD(w, h, d, 3, pixels, GPU_RGBA8, 4, 0, true, err_out);
}
-GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+GPUTexture *GPU_texture_create_3D_custom(int w, int h, int d, int channels, GPUFormat data_type, const float *pixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, 0, err_out);
-
- if (tex) {
- /* Now we tweak some of the settings */
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ return GPU_texture_create_nD(w, h, d, 3, pixels, data_type, channels, 0, true, err_out);
+}
- GPU_texture_unbind(tex);
- }
+GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, err_out);
+}
- return tex;
+GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256])
+{
+ return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, samples, false, err_out);
}
void GPU_invalid_tex_init(void)
{
const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
- GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
+ GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, color, NULL);
}
void GPU_invalid_tex_bind(int mode)
@@ -659,7 +632,7 @@ int GPU_texture_bound_number(GPUTexture *tex)
return tex->number;
}
-void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
if (tex->number >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
@@ -672,13 +645,53 @@ void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
if (tex->number != 0)
glActiveTexture(GL_TEXTURE0 + tex->number);
- if (tex->depth) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+ if (tex->depth)
+ glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, use_compare ? GL_COMPARE_R_TO_TEXTURE : GL_NONE);
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
+{
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
}
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
GLenum filter = use_filter ? GL_LINEAR : GL_NEAREST;
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat)
+{
+ if (tex->number >= GPU_max_textures()) {
+ fprintf(stderr, "Not enough texture slots.\n");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ if (tex->number != 0)
+ glActiveTexture(GL_TEXTURE0 + tex->number);
+
+ GLenum repeat = use_repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE;
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
+ if (tex->target_base != GL_TEXTURE_1D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
+ if (tex->target_base == GL_TEXTURE_3D)
+ glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
if (tex->number != 0)
glActiveTexture(GL_TEXTURE0);
diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c
new file mode 100644
index 00000000000..76aa1a8226f
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_uniformbuffer.c
@@ -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
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index 2f91adde133..b1964857ab1 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -31,10 +31,19 @@
* 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,26 +52,207 @@ 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 ********************/
bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256])
{
- viewport->debug_depth = GPU_texture_create_2D(width, height, NULL, GPU_HDR_HALF_FLOAT, err_out);
+ viewport->debug_depth = GPU_texture_create_2D_custom(width, height, 4, GPU_RGBA16F, NULL, err_out);
return (viewport->debug_depth != NULL);
}
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
index 00000000000..7eb321f2996
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_3D_instance_vert.glsl
@@ -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/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h
index 0c500e366a7..824925634d4 100644
--- a/source/blender/makesdna/DNA_material_types.h
+++ b/source/blender/makesdna/DNA_material_types.h
@@ -90,6 +90,52 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
+/* Material Engine Settings */
+typedef struct MaterialEngineSettings {
+ struct MaterialEngineSettings *next, *prev;
+ char name[32]; /* engine name - MAX_NAME */
+ void *runtime; /* To be free on file read */
+ void *data;
+} MaterialEngineSettings;
+
+/* Clay engine */
+
+/* Runtime Data Not saved in file */
+typedef struct MaterialRuntimeClay {
+ short type;
+ short flag;
+ int material_id; /* Index in materials UBO */
+ int matcap_id; /* Icon ID */
+ float matcap_rot[2];
+ float matcap_hsv[3];
+ float ssao_params_var[4];
+} MaterialRuntimeClay;
+
+/* 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;
+
+ float pad;
+} 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 +249,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;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index cb267002a5f..1ae914eeea2 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -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;
@@ -545,6 +546,49 @@ 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 *runtime; /* Here to be free on file read */
+ 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;
+
+ float pad;
+ /* 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 */
typedef struct RenderData {
@@ -1713,6 +1757,9 @@ typedef struct Scene {
struct SceneCollection *collection;
int active_layer;
int pad4;
+
+ ListBase engines_settings; /* RenderEngineSettings */
+ int pad5[2];
} Scene;
/* **************** RENDERDATA ********************* */
@@ -1901,6 +1948,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 ********************* */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 9c45e34f211..d3b4c350487 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -385,6 +385,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 +502,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;
diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt
index 0f3ea27a7f9..608d4781e60 100644
--- a/source/blender/makesrna/intern/CMakeLists.txt
+++ b/source/blender/makesrna/intern/CMakeLists.txt
@@ -341,6 +341,7 @@ blender_include_dirs(
../../bmesh
../../blentranslation
../../depsgraph
+ ../../draw
../../gpu
../../imbuf
../../ikplugin
diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c
index b293f20dd95..3df4164cb6a 100644
--- a/source/blender/makesrna/intern/rna_material.c
+++ b/source/blender/makesrna/intern/rna_material.c
@@ -313,6 +313,31 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value)
}
}
+static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr)
+{
+ MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data;
+
+ if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_MaterialEngineSettingsClay;
+ }
+
+ 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);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index bc442692b67..b9ca9ea277b 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -52,6 +52,8 @@
#include "GPU_extensions.h"
+#include "DRW_engine.h"
+
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -1872,6 +1874,45 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value)
gm->exitkey = value;
}
+static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr)
+{
+ RenderEngineSettings *res = (RenderEngineSettings *)ptr->data;
+
+ if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
+ return &RNA_RenderEngineSettingsClay;
+ }
+
+ 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, NULL);
+
+ 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;
+ void **runtime;
+
+ DRW_render_settings_get(sce, sce->r.engine, (void ***)&runtime);
+
+ if (*runtime) {
+ MEM_freeN(*runtime);
+ *runtime = NULL;
+ }
+
+ 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");
@@ -6580,6 +6621,111 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna)
}
#endif
+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);
+}
+
+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");
+
+ rna_def_render_engine_settings_clay(brna);
+}
+
static void rna_def_scene_render_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -8075,7 +8221,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");
@@ -8227,6 +8383,7 @@ void RNA_def_scene(BlenderRNA *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);
diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt
index 9e40ab02ee4..27fa119bc88 100644
--- a/source/blender/render/CMakeLists.txt
+++ b/source/blender/render/CMakeLists.txt
@@ -35,6 +35,7 @@ set(INC
../makesdna
../makesrna
../physics
+ ../draw
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern
diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h
index f83a210275f..42e3cfb16d0 100644
--- a/source/blender/render/extern/include/RE_engine.h
+++ b/source/blender/render/extern/include/RE_engine.h
@@ -63,6 +63,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
diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c
index fd9d95c63b6..f5a64550daa 100644
--- a/source/blender/render/intern/source/external_engine.c
+++ b/source/blender/render/intern/source/external_engine.c
@@ -58,6 +58,8 @@
#include "RE_pipeline.h"
#include "RE_bake.h"
+#include "DRW_engine.h"
+
#include "initrender.h"
#include "renderpipeline.h"
#include "render_types.h"
@@ -91,12 +93,15 @@ void RE_engines_init(void)
#ifdef WITH_GAMEENGINE
BLI_addtail(&R_engines, &internal_game_type);
#endif
+ DRW_engines_init();
}
void RE_engines_exit(void)
{
RenderEngineType *type, *next;
+ DRW_engines_free();
+
for (type = R_engines.first; type; type = next) {
next = type->next;