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:
Clément Foucault
2017-02-07 11:20:15 +01:00
committed by Dalai Felinto
parent aeb8e81f27
commit 83adc54438
64 changed files with 5958 additions and 33 deletions

View File

@@ -242,6 +242,8 @@ endif()
option(WITH_PLAYER "Build Player" OFF)
option(WITH_OPENCOLORIO "Enable OpenColorIO color management" ${_init_OPENCOLORIO})
option(WITH_CLAY_ENGINE "Enable New Clay engine (Breaks Mac and Intel compatibility)" ON)
# Compositor
option(WITH_COMPOSITOR "Enable the tile based nodal compositor" ON)

View File

@@ -598,6 +598,7 @@ function(SETUP_BLENDER_SORTED_LIBS)
bf_modifiers
bf_bmesh
bf_gpu
bf_draw
bf_blenloader
bf_blenkernel
bf_physics

View File

@@ -75,5 +75,54 @@ class COLLECTION_PT_objects(CollectionButtonsPanel, Panel):
row.operator("collections.objects_deselect", text="Deselect")
def template_engine_settings(col, settings, name, use_icon_view=False):
icons = {
False: 'ZOOMIN',
True: 'X',
}
use_name = "{0}_use".format(name)
use = getattr(settings, use_name)
row = col.row()
col = row.column()
col.active = use
if use_icon_view:
col.template_icon_view(settings, name)
else:
col.prop(settings, name)
row.prop(settings, "{}_use".format(name), text="", icon=icons[use], emboss=False)
class COLLECTION_PT_clay_settings(CollectionButtonsPanel, Panel):
bl_label = "Render Settings"
COMPAT_ENGINES = {'BLENDER_CLAY'}
@classmethod
def poll(cls, context):
scene = context.scene
return scene and (scene.render.engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
collection = context.layer_collection
settings = collection.get_engine_settings()
col = layout.column()
template_engine_settings(col, settings, "type")
template_engine_settings(col, settings, "matcap_icon", use_icon_view=True)
template_engine_settings(col, settings, "matcap_rotation")
template_engine_settings(col, settings, "matcap_hue")
template_engine_settings(col, settings, "matcap_saturation")
template_engine_settings(col, settings, "matcap_value")
template_engine_settings(col, settings, "ssao_factor_cavity")
template_engine_settings(col, settings, "ssao_factor_edge")
template_engine_settings(col, settings, "ssao_distance")
template_engine_settings(col, settings, "ssao_attenuation")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -584,5 +584,24 @@ class RENDER_PT_bake(RenderButtonsPanel, Panel):
sub.prop(rd, "bake_user_scale", text="User Scale")
class RENDER_PT_clay(RenderButtonsPanel, Panel):
bl_label = "Default Clay"
COMPAT_ENGINES = {'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout;
settings = context.scene.active_engine_settings
layout.template_icon_view(settings, "matcap_icon")
layout.prop(settings, "matcap_rotation")
layout.prop(settings, "matcap_hue")
layout.prop(settings, "matcap_saturation")
layout.prop(settings, "matcap_value")
layout.prop(settings, "ssao_factor_cavity")
layout.prop(settings, "ssao_factor_edge")
layout.prop(settings, "ssao_distance")
layout.prop(settings, "ssao_attenuation")
layout.prop(settings, "ssao_samples")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)

View File

@@ -48,7 +48,7 @@ class RENDERLAYER_UL_renderlayers(UIList):
class RENDERLAYER_PT_layers(RenderLayerButtonsPanel, Panel):
bl_label = "Layer List"
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
def draw(self, context):
layout = self.layout

View File

@@ -100,6 +100,7 @@ add_subdirectory(windowmanager)
add_subdirectory(blenkernel)
add_subdirectory(blenlib)
add_subdirectory(bmesh)
add_subdirectory(draw)
add_subdirectory(render)
add_subdirectory(blenfont)
add_subdirectory(blentranslation)

View File

@@ -39,13 +39,17 @@ extern "C" {
#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
#define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */
#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
#define TODO_LAYER_DEPSGRAPH /* placeholder for real Depsgraph fix */
#define TODO_LAYER /* generic todo */
struct Base;
struct ID;
struct CollectionEngineSettings;
struct LayerCollection;
struct ID;
struct ListBase;
struct Main;
struct Object;
struct Base;
struct RenderEngine;
struct Scene;
struct SceneCollection;
struct SceneLayer;
@@ -66,6 +70,9 @@ void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
void BKE_scene_layer_engine_settings_recalculate(struct SceneLayer *sl);
void BKE_scene_layer_engine_settings_update(struct SceneLayer *sl);
void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
@@ -91,6 +98,24 @@ void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *s
void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
/* engine settings */
typedef void (*CollectionEngineSettingsCB)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
struct CollectionEngineSettings *BKE_layer_collection_engine_get(struct LayerCollection *lc, const char *engine_name);
void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, CollectionEngineSettingsCB func);
void BKE_layer_collection_engine_settings_callback_free(void);
void BKE_layer_collection_engine_settings_create(struct ListBase *lb, const char *engine_name);
void BKE_layer_collection_engine_settings_free(struct ListBase *lb);
void BKE_collection_engine_property_add_float(struct CollectionEngineSettings *ces, const char *name, float value);
void BKE_collection_engine_property_add_int(struct CollectionEngineSettings *ces, const char *name, int value);
struct CollectionEngineProperty *BKE_collection_engine_property_get(struct CollectionEngineSettings *ces, const char *name);
int BKE_collection_engine_property_value_get_int(struct CollectionEngineSettings *ces, const char *name);
float BKE_collection_engine_property_value_get_float(struct CollectionEngineSettings *ces, const char *name);
void BKE_collection_engine_property_value_set_int(struct CollectionEngineSettings *ces, const char *name, int value);
void BKE_collection_engine_property_value_set_float(struct CollectionEngineSettings *ces, const char *name, float value);
bool BKE_collection_engine_property_use_get(struct CollectionEngineSettings *ces, const char *name);
void BKE_collection_engine_property_use_set(struct CollectionEngineSettings *ces, const char *name, bool value);
/* iterators */
void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
@@ -172,6 +197,9 @@ void BKE_visible_bases_Iterator_end(Iterator *iter);
/* temporary hacky solution waiting for final depsgraph evaluation */
#define DEG_OBJECT_ITER(sl_, ob_) \
{ \
/* temporary solution, waiting for depsgraph update */ \
BKE_scene_layer_engine_settings_update(sl); \
\
/* flush all the data to objects*/ \
Base *base_; \
for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \

View File

@@ -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 */

View File

@@ -111,6 +111,12 @@ void BKE_material_free(Material *ma)
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
for (MaterialEngineSettings *mes = ma->engines_settings.first; mes; mes = mes->next) {
if (mes->data)
MEM_SAFE_FREE(mes->data);
}
BLI_freelistN(&ma->engines_settings);
}
void BKE_material_init(Material *ma)
@@ -248,6 +254,8 @@ Material *BKE_material_copy(Main *bmain, Material *ma)
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
BKE_id_copy_ensure_local(bmain, &ma->id, &man->id);
return man;
@@ -279,6 +287,8 @@ Material *localize_material(Material *ma)
man->nodetree = ntreeLocalize(ma->nodetree);
BLI_listbase_clear(&man->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
return man;
}
@@ -1698,6 +1708,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
matcopied = 1;
}

View File

