diff options
Diffstat (limited to 'source/blender/draw/intern')
-rw-r--r-- | source/blender/draw/intern/DRW_render.h | 109 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_common.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_hair.c | 51 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 38 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_data.c | 20 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_exec.c | 187 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_shader.c | 141 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager_texture.c | 16 |
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) |