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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r--source/blender/draw/intern/DRW_render.h109
-rw-r--r--source/blender/draw/intern/draw_common.h5
-rw-r--r--source/blender/draw/intern/draw_hair.c51
-rw-r--r--source/blender/draw/intern/draw_manager.c38
-rw-r--r--source/blender/draw/intern/draw_manager_data.c20
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c187
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c141
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c16
8 files changed, 394 insertions, 173 deletions
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index cc257b80daf..8ed7bb25336 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -81,6 +81,7 @@ typedef struct DRWPass DRWPass;
typedef struct DRWShadingGroup DRWShadingGroup;
typedef struct DRWUniform DRWUniform;
typedef struct DRWView DRWView;
+typedef struct DRWShaderLibrary DRWShaderLibrary;
/* TODO Put it somewhere else? */
typedef struct BoundSphere {
@@ -148,6 +149,8 @@ struct GPUTexture *DRW_texture_pool_query_2d(int w,
int h,
eGPUTextureFormat format,
DrawEngineType *engine_type);
+struct GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format,
+ DrawEngineType *engine_type);
struct GPUTexture *DRW_texture_create_1d(int w,
eGPUTextureFormat format,
@@ -163,6 +166,8 @@ struct GPUTexture *DRW_texture_create_cube(int w,
eGPUTextureFormat format,
DRWTextureFlag flags,
const float *fpixels);
+struct GPUTexture *DRW_texture_create_cube_array(
+ int w, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels);
void DRW_texture_ensure_fullscreen_2d(struct GPUTexture **tex,
eGPUTextureFormat format,
@@ -211,16 +216,17 @@ struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *def
struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
- int options,
+ const int options,
bool deferred);
struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
const void *engine_type,
- int options,
+ const int options,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -229,7 +235,8 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -244,51 +251,72 @@ void DRW_shader_free(struct GPUShader *shader);
} \
} while (0)
-/* Batches */
+DRWShaderLibrary *DRW_shader_library_create(void);
+
+/* Warning: Each library must be added after all its dependencies. */
+void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const char *lib_name);
+#define DRW_SHADER_LIB_ADD(lib, lib_name) \
+ DRW_shader_library_add_file(lib, datatoc_##lib_name##_glsl, STRINGIFY(lib_name) ".glsl")
+
+char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code);
+
+void DRW_shader_library_free(DRWShaderLibrary *lib);
+#define DRW_SHADER_LIB_FREE_SAFE(lib) \
+ do { \
+ if (lib != NULL) { \
+ DRW_shader_library_free(lib); \
+ lib = NULL; \
+ } \
+ } while (0)
+/* Batches */
+/* DRWState is a bitmask that stores the current render state and the desired render state. Based
+ * on the differences the minimum state changes can be invoked to setup the desired render state.
+ *
+ * The Write Stencil, Stencil test, Depth test and Blend state options are mutual exclusive
+ * therefore they aren't ordered as a bit mask.*/
typedef enum {
/** Write mask */
DRW_STATE_WRITE_DEPTH = (1 << 0),
DRW_STATE_WRITE_COLOR = (1 << 1),
+ /* Write Stencil. These options are mutual exclusive and packed into 2 bits */
DRW_STATE_WRITE_STENCIL = (1 << 2),
- DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (1 << 3),
- DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (1 << 4),
-
- /** Depth test */
- DRW_STATE_DEPTH_ALWAYS = (1 << 5),
- DRW_STATE_DEPTH_LESS = (1 << 6),
- DRW_STATE_DEPTH_LESS_EQUAL = (1 << 7),
- DRW_STATE_DEPTH_EQUAL = (1 << 8),
- DRW_STATE_DEPTH_GREATER = (1 << 9),
- DRW_STATE_DEPTH_GREATER_EQUAL = (1 << 10),
+ DRW_STATE_WRITE_STENCIL_SHADOW_PASS = (2 << 2),
+ DRW_STATE_WRITE_STENCIL_SHADOW_FAIL = (3 << 2),
+ /** Depth test. These options are mutual exclusive and packed into 3 bits */
+ DRW_STATE_DEPTH_ALWAYS = (1 << 4),
+ DRW_STATE_DEPTH_LESS = (2 << 4),
+ DRW_STATE_DEPTH_LESS_EQUAL = (3 << 4),
+ DRW_STATE_DEPTH_EQUAL = (4 << 4),
+ DRW_STATE_DEPTH_GREATER = (5 << 4),
+ DRW_STATE_DEPTH_GREATER_EQUAL = (6 << 4),
/** Culling test */
- DRW_STATE_CULL_BACK = (1 << 11),
- DRW_STATE_CULL_FRONT = (1 << 12),
- /** Stencil test */
- DRW_STATE_STENCIL_ALWAYS = (1 << 13),
- DRW_STATE_STENCIL_EQUAL = (1 << 14),
- DRW_STATE_STENCIL_NEQUAL = (1 << 15),
-
- /** Blend state */
- DRW_STATE_BLEND_ADD = (1 << 16),
+ DRW_STATE_CULL_BACK = (1 << 7),
+ DRW_STATE_CULL_FRONT = (1 << 8),
+ /** Stencil test . These options are mutal exclusive and packed into 2 bits*/
+ DRW_STATE_STENCIL_ALWAYS = (1 << 9),
+ DRW_STATE_STENCIL_EQUAL = (2 << 9),
+ DRW_STATE_STENCIL_NEQUAL = (3 << 9),
+
+ /** Blend state. These options are mutual exclusive and packed into 4 bits */
+ DRW_STATE_BLEND_ADD = (1 << 11),
/** Same as additive but let alpha accumulate without premult. */
- DRW_STATE_BLEND_ADD_FULL = (1 << 17),
+ DRW_STATE_BLEND_ADD_FULL = (2 << 11),
/** Standard alpha blending. */
- DRW_STATE_BLEND_ALPHA = (1 << 18),
+ DRW_STATE_BLEND_ALPHA = (3 << 11),
/** Use that if color is already premult by alpha. */
- DRW_STATE_BLEND_ALPHA_PREMUL = (1 << 19),
- DRW_STATE_BLEND_BACKGROUND = (1 << 20),
- DRW_STATE_BLEND_OIT = (1 << 21),
- DRW_STATE_BLEND_MUL = (1 << 22),
- DRW_STATE_BLEND_SUB = (1 << 23),
+ DRW_STATE_BLEND_ALPHA_PREMUL = (4 << 11),
+ DRW_STATE_BLEND_BACKGROUND = (5 << 11),
+ DRW_STATE_BLEND_OIT = (6 << 11),
+ DRW_STATE_BLEND_MUL = (7 << 11),
+ DRW_STATE_BLEND_SUB = (8 << 11),
/** Use dual source blending. WARNING: Only one color buffer allowed. */
- DRW_STATE_BLEND_CUSTOM = (1 << 24),
+ DRW_STATE_BLEND_CUSTOM = (9 << 11),
+ DRW_STATE_LOGIC_INVERT = (10 << 11),
- DRW_STATE_IN_FRONT_SELECT = (1 << 25),
- DRW_STATE_LOGIC_INVERT = (1 << 26),
- DRW_STATE_SHADOW_OFFSET = (1 << 27),
- DRW_STATE_CLIP_PLANES = (1 << 28),
- // DRW_STATE_WIRE_SMOOTH = (1 << 29), /* UNUSED */
+ DRW_STATE_IN_FRONT_SELECT = (1 << 27),
+ DRW_STATE_SHADOW_OFFSET = (1 << 28),
+ DRW_STATE_CLIP_PLANES = (1 << 29),
DRW_STATE_FIRST_VERTEX_CONVENTION = (1 << 30),
/** DO NOT USE. Assumed always enabled. Only used internally. */
DRW_STATE_PROGRAM_POINT_SIZE = (1u << 31),
@@ -401,18 +429,21 @@ void DRW_buffer_add_entry_array(DRWCallBuffer *buffer, const void *attr[], uint
DRW_buffer_add_entry_array(buffer, array, (sizeof(array) / sizeof(*array))); \
} while (0)
+/* Can only be called during iter phase. */
+uint32_t DRW_object_resource_id_get(Object *UNUSED(ob));
+
void DRW_shgroup_state_enable(DRWShadingGroup *shgroup, DRWState state);
void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state);
/* Reminders:
* - (compare_mask & reference) is what is tested against (compare_mask & stencil_value)
* stencil_value being the value stored in the stencil buffer.
- * - (writemask & reference) is what gets written if the test condition is fullfiled.
+ * - (write-mask & reference) is what gets written if the test condition is fulfilled.
**/
void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
uint write_mask,
uint reference,
- uint comp_mask);
+ uint compare_mask);
/* TODO remove this function. Obsolete version. mask is actually reference value. */
void DRW_shgroup_stencil_mask(DRWShadingGroup *shgroup, uint mask);
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index 24d3b7fa7b6..5818d84a7af 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -177,6 +177,11 @@ struct DRWShadingGroup *DRW_shgroup_hair_create(struct Object *object,
struct DRWPass *hair_pass,
struct GPUShader *shader);
+struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
+ struct ParticleSystem *psys,
+ struct ModifierData *md,
+ struct DRWShadingGroup *shgrp);
+
struct DRWShadingGroup *DRW_shgroup_material_hair_create(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 08256b931ba..c88071dc6d6 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -36,6 +36,7 @@
#include "GPU_batch.h"
#include "GPU_shader.h"
+#include "GPU_vertex_buffer.h"
#include "draw_hair_private.h"
@@ -62,6 +63,8 @@ static int g_tf_target_width;
static int g_tf_target_height;
#endif
+static GPUVertBuf *g_dummy_vbo = NULL;
+static GPUTexture *g_dummy_texture = NULL;
static GPUShader *g_refine_shaders[PART_REFINE_MAX_SHADER] = {NULL};
static DRWPass *g_tf_pass; /* XXX can be a problem with multiple DRWManager in the future */
@@ -102,12 +105,29 @@ void DRW_hair_init(void)
#else
g_tf_pass = DRW_pass_create("Update Hair Pass", DRW_STATE_WRITE_COLOR);
#endif
+
+ if (g_dummy_vbo == NULL) {
+ /* initialize vertex format */
+ GPUVertFormat format = {0};
+ uint dummy_id = GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 4, GPU_FETCH_FLOAT);
+
+ g_dummy_vbo = GPU_vertbuf_create_with_format(&format);
+
+ float vert[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ GPU_vertbuf_data_alloc(g_dummy_vbo, 1);
+ GPU_vertbuf_attr_fill(g_dummy_vbo, dummy_id, vert);
+ /* Create vbo immediately to bind to texture buffer. */
+ GPU_vertbuf_use(g_dummy_vbo);
+
+ g_dummy_texture = GPU_texture_create_from_vertbuf(g_dummy_vbo);
+ }
}
static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
ParticleSystem *psys,
ModifierData *md,
DRWPass *hair_pass,
+ DRWShadingGroup *shgrp_parent,
struct GPUMaterial *gpu_mat,
GPUShader *gpu_shader)
{
@@ -127,7 +147,10 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
object, psys, md, &hair_cache, subdiv, thickness_res);
DRWShadingGroup *shgrp;
- if (gpu_mat) {
+ if (shgrp_parent) {
+ shgrp = DRW_shgroup_create_sub(shgrp_parent);
+ }
+ else if (gpu_mat) {
shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass);
}
else if (gpu_shader) {
@@ -151,6 +174,17 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
}
}
+ /* Fix issue with certain driver not drawing anything if there is no texture bound to
+ * "ac", "au", "u" or "c". */
+ if (hair_cache->num_uv_layers == 0) {
+ DRW_shgroup_uniform_texture(shgrp, "u", g_dummy_texture);
+ DRW_shgroup_uniform_texture(shgrp, "au", g_dummy_texture);
+ }
+ if (hair_cache->num_col_layers == 0) {
+ DRW_shgroup_uniform_texture(shgrp, "c", g_dummy_texture);
+ DRW_shgroup_uniform_texture(shgrp, "ac", g_dummy_texture);
+ }
+
if ((dupli_parent != NULL) && (dupli_object != NULL)) {
if (dupli_object->type & OB_DUPLICOLLECTION) {
copy_m4_m4(dupli_mat, dupli_parent->obmat);
@@ -220,7 +254,15 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
DRWShadingGroup *DRW_shgroup_hair_create(
Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader)
{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, shader);
+ return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, NULL, shader);
+}
+
+DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
+ ParticleSystem *psys,
+ ModifierData *md,
+ DRWShadingGroup *shgrp)
+{
+ return drw_shgroup_create_hair_procedural_ex(object, psys, md, NULL, shgrp, NULL, NULL);
}
DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object,
@@ -229,7 +271,7 @@ DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object,
DRWPass *hair_pass,
struct GPUMaterial *material)
{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, material, NULL);
+ return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, material, NULL);
}
void DRW_hair_update(void)
@@ -313,4 +355,7 @@ void DRW_hair_free(void)
for (int i = 0; i < PART_REFINE_MAX_SHADER; i++) {
DRW_SHADER_FREE_SAFE(g_refine_shaders[i]);
}
+
+ GPU_VERTBUF_DISCARD_SAFE(g_dummy_vbo);
+ DRW_TEXTURE_FREE_SAFE(g_dummy_texture);
}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index b9711b4f88f..6d81d82a6cf 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1118,45 +1118,23 @@ static void use_drw_engine(DrawEngineType *engine)
BLI_addtail(&DST.enabled_engines, ld);
}
-/**
- * Use for external render engines.
- */
-static void drw_engines_enable_external(void)
-{
- use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
-}
-
-/* TODO revisit this when proper layering is implemented */
/* Gather all draw engines needed and store them in DST.enabled_engines
* That also define the rendering order of engines */
-static void drw_engines_enable_from_engine(RenderEngineType *engine_type,
- eDrawType drawtype,
- bool use_xray)
+static void drw_engines_enable_from_engine(RenderEngineType *engine_type, eDrawType drawtype)
{
switch (drawtype) {
case OB_WIRE:
- use_drw_engine(&draw_engine_workbench_transparent);
- break;
-
case OB_SOLID:
- if (use_xray) {
- use_drw_engine(&draw_engine_workbench_transparent);
- }
- else {
- use_drw_engine(&draw_engine_workbench_solid);
- }
+ use_drw_engine(DRW_engine_viewport_workbench_type.draw_engine);
break;
-
case OB_MATERIAL:
case OB_RENDER:
default:
- /* TODO layers */
if (engine_type->draw_engine != NULL) {
use_drw_engine(engine_type->draw_engine);
}
-
- if ((engine_type->flag & RE_INTERNAL) == 0) {
- drw_engines_enable_external();
+ else if ((engine_type->flag & RE_INTERNAL) == 0) {
+ use_drw_engine(DRW_engine_viewport_external_type.draw_engine);
}
break;
}
@@ -1182,7 +1160,7 @@ static void drw_engines_enable(ViewLayer *UNUSED(view_layer),
const eDrawType drawtype = v3d->shading.type;
const bool use_xray = XRAY_ENABLED(v3d);
- drw_engines_enable_from_engine(engine_type, drawtype, use_xray);
+ drw_engines_enable_from_engine(engine_type, drawtype);
if (gpencil_engine_needed && ((drawtype >= OB_SOLID) || !use_xray)) {
use_drw_engine(&draw_engine_gpencil_type);
}
@@ -1608,6 +1586,9 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph,
GPU_blend(true);
}
+ GPU_matrix_identity_set();
+ GPU_matrix_identity_projection_set();
+
GPU_viewport_unbind_from_offscreen(render_viewport, ofs, do_color_management);
if (draw_background) {
@@ -2646,9 +2627,6 @@ void DRW_engines_register(void)
RE_engines_register(&DRW_engine_viewport_eevee_type);
RE_engines_register(&DRW_engine_viewport_workbench_type);
- DRW_engine_register(&draw_engine_workbench_solid);
- DRW_engine_register(&draw_engine_workbench_transparent);
-
DRW_engine_register(&draw_engine_gpencil_type);
DRW_engine_register(&draw_engine_overlay_type);
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 83142da051a..be0dd7751ed 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -562,6 +562,16 @@ static DRWResourceHandle drw_resource_handle_new(float (*obmat)[4], Object *ob)
return handle;
}
+uint32_t DRW_object_resource_id_get(Object *UNUSED(ob))
+{
+ DRWResourceHandle handle = DST.ob_handle;
+ if (handle == 0) {
+ /* Handle not yet allocated. Return next handle. */
+ handle = DST.resource_handle;
+ }
+ return handle;
+}
+
static DRWResourceHandle drw_resource_handle(DRWShadingGroup *shgroup,
float (*obmat)[4],
Object *ob)
@@ -693,14 +703,14 @@ static void drw_command_set_select_id(DRWShadingGroup *shgroup, GPUVertBuf *buf,
static void drw_command_set_stencil_mask(DRWShadingGroup *shgroup,
uint write_mask,
uint reference,
- uint comp_mask)
+ uint compare_mask)
{
BLI_assert(write_mask <= 0xFF);
BLI_assert(reference <= 0xFF);
- BLI_assert(comp_mask <= 0xFF);
+ BLI_assert(compare_mask <= 0xFF);
DRWCommandSetStencil *cmd = drw_command_create(shgroup, DRW_CMD_STENCIL);
cmd->write_mask = write_mask;
- cmd->comp_mask = comp_mask;
+ cmd->comp_mask = compare_mask;
cmd->ref = reference;
}
@@ -1341,9 +1351,9 @@ void DRW_shgroup_state_disable(DRWShadingGroup *shgroup, DRWState state)
void DRW_shgroup_stencil_set(DRWShadingGroup *shgroup,
uint write_mask,
uint reference,
- uint comp_mask)
+ uint compare_mask)
{
- drw_command_set_stencil_mask(shgroup, write_mask, reference, comp_mask);
+ drw_command_set_stencil_mask(shgroup, write_mask, reference, compare_mask);
}
/* TODO remove this function. */
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 85525ea7b55..3d1b43537b7 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -114,19 +114,20 @@ void drw_state_set(DRWState state)
/* Stencil Write */
if (test) {
glStencilMask(0xFF);
- if (test & DRW_STATE_WRITE_STENCIL) {
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
- }
- else if (test & DRW_STATE_WRITE_STENCIL_SHADOW_PASS) {
- glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
- glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
- }
- else if (test & DRW_STATE_WRITE_STENCIL_SHADOW_FAIL) {
- glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
- glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
- }
- else {
- BLI_assert(0);
+ switch (test) {
+ case DRW_STATE_WRITE_STENCIL:
+ glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ break;
+ case DRW_STATE_WRITE_STENCIL_SHADOW_PASS:
+ glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_INCR_WRAP);
+ glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_DECR_WRAP);
+ break;
+ case DRW_STATE_WRITE_STENCIL_SHADOW_FAIL:
+ glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP);
+ glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP);
+ break;
+ default:
+ BLI_assert(0);
}
}
else {
@@ -191,26 +192,27 @@ void drw_state_set(DRWState state)
if (test) {
glEnable(GL_DEPTH_TEST);
- if (state & DRW_STATE_DEPTH_LESS) {
- glDepthFunc(GL_LESS);
- }
- else if (state & DRW_STATE_DEPTH_LESS_EQUAL) {
- glDepthFunc(GL_LEQUAL);
- }
- else if (state & DRW_STATE_DEPTH_EQUAL) {
- glDepthFunc(GL_EQUAL);
- }
- else if (state & DRW_STATE_DEPTH_GREATER) {
- glDepthFunc(GL_GREATER);
- }
- else if (state & DRW_STATE_DEPTH_GREATER_EQUAL) {
- glDepthFunc(GL_GEQUAL);
- }
- else if (state & DRW_STATE_DEPTH_ALWAYS) {
- glDepthFunc(GL_ALWAYS);
- }
- else {
- BLI_assert(0);
+ switch (test) {
+ case DRW_STATE_DEPTH_LESS:
+ glDepthFunc(GL_LESS);
+ break;
+ case DRW_STATE_DEPTH_LESS_EQUAL:
+ glDepthFunc(GL_LEQUAL);
+ break;
+ case DRW_STATE_DEPTH_EQUAL:
+ glDepthFunc(GL_EQUAL);
+ break;
+ case DRW_STATE_DEPTH_GREATER:
+ glDepthFunc(GL_GREATER);
+ break;
+ case DRW_STATE_DEPTH_GREATER_EQUAL:
+ glDepthFunc(GL_GEQUAL);
+ break;
+ case DRW_STATE_DEPTH_ALWAYS:
+ glDepthFunc(GL_ALWAYS);
+ break;
+ default:
+ BLI_assert(0);
}
}
else {
@@ -244,62 +246,63 @@ void drw_state_set(DRWState state)
if (test) {
glEnable(GL_BLEND);
- if ((state & DRW_STATE_BLEND_ALPHA) != 0) {
- glBlendFuncSeparate(GL_SRC_ALPHA,
- GL_ONE_MINUS_SRC_ALPHA, /* RGB */
- GL_ONE,
- GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
- }
- else if ((state & DRW_STATE_BLEND_BACKGROUND) != 0) {
- /* Special blend to add color under and multiply dst by alpha. */
- glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA,
- GL_SRC_ALPHA, /* RGB */
- GL_ZERO,
- GL_SRC_ALPHA); /* Alpha */
- }
- else if ((state & DRW_STATE_BLEND_ALPHA_PREMUL) != 0) {
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
- }
- else if ((state & DRW_STATE_BLEND_MUL) != 0) {
- glBlendFunc(GL_DST_COLOR, GL_ZERO);
- }
- else if ((state & DRW_STATE_BLEND_OIT) != 0) {
- glBlendFuncSeparate(GL_ONE,
- GL_ONE, /* RGB */
- GL_ZERO,
- GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
- }
- else if ((state & DRW_STATE_BLEND_ADD) != 0) {
- /* Do not let alpha accumulate but premult the source RGB by it. */
- glBlendFuncSeparate(GL_SRC_ALPHA,
- GL_ONE, /* RGB */
- GL_ZERO,
- GL_ONE); /* Alpha */
- }
- else if ((state & DRW_STATE_BLEND_ADD_FULL) != 0) {
- /* Let alpha accumulate. */
- glBlendFunc(GL_ONE, GL_ONE);
- }
- else if ((state & DRW_STATE_BLEND_SUB) != 0) {
- glBlendFunc(GL_ONE, GL_ONE);
- }
- else if ((state & DRW_STATE_BLEND_CUSTOM) != 0) {
- /* Custom blend parameters using dual source blending.
- * Can only be used with one Draw Buffer. */
- glBlendFunc(GL_ONE, GL_SRC1_COLOR);
- }
- else if ((state & DRW_STATE_LOGIC_INVERT) != 0) {
- /* Replace logic op by blend func to support floating point framebuffer. */
- glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR,
- GL_ZERO, /* RGB */
- GL_ZERO,
- GL_ONE); /* Alpha */
- }
- else {
- BLI_assert(0);
+ switch (test) {
+ case DRW_STATE_BLEND_ALPHA:
+ glBlendFuncSeparate(GL_SRC_ALPHA,
+ GL_ONE_MINUS_SRC_ALPHA, /* RGB */
+ GL_ONE,
+ GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
+ break;
+ case DRW_STATE_BLEND_BACKGROUND:
+ /* Special blend to add color under and multiply dst by alpha. */
+ glBlendFuncSeparate(GL_ONE_MINUS_DST_ALPHA,
+ GL_SRC_ALPHA, /* RGB */
+ GL_ZERO,
+ GL_SRC_ALPHA); /* Alpha */
+ break;
+ case DRW_STATE_BLEND_ALPHA_PREMUL:
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ break;
+ case DRW_STATE_BLEND_MUL:
+ glBlendFunc(GL_DST_COLOR, GL_ZERO);
+ break;
+ case DRW_STATE_BLEND_OIT:
+ glBlendFuncSeparate(GL_ONE,
+ GL_ONE, /* RGB */
+ GL_ZERO,
+ GL_ONE_MINUS_SRC_ALPHA); /* Alpha */
+ break;
+ case DRW_STATE_BLEND_ADD:
+ /* Do not let alpha accumulate but premult the source RGB by it. */
+ glBlendFuncSeparate(GL_SRC_ALPHA,
+ GL_ONE, /* RGB */
+ GL_ZERO,
+ GL_ONE); /* Alpha */
+ break;
+ case DRW_STATE_BLEND_ADD_FULL:
+ /* Let alpha accumulate. */
+ glBlendFunc(GL_ONE, GL_ONE);
+ break;
+ case DRW_STATE_BLEND_SUB:
+ glBlendFunc(GL_ONE, GL_ONE);
+ break;
+ case DRW_STATE_BLEND_CUSTOM:
+ /* Custom blend parameters using dual source blending.
+ * Can only be used with one Draw Buffer. */
+ glBlendFunc(GL_ONE, GL_SRC1_COLOR);
+ break;
+ case DRW_STATE_LOGIC_INVERT:
+ /* Replace logic op by blend func to support floating point framebuffer. */
+ glBlendFuncSeparate(GL_ONE_MINUS_DST_COLOR,
+ GL_ZERO, /* RGB */
+ GL_ZERO,
+ GL_ONE); /* Alpha */
+ break;
+ default:
+ BLI_assert(0);
}
- if ((state & DRW_STATE_BLEND_SUB) != 0) {
+ if (test == DRW_STATE_BLEND_SUB) {
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
}
else {
@@ -402,17 +405,17 @@ static void drw_stencil_state_set(uint write_mask, uint reference, uint compare_
/* Reminders:
* - (compare_mask & reference) is what is tested against (compare_mask & stencil_value)
* stencil_value being the value stored in the stencil buffer.
- * - (writemask & reference) is what gets written if the test condition is fullfiled.
+ * - (write-mask & reference) is what gets written if the test condition is fulfilled.
**/
glStencilMask(write_mask);
-
- if ((DST.state & DRW_STATE_STENCIL_ALWAYS) != 0) {
+ DRWState stencil_test = DST.state & DRW_STATE_STENCIL_TEST_ENABLED;
+ if (stencil_test == DRW_STATE_STENCIL_ALWAYS) {
glStencilFunc(GL_ALWAYS, reference, compare_mask);
}
- else if ((DST.state & DRW_STATE_STENCIL_EQUAL) != 0) {
+ else if (stencil_test == DRW_STATE_STENCIL_EQUAL) {
glStencilFunc(GL_EQUAL, reference, compare_mask);
}
- else if ((DST.state & DRW_STATE_STENCIL_NEQUAL) != 0) {
+ else if (stencil_test == DRW_STATE_STENCIL_NEQUAL) {
glStencilFunc(GL_NOTEQUAL, reference, compare_mask);
}
}
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 9c34cdbac3b..7b08f44921f 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -24,6 +24,7 @@
#include "DNA_world_types.h"
#include "DNA_material_types.h"
+#include "BLI_dynstr.h"
#include "BLI_listbase.h"
#include "BLI_string_utils.h"
#include "BLI_threads.h"
@@ -282,6 +283,8 @@ void DRW_deferred_shader_remove(GPUMaterial *mat)
/* -------------------------------------------------------------------- */
+/** \{ */
+
GPUShader *DRW_shader_create(const char *vert,
const char *geom,
const char *frag,
@@ -356,7 +359,7 @@ GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
- int options,
+ const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
@@ -372,7 +375,7 @@ GPUMaterial *DRW_shader_find_from_world(World *wo,
GPUMaterial *DRW_shader_find_from_material(Material *ma,
const void *engine_type,
- int options,
+ const int options,
bool deferred)
{
GPUMaterial *mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
@@ -389,7 +392,8 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -409,6 +413,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
&wo->gpumaterial,
engine_type,
options,
+ is_volume_shader,
vert,
geom,
frag_lib,
@@ -426,7 +431,8 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
const void *engine_type,
- int options,
+ const int options,
+ const bool is_volume_shader,
const char *vert,
const char *geom,
const char *frag_lib,
@@ -446,6 +452,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
&ma->gpumaterial,
engine_type,
options,
+ is_volume_shader,
vert,
geom,
frag_lib,
@@ -464,3 +471,129 @@ void DRW_shader_free(GPUShader *shader)
{
GPU_shader_free(shader);
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+
+/** \name Shader Library
+ *
+ * Simple include system for glsl files.
+ *
+ * Usage: Create a DRWShaderLibrary and add the library in the right order.
+ * You can have nested dependencies but each new library needs to have all its dependencies already
+ * added to the DRWShaderLibrary.
+ * Finally you can use DRW_shader_library_create_shader_string to get a shader string that also
+ * contains the needed libraries for this shader.
+ * \{ */
+
+/* 32 because we use a 32bit bitmap. */
+#define MAX_LIB 32
+#define MAX_LIB_NAME 64
+#define MAX_LIB_DEPS 8
+
+struct DRWShaderLibrary {
+ char *libs[MAX_LIB];
+ char libs_name[MAX_LIB][MAX_LIB_NAME];
+ uint32_t libs_deps[MAX_LIB];
+};
+
+DRWShaderLibrary *DRW_shader_library_create(void)
+{
+ return MEM_callocN(sizeof(DRWShaderLibrary), "DRWShaderLibrary");
+}
+
+void DRW_shader_library_free(DRWShaderLibrary *lib)
+{
+ MEM_SAFE_FREE(lib);
+}
+
+static int drw_shader_library_search(DRWShaderLibrary *lib, const char *name)
+{
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (lib->libs[i]) {
+ if (!strncmp(lib->libs_name[i], name, strlen(lib->libs_name[i]))) {
+ return i;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ return -1;
+}
+
+/* Return bitmap of dependencies. */
+static uint32_t drw_shader_dependencies_get(DRWShaderLibrary *lib, char *lib_code)
+{
+ /* Search dependencies. */
+ uint32_t deps = 0;
+ char *haystack = lib_code;
+ while ((haystack = strstr(haystack, "BLENDER_REQUIRE("))) {
+ haystack += 16;
+ int dep = drw_shader_library_search(lib, haystack);
+ if (dep == -1) {
+ printf(
+ "Error: Dependency not found.\n"
+ "This might be due to bad lib ordering.\n");
+ BLI_assert(0);
+ }
+ else {
+ deps |= 1u << (uint32_t)dep;
+ }
+ }
+ return deps;
+}
+
+void DRW_shader_library_add_file(DRWShaderLibrary *lib, char *lib_code, const char *lib_name)
+{
+ int index = -1;
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (lib->libs[i] == NULL) {
+ index = i;
+ break;
+ }
+ }
+
+ if (index > -1) {
+ lib->libs[index] = lib_code;
+ BLI_strncpy(lib->libs_name[index], lib_name, MAX_LIB_NAME);
+ }
+ else {
+ printf("Error: Too many libraries. Cannot add %s.\n", lib_name);
+ BLI_assert(0);
+ }
+
+ lib->libs_deps[index] = drw_shader_dependencies_get(lib, lib_code);
+}
+
+/* Return an allocN'ed string containing the shader code with its dependencies prepended.
+ * Caller must free the string with MEM_freeN after use. */
+char *DRW_shader_library_create_shader_string(DRWShaderLibrary *lib, char *shader_code)
+{
+ uint32_t deps = drw_shader_dependencies_get(lib, shader_code);
+
+ DynStr *ds = BLI_dynstr_new();
+ /* Add all dependencies recursively. */
+ for (int i = MAX_LIB - 1; i > -1; i--) {
+ if (lib->libs[i] && (deps & (1u << (uint32_t)i))) {
+ deps |= lib->libs_deps[i];
+ }
+ }
+ /* Concatenate all needed libs into one string. */
+ for (int i = 0; i < MAX_LIB; i++) {
+ if (deps & 1u) {
+ BLI_dynstr_append(ds, lib->libs[i]);
+ }
+ deps = deps >> 1;
+ }
+
+ BLI_dynstr_append(ds, shader_code);
+
+ char *str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+/** \} */
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 373810b2f7f..3f11fe9d11e 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -123,6 +123,15 @@ GPUTexture *DRW_texture_create_cube(int w,
return tex;
}
+GPUTexture *DRW_texture_create_cube_array(
+ int w, int d, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
+{
+ GPUTexture *tex = GPU_texture_create_cube_array(w, d, format, fpixels, NULL);
+ drw_texture_set_parameters(tex, flags);
+
+ return tex;
+}
+
GPUTexture *DRW_texture_pool_query_2d(int w,
int h,
eGPUTextureFormat format,
@@ -134,6 +143,13 @@ GPUTexture *DRW_texture_pool_query_2d(int w,
return tex;
}
+GPUTexture *DRW_texture_pool_query_fullscreen(eGPUTextureFormat format,
+ DrawEngineType *engine_type)
+{
+ const float *size = DRW_viewport_size_get();
+ return DRW_texture_pool_query_2d((int)size[0], (int)size[1], format, engine_type);
+}
+
void DRW_texture_ensure_fullscreen_2d(GPUTexture **tex,
eGPUTextureFormat format,
DRWTextureFlag flags)