@@ -47,7 +47,7 @@
/* Mesh Interface */
#define MESH_RENDER_FUNCTION(func_name) \
if (me->edit_btmesh) { \
if (me->edit_btmesh && me->edit_btmesh->derivedFinal) { \
return mesh_bmesh_##func_name(me); \
} \
else { \

View File

@@ -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)

View File

@@ -3970,6 +3970,7 @@ static void lib_link_material(FileData *fd, Main *main)
static void direct_link_material(FileData *fd, Material *ma)
{
int a;
MaterialEngineSettings *mes;
ma->adt = newdataadr(fd, ma->adt);
direct_link_animdata(fd, ma->adt);
@@ -3990,6 +3991,11 @@ static void direct_link_material(FileData *fd, Material *ma)
ma->preview = direct_link_preview_image(fd, ma->preview);
BLI_listbase_clear(&ma->gpumaterial);
link_list(fd, &ma->engines_settings);
for (mes = ma->engines_settings.first; mes; mes = mes->next) {
mes->data = newdataadr(fd, mes->data);
}
}
/* ************ READ PARTICLE SETTINGS ***************** */
@@ -5552,6 +5558,7 @@ static void direct_link_object(FileData *fd, Object *ob)
ob->bb = NULL;
ob->derivedDeform = NULL;
ob->derivedFinal = NULL;
ob->collection_settings = NULL;
BLI_listbase_clear(&ob->gpulamp);
link_list(fd, &ob->pc_ids);
@@ -5924,6 +5931,14 @@ static void direct_link_scene_collection(FileData *fd, SceneCollection *sc)
}
}
static void direct_link_engine_settings(FileData *fd, ListBase *lb)
{
link_list(fd, lb);
for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
link_list(fd, &ces->properties);
}
}
static void direct_link_layer_collections(FileData *fd, ListBase *lb)
{
link_list(fd, lb);
@@ -5938,6 +5953,8 @@ static void direct_link_layer_collections(FileData *fd, ListBase *lb)
link_list(fd, &lc->overrides);
direct_link_engine_settings(fd, &lc->engine_settings);
direct_link_layer_collections(fd, &lc->layer_collections);
}
}
@@ -5950,6 +5967,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
RigidBodyWorld *rbw;
SceneLayer *sl;
SceneRenderLayer *srl;
RenderEngineSettings *res;
sce->theDag = NULL;
sce->depsgraph = NULL;
@@ -6212,6 +6230,11 @@ static void direct_link_scene(FileData *fd, Scene *sce)
sl->basact = newdataadr(fd, sl->basact);
direct_link_layer_collections(fd, &sl->layer_collections);
}
link_list(fd, &sce->engines_settings);
for (res = sce->engines_settings.first; res; res = res->next) {
res->data = newdataadr(fd, res->data);
}
}
/* ************ READ WM ***************** */

View File

@@ -30,6 +30,7 @@
#include "DNA_object_types.h"
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_scene_types.h"
#include "DNA_genfile.h"

View File

@@ -1894,6 +1894,8 @@ static void write_objects(WriteData *wd, ListBase *idbase)
writelist(wd, DATA, LinkData, &ob->pc_ids);
writelist(wd, DATA, LodLevel, &ob->lodlevels);
ob->collection_settings = NULL;
}
write_previews(wd, ob->preview);
@@ -2469,6 +2471,21 @@ static void write_textures(WriteData *wd, ListBase *idbase)
mywrite_flush(wd);
}
static void write_material_engines_settings(WriteData *wd, ListBase *lb)
{
for (MaterialEngineSettings *res = lb->first; res; res = res->next) {
writestruct(wd, DATA, MaterialEngineSettings, 1, res);
if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
writestruct(wd, DATA, MaterialEngineSettingsClay, 1, res->data);
}
else {
/* No engine matched */
/* error: don't know how to write this file */
}
}
}
static void write_materials(WriteData *wd, ListBase *idbase)
{
Material *ma;
@@ -2505,6 +2522,8 @@ static void write_materials(WriteData *wd, ListBase *idbase)
}
write_previews(wd, ma->preview);
write_material_engines_settings(wd, &ma->engines_settings);
}
ma = ma->id.next;
}
@@ -2639,6 +2658,26 @@ static void write_scene_collection(WriteData *wd, SceneCollection *sc)
}
}
static void write_collection_engine_settings(WriteData *wd, ListBase *lb)
{
for (CollectionEngineSettings *ces = lb->first; ces; ces = ces->next) {
writestruct(wd, DATA, CollectionEngineSettings, 1, ces);
for (CollectionEngineProperty *prop = ces->properties.first; prop; prop = prop->next) {
switch (prop->type) {
case COLLECTION_PROP_TYPE_FLOAT:
writestruct(wd, DATA, CollectionEnginePropertyFloat, 1, prop);
break;
case COLLECTION_PROP_TYPE_INT:
writestruct(wd, DATA, CollectionEnginePropertyInt, 1, prop);
break;
default:
; /* error: don't know how to write this file */
}
}
}
}
static void write_layer_collections(WriteData *wd, ListBase *lb)
{
for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
@@ -2647,10 +2686,27 @@ static void write_layer_collections(WriteData *wd, ListBase *lb)
writelist(wd, DATA, LinkData, &lc->object_bases);
writelist(wd, DATA, CollectionOverride, &lc->overrides);
write_collection_engine_settings(wd, &lc->engine_settings);
write_layer_collections(wd, &lc->layer_collections);
}
}
static void write_render_engines_settings(WriteData *wd, ListBase *lb)
{
for (RenderEngineSettings *res = lb->first; res; res = res->next) {
writestruct(wd, DATA, RenderEngineSettings, 1, res);
if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
writestruct(wd, DATA, RenderEngineSettingsClay, 1, res->data);
}
else {
/* No engine matched */
/* error: don't know how to write this file */
}
}
}
static void write_scenes(WriteData *wd, ListBase *scebase)
{
Scene *sce;
@@ -2880,6 +2936,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
write_layer_collections(wd, &sl->layer_collections);
}
write_render_engines_settings(wd, &sce->engines_settings);
sce = sce->id.next;
}

View File

@@ -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}")

View 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__ */

View 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

View File

@@ -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__ */

View 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);
}

View 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);
}

View 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;
}

View 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;
}

View 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__ */

View 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

View 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__ */

View 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
}

View 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);
}
}

View 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__ */

View File

@@ -586,6 +586,7 @@ static void view3d_main_region_exit(wmWindowManager *wm, ARegion *ar)
if (rv3d->viewport) {
GPU_viewport_free(rv3d->viewport);
MEM_freeN(rv3d->viewport);
rv3d->viewport = NULL;
}
}
@@ -747,6 +748,7 @@ static void view3d_main_region_free(ARegion *ar)
}
if (rv3d->viewport) {
GPU_viewport_free(rv3d->viewport);
MEM_freeN(rv3d->viewport);
}
MEM_freeN(rv3d);

View File

@@ -2098,12 +2098,42 @@ static void view3d_draw_view(const bContext *C, ARegion *ar, DrawData *draw_data
#endif
}
static void view3d_render_pass(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
RenderEngineType *type = RE_engines_find(scene->r.engine); /* In the future we should get that from Layers */
if (type->flag & RE_USE_OGL_PIPELINE) {
type->view_draw(NULL, C);
}
else {
// Offline Render engine
}
}
static void view3d_draw_view_new(const bContext *C, ARegion *ar, DrawData *UNUSED(draw_data))
{
view3d_draw_setup_view(C, ar);
/* Only 100% compliant on new spec goes bellow */
view3d_render_pass(C, ar);
view3d_draw_grid(C, ar);
view3d_draw_manipulator(C);
view3d_draw_region_info(C, ar);
}
void view3d_main_region_draw(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = ar->regiondata;
/* TODO layers - In the future we should get RE from Layers */
RenderEngineType *type = RE_engines_find(scene->r.engine);
if (IS_VIEWPORT_LEGACY(v3d)) {
if (IS_VIEWPORT_LEGACY(v3d) && ((type->flag & RE_USE_OGL_PIPELINE) == 0)) {
view3d_main_region_draw_legacy(C, ar);
return;
}
@@ -2111,12 +2141,20 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar)
if (!rv3d->viewport)
rv3d->viewport = GPU_viewport_create();
GPU_viewport_bind(rv3d->viewport, &ar->winrct);
/* TODO viewport - there is so much to be done, in fact a lot will need to happen in the space_view3d.c
* before we even call the drawing routine, but let's move on for now (dfelinto)
* but this is a provisory way to start seeing things in the viewport */
DrawData draw_data;
view3d_draw_data_init(C, ar, rv3d, &draw_data);
view3d_draw_view(C, ar, &draw_data);
if (type->flag & RE_USE_OGL_PIPELINE)
view3d_draw_view_new(C, ar, &draw_data);
else
view3d_draw_view(C, ar, &draw_data);
GPU_viewport_unbind(rv3d->viewport);
v3d->flag |= V3D_INVALID_BACKBUF;
}

