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