View File

@@ -38,6 +38,7 @@
struct ARegion;
struct ARegionType;
struct BoundBox;
struct Batch;
struct DerivedMesh;
struct Object;
struct SmokeDomainSettings;

View File

@@ -31,6 +31,7 @@ set(INC
../imbuf
../makesdna
../makesrna
../draw
../editors/include
@@ -64,6 +65,7 @@ set(SRC
intern/gpu_select.c
intern/gpu_shader.c
intern/gpu_texture.c
intern/gpu_uniformbuffer.c
intern/gpu_viewport.c
gawain/attrib_binding.c
@@ -122,6 +124,7 @@ set(SRC
GPU_select.h
GPU_shader.h
GPU_texture.h
GPU_uniformbuffer.h
GPU_viewport.h
intern/gpu_codegen.h
@@ -145,10 +148,16 @@ data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_instance_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_flat_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_smooth_color_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_smooth_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_lamp_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC)

View File

@@ -53,6 +53,8 @@ int GPU_max_textures(void);
float GPU_max_texture_anisotropy(void);
int GPU_max_color_texture_samples(void);
int GPU_max_cube_map_size(void);
int GPU_max_ubo_binds(void);
int GPU_max_ubo_size(void);
int GPU_color_depth(void);
void GPU_get_dfdy_factors(float fac[2]);

View File

@@ -52,6 +52,7 @@ void GPU_texture_bind_as_framebuffer(struct GPUTexture *tex);
GPUFrameBuffer *GPU_framebuffer_create(void);
bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot);
void GPU_framebuffer_texture_detach(struct GPUTexture *tex);
void GPU_framebuffer_bind(GPUFrameBuffer *fb);
void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, struct GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);

View File

@@ -38,6 +38,7 @@ extern "C" {
typedef struct GPUShader GPUShader;
struct GPUTexture;
struct GPUUniformBuffer;
/* GPU Shader
* - only for fragment shaders now
@@ -69,14 +70,17 @@ void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
void GPU_shader_unbind(void);
int GPU_shader_get_program(GPUShader *shader);
void *GPU_shader_get_interface(GPUShader *shader);
void GPU_shader_set_interface(GPUShader *shader, void *interface);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
int arraysize, const float *value);
void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
int arraysize, const int *value);
void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
@@ -104,6 +108,7 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_2D_IMAGE_COLOR,
/* for simple 3D drawing */
GPU_SHADER_3D_UNIFORM_COLOR,
GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE,
GPU_SHADER_3D_FLAT_COLOR,
GPU_SHADER_3D_SMOOTH_COLOR,
GPU_SHADER_3D_DEPTH_ONLY,
@@ -126,6 +131,10 @@ typedef enum GPUBuiltinShader {
GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH,
GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR,
GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR,
/* lamp drawing */
GPU_SHADER_3D_GROUNDPOINT,
GPU_SHADER_3D_GROUNDLINE,
GPU_SHADER_3D_LAMP_COMMON,
GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */
} GPUBuiltinShader;

View 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);

View File

@@ -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);

View File

@@ -247,3 +247,89 @@ void Batch_draw(Batch* batch)
Batch_done_using_program(batch);
glBindVertexArray(0);
}
/* clement : temp stuff */
void Batch_draw_stupid(Batch* batch)
{
if (batch->vao_id)
glBindVertexArray(batch->vao_id);
else
Batch_prime(batch);
if (batch->program_dirty)
Batch_update_program_bindings(batch);
// Batch_use_program(batch);
//gpuBindMatrices(batch->program);
if (batch->elem)
{
const ElementList* el = batch->elem;
#if TRACK_INDEX_RANGE
if (el->base_index)
glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index);
else
glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0);
#else
glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0);
#endif
}
else
glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct);
// Batch_done_using_program(batch);
glBindVertexArray(0);
}
/* clement : temp stuff */
void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count)
{
if (batch->vao_id)
glBindVertexArray(batch->vao_id);
else
Batch_prime(batch);
if (batch->program_dirty)
Batch_update_program_bindings(batch);
const GLint loc = glGetAttribLocation(batch->program, "InstanceModelMatrix");
#if TRUST_NO_ONE
assert(loc != -1);
#endif
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc + 0, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)0);
glEnableVertexAttribArray(loc + 1);
glVertexAttribPointer(loc + 1, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(sizeof(float)*4));
glEnableVertexAttribArray(loc + 2);
glVertexAttribPointer(loc + 2, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(2 * sizeof(float)*4));
glEnableVertexAttribArray(loc + 3);
glVertexAttribPointer(loc + 3, 4, GL_FLOAT, GL_FALSE, sizeof(float)*4*4, (GLvoid*)(3 * sizeof(float)*4));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glVertexAttribDivisor(loc + 0, 1);
glVertexAttribDivisor(loc + 1, 1);
glVertexAttribDivisor(loc + 2, 1);
glVertexAttribDivisor(loc + 3, 1);
// Batch_use_program(batch);
//gpuBindMatrices(batch->program);
if (batch->elem)
{
const ElementList* el = batch->elem;
glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count);
}
else
glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count);
// Batch_done_using_program(batch);
glBindVertexArray(0);
}

View File

@@ -57,6 +57,8 @@ void Batch_Uniform3fv(Batch*, const char* name, const float data[3]);
void Batch_Uniform4fv(Batch*, const char* name, const float data[4]);
void Batch_draw(Batch*);
void Batch_draw_stupid(Batch* batch);
void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count);

View File

@@ -69,6 +69,8 @@ static struct GPUGlobal {
GLint maxtexsize;
GLint maxcubemapsize;
GLint maxtextures;
GLint maxubosize;
GLint maxubobinds;
bool extdisabled;
int colordepth;
int samples_color_texture_max;
@@ -121,6 +123,16 @@ int GPU_max_cube_map_size(void)
return GG.maxcubemapsize;
}
int GPU_max_ubo_binds(void)
{
return GG.maxubobinds;
}
int GPU_max_ubo_size(void)
{
return GG.maxubosize;
}
void GPU_get_dfdy_factors(float fac[2])
{
copy_v2_v2(fac, GG.dfdyfactors);
@@ -154,6 +166,9 @@ void gpu_extensions_init(void)
else
GG.max_anisotropy = 1.0f;
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &GG.maxubobinds);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize);
GLint r, g, b;
glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g);

View File

@@ -260,6 +260,43 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
glPushMatrix();
}
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
{
int numslots = 0, i;
GLenum attachments[4];
GLenum readattachement = 0;
GPUTexture *tex;
for (i = 0; i < 4; i++) {
if (fb->colortex[i]) {
attachments[numslots] = GL_COLOR_ATTACHMENT0 + i;
tex = fb->colortex[i];
if (!readattachement)
readattachement = GL_COLOR_ATTACHMENT0 + i;
numslots++;
}
}
/* bind framebuffer */
glBindFramebuffer(GL_FRAMEBUFFER, fb->object);
if (numslots == 0) {
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
tex = fb->depthtex;
}
else {
/* last bound prevails here, better allow explicit control here too */
glDrawBuffers(numslots, attachments);
glReadBuffer(readattachement);
}
glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex));
GG.currentfb = fb->object;
}
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
@@ -283,7 +320,6 @@ void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
/* push matrices and set default viewport and matrix */
glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot]));
GG.currentfb = fb->object;
GG.currentfb = fb->object;
}
bool GPU_framebuffer_bound(GPUFrameBuffer *fb)

View File

@@ -37,6 +37,7 @@
#include "GPU_debug.h"
#include "GPU_extensions.h"
#include "GPU_shader.h"
#include "GPU_uniformbuffer.h"
#include "GPU_texture.h"
#include "gpu_shader_private.h"
@@ -64,10 +65,16 @@ extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_rect_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
extern char datatoc_gpu_shader_3D_vert_glsl[];
extern char datatoc_gpu_shader_3D_instance_vert_glsl[];
extern char datatoc_gpu_shader_3D_flat_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_vert_glsl[];
extern char datatoc_gpu_shader_3D_smooth_color_frag_glsl[];
extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_vert_glsl[];
extern char datatoc_gpu_shader_3D_groundline_geom_glsl[];
extern char datatoc_gpu_shader_3D_lamp_vert_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[];
extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[];
@@ -511,11 +518,24 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
return glGetUniformLocation(shader->program, name);
}
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
return glGetUniformBlockIndex(shader->program, name);
}
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->uniform_interface;
}
/* Clement : Temp */
int GPU_shader_get_program(GPUShader *shader)
{
return (int)shader->program;
}
void GPU_shader_set_interface(GPUShader *shader, void *interface)
{
shader->uniform_interface = interface;
@@ -563,6 +583,17 @@ void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int ou
}
}
void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
{
int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
if (location == -1) {
return;
}
glUniformBlockBinding(shader->program, location, bindpoint);
}
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
{
int number = GPU_texture_bound_number(tex);
@@ -645,12 +676,21 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
[GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl,
datatoc_gpu_shader_image_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE] = { datatoc_gpu_shader_3D_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl },
[GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl,
datatoc_gpu_shader_flat_color_frag_glsl },
[GPU_SHADER_3D_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl,
datatoc_gpu_shader_3D_smooth_color_frag_glsl },
[GPU_SHADER_3D_DEPTH_ONLY] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_depth_only_frag_glsl },
[GPU_SHADER_3D_GROUNDPOINT] = { datatoc_gpu_shader_3D_groundpoint_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
[GPU_SHADER_3D_GROUNDLINE] = { datatoc_gpu_shader_3D_groundline_vert_glsl,
datatoc_gpu_shader_uniform_color_frag_glsl,
datatoc_gpu_shader_3D_groundline_geom_glsl },
[GPU_SHADER_3D_LAMP_COMMON] = { datatoc_gpu_shader_3D_lamp_vert_glsl,
datatoc_gpu_shader_uniform_color_frag_glsl},
[GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] =
{ datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl },
[GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] =

View File

@@ -91,6 +91,7 @@ static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type,
/* Formats texture & renderbuffer */
case GPU_RGBA16F: return GL_RGBA16F;
case GPU_RG32F: return GL_RG32F;
case GPU_RG16F: return GL_RG16F;
case GPU_RGBA8: return GL_RGBA8;
case GPU_R8: return GL_R8;
/* Special formats texture & renderbuffer */

View 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;
}

View File

@@ -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 ********************/

View File

@@ -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();
}

View File

@@ -0,0 +1,8 @@
/* Does Nothing */
in vec3 pos;
void main()
{
gl_Position = vec4(pos, 1.0);
}

View File

@@ -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;
}

View File

@@ -0,0 +1,10 @@
uniform mat4 ViewProjectionMatrix;
in vec3 pos;
in mat4 InstanceModelMatrix;
void main()
{
gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0);
}

View 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);
}

View File

@@ -59,6 +59,7 @@ typedef struct LayerCollection {
ListBase object_bases; /* (ObjectBase *)LinkData->data - synced with collection->objects and collection->filter_objects */
ListBase overrides;
ListBase layer_collections; /* synced with collection->collections */
ListBase engine_settings; /* CollectionEngineSettings */
} LayerCollection;
typedef struct SceneLayer {
@@ -102,8 +103,54 @@ enum {
/* SceneLayer->flag */
enum {
SCENE_LAYER_RENDER = (1 << 0),
SCENE_LAYER_ENGINE_DIRTY = (1 << 1),
};
/* *************************************************************** */
/* Engine Settings */
typedef struct CollectionEngineProperty {
struct CollectionEngineProperty *next, *prev;
char name[64]; /* MAX_NAME */
short type;
short pad;
char flag;
char pad2[3];
} CollectionEngineProperty;
typedef struct CollectionEnginePropertyInt {
struct CollectionEngineProperty data;
int value;
int pad;
} CollectionEnginePropertyInt;
typedef struct CollectionEnginePropertyFloat {
struct CollectionEngineProperty data;
float value;
float pad;
} CollectionEnginePropertyFloat;
typedef struct CollectionEngineSettings {
struct CollectionEngineSettings *next, *prev;
char name[32]; /* engine name - MAX_NAME */
ListBase properties; /* CollectionProperty */
} CollectionEngineSettings;
/* CollectionEngineProperty->flag */
enum {
COLLECTION_PROP_USE = (1 << 0),
};
/* CollectionEntineProperty.type */
typedef enum CollectionEnginePropertyType {
COLLECTION_PROP_TYPE_FLOAT = 0,
COLLECTION_PROP_TYPE_INT = 1,
} CollectionEnginePropertyType;
/* *************************************************************** */
#ifdef __cplusplus
}
#endif

View File

@@ -90,6 +90,43 @@ typedef struct TexPaintSlot {
int pad;
} TexPaintSlot;
/* Material Engine Settings */
typedef struct MaterialEngineSettings {
struct MaterialEngineSettings *next, *prev;
char name[32]; /* engine name - MAX_NAME */
void *data;
} MaterialEngineSettings;
/* Clay engine */
/* MaterialRuntimeClay.flag */
#define CLAY_OUTDATED 1
typedef struct MaterialEngineSettingsClay {
short type;
short matcap_icon; /* Icon ID */
float matcap_rot;
float matcap_hue;
float matcap_sat;
float matcap_val;
float ssao_distance;
float ssao_attenuation;
float ssao_factor_cavity;
float ssao_factor_edge;
/* Runtime */
short flag;
short pad;
int ubo_index;
} MaterialEngineSettingsClay;
/* MaterialEngineSettingsClay.type */
#define CLAY_MATCAP_NONE 0
#define CLAY_MATCAP_SIMPLE 1
#define CLAY_MATCAP_COMPLETE 2
typedef struct Material {
ID id;
struct AnimData *adt; /* animation data (must be immediately after id for utilities to use it) */
@@ -203,6 +240,9 @@ typedef struct Material {
struct TexPaintSlot *texpaintslot; /* cached slot for painting. Make sure to recalculate before use
* with refresh_texpaint_image_cache */
/* Engine Settings */
ListBase engines_settings; /* MaterialEngineSettings */
ListBase gpumaterial; /* runtime */
} Material;

View File

@@ -46,6 +46,7 @@ struct Object;
struct AnimData;
struct Ipo;
struct BoundBox;
struct CollectionSettings;
struct Path;
struct Material;
struct PartDeflect;
@@ -302,6 +303,8 @@ typedef struct Object {
LodLevel *currentlod;
struct PreviewImage *preview;
struct ListBase *collection_settings; /* used by depsgraph, flushed from collection-tree */
} Object;
/* Warning, this is not used anymore because hooks are now modifiers */

View File

@@ -48,6 +48,7 @@ extern "C" {
#include "DNA_freestyle_types.h"
#include "DNA_gpu_types.h"
#include "DNA_layer_types.h"
#include "DNA_material_types.h"
#include "DNA_userdef_types.h"
struct CurveMapping;
@@ -538,6 +539,50 @@ typedef enum BakePassFilter {
#define R_BAKE_PASS_FILTER_ALL (~0)
/* *************************************************************** */
/* Engine Settings */
typedef struct RenderEngineSettings {
struct RenderEngineSettings *next, *prev;
char name[32]; /* engine name */
void *data;
} RenderEngineSettings;
/* Render Data */
typedef struct RenderEngineSettingsClay {
/* Use same layout as MaterialEngineSettingsClay so this struct
* can be used as Material Settings. */
short type;
short matcap_icon; /* Icon ID */
float matcap_rot;
float matcap_hue;
float matcap_sat;
float matcap_val;
float ssao_distance;
float ssao_attenuation;
float ssao_factor_cavity;
float ssao_factor_edge;
short flag;
short pad;
int ubo_index;
/* end of MaterialEngineSettingsClay */
/* Global Settings */
short options;
short pad1;
int ssao_samples;
int pad2[2];
} RenderEngineSettingsClay;
/* RenderEngineSettingsClay.options */
typedef enum ClayFlagSettings {
CLAY_USE_AO = (1 << 0),
CLAY_USE_HSV = (1 << 1),
} ClayFlagSettings;
/* *************************************************************** */
/* Render Data */
@@ -1707,6 +1752,9 @@ typedef struct Scene {
struct SceneCollection *collection;
int active_layer;
int pad4;
ListBase engines_settings; /* RenderEngineSettings */
int pad5[2];
} Scene;
/* **************** RENDERDATA ********************* */
@@ -1895,6 +1943,7 @@ enum {
/* scene->r.engine (scene.c) */
extern const char *RE_engine_id_BLENDER_RENDER;
extern const char *RE_engine_id_BLENDER_GAME;
extern const char *RE_engine_id_BLENDER_CLAY;
extern const char *RE_engine_id_CYCLES;
/* **************** SCENE ********************* */

View File

@@ -106,6 +106,7 @@ extern StructRNA RNA_ClothCollisionSettings;
extern StructRNA RNA_ClothModifier;
extern StructRNA RNA_ClothSettings;
extern StructRNA RNA_CloudsTexture;
extern StructRNA RNA_CollectionEngineSettings;
extern StructRNA RNA_CollectionProperty;
extern StructRNA RNA_CollisionModifier;
extern StructRNA RNA_CollisionSensor;
@@ -385,6 +386,8 @@ extern StructRNA RNA_MaterialStrand;
extern StructRNA RNA_MaterialSubsurfaceScattering;
extern StructRNA RNA_MaterialTextureSlot;
extern StructRNA RNA_MaterialVolume;
extern StructRNA RNA_MaterialEngineSettings;
extern StructRNA RNA_MaterialEngineSettingsClay;
extern StructRNA RNA_Mask;
extern StructRNA RNA_MaskLayer;
extern StructRNA RNA_Menu;
@@ -500,6 +503,8 @@ extern StructRNA RNA_RenderLayer;
extern StructRNA RNA_RenderPass;
extern StructRNA RNA_RenderResult;
extern StructRNA RNA_RenderSettings;
extern StructRNA RNA_RenderEngineSettings;
extern StructRNA RNA_RenderEngineSettingsClay;
extern StructRNA RNA_RigidBodyWorld;
extern StructRNA RNA_RigidBodyObject;
extern StructRNA RNA_RigidBodyJointConstraint;

View File

@@ -192,6 +192,10 @@ if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
endif()
if(WITH_CLAY_ENGINE)
add_definitions(-DWITH_CLAY_ENGINE)
endif()
if(WITH_IMAGE_OPENEXR)
add_definitions(-DWITH_OPENEXR)
endif()
@@ -341,6 +345,7 @@ blender_include_dirs(
../../bmesh
../../blentranslation
../../depsgraph
../../draw
../../gpu
../../imbuf
../../ikplugin

View File

@@ -313,6 +313,31 @@ static void rna_MaterialTextureSlot_use_set(PointerRNA *ptr, int value)
}
}
static StructRNA *rna_MaterialEngineSettings_refine(PointerRNA *ptr)
{
#ifdef WITH_CLAY_ENGINE
MaterialEngineSettings *mes = (MaterialEngineSettings *)ptr->data;
if (STREQ(mes->name, RE_engine_id_BLENDER_CLAY)) {
return &RNA_MaterialEngineSettingsClay;
}
#endif
return &RNA_MaterialEngineSettings;
}
static void rna_Material_update_engine_data(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
#if 0
Material *ma = (Material *)ptr->data;
RenderEngineSettings *ed = DRW_material_settings_get(ma, sce->r.engine, NULL);
if (ed->runtime) {
MEM_freeN(ed->runtime);
ed->runtime = NULL;
}
#endif
WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
static void rna_Material_use_diffuse_ramp_set(PointerRNA *ptr, int value)
{
Material *ma = (Material *)ptr->data;
@@ -824,6 +849,118 @@ static void rna_def_material_mtex(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_Material_update");
}
static void rna_def_material_settings_clay(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem clay_matcap_items[] = {
{ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
{ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
{ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
{ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
{ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
{ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
{ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
{ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
{ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
{ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
{ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
{ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
{ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
{ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
{ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
{ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
{ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
{ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
{ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
{ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
{ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
{ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
{ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
{ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem clay_matcap_type[] = {
{CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
{CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
{CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "MaterialEngineSettingsClay", "MaterialEngineSettings");
RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
RNA_def_struct_sdna_from(srna, "MaterialEngineSettingsClay", "data");
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, clay_matcap_type);
RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, clay_matcap_items);
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_val");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
RNA_def_property_range(prop, 0.0f, 100000.0f);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
RNA_def_property_range(prop, 1.0f, 100000.0f);
RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
RNA_def_property_update(prop, 0, "rna_Material_update_engine_data");
}
static void rna_def_material_engine_settings(BlenderRNA *brna)
{
StructRNA *srna;
srna = RNA_def_struct(brna, "MaterialEngineSettings", NULL);
RNA_def_struct_ui_text(srna, "Engine Settings", "Engine specific settings");
RNA_def_struct_sdna(srna, "MaterialEngineSettings");
RNA_def_struct_refine_func(srna, "rna_MaterialEngineSettings_refine");
rna_def_material_settings_clay(brna);
}
static void rna_def_material_gamesettings(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2087,6 +2224,11 @@ void RNA_def_material(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "MaterialGameSettings");
RNA_def_property_ui_text(prop, "Game Settings", "Game material settings");
/* Engine settings */
prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "MaterialEngineSettings");
RNA_def_property_ui_text(prop, "Material Engine Settings", "Engine specific settings");
/* nodetree */
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
@@ -2136,6 +2278,7 @@ void RNA_def_material(BlenderRNA *brna)
rna_def_material_strand(brna);
rna_def_material_physics(brna);
rna_def_material_gamesettings(brna);
rna_def_material_engine_settings(brna);
RNA_api_material(srna);
}

View File

@@ -261,6 +261,24 @@ static void engine_update_script_node(RenderEngine *engine, struct bNodeTree *nt
RNA_parameter_list_free(&list);
}
static void engine_collection_settings_create(RenderEngine *engine, struct CollectionEngineSettings *ces)
{
extern FunctionRNA rna_RenderEngine_collection_settings_create_func;
PointerRNA ptr,cesptr;
ParameterList list;
FunctionRNA *func;
RNA_pointer_create(NULL, engine->type->ext.srna, engine, &ptr);
RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &cesptr);
func = &rna_RenderEngine_collection_settings_create_func;
RNA_parameter_list_create(&list, &ptr, func);
RNA_parameter_set_lookup(&list, "collection_settings", &cesptr);
engine->type->ext.call(NULL, &ptr, func, &list);
RNA_parameter_list_free(&list);
}
/* RenderEngine registration */
static void rna_RenderEngine_unregister(Main *UNUSED(bmain), StructRNA *type)
@@ -281,7 +299,7 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
RenderEngineType *et, dummyet = {NULL};
RenderEngine dummyengine = {NULL};
PointerRNA dummyptr;
int have_function[6];
int have_function[7];
/* setup dummy engine & engine type to store static properties in */
dummyengine.type = &dummyet;
@@ -323,8 +341,9 @@ static StructRNA *rna_RenderEngine_register(Main *bmain, ReportList *reports, vo
et->view_update = (have_function[3]) ? engine_view_update : NULL;
et->view_draw = (have_function[4]) ? engine_view_draw : NULL;
et->update_script_node = (have_function[5]) ? engine_update_script_node : NULL;
et->collection_settings_create = (have_function[6]) ? engine_collection_settings_create : NULL;
BLI_addtail(&R_engines, et);
RE_engines_register(bmain, et);
return et->ext.srna;
}
@@ -489,6 +508,13 @@ static void rna_def_render_engine(BlenderRNA *brna)
parm = RNA_def_pointer(func, "node", "Node", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
/* per-collection engine settings initialization */
func = RNA_def_function(srna, "collection_settings_create", NULL);
RNA_def_function_ui_description(func, "Create the per collection settings for the engine");
RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL | FUNC_ALLOW_WRITE);
parm = RNA_def_pointer(func, "collection_settings", "CollectionEngineSettings", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
/* tag for redraw */
func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw");
RNA_def_function_ui_description(func, "Request redraw for viewport rendering");

View File

@@ -52,6 +52,8 @@
#include "GPU_extensions.h"
#include "DRW_engine.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
@@ -80,6 +82,8 @@
#include "BLI_threads.h"
#define NO_ENGINE "NO_ENGINE"
#ifdef WITH_OPENEXR
EnumPropertyItem rna_enum_exr_codec_items[] = {
{R_IMF_EXR_CODEC_NONE, "NONE", 0, "None", ""},
@@ -1872,6 +1876,43 @@ static void rna_GameSettings_exit_key_set(PointerRNA *ptr, int value)
gm->exitkey = value;
}
static StructRNA *rna_RenderEngineSettings_refine(PointerRNA *ptr)
{
#ifdef WITH_CLAY_ENGINE
RenderEngineSettings *res = (RenderEngineSettings *)ptr->data;
if (STREQ(res->name, RE_engine_id_BLENDER_CLAY)) {
return &RNA_RenderEngineSettingsClay;
}
#endif
return &RNA_RenderEngineSettings;
}
static PointerRNA rna_RenderEngineSettings_active_get(PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->data;
RenderEngineSettings *res;
/* Ensure settings exists */
DRW_render_settings_get(scene, scene->r.engine);
res = BLI_findstring(&scene->engines_settings, scene->r.engine, offsetof(RenderEngineSettings, name));
return rna_pointer_inherit_refine(ptr, &RNA_RenderEngineSettings, res);
}
static void rna_RenderEngineSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *sce = (Scene *)ptr->id.data;
MaterialEngineSettingsClay *res;
res = (MaterialEngineSettingsClay *)DRW_render_settings_get(sce, sce->r.engine);
res->flag = CLAY_OUTDATED;
WM_main_add_notifier(NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
static TimeMarker *rna_TimeLine_add(Scene *scene, const char name[], int frame)
{
TimeMarker *marker = MEM_callocN(sizeof(TimeMarker), "TimeMarker");
@@ -2311,6 +2352,83 @@ static void rna_SceneCollection_object_unlink(
WM_main_add_notifier(NC_SCENE | ND_LAYER | ND_OB_ACTIVE, scene);
}
/****** layer collection engine settings *******/
static StructRNA *rna_CollectionEngineSettings_refine(struct PointerRNA *ptr)
{
CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data;
if (STREQ(ces->name, "BLENDER_CLAY")) {
return &RNA_CollectionEngineSettingsClay;
}
/* TODO - handle other engines */
TODO_LAYER;
(void) ces;
return &RNA_CollectionEngineSettings;
}
/****** clay engine settings *******/
#define RNA_LAYER_ENGINE_USE_GET_SET(_NAME_) \
static int rna_LayerEngineSettings_##_NAME_##_use_get(PointerRNA *ptr) \
{ \
CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
return BKE_collection_engine_property_use_get(ces, #_NAME_) ? 1 : 0; \
} \
\
static void rna_LayerEngineSettings_##_NAME_##_use_set(PointerRNA *ptr, int value) \
{ \
CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
BKE_collection_engine_property_use_set(ces, #_NAME_, value? true : false); \
}
#define RNA_LAYER_ENGINE_GET_SET(_TYPE_, _NAME_) \
static _TYPE_ rna_LayerEngineSettings_##_NAME_##_get(PointerRNA *ptr) \
{ \
CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
return BKE_collection_engine_property_value_get_##_TYPE_(ces, #_NAME_); \
} \
\
static void rna_LayerEngineSettings_##_NAME_##_set(PointerRNA *ptr, _TYPE_ value) \
{ \
CollectionEngineSettings *ces = (CollectionEngineSettings *)ptr->data; \
BKE_collection_engine_property_value_set_##_TYPE_(ces, #_NAME_, value); \
} \
RNA_LAYER_ENGINE_USE_GET_SET(_NAME_)
#define RNA_LAYER_ENGINE_GET_SET_FLOAT(_NAME_) \
RNA_LAYER_ENGINE_GET_SET(float, _NAME_)
#define RNA_LAYER_ENGINE_GET_SET_INT(_NAME_) \
RNA_LAYER_ENGINE_GET_SET(int, _NAME_)
RNA_LAYER_ENGINE_GET_SET_INT(type)
RNA_LAYER_ENGINE_GET_SET_INT(matcap_icon)
RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_rotation)
RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_hue)
RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_saturation)
RNA_LAYER_ENGINE_GET_SET_FLOAT(matcap_value)
RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_cavity)
RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_factor_edge)
RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_distance)
RNA_LAYER_ENGINE_GET_SET_FLOAT(ssao_attenuation)
#undef RNA_LAYER_ENGINE_GET_SET_INT
#undef RNA_LAYER_ENGINE_GET_SET_FLOAT
#undef RNA_LAYER_ENGINE_GET_SET
#undef RNA_LAYER_ENGINE_USE_GET_SET
static void rna_CollectionEngineSettings_update(bContext *C, PointerRNA *UNUSED(ptr))
{
SceneLayer *sl = CTX_data_scene_layer(C);
BKE_scene_layer_engine_settings_recalculate(sl);
}
/***********************************/
static void rna_LayerCollection_name_get(PointerRNA *ptr, char *value)
{
SceneCollection *sc = ((LayerCollection *)ptr->data)->scene_collection;
@@ -2340,6 +2458,25 @@ static PointerRNA rna_LayerCollection_objects_get(CollectionPropertyIterator *it
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, base->object);
}
static PointerRNA rna_LayerCollection_engine_settings_get(ID *UNUSED(id), LayerCollection *lc, bContext *C, const char *engine)
{
Scene *scene = CTX_data_scene(C);
const char *engine_name;
if (STREQ(engine, NO_ENGINE)) {
RenderData *rd = &scene->r;
engine_name = rd->engine;
}
else {
engine_name = engine;
}
PointerRNA ptr;
CollectionEngineSettings *ces = BKE_layer_collection_engine_get(lc, engine_name);
RNA_pointer_create(NULL, &RNA_CollectionEngineSettings, ces, &ptr);
return rna_pointer_inherit_refine(&ptr, &RNA_CollectionEngineSettings, ces);
}
static void rna_LayerCollection_hide_update(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -5602,11 +5739,176 @@ static void rna_def_layer_collection_override(BlenderRNA *brna)
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, NULL);
}
#define RNA_LAYER_ENGINE_USE(_NAME_) \
prop = RNA_def_property(srna, #_NAME_"_use", PROP_BOOLEAN, PROP_NONE); \
RNA_def_property_boolean_funcs(prop, \
"rna_LayerEngineSettings_"#_NAME_"_use_get", \
"rna_LayerEngineSettings_"#_NAME_"_use_set"); \
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); \
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
static void rna_def_layer_collection_engine_settings_clay(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem clay_matcap_items[] = {
{ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
{ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
{ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
{ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
{ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
{ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
{ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
{ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
{ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
{ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
{ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
{ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
{ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
{ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
{ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
{ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
{ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
{ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
{ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
{ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
{ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
{ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
{ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
{ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
{0, NULL, 0, NULL, NULL}
};
static EnumPropertyItem clay_matcap_type[] = {
{CLAY_MATCAP_NONE, "NONE", 0, "Scene", "Use default scene matcap"},
{CLAY_MATCAP_SIMPLE, "SIMPLE", 0, "Simple", "Let you choose the texture to use with the default settings"},
{CLAY_MATCAP_COMPLETE, "COMPLETE", 0, "Complete", "Expose all settings"},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "CollectionEngineSettingsClay", NULL);
RNA_def_struct_sdna(srna, "CollectionEngineSettings");
RNA_def_struct_ui_text(srna, "Collections Clay Engine Settings", "Engine specific settings for this collection");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Engine name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
/* see RNA_LAYER_ENGINE_GET_SET macro */
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_type_get", "rna_LayerEngineSettings_type_set", NULL);
RNA_def_property_enum_items(prop, clay_matcap_type);
RNA_def_property_ui_text(prop, "Settings Type", "What settings to use for this material");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(type)
prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_funcs(prop, "rna_LayerEngineSettings_matcap_icon_get", "rna_LayerEngineSettings_matcap_icon_set", NULL);
RNA_def_property_enum_items(prop, clay_matcap_items);
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(matcap_icon)
prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_rotation_get", "rna_LayerEngineSettings_matcap_rotation_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(matcap_rotation)
prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_hue_get", "rna_LayerEngineSettings_matcap_hue_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(matcap_hue)
prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_saturation_get", "rna_LayerEngineSettings_matcap_saturation_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(matcap_saturation)
prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_matcap_value_get", "rna_LayerEngineSettings_matcap_value_set", NULL);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(matcap_value)
prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_cavity_get", "rna_LayerEngineSettings_ssao_factor_cavity_set", NULL);
RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(ssao_factor_cavity)
prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_factor_edge_get", "rna_LayerEngineSettings_ssao_factor_edge_set", NULL);
RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(ssao_factor_edge)
prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_distance_get", "rna_LayerEngineSettings_ssao_distance_set", NULL);
RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
RNA_def_property_range(prop, 0.0f, 100000.0f);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(ssao_distance)
prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_ssao_attenuation_get", "rna_LayerEngineSettings_ssao_attenuation_set", NULL);
RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
RNA_def_property_range(prop, 1.0f, 100000.0f);
RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_CollectionEngineSettings_update");
RNA_LAYER_ENGINE_USE(ssao_attenuation)
}
static void rna_def_layer_collection_engine_settings(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "CollectionEngineSettings", NULL);
RNA_def_struct_ui_text(srna, "Collections Engine Settings", "Engine specific settings for this collection");
RNA_def_struct_refine_func(srna, "rna_CollectionEngineSettings_refine");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Name", "Engine name");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_struct_name_property(srna, prop);
/* the engine specific structs */
rna_def_layer_collection_engine_settings_clay(brna);
}
#undef RNA_LAYER_ENGINE_USE
static void rna_def_layer_collection(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
FunctionRNA *func;
PropertyRNA *parm;
srna = RNA_def_struct(brna, "LayerCollection", NULL);
RNA_def_struct_ui_text(srna, "Layer Collection", "Layer collection");
@@ -5638,6 +5940,15 @@ static void rna_def_layer_collection(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "LayerCollectionOverride");
RNA_def_property_ui_text(prop, "Collection Overrides", "");
func = RNA_def_function(srna, "get_engine_settings", "rna_LayerCollection_engine_settings_get");
RNA_def_function_ui_description(func, "Return the engine settings for this collection");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "engine", NO_ENGINE, MAX_NAME, "Engine", "use context one by default");
RNA_def_parameter_clear_flags(parm, 0, PARM_REQUIRED);
parm = RNA_def_pointer(func, "result", "CollectionEngineSettings", "", "");
RNA_def_parameter_flags(parm, 0, PARM_RNAPTR);
RNA_def_function_return(func, parm);
/* Flags */
prop = RNA_def_property(srna, "hide", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", COLLECTION_VISIBLE);
@@ -6580,6 +6891,115 @@ static void rna_def_scene_quicktime_settings(BlenderRNA *brna)
}
#endif
#ifdef WITH_CLAY_ENGINE
static void rna_def_render_engine_settings_clay(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem clay_matcap_items[] = {
{ICON_MATCAP_01, "01", ICON_MATCAP_01, "", ""},
{ICON_MATCAP_02, "02", ICON_MATCAP_02, "", ""},
{ICON_MATCAP_03, "03", ICON_MATCAP_03, "", ""},
{ICON_MATCAP_04, "04", ICON_MATCAP_04, "", ""},
{ICON_MATCAP_05, "05", ICON_MATCAP_05, "", ""},
{ICON_MATCAP_06, "06", ICON_MATCAP_06, "", ""},
{ICON_MATCAP_07, "07", ICON_MATCAP_07, "", ""},
{ICON_MATCAP_08, "08", ICON_MATCAP_08, "", ""},
{ICON_MATCAP_09, "09", ICON_MATCAP_09, "", ""},
{ICON_MATCAP_10, "10", ICON_MATCAP_10, "", ""},
{ICON_MATCAP_11, "11", ICON_MATCAP_11, "", ""},
{ICON_MATCAP_12, "12", ICON_MATCAP_12, "", ""},
{ICON_MATCAP_13, "13", ICON_MATCAP_13, "", ""},
{ICON_MATCAP_14, "14", ICON_MATCAP_14, "", ""},
{ICON_MATCAP_15, "15", ICON_MATCAP_15, "", ""},
{ICON_MATCAP_16, "16", ICON_MATCAP_16, "", ""},
{ICON_MATCAP_17, "17", ICON_MATCAP_17, "", ""},
{ICON_MATCAP_18, "18", ICON_MATCAP_18, "", ""},
{ICON_MATCAP_19, "19", ICON_MATCAP_19, "", ""},
{ICON_MATCAP_20, "20", ICON_MATCAP_20, "", ""},
{ICON_MATCAP_21, "21", ICON_MATCAP_21, "", ""},
{ICON_MATCAP_22, "22", ICON_MATCAP_22, "", ""},
{ICON_MATCAP_23, "23", ICON_MATCAP_23, "", ""},
{ICON_MATCAP_24, "24", ICON_MATCAP_24, "", ""},
{0, NULL, 0, NULL, NULL}
};
srna = RNA_def_struct(brna, "RenderEngineSettingsClay", "RenderEngineSettings");
RNA_def_struct_ui_text(srna, "Material Clay Settings", "Clay Engine settings for a Material data-block");
RNA_def_struct_sdna_from(srna, "RenderEngineSettingsClay", "data");
prop = RNA_def_property(srna, "matcap_icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, clay_matcap_items);
RNA_def_property_ui_text(prop, "Matcap", "Image to use for Material Capture by this material");
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "matcap_rotation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_rot");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Rotation", "Orientation of the matcap on the model");
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "matcap_hue", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Hue shift", "Hue correction of the matcap");
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "matcap_saturation", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_sat");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Saturation", "Saturation correction of the matcap");
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "matcap_value", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "matcap_val");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Matcap Value", "Value correction of the matcap");
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "ssao_factor_cavity", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Cavity Strength", "Strength of the Cavity effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "ssao_factor_edge", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Edge Strength", "Strength of the Edge effect");
RNA_def_property_range(prop, 0.0f, 250.0f);
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "ssao_distance", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Distance", "Distance of object that contribute to the Cavity/Edge effect");
RNA_def_property_range(prop, 0.0f, 100000.0f);
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 1, 3);
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
prop = RNA_def_property(srna, "ssao_attenuation", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "Attenuation", "Attenuation constant");
RNA_def_property_range(prop, 1.0f, 100000.0f);
RNA_def_property_ui_range(prop, 1.0f, 100.0f, 1, 3);
RNA_def_property_update(prop, 0, "rna_RenderEngineSettings_update");
/* Clay settings */
prop = RNA_def_property(srna, "ssao_samples", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(prop, "Samples", "Number of samples");
RNA_def_property_range(prop, 1, 500);
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
}
#endif
static void rna_def_scene_render_engine(BlenderRNA *brna)
{
StructRNA *srna;
srna = RNA_def_struct(brna, "RenderEngineSettings", NULL);
RNA_def_struct_ui_text(srna, "Render Engine Settings", "Engine specific render settings");
RNA_def_struct_sdna(srna, "RenderEngineSettings");
RNA_def_struct_refine_func(srna, "rna_RenderEngineSettings_refine");
#ifdef WITH_CLAY_ENGINE
rna_def_render_engine_settings_clay(brna);
#endif
}
static void rna_def_scene_render_data(BlenderRNA *brna)
{
StructRNA *srna;
@@ -8075,7 +8495,17 @@ void RNA_def_scene(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "r");
RNA_def_property_struct_type(prop, "RenderSettings");
RNA_def_property_ui_text(prop, "Render Data", "");
/* Render Engine Data */
prop = RNA_def_property(srna, "engines_settings", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "RenderEngineSettings");
RNA_def_property_ui_text(prop, "Render Engine Settings", "Engine specific render settings");
prop = RNA_def_property(srna, "active_engine_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "RenderEngineSettings");
RNA_def_property_pointer_funcs(prop, "rna_RenderEngineSettings_active_get", NULL, NULL, NULL);
RNA_def_property_ui_text(prop, "Active Render Engine Settings", "Active Engine specific render settings for this scene");
/* Safe Areas */
prop = RNA_def_property(srna, "safe_areas", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "safe_areas");
@@ -8222,11 +8652,13 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_scene_collection(brna);
rna_def_layer_collection(brna);
rna_def_layer_collection_override(brna);
rna_def_layer_collection_engine_settings(brna);
rna_def_scene_layer(brna);
rna_def_object_base(brna);
RNA_define_animate_sdna(true);
/* *** Animated *** */
rna_def_scene_render_data(brna);
rna_def_scene_render_engine(brna);
rna_def_scene_render_layer(brna);
rna_def_gpu_fx(brna);
rna_def_scene_render_view(brna);
@@ -8236,3 +8668,5 @@ void RNA_def_scene(BlenderRNA *brna)
}
#endif
#undef NO_ENGINE

View File

@@ -35,6 +35,7 @@ set(INC
../makesdna
../makesrna
../physics
../draw
../../../intern/guardedalloc
../../../intern/mikktspace
../../../intern/smoke/extern

View File

@@ -39,6 +39,8 @@
struct bNode;
struct bNodeTree;
struct CollectionEngineSettings;
struct Main;
struct Object;
struct Render;
struct RenderData;
@@ -63,6 +65,7 @@ struct BakePixel;
#define RE_USE_TEXTURE_PREVIEW 128
#define RE_USE_SHADING_NODES_CUSTOM 256
#define RE_USE_SPHERICAL_STEREO 512
#define RE_USE_OGL_PIPELINE 1024
/* RenderEngine.flag */
#define RE_ENGINE_ANIMATION 1
@@ -97,6 +100,8 @@ typedef struct RenderEngineType {
void (*update_script_node)(struct RenderEngine *engine, struct bNodeTree *ntree, struct bNode *node);
void (*collection_settings_create)(struct RenderEngine *engine, struct CollectionEngineSettings *ces);
/* RNA integration */
ExtensionRNA ext;
} RenderEngineType;
@@ -164,6 +169,7 @@ void RE_engine_frame_set(struct RenderEngine *engine, int frame, float subframe)
void RE_engines_init(void);
void RE_engines_exit(void);
void RE_engines_register(struct Main *bmain, RenderEngineType *render_type);
RenderEngineType *RE_engines_find(const char *idname);

View File

@@ -45,6 +45,7 @@
#include "BKE_camera.h"
#include "BKE_global.h"
#include "BKE_colortools.h"
#include "BKE_layer.h"
#include "BKE_report.h"
#include "BKE_scene.h"
@@ -58,6 +59,8 @@
#include "RE_pipeline.h"
#include "RE_bake.h"
#include "DRW_engine.h"
#include "initrender.h"
#include "renderpipeline.h"
#include "render_types.h"
@@ -68,7 +71,7 @@
static RenderEngineType internal_render_type = {
NULL, NULL,
"BLENDER_RENDER", N_("Blender Render"), RE_INTERNAL,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -77,7 +80,7 @@ static RenderEngineType internal_render_type = {
static RenderEngineType internal_game_type = {
NULL, NULL,
"BLENDER_GAME", N_("Blender Game"), RE_INTERNAL | RE_GAME,
NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
{NULL, NULL, NULL}
};
@@ -87,16 +90,21 @@ ListBase R_engines = {NULL, NULL};
void RE_engines_init(void)
{
BLI_addtail(&R_engines, &internal_render_type);
RE_engines_register(NULL, &internal_render_type);
#ifdef WITH_GAMEENGINE
BLI_addtail(&R_engines, &internal_game_type);
RE_engines_register(NULL, &internal_game_type);
#endif
DRW_engines_init();
}
void RE_engines_exit(void)
{
RenderEngineType *type, *next;
DRW_engines_free();
BKE_layer_collection_engine_settings_callback_free();
for (type = R_engines.first; type; type = next) {
next = type->next;
@@ -111,6 +119,14 @@ void RE_engines_exit(void)
}
}
void RE_engines_register(Main *bmain, RenderEngineType *render_type)
{
if (render_type->collection_settings_create) {
BKE_layer_collection_engine_settings_callback_register(bmain, render_type->idname, render_type->collection_settings_create);
}
BLI_addtail(&R_engines, render_type);
}
RenderEngineType *RE_engines_find(const char *idname)
{
RenderEngineType *type;

View File

@@ -186,6 +186,7 @@ struct wmWindowManager;
#include "../blender/render/extern/include/RE_pipeline.h"
#include "../blender/render/extern/include/RE_render_ext.h"
#include "../blender/render/extern/include/RE_shader_ext.h"
#include "../blender/draw/DRW_engine.h"
#include "../blender/windowmanager/WM_api.h"
@@ -663,6 +664,7 @@ void RE_ReleaseResultImage(struct Render *re) RET_NONE
int RE_engine_test_break(struct RenderEngine *engine) RET_ZERO
void RE_engines_init() RET_NONE
void RE_engines_exit() RET_NONE
void RE_engines_register(struct Main *bmain, RenderEngineType *render_type) RET_NONE
void RE_engine_report(struct RenderEngine *engine, int type, const char *msg) RET_NONE
ListBase R_engines = {NULL, NULL};
void RE_engine_free(struct RenderEngine *engine) RET_NONE
@@ -679,6 +681,9 @@ void RE_instance_get_particle_info(struct ObjectInstanceRen *obi, float *index,
void RE_FreeAllPersistentData(void) RET_NONE
float RE_fresnel_dielectric(float incoming[3], float normal[3], float eta) RET_ZERO
/* Draw */
void *DRW_render_settings_get(struct Scene *scene, const char *engine_name) RET_NULL
/* python */
struct wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) RET_NULL
void WM_operatortype_iter(struct GHashIterator *ghi) RET_NONE