From e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Apr 2019 06:17:24 +0200 Subject: ClangFormat: apply to source, most of intern Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat --- source/blender/gpu/CMakeLists.txt | 178 +- source/blender/gpu/GPU_attr_binding.h | 8 +- source/blender/gpu/GPU_batch.h | 187 +- source/blender/gpu/GPU_batch_presets.h | 2 +- source/blender/gpu/GPU_batch_utils.h | 10 +- source/blender/gpu/GPU_buffers.h | 60 +- source/blender/gpu/GPU_common.h | 2 +- source/blender/gpu/GPU_draw.h | 36 +- source/blender/gpu/GPU_element.h | 53 +- source/blender/gpu/GPU_extensions.h | 32 +- source/blender/gpu/GPU_framebuffer.h | 130 +- source/blender/gpu/GPU_immediate.h | 2 +- source/blender/gpu/GPU_immediate_util.h | 37 +- source/blender/gpu/GPU_legacy_stubs.h | 717 ++-- source/blender/gpu/GPU_material.h | 174 +- source/blender/gpu/GPU_matrix.h | 146 +- source/blender/gpu/GPU_primitive.h | 36 +- source/blender/gpu/GPU_select.h | 17 +- source/blender/gpu/GPU_shader.h | 616 ++- source/blender/gpu/GPU_shader_interface.h | 102 +- source/blender/gpu/GPU_state.h | 23 +- source/blender/gpu/GPU_texture.h | 234 +- source/blender/gpu/GPU_uniformbuffer.h | 2 +- source/blender/gpu/GPU_vertex_buffer.h | 65 +- source/blender/gpu/GPU_vertex_format.h | 76 +- source/blender/gpu/GPU_viewport.h | 59 +- source/blender/gpu/intern/gpu_attr_binding.c | 50 +- .../blender/gpu/intern/gpu_attr_binding_private.h | 8 +- source/blender/gpu/intern/gpu_batch.c | 902 ++-- source/blender/gpu/intern/gpu_batch_presets.c | 314 +- source/blender/gpu/intern/gpu_batch_utils.c | 375 +- source/blender/gpu/intern/gpu_buffers.c | 1801 ++++---- source/blender/gpu/intern/gpu_codegen.c | 3362 +++++++-------- source/blender/gpu/intern/gpu_codegen.h | 225 +- source/blender/gpu/intern/gpu_context.cpp | 304 +- source/blender/gpu/intern/gpu_debug.c | 284 +- source/blender/gpu/intern/gpu_draw.c | 2200 +++++----- source/blender/gpu/intern/gpu_element.c | 366 +- source/blender/gpu/intern/gpu_extensions.c | 478 ++- source/blender/gpu/intern/gpu_framebuffer.c | 1305 +++--- source/blender/gpu/intern/gpu_immediate.c | 925 ++--- source/blender/gpu/intern/gpu_immediate_util.c | 654 +-- source/blender/gpu/intern/gpu_init_exit.c | 54 +- source/blender/gpu/intern/gpu_material.c | 1004 ++--- source/blender/gpu/intern/gpu_matrix.c | 639 +-- source/blender/gpu/intern/gpu_primitive.c | 64 +- source/blender/gpu/intern/gpu_private.h | 2 +- source/blender/gpu/intern/gpu_select.c | 261 +- source/blender/gpu/intern/gpu_select_pick.c | 1026 ++--- source/blender/gpu/intern/gpu_select_private.h | 6 +- .../blender/gpu/intern/gpu_select_sample_query.c | 314 +- source/blender/gpu/intern/gpu_shader.c | 1920 ++++----- source/blender/gpu/intern/gpu_shader_interface.c | 503 +-- source/blender/gpu/intern/gpu_shader_private.h | 26 +- source/blender/gpu/intern/gpu_state.c | 128 +- source/blender/gpu/intern/gpu_texture.c | 2805 +++++++------ source/blender/gpu/intern/gpu_uniformbuffer.c | 395 +- source/blender/gpu/intern/gpu_vertex_buffer.c | 250 +- source/blender/gpu/intern/gpu_vertex_format.c | 630 +-- source/blender/gpu/intern/gpu_viewport.c | 786 ++-- .../shaders/gpu_shader_2D_area_borders_frag.glsl | 8 +- .../shaders/gpu_shader_2D_area_borders_vert.glsl | 45 +- .../shaders/gpu_shader_2D_edituvs_edges_vert.glsl | 12 +- .../gpu_shader_2D_edituvs_facedots_vert.glsl | 6 +- .../shaders/gpu_shader_2D_edituvs_faces_vert.glsl | 14 +- .../shaders/gpu_shader_2D_edituvs_points_vert.glsl | 36 +- .../gpu_shader_2D_edituvs_stretch_vert.glsl | 88 +- .../gpu/shaders/gpu_shader_2D_flat_color_vert.glsl | 4 +- .../gpu_shader_2D_image_multi_rect_vert.glsl | 67 +- .../gpu/shaders/gpu_shader_2D_image_rect_vert.glsl | 40 +- .../gpu/shaders/gpu_shader_2D_image_vert.glsl | 6 +- .../shaders/gpu_shader_2D_line_dashed_frag.glsl | 62 +- .../shaders/gpu_shader_2D_line_dashed_geom.glsl | 55 +- ...u_shader_2D_line_dashed_uniform_color_vert.glsl | 4 +- .../gpu_shader_2D_line_dashed_width_geom.glsl | 62 +- .../gpu/shaders/gpu_shader_2D_nodelink_frag.glsl | 7 +- .../gpu/shaders/gpu_shader_2D_nodelink_vert.glsl | 121 +- .../gpu_shader_2D_point_uniform_size_aa_vert.glsl | 21 +- ...ader_2D_point_uniform_size_outline_aa_vert.glsl | 25 +- ...uniform_size_varying_color_outline_aa_vert.glsl | 27 +- ...r_2D_point_varying_size_varying_color_vert.glsl | 6 +- .../gpu_shader_2D_smooth_color_dithered_frag.glsl | 18 +- .../shaders/gpu_shader_2D_smooth_color_frag.glsl | 2 +- .../shaders/gpu_shader_2D_smooth_color_vert.glsl | 4 +- source/blender/gpu/shaders/gpu_shader_2D_vert.glsl | 2 +- .../shaders/gpu_shader_2D_widget_base_frag.glsl | 42 +- .../shaders/gpu_shader_2D_widget_base_vert.glsl | 320 +- .../shaders/gpu_shader_2D_widget_shadow_frag.glsl | 6 +- .../shaders/gpu_shader_2D_widget_shadow_vert.glsl | 88 +- .../gpu_shader_3D_clipped_uniform_color_vert.glsl | 4 +- .../gpu/shaders/gpu_shader_3D_flat_color_vert.glsl | 17 +- .../gpu/shaders/gpu_shader_3D_groundline_geom.glsl | 16 +- .../shaders/gpu_shader_3D_groundpoint_vert.glsl | 8 +- .../gpu/shaders/gpu_shader_3D_image_vert.glsl | 4 +- ...r_3D_line_dashed_uniform_color_legacy_vert.glsl | 8 +- ...u_shader_3D_line_dashed_uniform_color_vert.glsl | 8 +- .../gpu_shader_3D_normal_smooth_color_vert.glsl | 6 +- .../gpu/shaders/gpu_shader_3D_normal_vert.glsl | 4 +- .../shaders/gpu_shader_3D_passthrough_vert.glsl | 6 +- ...der_3D_point_fixed_size_varying_color_vert.glsl | 4 +- .../gpu_shader_3D_point_uniform_size_aa_vert.glsl | 25 +- ...ader_3D_point_uniform_size_outline_aa_vert.glsl | 29 +- ...r_3D_point_varying_size_varying_color_vert.glsl | 6 +- .../gpu_shader_3D_point_varying_size_vert.glsl | 4 +- .../shaders/gpu_shader_3D_selection_id_vert.glsl | 10 +- .../shaders/gpu_shader_3D_smooth_color_frag.glsl | 2 +- .../shaders/gpu_shader_3D_smooth_color_vert.glsl | 6 +- source/blender/gpu/shaders/gpu_shader_3D_vert.glsl | 4 +- .../gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl | 34 +- .../gpu/shaders/gpu_shader_checker_frag.glsl | 16 +- .../gpu/shaders/gpu_shader_depth_only_frag.glsl | 4 +- .../gpu/shaders/gpu_shader_diag_stripes_frag.glsl | 15 +- .../gpu_shader_edges_front_back_ortho_vert.glsl | 42 +- .../gpu_shader_edges_front_back_persp_geom.glsl | 46 +- ..._shader_edges_front_back_persp_legacy_vert.glsl | 38 +- .../gpu_shader_edges_front_back_persp_vert.glsl | 24 +- .../gpu/shaders/gpu_shader_edges_overlay_frag.glsl | 11 +- .../gpu/shaders/gpu_shader_edges_overlay_geom.glsl | 83 +- .../gpu_shader_edges_overlay_simple_geom.glsl | 64 +- .../gpu/shaders/gpu_shader_edges_overlay_vert.glsl | 7 +- .../gpu_shader_flat_color_alpha_test_0_frag.glsl | 8 +- .../gpu/shaders/gpu_shader_flat_color_frag.glsl | 2 +- .../gpu/shaders/gpu_shader_flat_id_frag.glsl | 2 +- .../blender/gpu/shaders/gpu_shader_geometry.glsl | 140 +- .../gpu/shaders/gpu_shader_gpencil_fill_frag.glsl | 270 +- .../gpu/shaders/gpu_shader_gpencil_fill_vert.glsl | 4 +- .../shaders/gpu_shader_gpencil_stroke_frag.glsl | 24 +- .../shaders/gpu_shader_gpencil_stroke_geom.glsl | 362 +- .../shaders/gpu_shader_gpencil_stroke_vert.glsl | 21 +- .../shaders/gpu_shader_image_alpha_color_frag.glsl | 8 +- .../gpu/shaders/gpu_shader_image_color_frag.glsl | 2 +- .../shaders/gpu_shader_image_depth_copy_frag.glsl | 6 +- .../gpu_shader_image_depth_linear_frag.glsl | 8 +- .../shaders/gpu_shader_image_desaturate_frag.glsl | 6 +- .../blender/gpu/shaders/gpu_shader_image_frag.glsl | 2 +- .../shaders/gpu_shader_image_interlace_frag.glsl | 35 +- .../gpu/shaders/gpu_shader_image_linear_frag.glsl | 23 +- .../gpu_shader_image_mask_uniform_color_frag.glsl | 4 +- .../gpu_shader_image_modulate_alpha_frag.glsl | 4 +- .../gpu_shader_image_multisample_resolve_frag.glsl | 144 +- .../gpu_shader_image_shuffle_color_frag.glsl | 9 +- .../gpu_shader_image_varying_color_frag.glsl | 2 +- .../shaders/gpu_shader_instance_camera_vert.glsl | 66 +- .../gpu_shader_instance_distance_line_vert.glsl | 14 +- ..._shader_instance_edges_variying_color_geom.glsl | 48 +- ..._shader_instance_edges_variying_color_vert.glsl | 48 +- ...r_instance_objectspace_variying_color_vert.glsl | 14 +- .../gpu_shader_instance_screen_aligned_vert.glsl | 26 +- ...r_instance_screenspace_variying_color_vert.glsl | 15 +- ...instance_variying_size_variying_color_vert.glsl | 8 +- ...er_instance_variying_size_variying_id_vert.glsl | 4 +- .../gpu/shaders/gpu_shader_instance_vert.glsl | 2 +- .../shaders/gpu_shader_keyframe_diamond_frag.glsl | 142 +- .../shaders/gpu_shader_keyframe_diamond_vert.glsl | 85 +- .../blender/gpu/shaders/gpu_shader_material.glsl | 4304 +++++++++++--------- .../gpu_shader_point_uniform_color_aa_frag.glsl | 29 +- .../gpu_shader_point_uniform_color_frag.glsl | 14 +- ...shader_point_uniform_color_outline_aa_frag.glsl | 49 +- .../gpu_shader_point_varying_color_frag.glsl | 14 +- ...shader_point_varying_color_outline_aa_frag.glsl | 41 +- ...oint_varying_color_varying_outline_aa_frag.glsl | 41 +- .../gpu/shaders/gpu_shader_selection_id_frag.glsl | 2 +- .../shaders/gpu_shader_simple_lighting_frag.glsl | 4 +- ...er_simple_lighting_smooth_color_alpha_frag.glsl | 4 +- ...u_shader_simple_lighting_smooth_color_frag.glsl | 2 +- .../blender/gpu/shaders/gpu_shader_text_frag.glsl | 110 +- .../blender/gpu/shaders/gpu_shader_text_geom.glsl | 30 +- .../gpu/shaders/gpu_shader_text_simple_geom.glsl | 32 +- .../gpu/shaders/gpu_shader_text_simple_vert.glsl | 12 +- .../blender/gpu/shaders/gpu_shader_text_vert.glsl | 6 +- .../gpu/shaders/gpu_shader_uniform_color_frag.glsl | 13 +- 171 files changed, 18261 insertions(+), 17127 deletions(-) (limited to 'source/blender/gpu') diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 02f31b9664e..f949a79d039 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -23,113 +23,113 @@ # bf_gpu is allowed to have opengl regardless of this option. if(NOT WITH_OPENGL) - add_definitions(-DWITH_OPENGL) + add_definitions(-DWITH_OPENGL) endif() set(INC - . - ../blenkernel - ../blenlib - ../bmesh - ../imbuf - ../makesdna - ../makesrna - ../draw + . + ../blenkernel + ../blenlib + ../bmesh + ../imbuf + ../makesdna + ../makesrna + ../draw - ../editors/include + ../editors/include - # For node muting stuff... - ../nodes - ../nodes/intern + # For node muting stuff... + ../nodes + ../nodes/intern - ../../../intern/glew-mx - ../../../intern/guardedalloc - ../../../intern/smoke/extern + ../../../intern/glew-mx + ../../../intern/guardedalloc + ../../../intern/smoke/extern ) set(INC_SYS - ${GLEW_INCLUDE_PATH} + ${GLEW_INCLUDE_PATH} ) set(SRC - intern/gpu_attr_binding.c - intern/gpu_batch.c - intern/gpu_batch_presets.c - intern/gpu_batch_utils.c - intern/gpu_buffers.c - intern/gpu_codegen.c - intern/gpu_context.cpp - intern/gpu_debug.c - intern/gpu_draw.c - intern/gpu_element.c - intern/gpu_extensions.c - intern/gpu_framebuffer.c - intern/gpu_immediate.c - intern/gpu_immediate_util.c - intern/gpu_init_exit.c - intern/gpu_material.c - intern/gpu_matrix.c - intern/gpu_primitive.c - intern/gpu_select.c - intern/gpu_select_pick.c - intern/gpu_select_sample_query.c - intern/gpu_shader.c - intern/gpu_shader_interface.c - intern/gpu_state.c - intern/gpu_texture.c - intern/gpu_uniformbuffer.c - intern/gpu_vertex_buffer.c - intern/gpu_vertex_format.c - intern/gpu_viewport.c + intern/gpu_attr_binding.c + intern/gpu_batch.c + intern/gpu_batch_presets.c + intern/gpu_batch_utils.c + intern/gpu_buffers.c + intern/gpu_codegen.c + intern/gpu_context.cpp + intern/gpu_debug.c + intern/gpu_draw.c + intern/gpu_element.c + intern/gpu_extensions.c + intern/gpu_framebuffer.c + intern/gpu_immediate.c + intern/gpu_immediate_util.c + intern/gpu_init_exit.c + intern/gpu_material.c + intern/gpu_matrix.c + intern/gpu_primitive.c + intern/gpu_select.c + intern/gpu_select_pick.c + intern/gpu_select_sample_query.c + intern/gpu_shader.c + intern/gpu_shader_interface.c + intern/gpu_state.c + intern/gpu_texture.c + intern/gpu_uniformbuffer.c + intern/gpu_vertex_buffer.c + intern/gpu_vertex_format.c + intern/gpu_viewport.c - GPU_attr_binding.h - GPU_batch.h - GPU_batch_presets.h - GPU_batch_utils.h - GPU_buffers.h - GPU_common.h - GPU_context.h - GPU_debug.h - GPU_draw.h - GPU_element.h - GPU_extensions.h - GPU_framebuffer.h - GPU_glew.h - GPU_immediate.h - GPU_immediate_util.h - GPU_init_exit.h - GPU_legacy_stubs.h - GPU_material.h - GPU_matrix.h - GPU_primitive.h - GPU_select.h - GPU_shader.h - GPU_shader_interface.h - GPU_state.h - GPU_texture.h - GPU_uniformbuffer.h - GPU_vertex_buffer.h - GPU_vertex_format.h - GPU_viewport.h + GPU_attr_binding.h + GPU_batch.h + GPU_batch_presets.h + GPU_batch_utils.h + GPU_buffers.h + GPU_common.h + GPU_context.h + GPU_debug.h + GPU_draw.h + GPU_element.h + GPU_extensions.h + GPU_framebuffer.h + GPU_glew.h + GPU_immediate.h + GPU_immediate_util.h + GPU_init_exit.h + GPU_legacy_stubs.h + GPU_material.h + GPU_matrix.h + GPU_primitive.h + GPU_select.h + GPU_shader.h + GPU_shader_interface.h + GPU_state.h + GPU_texture.h + GPU_uniformbuffer.h + GPU_vertex_buffer.h + GPU_vertex_format.h + GPU_viewport.h - intern/gpu_attr_binding_private.h - intern/gpu_batch_private.h - intern/gpu_codegen.h - intern/gpu_context_private.h - intern/gpu_primitive_private.h - intern/gpu_private.h - intern/gpu_select_private.h - intern/gpu_shader_private.h - intern/gpu_vertex_format_private.h + intern/gpu_attr_binding_private.h + intern/gpu_batch_private.h + intern/gpu_codegen.h + intern/gpu_context_private.h + intern/gpu_primitive_private.h + intern/gpu_private.h + intern/gpu_select_private.h + intern/gpu_shader_private.h + intern/gpu_vertex_format_private.h ) set(LIB ) if(NOT WITH_SYSTEM_GLEW) - list(APPEND LIB - ${BLENDER_GLEW_LIBRARIES} - ) + list(APPEND LIB + ${BLENDER_GLEW_LIBRARIES} + ) endif() data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC) @@ -255,13 +255,13 @@ data_to_c_simple(shaders/gpu_shader_cfg_world_clip_lib.glsl SRC) if(WITH_MOD_SMOKE) - add_definitions(-DWITH_SMOKE) + add_definitions(-DWITH_SMOKE) endif() add_definitions(${GL_DEFINITIONS}) if(WITH_IMAGE_DDS) - add_definitions(-DWITH_DDS) + add_definitions(-DWITH_DDS) endif() blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/gpu/GPU_attr_binding.h b/source/blender/gpu/GPU_attr_binding.h index 4d7bdafe2eb..2fa892bf805 100644 --- a/source/blender/gpu/GPU_attr_binding.h +++ b/source/blender/gpu/GPU_attr_binding.h @@ -29,10 +29,10 @@ #include "GPU_common.h" typedef struct GPUAttrBinding { - /** Store 4 bits for each of the 16 attributes. */ - uint64_t loc_bits; - /** 1 bit for each attribute. */ - uint16_t enabled_bits; + /** Store 4 bits for each of the 16 attributes. */ + uint64_t loc_bits; + /** 1 bit for each attribute. */ + uint16_t enabled_bits; } GPUAttrBinding; #endif /* __GPU_ATTR_BINDING_H__ */ diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 9f6c9f50109..b9397a61ea4 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -33,10 +33,10 @@ #include "GPU_shader.h" typedef enum { - GPU_BATCH_READY_TO_FORMAT, - GPU_BATCH_READY_TO_BUILD, - GPU_BATCH_BUILDING, - GPU_BATCH_READY_TO_DRAW, + GPU_BATCH_READY_TO_FORMAT, + GPU_BATCH_READY_TO_BUILD, + GPU_BATCH_BUILDING, + GPU_BATCH_READY_TO_DRAW, } GPUBatchPhase; #define GPU_BATCH_VBO_MAX_LEN 4 @@ -44,69 +44,68 @@ typedef enum { #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16 typedef struct GPUBatch { - /* geometry */ - - /** verts[0] is required, others can be NULL */ - GPUVertBuf *verts[GPU_BATCH_VBO_MAX_LEN]; - /** Instance attributes. */ - GPUVertBuf *inst; - /** NULL if element list not needed */ - GPUIndexBuf *elem; - uint32_t gl_prim_type; - - /* cached values (avoid dereferencing later) */ - uint32_t vao_id; - uint32_t program; - const struct GPUShaderInterface *interface; - - /* book-keeping */ - uint owns_flag; - /** used to free all vaos. this implies all vaos were created under the same context. */ - struct GPUContext *context; - GPUBatchPhase phase; - bool program_in_use; - - /* Vao management: remembers all geometry state (vertex attribute bindings & element buffer) - * for each shader interface. Start with a static number of vaos and fallback to dynamic count - * if necessary. Once a batch goes dynamic it does not go back. */ - bool is_dynamic_vao_count; - union { - /** Static handle count */ - struct { - const struct GPUShaderInterface *interfaces[GPU_BATCH_VAO_STATIC_LEN]; - uint32_t vao_ids[GPU_BATCH_VAO_STATIC_LEN]; - } static_vaos; - /** Dynamic handle count */ - struct { - uint count; - const struct GPUShaderInterface **interfaces; - uint32_t *vao_ids; - } dynamic_vaos; - }; - - /* XXX This is the only solution if we want to have some data structure using - * batches as key to identify nodes. We must destroy these nodes with this callback. */ - void (*free_callback)(struct GPUBatch *, void *); - void *callback_data; + /* geometry */ + + /** verts[0] is required, others can be NULL */ + GPUVertBuf *verts[GPU_BATCH_VBO_MAX_LEN]; + /** Instance attributes. */ + GPUVertBuf *inst; + /** NULL if element list not needed */ + GPUIndexBuf *elem; + uint32_t gl_prim_type; + + /* cached values (avoid dereferencing later) */ + uint32_t vao_id; + uint32_t program; + const struct GPUShaderInterface *interface; + + /* book-keeping */ + uint owns_flag; + /** used to free all vaos. this implies all vaos were created under the same context. */ + struct GPUContext *context; + GPUBatchPhase phase; + bool program_in_use; + + /* Vao management: remembers all geometry state (vertex attribute bindings & element buffer) + * for each shader interface. Start with a static number of vaos and fallback to dynamic count + * if necessary. Once a batch goes dynamic it does not go back. */ + bool is_dynamic_vao_count; + union { + /** Static handle count */ + struct { + const struct GPUShaderInterface *interfaces[GPU_BATCH_VAO_STATIC_LEN]; + uint32_t vao_ids[GPU_BATCH_VAO_STATIC_LEN]; + } static_vaos; + /** Dynamic handle count */ + struct { + uint count; + const struct GPUShaderInterface **interfaces; + uint32_t *vao_ids; + } dynamic_vaos; + }; + + /* XXX This is the only solution if we want to have some data structure using + * batches as key to identify nodes. We must destroy these nodes with this callback. */ + void (*free_callback)(struct GPUBatch *, void *); + void *callback_data; } GPUBatch; enum { - GPU_BATCH_OWNS_VBO = (1 << 0), - /* each vbo index gets bit-shifted */ - GPU_BATCH_OWNS_INSTANCES = (1 << 30), - GPU_BATCH_OWNS_INDEX = (1u << 31u), + GPU_BATCH_OWNS_VBO = (1 << 0), + /* each vbo index gets bit-shifted */ + GPU_BATCH_OWNS_INSTANCES = (1 << 30), + GPU_BATCH_OWNS_INDEX = (1u << 31u), }; GPUBatch *GPU_batch_create_ex(GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag); void GPU_batch_init_ex(GPUBatch *, GPUPrimType, GPUVertBuf *, GPUIndexBuf *, uint owns_flag); void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src); -#define GPU_batch_create(prim, verts, elem) \ - GPU_batch_create_ex(prim, verts, elem, 0) -#define GPU_batch_init(batch, prim, verts, elem) \ - GPU_batch_init_ex(batch, prim, verts, elem, 0) +#define GPU_batch_create(prim, verts, elem) GPU_batch_create_ex(prim, verts, elem, 0) +#define GPU_batch_init(batch, prim, verts, elem) GPU_batch_init_ex(batch, prim, verts, elem, 0) -void GPU_batch_clear(GPUBatch *); /* Same as discard but does not free. (does not clal free callback) */ +void GPU_batch_clear( + GPUBatch *); /* Same as discard but does not free. (does not clal free callback) */ void GPU_batch_discard(GPUBatch *); /* verts & elem are not discarded */ void GPU_batch_vao_cache_clear(GPUBatch *); @@ -117,16 +116,15 @@ void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancin int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); -#define GPU_batch_vertbuf_add(batch, verts) \ - GPU_batch_vertbuf_add_ex(batch, verts, false) +#define GPU_batch_vertbuf_add(batch, verts) GPU_batch_vertbuf_add_ex(batch, verts, false) void GPU_batch_program_set_no_use(GPUBatch *, uint32_t program, const GPUShaderInterface *); void GPU_batch_program_set(GPUBatch *, uint32_t program, const GPUShaderInterface *); void GPU_batch_program_set_shader(GPUBatch *, GPUShader *shader); -void GPU_batch_program_set_builtin( - GPUBatch *batch, eGPUBuiltinShader shader_id); -void GPU_batch_program_set_builtin_with_config( - GPUBatch *batch, eGPUBuiltinShader shader_id, eGPUShaderConfig sh_cfg); +void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id); +void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, + eGPUBuiltinShader shader_id, + eGPUShaderConfig sh_cfg); /* Entire batch draws with one shader program, but can be redrawn later with another program. */ /* Vertex shader's inputs must be compatible with the batch's vertex format. */ @@ -164,19 +162,19 @@ void GPU_draw_primitive(GPUPrimType, int v_count); /* WithOwn variants reduce number of system allocations. */ typedef struct BatchWithOwnVertexBuffer { - GPUBatch batch; - GPUVertBuf verts; /* link batch.verts to this */ + GPUBatch batch; + GPUVertBuf verts; /* link batch.verts to this */ } BatchWithOwnVertexBuffer; typedef struct BatchWithOwnElementList { - GPUBatch batch; - GPUIndexBuf elem; /* link batch.elem to this */ + GPUBatch batch; + GPUIndexBuf elem; /* link batch.elem to this */ } BatchWithOwnElementList; typedef struct BatchWithOwnVertexBufferAndElementList { - GPUBatch batch; - GPUIndexBuf elem; /* link batch.elem to this */ - GPUVertBuf verts; /* link batch.verts to this */ + GPUBatch batch; + GPUIndexBuf elem; /* link batch.elem to this */ + GPUVertBuf verts; /* link batch.verts to this */ } BatchWithOwnVertexBufferAndElementList; GPUBatch *create_BatchWithOwnVertexBuffer(GPUPrimType, GPUVertFormat *, uint v_len, GPUIndexBuf *); @@ -193,28 +191,31 @@ void gpu_batch_exit(void); /* Macros */ -#define GPU_BATCH_DISCARD_SAFE(batch) do { \ - if (batch != NULL) { \ - GPU_batch_discard(batch); \ - batch = NULL; \ - } \ -} while (0) - -#define GPU_BATCH_CLEAR_SAFE(batch) do { \ - if (batch != NULL) { \ - GPU_batch_clear(batch); \ - memset(batch, 0, sizeof(*(batch))); \ - } \ -} while (0) - -#define GPU_BATCH_DISCARD_ARRAY_SAFE(_batch_array, _len) do { \ - if (_batch_array != NULL) { \ - BLI_assert(_len > 0); \ - for (int _i = 0; _i < _len; _i++) { \ - GPU_BATCH_DISCARD_SAFE(_batch_array[_i]); \ - } \ - MEM_freeN(_batch_array); \ - } \ -} while (0) +#define GPU_BATCH_DISCARD_SAFE(batch) \ + do { \ + if (batch != NULL) { \ + GPU_batch_discard(batch); \ + batch = NULL; \ + } \ + } while (0) + +#define GPU_BATCH_CLEAR_SAFE(batch) \ + do { \ + if (batch != NULL) { \ + GPU_batch_clear(batch); \ + memset(batch, 0, sizeof(*(batch))); \ + } \ + } while (0) + +#define GPU_BATCH_DISCARD_ARRAY_SAFE(_batch_array, _len) \ + do { \ + if (_batch_array != NULL) { \ + BLI_assert(_len > 0); \ + for (int _i = 0; _i < _len; _i++) { \ + GPU_BATCH_DISCARD_SAFE(_batch_array[_i]); \ + } \ + MEM_freeN(_batch_array); \ + } \ + } while (0) #endif /* __GPU_BATCH_H__ */ diff --git a/source/blender/gpu/GPU_batch_presets.h b/source/blender/gpu/GPU_batch_presets.h index 9e4ced93597..4b95783e6fa 100644 --- a/source/blender/gpu/GPU_batch_presets.h +++ b/source/blender/gpu/GPU_batch_presets.h @@ -45,4 +45,4 @@ bool gpu_batch_presets_unregister(struct GPUBatch *preset_batch); void gpu_batch_presets_reset(void); void gpu_batch_presets_exit(void); -#endif /* __GPU_BATCH_PRESETS_H__ */ +#endif /* __GPU_BATCH_PRESETS_H__ */ diff --git a/source/blender/gpu/GPU_batch_utils.h b/source/blender/gpu/GPU_batch_utils.h index c18f90479ef..3d41b957a67 100644 --- a/source/blender/gpu/GPU_batch_utils.h +++ b/source/blender/gpu/GPU_batch_utils.h @@ -28,13 +28,13 @@ struct rctf; /* gpu_batch_utils.c */ struct GPUBatch *GPU_batch_tris_from_poly_2d_encoded( - const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); struct GPUBatch *GPU_batch_wire_from_poly_2d_encoded( - const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect - ) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + const uchar *polys_flat, uint polys_flat_len, const struct rctf *rect) ATTR_WARN_UNUSED_RESULT + ATTR_NONNULL(1); /* Only use by draw manager. Use the presets function instead for interface. */ struct GPUBatch *gpu_batch_sphere(int lat_res, int lon_res) ATTR_WARN_UNUSED_RESULT; -#endif /* __GPU_BATCH_UTILS_H__ */ +#endif /* __GPU_BATCH_UTILS_H__ */ diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index 8762a1cb222..895887c2588 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -41,44 +41,46 @@ struct PBVH; typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers; /* build */ -GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( - const int (*face_vert_indices)[3], - const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri, - const struct MVert *verts, - const int *face_indices, - const int face_indices_len); +GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int (*face_vert_indices)[3], + const struct MPoly *mpoly, + const struct MLoop *mloop, + const struct MLoopTri *looptri, + const struct MVert *verts, + const int *face_indices, + const int face_indices_len); -GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( - int totgrid, - unsigned int **grid_hidden); +GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, unsigned int **grid_hidden); GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading); /* update */ enum { - GPU_PBVH_BUFFERS_SHOW_MASK = (1 << 1), + GPU_PBVH_BUFFERS_SHOW_MASK = (1 << 1), }; -void GPU_pbvh_mesh_buffers_update( - GPU_PBVH_Buffers *buffers, const struct MVert *mvert, - const int *vert_indices, int totvert, const float *vmask, - const int (*face_vert_indices)[3], - const int update_flags); - -void GPU_pbvh_bmesh_buffers_update( - GPU_PBVH_Buffers *buffers, - struct BMesh *bm, - struct GSet *bm_faces, - struct GSet *bm_unique_verts, - struct GSet *bm_other_verts, - const int update_flags); - -void GPU_pbvh_grid_buffers_update( - GPU_PBVH_Buffers *buffers, struct CCGElem **grids, - const struct DMFlagMat *grid_flag_mats, - int *grid_indices, int totgrid, const struct CCGKey *key, - const int update_flags); +void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers *buffers, + const struct MVert *mvert, + const int *vert_indices, + int totvert, + const float *vmask, + const int (*face_vert_indices)[3], + const int update_flags); + +void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers, + struct BMesh *bm, + struct GSet *bm_faces, + struct GSet *bm_unique_verts, + struct GSet *bm_other_verts, + const int update_flags); + +void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers *buffers, + struct CCGElem **grids, + const struct DMFlagMat *grid_flag_mats, + int *grid_indices, + int totgrid, + const struct CCGKey *key, + const int update_flags); /* draw */ struct GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires); diff --git a/source/blender/gpu/GPU_common.h b/source/blender/gpu/GPU_common.h index 36b369a31ff..a4bafe13500 100644 --- a/source/blender/gpu/GPU_common.h +++ b/source/blender/gpu/GPU_common.h @@ -29,7 +29,7 @@ #if defined(NDEBUG) # define TRUST_NO_ONE 0 #else - /* strict error checking, enabled for debug builds during early development */ +/* strict error checking, enabled for debug builds during early development */ # define TRUST_NO_ONE 1 #endif diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index ce9a20bcf7c..300fc7c65a2 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -75,13 +75,25 @@ float GPU_get_anisotropic(void); /* Image updates and free * - these deal with images bound as opengl textures */ -void GPU_paint_update_image(struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); -void GPU_create_gl_tex( - unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth, - int textarget, bool mipmap, bool use_hight_bit_depth, struct Image *ima); -void GPU_create_gl_tex_compressed( - unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, - int textarget, struct Image *ima, struct ImBuf *ibuf); +void GPU_paint_update_image( + struct Image *ima, struct ImageUser *iuser, int x, int y, int w, int h); +void GPU_create_gl_tex(unsigned int *bind, + unsigned int *rect, + float *frect, + int rectw, + int recth, + int textarget, + bool mipmap, + bool use_hight_bit_depth, + struct Image *ima); +void GPU_create_gl_tex_compressed(unsigned int *bind, + unsigned int *pix, + int x, + int y, + int mipmap, + int textarget, + struct Image *ima, + struct ImBuf *ibuf); bool GPU_upload_dxt_texture(struct ImBuf *ibuf); void GPU_free_image(struct Image *ima); void GPU_free_images(struct Main *bmain); @@ -100,11 +112,11 @@ void GPU_free_unused_buffers(struct Main *bmain); /* utilities */ typedef enum eGPUAttrMask { - GPU_DEPTH_BUFFER_BIT = (1 << 0), - GPU_ENABLE_BIT = (1 << 1), - GPU_SCISSOR_BIT = (1 << 2), - GPU_VIEWPORT_BIT = (1 << 3), - GPU_BLEND_BIT = (1 << 4), + GPU_DEPTH_BUFFER_BIT = (1 << 0), + GPU_ENABLE_BIT = (1 << 1), + GPU_SCISSOR_BIT = (1 << 2), + GPU_VIEWPORT_BIT = (1 << 3), + GPU_BLEND_BIT = (1 << 4), } eGPUAttrMask; void gpuPushAttr(eGPUAttrMask mask); diff --git a/source/blender/gpu/GPU_element.h b/source/blender/gpu/GPU_element.h index 5c877c80f65..d1a199f8193 100644 --- a/source/blender/gpu/GPU_element.h +++ b/source/blender/gpu/GPU_element.h @@ -33,40 +33,40 @@ #define GPU_PRIM_RESTART 0xFFFFFFFF typedef enum { - GPU_INDEX_U8, /* GL has this, Vulkan does not */ - GPU_INDEX_U16, - GPU_INDEX_U32, + GPU_INDEX_U8, /* GL has this, Vulkan does not */ + GPU_INDEX_U16, + GPU_INDEX_U32, } GPUIndexBufType; typedef struct GPUIndexBuf { - uint index_len; + uint index_len; #if GPU_TRACK_INDEX_RANGE - GPUIndexBufType index_type; - uint32_t gl_index_type; - uint min_index; - uint max_index; - uint base_index; + GPUIndexBufType index_type; + uint32_t gl_index_type; + uint min_index; + uint max_index; + uint base_index; #endif - uint32_t ibo_id; /* 0 indicates not yet sent to VRAM */ - void *data; /* non-NULL indicates not yet sent to VRAM */ - bool use_prim_restart; + uint32_t ibo_id; /* 0 indicates not yet sent to VRAM */ + void *data; /* non-NULL indicates not yet sent to VRAM */ + bool use_prim_restart; } GPUIndexBuf; void GPU_indexbuf_use(GPUIndexBuf *); uint GPU_indexbuf_size_get(const GPUIndexBuf *); typedef struct GPUIndexBufBuilder { - uint max_allowed_index; - uint max_index_len; - uint index_len; - GPUPrimType prim_type; - uint *data; - bool use_prim_restart; + uint max_allowed_index; + uint max_index_len; + uint index_len; + GPUPrimType prim_type; + uint *data; + bool use_prim_restart; } GPUIndexBufBuilder; - /* supports all primitive types. */ -void GPU_indexbuf_init_ex(GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len, bool use_prim_restart); +void GPU_indexbuf_init_ex( + GPUIndexBufBuilder *, GPUPrimType, uint index_len, uint vertex_len, bool use_prim_restart); /* supports only GPU_PRIM_POINTS, GPU_PRIM_LINES and GPU_PRIM_TRIS. */ void GPU_indexbuf_init(GPUIndexBufBuilder *, GPUPrimType, uint prim_len, uint vertex_len); @@ -88,11 +88,12 @@ int GPU_indexbuf_primitive_len(GPUPrimType prim_type); /* Macros */ -#define GPU_INDEXBUF_DISCARD_SAFE(elem) do { \ - if (elem != NULL) { \ - GPU_indexbuf_discard(elem); \ - elem = NULL; \ - } \ -} while (0) +#define GPU_INDEXBUF_DISCARD_SAFE(elem) \ + do { \ + if (elem != NULL) { \ + GPU_indexbuf_discard(elem); \ + elem = NULL; \ + } \ + } while (0) #endif /* __GPU_ELEMENT_H__ */ diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index b656bb74d4b..8f602bf1398 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -56,27 +56,27 @@ void GPU_code_generate_glsl_lib(void); /* GPU Types */ typedef enum eGPUDeviceType { - GPU_DEVICE_NVIDIA = (1 << 0), - GPU_DEVICE_ATI = (1 << 1), - GPU_DEVICE_INTEL = (1 << 2), - GPU_DEVICE_INTEL_UHD = (1 << 3), - GPU_DEVICE_SOFTWARE = (1 << 4), - GPU_DEVICE_UNKNOWN = (1 << 5), - GPU_DEVICE_ANY = (0xff), + GPU_DEVICE_NVIDIA = (1 << 0), + GPU_DEVICE_ATI = (1 << 1), + GPU_DEVICE_INTEL = (1 << 2), + GPU_DEVICE_INTEL_UHD = (1 << 3), + GPU_DEVICE_SOFTWARE = (1 << 4), + GPU_DEVICE_UNKNOWN = (1 << 5), + GPU_DEVICE_ANY = (0xff), } eGPUDeviceType; typedef enum eGPUOSType { - GPU_OS_WIN = (1 << 8), - GPU_OS_MAC = (1 << 9), - GPU_OS_UNIX = (1 << 10), - GPU_OS_ANY = (0xff00), + GPU_OS_WIN = (1 << 8), + GPU_OS_MAC = (1 << 9), + GPU_OS_UNIX = (1 << 10), + GPU_OS_ANY = (0xff00), } eGPUOSType; typedef enum eGPUDriverType { - GPU_DRIVER_OFFICIAL = (1 << 16), - GPU_DRIVER_OPENSOURCE = (1 << 17), - GPU_DRIVER_SOFTWARE = (1 << 18), - GPU_DRIVER_ANY = (0xff0000), + GPU_DRIVER_OFFICIAL = (1 << 16), + GPU_DRIVER_OPENSOURCE = (1 << 17), + GPU_DRIVER_SOFTWARE = (1 << 18), + GPU_DRIVER_ANY = (0xff0000), } eGPUDriverType; bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver); @@ -85,4 +85,4 @@ bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType drive } #endif -#endif /* __GPU_EXTENSIONS_H__ */ +#endif /* __GPU_EXTENSIONS_H__ */ diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 77573b80a1b..3cc972fabfb 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -31,14 +31,14 @@ extern "C" { struct GPUTexture; typedef struct GPUAttachment { - struct GPUTexture *tex; - int mip, layer; + struct GPUTexture *tex; + int mip, layer; } GPUAttachment; typedef enum eGPUFrameBufferBits { - GPU_COLOR_BIT = (1 << 0), - GPU_DEPTH_BIT = (1 << 1), - GPU_STENCIL_BIT = (1 << 2), + GPU_COLOR_BIT = (1 << 0), + GPU_DEPTH_BIT = (1 << 1), + GPU_STENCIL_BIT = (1 << 2), } eGPUFrameBufferBits; typedef struct GPUFrameBuffer GPUFrameBuffer; @@ -63,25 +63,24 @@ bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]); GPUFrameBuffer *GPU_framebuffer_active_get(void); -#define GPU_FRAMEBUFFER_FREE_SAFE(fb) do { \ - if (fb != NULL) { \ - GPU_framebuffer_free(fb); \ - fb = NULL; \ - } \ -} while (0) +#define GPU_FRAMEBUFFER_FREE_SAFE(fb) \ + do { \ + if (fb != NULL) { \ + GPU_framebuffer_free(fb); \ + fb = NULL; \ + } \ + } while (0) /* Framebuffer setup : You need to call GPU_framebuffer_bind for theses * to be effective. */ -void GPU_framebuffer_texture_attach( - GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip); +void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int mip); void GPU_framebuffer_texture_layer_attach( - GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip); + GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int layer, int mip); void GPU_framebuffer_texture_cubeface_attach( - GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip); + GPUFrameBuffer *fb, struct GPUTexture *tex, int slot, int face, int mip); void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, struct GPUTexture *tex); -void GPU_framebuffer_texture_detach_slot( - GPUFrameBuffer *fb, struct GPUTexture *tex, int type); +void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, struct GPUTexture *tex, int type); /** * How to use #GPU_framebuffer_ensure_config(). @@ -102,79 +101,99 @@ void GPU_framebuffer_texture_detach_slot( * \note Make sure that the dimensions of your textures matches * otherwise you will have an invalid framebuffer error. */ -#define GPU_framebuffer_ensure_config(_fb, ...) do { \ - if (*(_fb) == NULL) { \ - *(_fb) = GPU_framebuffer_create(); \ - } \ - GPUAttachment config[] = __VA_ARGS__; \ - GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \ -} while (0) +#define GPU_framebuffer_ensure_config(_fb, ...) \ + do { \ + if (*(_fb) == NULL) { \ + *(_fb) = GPU_framebuffer_create(); \ + } \ + GPUAttachment config[] = __VA_ARGS__; \ + GPU_framebuffer_config_array(*(_fb), config, (sizeof(config) / sizeof(GPUAttachment))); \ + } while (0) void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len); #define GPU_ATTACHMENT_NONE \ - { .tex = NULL, .layer = -1, .mip = 0, } + { \ + .tex = NULL, .layer = -1, .mip = 0, \ + } #define GPU_ATTACHMENT_LEAVE \ - { .tex = NULL, .layer = -1, .mip = -1, } + { \ + .tex = NULL, .layer = -1, .mip = -1, \ + } #define GPU_ATTACHMENT_TEXTURE(_tex) \ - { .tex = _tex, .layer = -1, .mip = 0, } + { \ + .tex = _tex, .layer = -1, .mip = 0, \ + } #define GPU_ATTACHMENT_TEXTURE_MIP(_tex, _mip) \ - { .tex = _tex, .layer = -1, .mip = _mip, } + { \ + .tex = _tex, .layer = -1, .mip = _mip, \ + } #define GPU_ATTACHMENT_TEXTURE_LAYER(_tex, _layer) \ - { .tex = _tex, .layer = _layer, .mip = 0, } + { \ + .tex = _tex, .layer = _layer, .mip = 0, \ + } #define GPU_ATTACHMENT_TEXTURE_LAYER_MIP(_tex, _layer, _mip) \ - { .tex = _tex, .layer = _layer, .mip = _mip, } + { \ + .tex = _tex, .layer = _layer, .mip = _mip, \ + } #define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_tex, _face) \ - { .tex = _tex, .layer = _face, .mip = 0, } + { \ + .tex = _tex, .layer = _face, .mip = 0, \ + } #define GPU_ATTACHMENT_TEXTURE_CUBEFACE_MIP(_tex, _face, _mip) \ - { .tex = _tex, .layer = _face, .mip = _mip, } + { \ + .tex = _tex, .layer = _face, .mip = _mip, \ + } /* Framebuffer operations */ void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h); -void GPU_framebuffer_clear( - GPUFrameBuffer *fb, eGPUFrameBufferBits buffers, - const float clear_col[4], float clear_depth, unsigned int clear_stencil); +void GPU_framebuffer_clear(GPUFrameBuffer *fb, + eGPUFrameBufferBits buffers, + const float clear_col[4], + float clear_depth, + unsigned int clear_stencil); #define GPU_framebuffer_clear_color(fb, col) \ - GPU_framebuffer_clear(fb, GPU_COLOR_BIT, col, 0.0f, 0x00) + GPU_framebuffer_clear(fb, GPU_COLOR_BIT, col, 0.0f, 0x00) #define GPU_framebuffer_clear_depth(fb, depth) \ - GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, depth, 0x00) + GPU_framebuffer_clear(fb, GPU_DEPTH_BIT, NULL, depth, 0x00) #define GPU_framebuffer_clear_color_depth(fb, col, depth) \ - GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT, col, depth, 0x00) + GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT, col, depth, 0x00) #define GPU_framebuffer_clear_stencil(fb, stencil) \ - GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, stencil) + GPU_framebuffer_clear(fb, GPU_STENCIL_BIT, NULL, 0.0f, stencil) #define GPU_framebuffer_clear_depth_stencil(fb, depth, stencil) \ - GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, depth, stencil) + GPU_framebuffer_clear(fb, GPU_DEPTH_BIT | GPU_STENCIL_BIT, NULL, depth, stencil) #define GPU_framebuffer_clear_color_depth_stencil(fb, col, depth, stencil) \ - GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil) + GPU_framebuffer_clear(fb, GPU_COLOR_BIT | GPU_DEPTH_BIT | GPU_STENCIL_BIT, col, depth, stencil) void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data); void GPU_framebuffer_read_color( - GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data); + GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data); -void GPU_framebuffer_blit( - GPUFrameBuffer *fb_read, int read_slot, - GPUFrameBuffer *fb_write, int write_slot, - eGPUFrameBufferBits blit_buffers); +void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, + int read_slot, + GPUFrameBuffer *fb_write, + int write_slot, + eGPUFrameBufferBits blit_buffers); -void GPU_framebuffer_recursive_downsample( - GPUFrameBuffer *fb, int max_lvl, - void (*callback)(void *userData, int level), void *userData); +void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb, + int max_lvl, + void (*callback)(void *userData, int level), + void *userData); /* GPU OffScreen * - wrapper around framebuffer and texture for simple offscreen drawing */ GPUOffScreen *GPU_offscreen_create( - int width, int height, int samples, - bool depth, bool high_bitdepth, char err_out[256]); + int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256]); void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs, bool save); void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore); @@ -184,9 +203,10 @@ int GPU_offscreen_width(const GPUOffScreen *ofs); int GPU_offscreen_height(const GPUOffScreen *ofs); struct GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs); -void GPU_offscreen_viewport_data_get( - GPUOffScreen *ofs, - GPUFrameBuffer **r_fb, struct GPUTexture **r_color, struct GPUTexture **r_depth); +void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs, + GPUFrameBuffer **r_fb, + struct GPUTexture **r_color, + struct GPUTexture **r_depth); void GPU_clear_color(float red, float green, float blue, float alpha); void GPU_clear(eGPUFrameBufferBits flags); @@ -195,4 +215,4 @@ void GPU_clear(eGPUFrameBufferBits flags); } #endif -#endif /* __GPU_FRAMEBUFFER_H__ */ +#endif /* __GPU_FRAMEBUFFER_H__ */ diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h index b7d2901daeb..30a6020f74a 100644 --- a/source/blender/gpu/GPU_immediate.h +++ b/source/blender/gpu/GPU_immediate.h @@ -145,4 +145,4 @@ void immActivate(void); void immDeactivate(void); void immDestroy(void); -#endif /* __GPU_IMMEDIATE_H__ */ +#endif /* __GPU_IMMEDIATE_H__ */ diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h index 50d20c753a3..370c576006f 100644 --- a/source/blender/gpu/GPU_immediate_util.h +++ b/source/blender/gpu/GPU_immediate_util.h @@ -30,16 +30,20 @@ void immRecti(uint pos, int x1, int y1, int x2, int y2); /* Same as immRectf/immRecti but does not call immBegin/immEnd. To use with GPU_PRIM_TRIS. */ void immRectf_fast(uint pos, float x1, float y1, float x2, float y2); -void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]); -void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]); +void immRectf_fast_with_color( + uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]); +void immRecti_fast_with_color( + uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]); void imm_cpack(uint x); void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float radius, int nsegments); void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float radius, int nsegments); -void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments); -void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments); +void imm_draw_circle_wire_aspect_2d( + uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments); +void imm_draw_circle_fill_aspect_2d( + uint shdr_pos, float x, float y, float radius_x, float radius_y, int nsegments); /* use this version when GPUVertFormat has a vec3 position */ void imm_draw_circle_wire_3d(uint pos, float x, float y, float radius, int nsegments); @@ -47,12 +51,16 @@ void imm_draw_circle_fill_3d(uint pos, float x, float y, float radius, int nsegm /* same as 'imm_draw_disk_partial_fill_2d', except it draws a wire arc. */ void imm_draw_circle_partial_wire_2d( - uint pos, float x, float y, - float radius, int nsegments, float start, float sweep); + uint pos, float x, float y, float radius, int nsegments, float start, float sweep); -void imm_draw_disk_partial_fill_2d( - uint pos, float x, float y, - float radius_inner, float radius_outer, int nsegments, float start, float sweep); +void imm_draw_disk_partial_fill_2d(uint pos, + float x, + float y, + float radius_inner, + float radius_outer, + int nsegments, + float start, + float sweep); void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2); void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2); @@ -63,13 +71,10 @@ void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]); void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3]); void imm_draw_cylinder_fill_normal_3d( - uint pos, uint nor, float base, float top, float height, - int slices, int stacks); + uint pos, uint nor, float base, float top, float height, int slices, int stacks); void imm_draw_cylinder_wire_3d( - uint pos, float base, float top, float height, - int slices, int stacks); + uint pos, float base, float top, float height, int slices, int stacks); void imm_draw_cylinder_fill_3d( - uint pos, float base, float top, float height, - int slices, int stacks); + uint pos, float base, float top, float height, int slices, int stacks); -#endif /* __GPU_IMMEDIATE_UTIL_H__ */ +#endif /* __GPU_IMMEDIATE_UTIL_H__ */ diff --git a/source/blender/gpu/GPU_legacy_stubs.h b/source/blender/gpu/GPU_legacy_stubs.h index 9d45c051f39..f26765a28f0 100644 --- a/source/blender/gpu/GPU_legacy_stubs.h +++ b/source/blender/gpu/GPU_legacy_stubs.h @@ -35,7 +35,7 @@ # pragma GCC diagnostic ignored "-Wunused-function" #endif -#include /* for abort(). */ +#include /* for abort(). */ #include "BLI_utildefines.h" @@ -45,74 +45,75 @@ */ static void gl_deprecated(void) { - BLI_assert(true); + BLI_assert(true); } #define _GL_BOOL BLI_INLINE GLboolean -#define _GL_BOOL_RET { \ - gl_deprecated(); \ - return false; \ -} +#define _GL_BOOL_RET \ + { \ + gl_deprecated(); \ + return false; \ + } #define _GL_ENUM BLI_INLINE GLenum -#define _GL_ENUM_RET { \ - gl_deprecated(); \ - return 0; \ -} +#define _GL_ENUM_RET \ + { \ + gl_deprecated(); \ + return 0; \ + } #define _GL_INT BLI_INLINE GLint -#define _GL_INT_RET { \ - gl_deprecated(); \ - return 0; \ -} - +#define _GL_INT_RET \ + { \ + gl_deprecated(); \ + return 0; \ + } #define _GL_UINT BLI_INLINE GLuint -#define _GL_UINT_RET { \ - gl_deprecated(); \ - return 0; \ -} +#define _GL_UINT_RET \ + { \ + gl_deprecated(); \ + return 0; \ + } #define _GL_VOID BLI_INLINE void -#define _GL_VOID_RET { \ - gl_deprecated(); \ -} +#define _GL_VOID_RET \ + { \ + gl_deprecated(); \ + } static bool disable_enable_check(GLenum cap) { - const bool is_deprecated = \ - ELEM( - cap, - GL_ALPHA_TEST, - GL_LINE_STIPPLE, - GL_POINT_SPRITE, - GL_TEXTURE_1D, - GL_TEXTURE_2D, - GL_TEXTURE_GEN_S, - GL_TEXTURE_GEN_T, - -1 - ); + const bool is_deprecated = ELEM(cap, + GL_ALPHA_TEST, + GL_LINE_STIPPLE, + GL_POINT_SPRITE, + GL_TEXTURE_1D, + GL_TEXTURE_2D, + GL_TEXTURE_GEN_S, + GL_TEXTURE_GEN_T, + -1); - if (is_deprecated) { - gl_deprecated(); - } + if (is_deprecated) { + gl_deprecated(); + } - return is_deprecated; + return is_deprecated; } -_GL_VOID USE_CAREFULLY_glDisable (GLenum cap) +_GL_VOID USE_CAREFULLY_glDisable(GLenum cap) { - if (!disable_enable_check(cap)) { - glDisable(cap); - } + if (!disable_enable_check(cap)) { + glDisable(cap); + } } #define glDisable USE_CAREFULLY_glDisable -_GL_VOID USE_CAREFULLY_glEnable (GLenum cap) +_GL_VOID USE_CAREFULLY_glEnable(GLenum cap) { - if (!disable_enable_check(cap)) { - glEnable(cap); - } + if (!disable_enable_check(cap)) { + glEnable(cap); + } } #define glEnable USE_CAREFULLY_glEnable @@ -120,8 +121,7 @@ _GL_VOID USE_CAREFULLY_glEnable (GLenum cap) * Hand written cases */ -_GL_VOID DO_NOT_USE_glClientActiveTexture (GLenum texture) _GL_VOID_RET - +_GL_VOID DO_NOT_USE_glClientActiveTexture(GLenum texture) _GL_VOID_RET /** * List automatically generated from `gl-deprecated.h` and `glew.h` @@ -147,290 +147,357 @@ _GL_VOID DO_NOT_USE_glClientActiveTexture (GLenum texture) _GL_VOID_RET #define DO_NOT_USE_GL_SOURCE2_ALPHA 0 #define DO_NOT_USE_GL_SOURCE2_RGB 0 -/** + /** * Functions */ -_GL_VOID DO_NOT_USE_glAccum (GLenum op, GLfloat value) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glAlphaFunc (GLenum func, GLclampf ref) _GL_VOID_RET -_GL_BOOL DO_NOT_USE_glAreTexturesResident (GLsizei n, const GLuint *textures, GLboolean *residences) _GL_BOOL_RET -_GL_VOID DO_NOT_USE_glArrayElement (GLint i) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glBegin (GLenum mode) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glBitmap (GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glCallList (GLuint list) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glCallLists (GLsizei n, GLenum type, const void *lists) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glClearAccum (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glClearIndex (GLfloat c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glClipPlane (GLenum plane, const GLdouble *equation) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3b (GLbyte red, GLbyte green, GLbyte blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3bv (const GLbyte *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3d (GLdouble red, GLdouble green, GLdouble blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3f (GLfloat red, GLfloat green, GLfloat blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3i (GLint red, GLint green, GLint blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3s (GLshort red, GLshort green, GLshort blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3ub (GLubyte red, GLubyte green, GLubyte blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3ubv (const GLubyte *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3ui (GLuint red, GLuint green, GLuint blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3uiv (const GLuint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3us (GLushort red, GLushort green, GLushort blue) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor3usv (const GLushort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4b (GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4bv (const GLbyte *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4d (GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4f (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4i (GLint red, GLint green, GLint blue, GLint alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4s (GLshort red, GLshort green, GLshort blue, GLshort alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4ub (GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4ubv (const GLubyte *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4ui (GLuint red, GLuint green, GLuint blue, GLuint alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4uiv (const GLuint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4us (GLushort red, GLushort green, GLushort blue, GLushort alpha) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColor4usv (const GLushort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColorMaterial (GLenum face, GLenum mode) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glColorPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glCopyPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glDeleteLists (GLuint list, GLsizei range) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glDisableClientState (GLenum array) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glDrawPixels (GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEdgeFlag (GLboolean flag) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEdgeFlagPointer (GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEdgeFlagv (const GLboolean *flag) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEnableClientState (GLenum array) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEnd (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEndList (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord1d (GLdouble u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord1dv (const GLdouble *u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord1f (GLfloat u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord1fv (const GLfloat *u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord2d (GLdouble u, GLdouble v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord2dv (const GLdouble *u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord2f (GLfloat u, GLfloat v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalCoord2fv (const GLfloat *u) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalMesh1 (GLenum mode, GLint i1, GLint i2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalMesh2 (GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalPoint1 (GLint i) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glEvalPoint2 (GLint i, GLint j) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFeedbackBuffer (GLsizei size, GLenum type, GLfloat *buffer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFogf (GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFogfv (GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFogi (GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFogiv (GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glFrustum (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET -_GL_UINT DO_NOT_USE_glGenLists (GLsizei range) _GL_UINT_RET -_GL_VOID DO_NOT_USE_glGetClipPlane (GLenum plane, GLdouble *equation) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetLightfv (GLenum light, GLenum pname, GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetLightiv (GLenum light, GLenum pname, GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetMapdv (GLenum target, GLenum query, GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetMapfv (GLenum target, GLenum query, GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetMapiv (GLenum target, GLenum query, GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetMaterialfv (GLenum face, GLenum pname, GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetMaterialiv (GLenum face, GLenum pname, GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetPixelMapfv (GLenum map, GLfloat *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetPixelMapuiv (GLenum map, GLuint *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetPixelMapusv (GLenum map, GLushort *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetPolygonStipple (GLubyte *mask) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetTexEnvfv (GLenum target, GLenum pname, GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetTexEnviv (GLenum target, GLenum pname, GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetTexGendv (GLenum coord, GLenum pname, GLdouble *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetTexGenfv (GLenum coord, GLenum pname, GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glGetTexGeniv (GLenum coord, GLenum pname, GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexMask (GLuint mask) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexd (GLdouble c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexdv (const GLdouble *c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexf (GLfloat c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexfv (const GLfloat *c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexi (GLint c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexiv (const GLint *c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexs (GLshort c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexsv (const GLshort *c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexub (GLubyte c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glIndexubv (const GLubyte *c) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glInitNames (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glInterleavedArrays (GLenum format, GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_BOOL DO_NOT_USE_glIsList (GLuint list) _GL_BOOL_RET -_GL_VOID DO_NOT_USE_glLightModelf (GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightModelfv (GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightModeli (GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightModeliv (GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightf (GLenum light, GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightfv (GLenum light, GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLighti (GLenum light, GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLightiv (GLenum light, GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLineStipple (GLint factor, GLushort pattern) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glListBase (GLuint base) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLoadIdentity (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLoadMatrixd (const GLdouble *m) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLoadMatrixf (const GLfloat *m) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glLoadName (GLuint name) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMap1d (GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMap1f (GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMap2d (GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMap2f (GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMapGrid1d (GLint un, GLdouble u1, GLdouble u2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMapGrid1f (GLint un, GLfloat u1, GLfloat u2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMapGrid2d (GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMapGrid2f (GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMaterialf (GLenum face, GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMaterialfv (GLenum face, GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMateriali (GLenum face, GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMaterialiv (GLenum face, GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMatrixMode (GLenum mode) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMultMatrixd (const GLdouble *m) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glMultMatrixf (const GLfloat *m) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNewList (GLuint list, GLenum mode) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3b (GLbyte nx, GLbyte ny, GLbyte nz) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3bv (const GLbyte *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3d (GLdouble nx, GLdouble ny, GLdouble nz) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3f (GLfloat nx, GLfloat ny, GLfloat nz) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3i (GLint nx, GLint ny, GLint nz) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3s (GLshort nx, GLshort ny, GLshort nz) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormal3sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glNormalPointer (GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glOrtho (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPassThrough (GLfloat token) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelMapfv (GLenum map, GLsizei mapsize, const GLfloat *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelMapuiv (GLenum map, GLsizei mapsize, const GLuint *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelMapusv (GLenum map, GLsizei mapsize, const GLushort *values) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelTransferf (GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelTransferi (GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPixelZoom (GLfloat xfactor, GLfloat yfactor) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPolygonStipple (const GLubyte *mask) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPopAttrib (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPopClientAttrib (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPopMatrix (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPopName (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPrioritizeTextures (GLsizei n, const GLuint *textures, const GLclampf *priorities) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPushAttrib (GLbitfield mask) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPushClientAttrib (GLbitfield mask) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPushMatrix (void) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glPushName (GLuint name) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2d (GLdouble x, GLdouble y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2f (GLfloat x, GLfloat y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2i (GLint x, GLint y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2s (GLshort x, GLshort y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos2sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3i (GLint x, GLint y, GLint z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos3sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRasterPos4sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectd (GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectdv (const GLdouble *v1, const GLdouble *v2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectf (GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectfv (const GLfloat *v1, const GLfloat *v2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRecti (GLint x1, GLint y1, GLint x2, GLint y2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectiv (const GLint *v1, const GLint *v2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRects (GLshort x1, GLshort y1, GLshort x2, GLshort y2) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRectsv (const GLshort *v1, const GLshort *v2) _GL_VOID_RET -_GL_INT DO_NOT_USE_glRenderMode (GLenum mode) _GL_INT_RET -_GL_VOID DO_NOT_USE_glRotated (GLdouble angle, GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glRotatef (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glScaled (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glScalef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glSelectBuffer (GLsizei size, GLuint *buffer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glShadeModel (GLenum mode) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1d (GLdouble s) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1f (GLfloat s) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1i (GLint s) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1s (GLshort s) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord1sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2d (GLdouble s, GLdouble t) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2f (GLfloat s, GLfloat t) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2i (GLint s, GLint t) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2s (GLshort s, GLshort t) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord2sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3d (GLdouble s, GLdouble t, GLdouble r) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3f (GLfloat s, GLfloat t, GLfloat r) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3i (GLint s, GLint t, GLint r) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3s (GLshort s, GLshort t, GLshort r) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord3sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4d (GLdouble s, GLdouble t, GLdouble r, GLdouble q) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4f (GLfloat s, GLfloat t, GLfloat r, GLfloat q) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4i (GLint s, GLint t, GLint r, GLint q) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4s (GLshort s, GLshort t, GLshort r, GLshort q) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoord4sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexCoordPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexEnvf (GLenum target, GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexEnvi (GLenum target, GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexEnviv (GLenum target, GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGend (GLenum coord, GLenum pname, GLdouble param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGendv (GLenum coord, GLenum pname, const GLdouble *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGenf (GLenum coord, GLenum pname, GLfloat param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGenfv (GLenum coord, GLenum pname, const GLfloat *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGeni (GLenum coord, GLenum pname, GLint param) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTexGeniv (GLenum coord, GLenum pname, const GLint *params) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTranslated (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glTranslatef (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2d (GLdouble x, GLdouble y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2f (GLfloat x, GLfloat y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2i (GLint x, GLint y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2s (GLshort x, GLshort y) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex2sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3d (GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3f (GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3i (GLint x, GLint y, GLint z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3s (GLshort x, GLshort y, GLshort z) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex3sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4d (GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4dv (const GLdouble *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4f (GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4fv (const GLfloat *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4i (GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4iv (const GLint *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4s (GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertex4sv (const GLshort *v) _GL_VOID_RET -_GL_VOID DO_NOT_USE_glVertexPointer (GLint size, GLenum type, GLsizei stride, const void *pointer) _GL_VOID_RET + _GL_VOID DO_NOT_USE_glAccum(GLenum op, GLfloat value) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glAlphaFunc(GLenum func, GLclampf ref) _GL_VOID_RET _GL_BOOL + DO_NOT_USE_glAreTexturesResident(GLsizei n, + const GLuint *textures, + GLboolean *residences) _GL_BOOL_RET _GL_VOID + DO_NOT_USE_glArrayElement(GLint i) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glBegin(GLenum mode) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glBitmap(GLsizei width, + GLsizei height, + GLfloat xorig, + GLfloat yorig, + GLfloat xmove, + GLfloat ymove, + const GLubyte *bitmap) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glCallList(GLuint list) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glCallLists(GLsizei n, GLenum type, const void *lists) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glClearIndex(GLfloat c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glClipPlane(GLenum plane, const GLdouble *equation) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3b(GLbyte red, GLbyte green, GLbyte blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3bv(const GLbyte *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3d(GLdouble red, GLdouble green, GLdouble blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3f(GLfloat red, GLfloat green, GLfloat blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3i(GLint red, GLint green, GLint blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3s(GLshort red, GLshort green, GLshort blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3ub(GLubyte red, GLubyte green, GLubyte blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3ubv(const GLubyte *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3ui(GLuint red, GLuint green, GLuint blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3uiv(const GLuint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3us(GLushort red, GLushort green, GLushort blue) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor3usv(const GLushort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4b(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4bv(const GLbyte *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4d(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4i(GLint red, GLint green, GLint blue, GLint alpha) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4s(GLshort red, GLshort green, GLshort blue, GLshort alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4ub(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4ubv(const GLubyte *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4ui(GLuint red, GLuint green, GLuint blue, GLuint alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4uiv(const GLuint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColor4us(GLushort red, GLushort green, GLushort blue, GLushort alpha) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glColor4usv(const GLushort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColorMaterial(GLenum face, GLenum mode) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) + _GL_VOID_RET _GL_VOID + DO_NOT_USE_glCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type) + _GL_VOID_RET _GL_VOID + DO_NOT_USE_glDeleteLists(GLuint list, GLsizei range) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glDisableClientState(GLenum array) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glDrawPixels(GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + const void *pixels) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEdgeFlag(GLboolean flag) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEdgeFlagPointer(GLsizei stride, const void *pointer) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEdgeFlagv(const GLboolean *flag) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEnableClientState(GLenum array) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEnd(void) _GL_VOID_RET _GL_VOID DO_NOT_USE_glEndList(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord1d(GLdouble u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord1dv(const GLdouble *u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord1f(GLfloat u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord1fv(const GLfloat *u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord2d(GLdouble u, GLdouble v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord2dv(const GLdouble *u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord2f(GLfloat u, GLfloat v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalCoord2fv(const GLfloat *u) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalMesh1(GLenum mode, GLint i1, GLint i2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) + _GL_VOID_RET _GL_VOID DO_NOT_USE_glEvalPoint1(GLint i) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glEvalPoint2(GLint i, GLint j) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFeedbackBuffer(GLsizei size, GLenum type, GLfloat *buffer) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFogf(GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFogfv(GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFogi(GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFogiv(GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glFrustum(GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble zNear, + GLdouble zFar) _GL_VOID_RET _GL_UINT + DO_NOT_USE_glGenLists(GLsizei range) _GL_UINT_RET _GL_VOID + DO_NOT_USE_glGetClipPlane(GLenum plane, GLdouble *equation) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetLightfv(GLenum light, GLenum pname, GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetLightiv(GLenum light, GLenum pname, GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetMapdv(GLenum target, GLenum query, GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetMapfv(GLenum target, GLenum query, GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetMapiv(GLenum target, GLenum query, GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetMaterialfv(GLenum face, GLenum pname, GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetMaterialiv(GLenum face, GLenum pname, GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetPixelMapfv(GLenum map, GLfloat *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetPixelMapuiv(GLenum map, GLuint *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetPixelMapusv(GLenum map, GLushort *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetPolygonStipple(GLubyte *mask) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetTexEnvfv(GLenum target, GLenum pname, GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetTexEnviv(GLenum target, GLenum pname, GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetTexGendv(GLenum coord, GLenum pname, GLdouble *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetTexGenfv(GLenum coord, GLenum pname, GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glGetTexGeniv(GLenum coord, GLenum pname, GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexMask(GLuint mask) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexPointer(GLenum type, + GLsizei stride, + const void *pointer) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexd(GLdouble c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexdv(const GLdouble *c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexf(GLfloat c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexfv(const GLfloat *c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexi(GLint c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexiv(const GLint *c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexs(GLshort c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexsv(const GLshort *c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexub(GLubyte c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glIndexubv(const GLubyte *c) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glInitNames(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glInterleavedArrays(GLenum format, + GLsizei stride, + const void *pointer) _GL_VOID_RET _GL_BOOL + DO_NOT_USE_glIsList(GLuint list) _GL_BOOL_RET _GL_VOID + DO_NOT_USE_glLightModelf(GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightModelfv(GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightModeli(GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightModeliv(GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightf(GLenum light, GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightfv(GLenum light, GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLighti(GLenum light, GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLightiv(GLenum light, GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLineStipple(GLint factor, GLushort pattern) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glListBase(GLuint base) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLoadIdentity(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLoadMatrixd(const GLdouble *m) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLoadMatrixf(const GLfloat *m) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glLoadName(GLuint name) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMap1d(GLenum target, + GLdouble u1, + GLdouble u2, + GLint stride, + GLint order, + const GLdouble *points) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMap1f(GLenum target, + GLfloat u1, + GLfloat u2, + GLint stride, + GLint order, + const GLfloat *points) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMap2d(GLenum target, + GLdouble u1, + GLdouble u2, + GLint ustride, + GLint uorder, + GLdouble v1, + GLdouble v2, + GLint vstride, + GLint vorder, + const GLdouble *points) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMap2f(GLenum target, + GLfloat u1, + GLfloat u2, + GLint ustride, + GLint uorder, + GLfloat v1, + GLfloat v2, + GLint vstride, + GLint vorder, + const GLfloat *points) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMapGrid1d(GLint un, GLdouble u1, GLdouble u2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2) + _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2) + _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMaterialf(GLenum face, GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMateriali(GLenum face, GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMaterialiv(GLenum face, GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMatrixMode(GLenum mode) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMultMatrixd(const GLdouble *m) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glMultMatrixf(const GLfloat *m) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNewList(GLuint list, GLenum mode) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3b(GLbyte nx, GLbyte ny, GLbyte nz) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3bv(const GLbyte *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3d(GLdouble nx, GLdouble ny, GLdouble nz) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3i(GLint nx, GLint ny, GLint nz) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3s(GLshort nx, GLshort ny, GLshort nz) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormal3sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glNormalPointer(GLenum type, + GLsizei stride, + const void *pointer) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glOrtho(GLdouble left, + GLdouble right, + GLdouble bottom, + GLdouble top, + GLdouble zNear, + GLdouble zFar) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPassThrough(GLfloat token) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelMapfv(GLenum map, + GLsizei mapsize, + const GLfloat *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelMapuiv(GLenum map, + GLsizei mapsize, + const GLuint *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelMapusv(GLenum map, + GLsizei mapsize, + const GLushort *values) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelTransferf(GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelTransferi(GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPixelZoom(GLfloat xfactor, GLfloat yfactor) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPolygonStipple(const GLubyte *mask) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPopAttrib(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPopClientAttrib(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPopMatrix(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPopName(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPrioritizeTextures(GLsizei n, + const GLuint *textures, + const GLclampf *priorities) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPushAttrib(GLbitfield mask) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPushClientAttrib(GLbitfield mask) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPushMatrix(void) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glPushName(GLuint name) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2d(GLdouble x, GLdouble y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2f(GLfloat x, GLfloat y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2i(GLint x, GLint y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2s(GLshort x, GLshort y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos2sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3d(GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3f(GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3i(GLint x, GLint y, GLint z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3s(GLshort x, GLshort y, GLshort z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos3sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4i(GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRasterPos4sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectdv(const GLdouble *v1, const GLdouble *v2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectfv(const GLfloat *v1, const GLfloat *v2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRecti(GLint x1, GLint y1, GLint x2, GLint y2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectiv(const GLint *v1, const GLint *v2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRectsv(const GLshort *v1, const GLshort *v2) _GL_VOID_RET _GL_INT + DO_NOT_USE_glRenderMode(GLenum mode) _GL_INT_RET _GL_VOID + DO_NOT_USE_glRotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glScaled(GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glScalef(GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glSelectBuffer(GLsizei size, GLuint *buffer) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glShadeModel(GLenum mode) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1d(GLdouble s) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1f(GLfloat s) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1i(GLint s) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1s(GLshort s) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord1sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2d(GLdouble s, GLdouble t) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2f(GLfloat s, GLfloat t) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2i(GLint s, GLint t) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2s(GLshort s, GLshort t) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord2sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3d(GLdouble s, GLdouble t, GLdouble r) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3f(GLfloat s, GLfloat t, GLfloat r) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3i(GLint s, GLint t, GLint r) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3s(GLshort s, GLshort t, GLshort r) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord3sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4d(GLdouble s, GLdouble t, GLdouble r, GLdouble q) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4i(GLint s, GLint t, GLint r, GLint q) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4s(GLshort s, GLshort t, GLshort r, GLshort q) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoord4sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) + _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexEnvf(GLenum target, GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexEnvfv(GLenum target, GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexEnvi(GLenum target, GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexEnviv(GLenum target, GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGend(GLenum coord, GLenum pname, GLdouble param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGendv(GLenum coord, GLenum pname, const GLdouble *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGenf(GLenum coord, GLenum pname, GLfloat param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGenfv(GLenum coord, GLenum pname, const GLfloat *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGeni(GLenum coord, GLenum pname, GLint param) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTexGeniv(GLenum coord, GLenum pname, const GLint *params) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTranslated(GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glTranslatef(GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2d(GLdouble x, GLdouble y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2f(GLfloat x, GLfloat y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2i(GLint x, GLint y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2s(GLshort x, GLshort y) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex2sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3d(GLdouble x, GLdouble y, GLdouble z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3f(GLfloat x, GLfloat y, GLfloat z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3i(GLint x, GLint y, GLint z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3s(GLshort x, GLshort y, GLshort z) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex3sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4dv(const GLdouble *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4fv(const GLfloat *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4i(GLint x, GLint y, GLint z, GLint w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4iv(const GLint *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4s(GLshort x, GLshort y, GLshort z, GLshort w) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertex4sv(const GLshort *v) _GL_VOID_RET _GL_VOID + DO_NOT_USE_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) + _GL_VOID_RET /** * End of automatically generated list */ - - #undef _GL_BOOL #undef _GL_BOOL_RET #undef _GL_ENUM diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 6d8319fbdd3..da61dc76422 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -61,85 +61,85 @@ typedef struct GPUParticleInfo GPUParticleInfo; /* Functions to create GPU Materials nodes */ typedef enum eGPUType { - /* Keep in sync with GPU_DATATYPE_STR */ - /* The value indicates the number of elements in each type */ - GPU_NONE = 0, - GPU_FLOAT = 1, - GPU_VEC2 = 2, - GPU_VEC3 = 3, - GPU_VEC4 = 4, - GPU_MAT3 = 9, - GPU_MAT4 = 16, - - /* Values not in GPU_DATATYPE_STR */ - GPU_TEX1D_ARRAY = 1001, - GPU_TEX2D = 1002, - GPU_TEX3D = 1003, - GPU_SHADOW2D = 1004, - GPU_TEXCUBE = 1005, - - /* GLSL Struct types */ - GPU_CLOSURE = 1006, - - /* Opengl Attributes */ - GPU_ATTR = 3001, + /* Keep in sync with GPU_DATATYPE_STR */ + /* The value indicates the number of elements in each type */ + GPU_NONE = 0, + GPU_FLOAT = 1, + GPU_VEC2 = 2, + GPU_VEC3 = 3, + GPU_VEC4 = 4, + GPU_MAT3 = 9, + GPU_MAT4 = 16, + + /* Values not in GPU_DATATYPE_STR */ + GPU_TEX1D_ARRAY = 1001, + GPU_TEX2D = 1002, + GPU_TEX3D = 1003, + GPU_SHADOW2D = 1004, + GPU_TEXCUBE = 1005, + + /* GLSL Struct types */ + GPU_CLOSURE = 1006, + + /* Opengl Attributes */ + GPU_ATTR = 3001, } eGPUType; typedef enum eGPUBuiltin { - GPU_VIEW_MATRIX = (1 << 0), - GPU_OBJECT_MATRIX = (1 << 1), - GPU_INVERSE_VIEW_MATRIX = (1 << 2), - GPU_INVERSE_OBJECT_MATRIX = (1 << 3), - GPU_VIEW_POSITION = (1 << 4), - GPU_VIEW_NORMAL = (1 << 5), - GPU_OBCOLOR = (1 << 6), - GPU_AUTO_BUMPSCALE = (1 << 7), - GPU_CAMERA_TEXCO_FACTORS = (1 << 8), - GPU_PARTICLE_SCALAR_PROPS = (1 << 9), - GPU_PARTICLE_LOCATION = (1 << 10), - GPU_PARTICLE_VELOCITY = (1 << 11), - GPU_PARTICLE_ANG_VELOCITY = (1 << 12), - GPU_LOC_TO_VIEW_MATRIX = (1 << 13), - GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), - GPU_OBJECT_INFO = (1 << 15), - GPU_VOLUME_DENSITY = (1 << 16), - GPU_VOLUME_FLAME = (1 << 17), - GPU_VOLUME_TEMPERATURE = (1 << 18), - GPU_BARYCENTRIC_TEXCO = (1 << 19), - GPU_BARYCENTRIC_DIST = (1 << 20), - GPU_INVERSE_NORMAL_MATRIX = (1 << 21), + GPU_VIEW_MATRIX = (1 << 0), + GPU_OBJECT_MATRIX = (1 << 1), + GPU_INVERSE_VIEW_MATRIX = (1 << 2), + GPU_INVERSE_OBJECT_MATRIX = (1 << 3), + GPU_VIEW_POSITION = (1 << 4), + GPU_VIEW_NORMAL = (1 << 5), + GPU_OBCOLOR = (1 << 6), + GPU_AUTO_BUMPSCALE = (1 << 7), + GPU_CAMERA_TEXCO_FACTORS = (1 << 8), + GPU_PARTICLE_SCALAR_PROPS = (1 << 9), + GPU_PARTICLE_LOCATION = (1 << 10), + GPU_PARTICLE_VELOCITY = (1 << 11), + GPU_PARTICLE_ANG_VELOCITY = (1 << 12), + GPU_LOC_TO_VIEW_MATRIX = (1 << 13), + GPU_INVERSE_LOC_TO_VIEW_MATRIX = (1 << 14), + GPU_OBJECT_INFO = (1 << 15), + GPU_VOLUME_DENSITY = (1 << 16), + GPU_VOLUME_FLAME = (1 << 17), + GPU_VOLUME_TEMPERATURE = (1 << 18), + GPU_BARYCENTRIC_TEXCO = (1 << 19), + GPU_BARYCENTRIC_DIST = (1 << 20), + GPU_INVERSE_NORMAL_MATRIX = (1 << 21), } eGPUBuiltin; typedef enum eGPUMatFlag { - GPU_MATFLAG_DIFFUSE = (1 << 0), - GPU_MATFLAG_GLOSSY = (1 << 1), - GPU_MATFLAG_REFRACT = (1 << 2), - GPU_MATFLAG_SSS = (1 << 3), + GPU_MATFLAG_DIFFUSE = (1 << 0), + GPU_MATFLAG_GLOSSY = (1 << 1), + GPU_MATFLAG_REFRACT = (1 << 2), + GPU_MATFLAG_SSS = (1 << 3), } eGPUMatFlag; typedef enum eGPUBlendMode { - GPU_BLEND_SOLID = 0, - GPU_BLEND_ADD = 1, - GPU_BLEND_ALPHA = 2, - GPU_BLEND_CLIP = 4, - GPU_BLEND_ALPHA_SORT = 8, - GPU_BLEND_ALPHA_TO_COVERAGE = 16, + GPU_BLEND_SOLID = 0, + GPU_BLEND_ADD = 1, + GPU_BLEND_ALPHA = 2, + GPU_BLEND_CLIP = 4, + GPU_BLEND_ALPHA_SORT = 8, + GPU_BLEND_ALPHA_TO_COVERAGE = 16, } eGPUBlendMode; typedef struct GPUNodeStack { - eGPUType type; - float vec[4]; - struct GPUNodeLink *link; - bool hasinput; - bool hasoutput; - short sockettype; - bool end; + eGPUType type; + float vec[4]; + struct GPUNodeLink *link; + bool hasinput; + bool hasoutput; + short sockettype; + bool end; } GPUNodeStack; typedef enum eGPUMaterialStatus { - GPU_MAT_FAILED = 0, - GPU_MAT_QUEUED, - GPU_MAT_SUCCESS, + GPU_MAT_FAILED = 0, + GPU_MAT_QUEUED, + GPU_MAT_SUCCESS, } eGPUMaterialStatus; GPUNodeLink *GPU_attribute(CustomDataType type, const char *name); @@ -150,24 +150,42 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *la GPUNodeLink *GPU_builtin(eGPUBuiltin builtin); bool GPU_link(GPUMaterial *mat, const char *name, ...); -bool GPU_stack_link(GPUMaterial *mat, struct bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...); -GPUNodeLink *GPU_uniformbuffer_link_out( - struct GPUMaterial *mat, struct bNode *node, - struct GPUNodeStack *stack, const int index); +bool GPU_stack_link(GPUMaterial *mat, + struct bNode *node, + const char *name, + GPUNodeStack *in, + GPUNodeStack *out, + ...); +GPUNodeLink *GPU_uniformbuffer_link_out(struct GPUMaterial *mat, + struct bNode *node, + struct GPUNodeStack *stack, + const int index); void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link); eGPUBuiltin GPU_get_material_builtins(GPUMaterial *material); -void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3], short *falloff_type, float *sharpness); -struct GPUUniformBuffer *GPU_material_sss_profile_get( - GPUMaterial *material, int sample_len, struct GPUTexture **tex_profile); +void GPU_material_sss_profile_create(GPUMaterial *material, + float radii[3], + short *falloff_type, + float *sharpness); +struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, + int sample_len, + struct GPUTexture **tex_profile); /* High level functions to create and use GPU materials */ -GPUMaterial *GPU_material_from_nodetree_find( - struct ListBase *gpumaterials, const void *engine_type, int options); -GPUMaterial *GPU_material_from_nodetree( - struct Scene *scene, struct bNodeTree *ntree, struct ListBase *gpumaterials, const void *engine_type, int options, - const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, const char *name); +GPUMaterial *GPU_material_from_nodetree_find(struct ListBase *gpumaterials, + const void *engine_type, + int options); +GPUMaterial *GPU_material_from_nodetree(struct Scene *scene, + struct bNodeTree *ntree, + struct ListBase *gpumaterials, + const void *engine_type, + int options, + const char *vert_code, + const char *geom_code, + const char *frag_lib, + const char *defines, + const char *name); void GPU_material_compile(GPUMaterial *mat); void GPU_material_free(struct ListBase *gpumaterial); @@ -182,9 +200,7 @@ struct GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material); void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs); struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void); -void GPU_material_vertex_attrs( - GPUMaterial *material, - struct GPUVertAttrLayers *attrs); +void GPU_material_vertex_attrs(GPUMaterial *material, struct GPUVertAttrLayers *attrs); bool GPU_material_do_color_management(GPUMaterial *mat); bool GPU_material_use_domain_surface(GPUMaterial *mat); diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index bd7d4478c6a..24a76c13e01 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -43,7 +43,6 @@ void GPU_matrix_identity_set(void); void GPU_matrix_scale_1f(float factor); - /* 3D ModelView Matrix */ void GPU_matrix_set(const float m[4][4]); @@ -53,14 +52,25 @@ void GPU_matrix_translate_3f(float x, float y, float z); void GPU_matrix_translate_3fv(const float vec[3]); void GPU_matrix_scale_3f(float x, float y, float z); void GPU_matrix_scale_3fv(const float vec[3]); -void GPU_matrix_rotate_3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */ -void GPU_matrix_rotate_3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */ +void GPU_matrix_rotate_3f(float deg, + float x, + float y, + float z); /* axis of rotation should be a unit vector */ +void GPU_matrix_rotate_3fv(float deg, + const float axis[3]); /* axis of rotation should be a unit vector */ void GPU_matrix_rotate_axis(float deg, char axis); /* TODO: enum for axis? */ -void GPU_matrix_look_at(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ); +void GPU_matrix_look_at(float eyeX, + float eyeY, + float eyeZ, + float centerX, + float centerY, + float centerZ, + float upX, + float upY, + float upZ); /* TODO: variant that takes eye[3], center[3], up[3] */ - /* 2D ModelView Matrix */ void GPU_matrix_translate_2f(float x, float y); @@ -80,19 +90,27 @@ void GPU_matrix_identity_projection_set(void); void GPU_matrix_projection_set(const float m[4][4]); void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far); -void GPU_matrix_frustum_set(float left, float right, float bottom, float top, float near, float far); +void GPU_matrix_frustum_set( + float left, float right, float bottom, float top, float near, float far); void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far); /* 3D Projection between Window and World Space */ -void GPU_matrix_project(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]); -bool GPU_matrix_unproject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]); +void GPU_matrix_project(const float world[3], + const float model[4][4], + const float proj[4][4], + const int view[4], + float win[3]); +bool GPU_matrix_unproject(const float win[3], + const float model[4][4], + const float proj[4][4], + const int view[4], + float world[3]); /* 2D Projection Matrix */ void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top); - /* functions to get matrix values */ const float (*GPU_matrix_model_view_get(float m[4][4]))[4]; const float (*GPU_matrix_projection_get(float m[4][4]))[4]; @@ -101,20 +119,17 @@ const float (*GPU_matrix_model_view_projection_get(float m[4][4]))[4]; const float (*GPU_matrix_normal_get(float m[3][3]))[3]; const float (*GPU_matrix_normal_inverse_get(float m[3][3]))[3]; - /* set uniform values for currently bound shader */ void GPU_matrix_bind(const struct GPUShaderInterface *); bool GPU_matrix_dirty_get(void); /* since last bind */ - /* Python API needs to be able to inspect the stack so errors raise exceptions instead of crashing. */ #ifdef USE_GPU_PY_MATRIX_API int GPU_matrix_stack_level_get_model_view(void); int GPU_matrix_stack_level_get_projection(void); /* static assert ensures this doesn't change! */ -#define GPU_PY_MATRIX_STACK_LEN 31 -#endif /* USE_GPU_PY_MATRIX_API */ - +# define GPU_PY_MATRIX_STACK_LEN 31 +#endif /* USE_GPU_PY_MATRIX_API */ #ifdef __cplusplus } @@ -122,61 +137,66 @@ int GPU_matrix_stack_level_get_projection(void); #ifndef SUPPRESS_GENERIC_MATRIX_API -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) -#define _GPU_MAT3_CONST_CAST(x) (_Generic((x), \ - void *: (const float (*)[3])(x), \ - float *: (const float (*)[3])(x), \ - float [9]: (const float (*)[3])(x), \ - float (*)[4]: (const float (*)[3])(x), \ - float [4][4]: (const float (*)[3])(x), \ - const void *: (const float (*)[3])(x), \ - const float *: (const float (*)[3])(x), \ - const float [9]: (const float (*)[3])(x), \ - const float (*)[3]: (const float (*)[3])(x), \ - const float [3][3]: (const float (*)[3])(x)) \ +# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# define _GPU_MAT3_CONST_CAST(x) \ + (_Generic((x), \ + void *: (const float (*)[3])(x), \ + float *: (const float (*)[3])(x), \ + float [9]: (const float (*)[3])(x), \ + float (*)[4]: (const float (*)[3])(x), \ + float [4][4]: (const float (*)[3])(x), \ + const void *: (const float (*)[3])(x), \ + const float *: (const float (*)[3])(x), \ + const float [9]: (const float (*)[3])(x), \ + const float (*)[3]: (const float (*)[3])(x), \ + const float [3][3]: (const float (*)[3])(x)) \ ) -#define _GPU_MAT3_CAST(x) (_Generic((x), \ - void *: (float (*)[3])(x), \ - float *: (float (*)[3])(x), \ - float [9]: (float (*)[3])(x), \ - float (*)[3]: (float (*)[3])(x), \ - float [3][3]: (float (*)[3])(x)) \ +# define _GPU_MAT3_CAST(x) \ + (_Generic((x), \ + void *: (float (*)[3])(x), \ + float *: (float (*)[3])(x), \ + float [9]: (float (*)[3])(x), \ + float (*)[3]: (float (*)[3])(x), \ + float [3][3]: (float (*)[3])(x)) \ ) -#define _GPU_MAT4_CONST_CAST(x) (_Generic((x), \ - void *: (const float (*)[4])(x), \ - float *: (const float (*)[4])(x), \ - float [16]: (const float (*)[4])(x), \ - float (*)[4]: (const float (*)[4])(x), \ - float [4][4]: (const float (*)[4])(x), \ - const void *: (const float (*)[4])(x), \ - const float *: (const float (*)[4])(x), \ - const float [16]: (const float (*)[4])(x), \ - const float (*)[4]: (const float (*)[4])(x), \ - const float [4][4]: (const float (*)[4])(x)) \ +# define _GPU_MAT4_CONST_CAST(x) \ + (_Generic((x), \ + void *: (const float (*)[4])(x), \ + float *: (const float (*)[4])(x), \ + float [16]: (const float (*)[4])(x), \ + float (*)[4]: (const float (*)[4])(x), \ + float [4][4]: (const float (*)[4])(x), \ + const void *: (const float (*)[4])(x), \ + const float *: (const float (*)[4])(x), \ + const float [16]: (const float (*)[4])(x), \ + const float (*)[4]: (const float (*)[4])(x), \ + const float [4][4]: (const float (*)[4])(x)) \ ) -#define _GPU_MAT4_CAST(x) (_Generic((x), \ - void *: (float (*)[4])(x), \ - float *: (float (*)[4])(x), \ - float [16]: (float (*)[4])(x), \ - float (*)[4]: (float (*)[4])(x), \ - float [4][4]: (float (*)[4])(x)) \ +# define _GPU_MAT4_CAST(x) \ + (_Generic((x), \ + void *: (float (*)[4])(x), \ + float *: (float (*)[4])(x), \ + float [16]: (float (*)[4])(x), \ + float (*)[4]: (float (*)[4])(x), \ + float [4][4]: (float (*)[4])(x)) \ ) -#else -# define _GPU_MAT3_CONST_CAST(x) (const float (*)[3])(x) -# define _GPU_MAT3_CAST(x) (float (*)[3])(x) -# define _GPU_MAT4_CONST_CAST(x) (const float (*)[4])(x) -# define _GPU_MAT4_CAST(x) (float (*)[4])(x) -#endif /* C11 */ +# else +# define _GPU_MAT3_CONST_CAST(x) (const float(*)[3])(x) +# define _GPU_MAT3_CAST(x) (float(*)[3])(x) +# define _GPU_MAT4_CONST_CAST(x) (const float(*)[4])(x) +# define _GPU_MAT4_CAST(x) (float(*)[4])(x) +# endif /* C11 */ /* make matrix inputs generic, to avoid warnings */ -# define GPU_matrix_mul(x) GPU_matrix_mul(_GPU_MAT4_CONST_CAST(x)) -# define GPU_matrix_set(x) GPU_matrix_set(_GPU_MAT4_CONST_CAST(x)) -# define GPU_matrix_projection_set(x) GPU_matrix_projection_set(_GPU_MAT4_CONST_CAST(x)) -# define GPU_matrix_model_view_get(x) GPU_matrix_model_view_get(_GPU_MAT4_CAST(x)) -# define GPU_matrix_projection_get(x) GPU_matrix_projection_get(_GPU_MAT4_CAST(x)) -# define GPU_matrix_model_view_projection_get(x) GPU_matrix_model_view_projection_get(_GPU_MAT4_CAST(x)) -# define GPU_matrix_normal_get(x) GPU_matrix_normal_get(_GPU_MAT3_CAST(x)) -# define GPU_matrix_normal_inverse_get(x) GPU_matrix_normal_inverse_get(_GPU_MAT3_CAST(x)) +# define GPU_matrix_mul(x) GPU_matrix_mul(_GPU_MAT4_CONST_CAST(x)) +# define GPU_matrix_set(x) GPU_matrix_set(_GPU_MAT4_CONST_CAST(x)) +# define GPU_matrix_projection_set(x) GPU_matrix_projection_set(_GPU_MAT4_CONST_CAST(x)) +# define GPU_matrix_model_view_get(x) GPU_matrix_model_view_get(_GPU_MAT4_CAST(x)) +# define GPU_matrix_projection_get(x) GPU_matrix_projection_get(_GPU_MAT4_CAST(x)) +# define GPU_matrix_model_view_projection_get(x) \ + GPU_matrix_model_view_projection_get(_GPU_MAT4_CAST(x)) +# define GPU_matrix_normal_get(x) GPU_matrix_normal_get(_GPU_MAT3_CAST(x)) +# define GPU_matrix_normal_inverse_get(x) GPU_matrix_normal_inverse_get(_GPU_MAT3_CAST(x)) #endif /* SUPPRESS_GENERIC_MATRIX_API */ #endif /* __GPU_MATRIX_H__ */ diff --git a/source/blender/gpu/GPU_primitive.h b/source/blender/gpu/GPU_primitive.h index fdb6f380f3b..0f4becc6bff 100644 --- a/source/blender/gpu/GPU_primitive.h +++ b/source/blender/gpu/GPU_primitive.h @@ -29,28 +29,28 @@ #include "GPU_common.h" typedef enum { - GPU_PRIM_POINTS, - GPU_PRIM_LINES, - GPU_PRIM_TRIS, - GPU_PRIM_LINE_STRIP, - GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */ - GPU_PRIM_TRI_STRIP, - GPU_PRIM_TRI_FAN, - - GPU_PRIM_LINES_ADJ, - GPU_PRIM_TRIS_ADJ, - GPU_PRIM_LINE_STRIP_ADJ, - - GPU_PRIM_NONE, + GPU_PRIM_POINTS, + GPU_PRIM_LINES, + GPU_PRIM_TRIS, + GPU_PRIM_LINE_STRIP, + GPU_PRIM_LINE_LOOP, /* GL has this, Vulkan does not */ + GPU_PRIM_TRI_STRIP, + GPU_PRIM_TRI_FAN, + + GPU_PRIM_LINES_ADJ, + GPU_PRIM_TRIS_ADJ, + GPU_PRIM_LINE_STRIP_ADJ, + + GPU_PRIM_NONE, } GPUPrimType; /* what types of primitives does each shader expect? */ typedef enum { - GPU_PRIM_CLASS_NONE = 0, - GPU_PRIM_CLASS_POINT = (1 << 0), - GPU_PRIM_CLASS_LINE = (1 << 1), - GPU_PRIM_CLASS_SURFACE = (1 << 2), - GPU_PRIM_CLASS_ANY = GPU_PRIM_CLASS_POINT | GPU_PRIM_CLASS_LINE | GPU_PRIM_CLASS_SURFACE, + GPU_PRIM_CLASS_NONE = 0, + GPU_PRIM_CLASS_POINT = (1 << 0), + GPU_PRIM_CLASS_LINE = (1 << 1), + GPU_PRIM_CLASS_SURFACE = (1 << 2), + GPU_PRIM_CLASS_ANY = GPU_PRIM_CLASS_POINT | GPU_PRIM_CLASS_LINE | GPU_PRIM_CLASS_SURFACE, } GPUPrimClass; GPUPrimClass GPU_primtype_class(GPUPrimType); diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h index b9dbeeccf30..c15d1b17448 100644 --- a/source/blender/gpu/GPU_select.h +++ b/source/blender/gpu/GPU_select.h @@ -30,16 +30,17 @@ struct rcti; /* flags for mode of operation */ enum { - GPU_SELECT_ALL = 1, - /* gpu_select_query */ - GPU_SELECT_NEAREST_FIRST_PASS = 2, - GPU_SELECT_NEAREST_SECOND_PASS = 3, - /* gpu_select_pick */ - GPU_SELECT_PICK_ALL = 4, - GPU_SELECT_PICK_NEAREST = 5, + GPU_SELECT_ALL = 1, + /* gpu_select_query */ + GPU_SELECT_NEAREST_FIRST_PASS = 2, + GPU_SELECT_NEAREST_SECOND_PASS = 3, + /* gpu_select_pick */ + GPU_SELECT_PICK_ALL = 4, + GPU_SELECT_PICK_NEAREST = 5, }; -void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits); +void GPU_select_begin( + unsigned int *buffer, unsigned int bufsize, const struct rcti *input, char mode, int oldhits); bool GPU_select_load_id(unsigned int id); void GPU_select_finalize(void); unsigned int GPU_select_end(void); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 03cb21eab80..d7addeb87b4 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -37,34 +37,34 @@ struct GPUUniformBuffer; * - must call texture bind before setting a texture as uniform! */ typedef enum eGPUShaderTFBType { - GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */ - GPU_SHADER_TFB_POINTS = 1, - GPU_SHADER_TFB_LINES = 2, - GPU_SHADER_TFB_TRIANGLES = 3, + GPU_SHADER_TFB_NONE = 0, /* Transform feedback unsupported. */ + GPU_SHADER_TFB_POINTS = 1, + GPU_SHADER_TFB_LINES = 2, + GPU_SHADER_TFB_TRIANGLES = 3, } eGPUShaderTFBType; -GPUShader *GPU_shader_create( - const char *vertexcode, - const char *fragcode, - const char *geocode, - const char *libcode, - const char *defines, - const char *shader_name); -GPUShader *GPU_shader_create_ex( - const char *vertexcode, - const char *fragcode, - const char *geocode, - const char *libcode, - const char *defines, - const eGPUShaderTFBType tf_type, - const char **tf_names, - const int tf_count, - const char *shader_name); -struct GPU_ShaderCreateFromArray_Params { const char **vert, **geom, **frag, **defs; }; +GPUShader *GPU_shader_create(const char *vertexcode, + const char *fragcode, + const char *geocode, + const char *libcode, + const char *defines, + const char *shader_name); +GPUShader *GPU_shader_create_ex(const char *vertexcode, + const char *fragcode, + const char *geocode, + const char *libcode, + const char *defines, + const eGPUShaderTFBType tf_type, + const char **tf_names, + const int tf_count, + const char *shader_name); +struct GPU_ShaderCreateFromArray_Params { + const char **vert, **geom, **frag, **defs; +}; struct GPUShader *GPU_shader_create_from_arrays_impl( - const struct GPU_ShaderCreateFromArray_Params *params); + const struct GPU_ShaderCreateFromArray_Params *params); #define GPU_shader_create_from_arrays(...) \ - GPU_shader_create_from_arrays_impl(&(const struct GPU_ShaderCreateFromArray_Params)__VA_ARGS__) + GPU_shader_create_from_arrays_impl(&(const struct GPU_ShaderCreateFromArray_Params)__VA_ARGS__) void GPU_shader_free(GPUShader *shader); @@ -84,11 +84,9 @@ int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name); int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin); 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); + 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); + 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); @@ -99,276 +97,276 @@ int GPU_shader_get_attribute(GPUShader *shader, const char *name); /* Builtin/Non-generated shaders */ typedef enum eGPUBuiltinShader { - /* specialized drawing */ - GPU_SHADER_TEXT, - GPU_SHADER_TEXT_SIMPLE, - GPU_SHADER_EDGES_FRONT_BACK_PERSP, - GPU_SHADER_EDGES_FRONT_BACK_ORTHO, - GPU_SHADER_EDGES_OVERLAY_SIMPLE, - GPU_SHADER_EDGES_OVERLAY, - GPU_SHADER_KEYFRAME_DIAMOND, - GPU_SHADER_SIMPLE_LIGHTING, - GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR, - GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR, - GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA, + /* specialized drawing */ + GPU_SHADER_TEXT, + GPU_SHADER_TEXT_SIMPLE, + GPU_SHADER_EDGES_FRONT_BACK_PERSP, + GPU_SHADER_EDGES_FRONT_BACK_ORTHO, + GPU_SHADER_EDGES_OVERLAY_SIMPLE, + GPU_SHADER_EDGES_OVERLAY, + GPU_SHADER_KEYFRAME_DIAMOND, + GPU_SHADER_SIMPLE_LIGHTING, + GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR, + GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR, + GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA, - /* for simple 2D drawing */ - /** - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_UNIFORM_COLOR, - /** - * Take a 2D position and color for each vertex without color interpolation. - * - * \param color: in vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_FLAT_COLOR, - /** - * Take a 2D position and color for each vertex with linear interpolation in window space. - * - * \param color: in vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_SMOOTH_COLOR, - GPU_SHADER_2D_SMOOTH_COLOR_DITHER, - GPU_SHADER_2D_IMAGE, - GPU_SHADER_2D_IMAGE_COLOR, - GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, - GPU_SHADER_2D_IMAGE_ALPHA_COLOR, - GPU_SHADER_2D_IMAGE_ALPHA, - GPU_SHADER_2D_IMAGE_RECT_COLOR, - GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_2, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_4, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_8, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_16, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST, - GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST, - GPU_SHADER_2D_CHECKER, - GPU_SHADER_2D_DIAG_STRIPES, - /* for simple 3D drawing */ - /** - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_UNIFORM_COLOR, - /* Sets Z-depth to 1.0 (draw onto background). */ - GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND, - GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, - /** - * Take a 3D position and color for each vertex without color interpolation. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_FLAT_COLOR, - /** - * Take a 3D position and color for each vertex with perspective correct interpolation. - * - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_SMOOTH_COLOR, - /** - * Take a 3D position for each vertex and output only depth. - * - * \param pos: in vec3 - */ - GPU_SHADER_3D_DEPTH_ONLY, - GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, - /* basic image drawing */ - GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB, - GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, - GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR, - /** - * Draw texture with alpha. Take a 3D position and a 2D texture coordinate for each vertex. - * - * \param alpha: uniform float - * \param image: uniform sampler2D - * \param texCoord: in vec2 - * \param pos: in vec3 - */ - GPU_SHADER_3D_IMAGE_MODULATE_ALPHA, - /** - * Draw linearized depth texture relate to near and far distances. - * Take a 3D position and a 2D texture coordinate for each vertex. - * - * \param znear: uniform float - * \param zfar: uniform float - * \param image: uniform sampler2D - * \param texCoord: in vec2 - * \param pos: in vec3 - */ - GPU_SHADER_3D_IMAGE_DEPTH, - GPU_SHADER_3D_IMAGE_DEPTH_COPY, - /* stereo 3d */ - GPU_SHADER_2D_IMAGE_INTERLACE, - /* points */ - /** - * Draw round points with a hardcoded size. - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR, - /** - * Draw round points with a constant size. - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param size: uniform float - * \param color: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - /** - * Draw round points with a constant size and an outline. - * Take a single color for all the vertices and a 2D position for each vertex. - * - * \param size: uniform float - * \param outlineWidth: uniform float - * \param color: uniform vec4 - * \param outlineColor: uniform vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, - /** - * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex. - * - * \param size: uniform float - * \param outlineWidth: uniform float - * \param outlineColor: uniform vec4 - * \param color: in vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA, - /** - * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex. - * - * \param size: in float - * \param color: in vec4 - * \param pos: in vec2 - */ - GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR, - /** - * Draw round points with a hardcoded size. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR, - /** - * Draw round points with a hardcoded size. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR, - /** - * Draw round points with a constant size. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param size: uniform float - * \param color: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - /** - * Draw round points with a constant size and an outline. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param size: uniform float - * \param outlineWidth: uniform float - * \param color: uniform vec4 - * \param outlineColor: uniform vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, - /** - * Draw round points with a constant size and an outline. - * Take a single color for all the vertices and a 3D position for each vertex. - * - * \param color: uniform vec4 - * \param size: in float - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR, - /** - * Draw round points with a constant size and an outline. Take a 3D position and a color for each vertex. - * - * \param size: in float - * \param color: in vec4 - * \param pos: in vec3 - */ - GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, - /* lines */ - GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR, - GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, - /* light drawing */ - GPU_SHADER_3D_GROUNDPOINT, - GPU_SHADER_3D_GROUNDLINE, - GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, - /* bone drawing */ - GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR, - GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR, - /* camera drawing */ - GPU_SHADER_CAMERA, - /* distance in front of objects */ - GPU_SHADER_DISTANCE_LINES, - /* axis name */ - GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS, - GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, - /* instance */ - GPU_SHADER_INSTANCE_UNIFORM_COLOR, - GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE, /* Uniformly scaled */ - GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */ - GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, - GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, - /* grease pencil drawing */ - GPU_SHADER_GPENCIL_STROKE, - GPU_SHADER_GPENCIL_FILL, - /* specialized for widget drawing */ - GPU_SHADER_2D_AREA_EDGES, - GPU_SHADER_2D_WIDGET_BASE, - GPU_SHADER_2D_WIDGET_BASE_INST, - GPU_SHADER_2D_WIDGET_SHADOW, - GPU_SHADER_2D_NODELINK, - GPU_SHADER_2D_NODELINK_INST, - /* specialized for edituv drawing */ - GPU_SHADER_2D_UV_UNIFORM_COLOR, - GPU_SHADER_2D_UV_VERTS, - GPU_SHADER_2D_UV_FACEDOTS, - GPU_SHADER_2D_UV_EDGES, - GPU_SHADER_2D_UV_EDGES_SMOOTH, - GPU_SHADER_2D_UV_FACES, - GPU_SHADER_2D_UV_FACES_STRETCH_AREA, - GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE, - /* Selection */ - GPU_SHADER_3D_FLAT_SELECT_ID, - GPU_SHADER_3D_UNIFORM_SELECT_ID, + /* for simple 2D drawing */ + /** + * Take a single color for all the vertices and a 2D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_UNIFORM_COLOR, + /** + * Take a 2D position and color for each vertex without color interpolation. + * + * \param color: in vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_FLAT_COLOR, + /** + * Take a 2D position and color for each vertex with linear interpolation in window space. + * + * \param color: in vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_SMOOTH_COLOR, + GPU_SHADER_2D_SMOOTH_COLOR_DITHER, + GPU_SHADER_2D_IMAGE, + GPU_SHADER_2D_IMAGE_COLOR, + GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, + GPU_SHADER_2D_IMAGE_ALPHA_COLOR, + GPU_SHADER_2D_IMAGE_ALPHA, + GPU_SHADER_2D_IMAGE_RECT_COLOR, + GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_2, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_4, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_8, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_16, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST, + GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST, + GPU_SHADER_2D_CHECKER, + GPU_SHADER_2D_DIAG_STRIPES, + /* for simple 3D drawing */ + /** + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_UNIFORM_COLOR, + /* Sets Z-depth to 1.0 (draw onto background). */ + GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND, + GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, + /** + * Take a 3D position and color for each vertex without color interpolation. + * + * \param color: in vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_FLAT_COLOR, + /** + * Take a 3D position and color for each vertex with perspective correct interpolation. + * + * \param color: in vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_SMOOTH_COLOR, + /** + * Take a 3D position for each vertex and output only depth. + * + * \param pos: in vec3 + */ + GPU_SHADER_3D_DEPTH_ONLY, + GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, + /* basic image drawing */ + GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB, + GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, + GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR, + /** + * Draw texture with alpha. Take a 3D position and a 2D texture coordinate for each vertex. + * + * \param alpha: uniform float + * \param image: uniform sampler2D + * \param texCoord: in vec2 + * \param pos: in vec3 + */ + GPU_SHADER_3D_IMAGE_MODULATE_ALPHA, + /** + * Draw linearized depth texture relate to near and far distances. + * Take a 3D position and a 2D texture coordinate for each vertex. + * + * \param znear: uniform float + * \param zfar: uniform float + * \param image: uniform sampler2D + * \param texCoord: in vec2 + * \param pos: in vec3 + */ + GPU_SHADER_3D_IMAGE_DEPTH, + GPU_SHADER_3D_IMAGE_DEPTH_COPY, + /* stereo 3d */ + GPU_SHADER_2D_IMAGE_INTERLACE, + /* points */ + /** + * Draw round points with a hardcoded size. + * Take a single color for all the vertices and a 2D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR, + /** + * Draw round points with a constant size. + * Take a single color for all the vertices and a 2D position for each vertex. + * + * \param size: uniform float + * \param color: uniform vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + /** + * Draw round points with a constant size and an outline. + * Take a single color for all the vertices and a 2D position for each vertex. + * + * \param size: uniform float + * \param outlineWidth: uniform float + * \param color: uniform vec4 + * \param outlineColor: uniform vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, + /** + * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex. + * + * \param size: uniform float + * \param outlineWidth: uniform float + * \param outlineColor: uniform vec4 + * \param color: in vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA, + /** + * Draw round points with a constant size and an outline. Take a 2D position and a color for each vertex. + * + * \param size: in float + * \param color: in vec4 + * \param pos: in vec2 + */ + GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR, + /** + * Draw round points with a hardcoded size. + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR, + /** + * Draw round points with a hardcoded size. + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param color: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR, + /** + * Draw round points with a constant size. + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param size: uniform float + * \param color: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + /** + * Draw round points with a constant size and an outline. + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param size: uniform float + * \param outlineWidth: uniform float + * \param color: uniform vec4 + * \param outlineColor: uniform vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, + /** + * Draw round points with a constant size and an outline. + * Take a single color for all the vertices and a 3D position for each vertex. + * + * \param color: uniform vec4 + * \param size: in float + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR, + /** + * Draw round points with a constant size and an outline. Take a 3D position and a color for each vertex. + * + * \param size: in float + * \param color: in vec4 + * \param pos: in vec3 + */ + GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, + /* lines */ + GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR, + GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR, + /* light drawing */ + GPU_SHADER_3D_GROUNDPOINT, + GPU_SHADER_3D_GROUNDLINE, + GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, + /* bone drawing */ + GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR, + GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR, + /* camera drawing */ + GPU_SHADER_CAMERA, + /* distance in front of objects */ + GPU_SHADER_DISTANCE_LINES, + /* axis name */ + GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS, + GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, + /* instance */ + GPU_SHADER_INSTANCE_UNIFORM_COLOR, + GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE, /* Uniformly scaled */ + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, /* Uniformly scaled */ + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, + GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, + /* grease pencil drawing */ + GPU_SHADER_GPENCIL_STROKE, + GPU_SHADER_GPENCIL_FILL, + /* specialized for widget drawing */ + GPU_SHADER_2D_AREA_EDGES, + GPU_SHADER_2D_WIDGET_BASE, + GPU_SHADER_2D_WIDGET_BASE_INST, + GPU_SHADER_2D_WIDGET_SHADOW, + GPU_SHADER_2D_NODELINK, + GPU_SHADER_2D_NODELINK_INST, + /* specialized for edituv drawing */ + GPU_SHADER_2D_UV_UNIFORM_COLOR, + GPU_SHADER_2D_UV_VERTS, + GPU_SHADER_2D_UV_FACEDOTS, + GPU_SHADER_2D_UV_EDGES, + GPU_SHADER_2D_UV_EDGES_SMOOTH, + GPU_SHADER_2D_UV_FACES, + GPU_SHADER_2D_UV_FACES_STRETCH_AREA, + GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE, + /* Selection */ + GPU_SHADER_3D_FLAT_SELECT_ID, + GPU_SHADER_3D_UNIFORM_SELECT_ID, } eGPUBuiltinShader; #define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_UNIFORM_SELECT_ID + 1) /** Support multiple configurations. */ typedef enum eGPUShaderConfig { - GPU_SHADER_CFG_DEFAULT = 0, - GPU_SHADER_CFG_CLIPPED = 1, + GPU_SHADER_CFG_DEFAULT = 0, + GPU_SHADER_CFG_CLIPPED = 1, } eGPUShaderConfig; #define GPU_SHADER_CFG_LEN (GPU_SHADER_CFG_CLIPPED + 1) typedef struct GPUShaderConfigData { - const char *lib; - const char *def; + const char *lib; + const char *def; } GPUShaderConfigData; /* gpu_shader.c */ extern const GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN]; @@ -378,20 +376,20 @@ extern const GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN]; * - `gpu_shader_image_rect_interlace_frag.glsl` */ typedef enum eGPUInterlaceShader { - GPU_SHADER_INTERLACE_ROW = 0, - GPU_SHADER_INTERLACE_COLUMN = 1, - GPU_SHADER_INTERLACE_CHECKER = 2, + GPU_SHADER_INTERLACE_ROW = 0, + GPU_SHADER_INTERLACE_COLUMN = 1, + GPU_SHADER_INTERLACE_CHECKER = 2, } eGPUInterlaceShader; -GPUShader *GPU_shader_get_builtin_shader_with_config( - eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg); -GPUShader *GPU_shader_get_builtin_shader( - eGPUBuiltinShader shader); +GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, + eGPUShaderConfig sh_cfg); +GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader); -void GPU_shader_get_builtin_shader_code( - eGPUBuiltinShader shader, - const char **r_vert, const char **r_frag, - const char **r_geom, const char **r_defines); +void GPU_shader_get_builtin_shader_code(eGPUBuiltinShader shader, + const char **r_vert, + const char **r_frag, + const char **r_geom, + const char **r_defines); void GPU_shader_free_builtin_shaders(void); @@ -400,20 +398,20 @@ void GPU_shader_free_builtin_shaders(void); #define GPU_MAX_ATTR 32 typedef struct GPUVertAttrLayers { - struct { - int type; - int glindex; - int glinfoindoex; - int gltexco; - int attr_id; - char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ - } layer[GPU_MAX_ATTR]; + struct { + int type; + int glindex; + int glinfoindoex; + int gltexco; + int attr_id; + char name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + } layer[GPU_MAX_ATTR]; - int totlayer; + int totlayer; } GPUVertAttrLayers; #ifdef __cplusplus } #endif -#endif /* __GPU_SHADER_H__ */ +#endif /* __GPU_SHADER_H__ */ diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h index ee2091c7cec..ace8832303b 100644 --- a/source/blender/gpu/GPU_shader_interface.h +++ b/source/blender/gpu/GPU_shader_interface.h @@ -29,71 +29,73 @@ #include "GPU_common.h" typedef enum { - GPU_UNIFORM_NONE = 0, /* uninitialized/unknown */ - - GPU_UNIFORM_MODEL, /* mat4 ModelMatrix */ - GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */ - GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */ - GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */ - GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */ - GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */ - - GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */ - GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */ - GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */ - GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */ - GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ - - GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ - GPU_UNIFORM_NORMAL_INV, /* mat3 NormalMatrixInverse */ - GPU_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */ - GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */ - GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ - - GPU_UNIFORM_COLOR, /* vec4 color */ - GPU_UNIFORM_EYE, /* vec3 eye */ - GPU_UNIFORM_CALLID, /* int callId */ - GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ - - GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */ - - GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */ + GPU_UNIFORM_NONE = 0, /* uninitialized/unknown */ + + GPU_UNIFORM_MODEL, /* mat4 ModelMatrix */ + GPU_UNIFORM_VIEW, /* mat4 ViewMatrix */ + GPU_UNIFORM_MODELVIEW, /* mat4 ModelViewMatrix */ + GPU_UNIFORM_PROJECTION, /* mat4 ProjectionMatrix */ + GPU_UNIFORM_VIEWPROJECTION, /* mat4 ViewProjectionMatrix */ + GPU_UNIFORM_MVP, /* mat4 ModelViewProjectionMatrix */ + + GPU_UNIFORM_MODEL_INV, /* mat4 ModelMatrixInverse */ + GPU_UNIFORM_VIEW_INV, /* mat4 ViewMatrixInverse */ + GPU_UNIFORM_MODELVIEW_INV, /* mat4 ModelViewMatrixInverse */ + GPU_UNIFORM_PROJECTION_INV, /* mat4 ProjectionMatrixInverse */ + GPU_UNIFORM_VIEWPROJECTION_INV, /* mat4 ViewProjectionMatrixInverse */ + + GPU_UNIFORM_NORMAL, /* mat3 NormalMatrix */ + GPU_UNIFORM_NORMAL_INV, /* mat3 NormalMatrixInverse */ + GPU_UNIFORM_WORLDNORMAL, /* mat3 WorldNormalMatrix */ + GPU_UNIFORM_CAMERATEXCO, /* vec4 CameraTexCoFactors */ + GPU_UNIFORM_ORCO, /* vec3 OrcoTexCoFactors[] */ + + GPU_UNIFORM_COLOR, /* vec4 color */ + GPU_UNIFORM_EYE, /* vec3 eye */ + GPU_UNIFORM_CALLID, /* int callId */ + GPU_UNIFORM_OBJECT_INFO, /* vec3 objectInfo */ + + GPU_UNIFORM_CUSTOM, /* custom uniform, not one of the above built-ins */ + + GPU_NUM_UNIFORMS, /* Special value, denotes number of builtin uniforms. */ } GPUUniformBuiltin; typedef struct GPUShaderInput { - struct GPUShaderInput *next; - uint32_t name_offset; - uint name_hash; - /** Only for uniform inputs. */ - GPUUniformBuiltin builtin_type; - /** Only for attribute inputs. */ - uint32_t gl_type; - /** Only for attribute inputs. */ - int32_t size; - int32_t location; + struct GPUShaderInput *next; + uint32_t name_offset; + uint name_hash; + /** Only for uniform inputs. */ + GPUUniformBuiltin builtin_type; + /** Only for attribute inputs. */ + uint32_t gl_type; + /** Only for attribute inputs. */ + int32_t size; + int32_t location; } GPUShaderInput; #define GPU_NUM_SHADERINTERFACE_BUCKETS 257 #define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16 typedef struct GPUShaderInterface { - int32_t program; - uint32_t name_buffer_offset; - GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; - GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS]; - char *name_buffer; - struct GPUBatch **batches; /* references to batches using this interface */ - uint batches_len; + int32_t program; + uint32_t name_buffer_offset; + GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; + GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; + GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]; + GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS]; + char *name_buffer; + struct GPUBatch **batches; /* references to batches using this interface */ + uint batches_len; } GPUShaderInterface; GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id); void GPU_shaderinterface_discard(GPUShaderInterface *); const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name); -const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *, const char *name); -const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *, GPUUniformBuiltin); +const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *, + const char *name); +const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *, + GPUUniformBuiltin); const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name); const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *, const char *name); diff --git a/source/blender/gpu/GPU_state.h b/source/blender/gpu/GPU_state.h index 23682815e4c..48c700adaed 100644 --- a/source/blender/gpu/GPU_state.h +++ b/source/blender/gpu/GPU_state.h @@ -23,24 +23,25 @@ /* These map directly to the GL_ blend functions, to minimize API add as needed*/ typedef enum eGPUBlendFunction { - GPU_ONE, - GPU_SRC_ALPHA, - GPU_ONE_MINUS_SRC_ALPHA, - GPU_DST_COLOR, - GPU_ZERO, + GPU_ONE, + GPU_SRC_ALPHA, + GPU_ONE_MINUS_SRC_ALPHA, + GPU_DST_COLOR, + GPU_ZERO, } eGPUBlendFunction; /* These map directly to the GL_ filter functions, to minimize API add as needed*/ typedef enum eGPUFilterFunction { - GPU_NEAREST, - GPU_LINEAR, + GPU_NEAREST, + GPU_LINEAR, } eGPUFilterFunction; void GPU_blend(bool enable); void GPU_blend_set_func(eGPUBlendFunction sfactor, eGPUBlendFunction dfactor); -void GPU_blend_set_func_separate( - eGPUBlendFunction src_rgb, eGPUBlendFunction dst_rgb, - eGPUBlendFunction src_alpha, eGPUBlendFunction dst_alpha); +void GPU_blend_set_func_separate(eGPUBlendFunction src_rgb, + eGPUBlendFunction dst_rgb, + eGPUBlendFunction src_alpha, + eGPUBlendFunction dst_alpha); void GPU_depth_range(float near, float far); void GPU_depth_test(bool enable); bool GPU_depth_test_enabled(void); @@ -57,4 +58,4 @@ void GPU_viewport_size_get_i(int coords[4]); void GPU_flush(void); void GPU_finish(void); -#endif /* __GPU_STATE_H__ */ +#endif /* __GPU_STATE_H__ */ diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index bd7ac508163..3527398a396 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -57,138 +57,162 @@ typedef struct GPUTexture GPUTexture; * are part of the OpenGL 3.3 core * specification. */ typedef enum eGPUTextureFormat { - /* Formats texture & renderbuffer */ - GPU_RGBA8UI, - GPU_RGBA8I, - GPU_RGBA8, - GPU_RGBA32UI, - GPU_RGBA32I, - GPU_RGBA32F, - GPU_RGBA16UI, - GPU_RGBA16I, - GPU_RGBA16F, - GPU_RGBA16, - GPU_RG8UI, - GPU_RG8I, - GPU_RG8, - GPU_RG32UI, - GPU_RG32I, - GPU_RG32F, - GPU_RG16UI, - GPU_RG16I, - GPU_RG16F, - GPU_RG16, - GPU_R8UI, - GPU_R8I, - GPU_R8, - GPU_R32UI, - GPU_R32I, - GPU_R32F, - GPU_R16UI, - GPU_R16I, - GPU_R16F, - GPU_R16, /* Max texture buffer format. */ - - /* Special formats texture & renderbuffer */ + /* Formats texture & renderbuffer */ + GPU_RGBA8UI, + GPU_RGBA8I, + GPU_RGBA8, + GPU_RGBA32UI, + GPU_RGBA32I, + GPU_RGBA32F, + GPU_RGBA16UI, + GPU_RGBA16I, + GPU_RGBA16F, + GPU_RGBA16, + GPU_RG8UI, + GPU_RG8I, + GPU_RG8, + GPU_RG32UI, + GPU_RG32I, + GPU_RG32F, + GPU_RG16UI, + GPU_RG16I, + GPU_RG16F, + GPU_RG16, + GPU_R8UI, + GPU_R8I, + GPU_R8, + GPU_R32UI, + GPU_R32I, + GPU_R32F, + GPU_R16UI, + GPU_R16I, + GPU_R16F, + GPU_R16, /* Max texture buffer format. */ + +/* Special formats texture & renderbuffer */ #if 0 - GPU_RGB10_A2, - GPU_RGB10_A2UI, + GPU_RGB10_A2, + GPU_RGB10_A2UI, #endif - GPU_R11F_G11F_B10F, - GPU_DEPTH32F_STENCIL8, - GPU_DEPTH24_STENCIL8, + GPU_R11F_G11F_B10F, + GPU_DEPTH32F_STENCIL8, + GPU_DEPTH24_STENCIL8, - /* Texture only format */ - GPU_RGB16F, + /* Texture only format */ + GPU_RGB16F, #if 0 - GPU_RGBA16_SNORM, - GPU_RGBA8_SNORM, - GPU_RGB32F, - GPU_RGB32I, - GPU_RGB32UI, - GPU_RGB16_SNORM, - GPU_RGB16I, - GPU_RGB16UI, - GPU_RGB16, - GPU_RGB8_SNORM, - GPU_RGB8, - GPU_RGB8I, - GPU_RGB8UI, - GPU_RG16_SNORM, - GPU_RG8_SNORM, - GPU_R16_SNORM, - GPU_R8_SNORM, + GPU_RGBA16_SNORM, + GPU_RGBA8_SNORM, + GPU_RGB32F, + GPU_RGB32I, + GPU_RGB32UI, + GPU_RGB16_SNORM, + GPU_RGB16I, + GPU_RGB16UI, + GPU_RGB16, + GPU_RGB8_SNORM, + GPU_RGB8, + GPU_RGB8I, + GPU_RGB8UI, + GPU_RG16_SNORM, + GPU_RG8_SNORM, + GPU_R16_SNORM, + GPU_R8_SNORM, #endif - /* Special formats texture only */ +/* Special formats texture only */ #if 0 - GPU_SRGB8_A8, - GPU_SRGB8, - GPU_RGB9_E5, - GPU_COMPRESSED_RG_RGTC2, - GPU_COMPRESSED_SIGNED_RG_RGTC2, - GPU_COMPRESSED_RED_RGTC1, - GPU_COMPRESSED_SIGNED_RED_RGTC1, + GPU_SRGB8_A8, + GPU_SRGB8, + GPU_RGB9_E5, + GPU_COMPRESSED_RG_RGTC2, + GPU_COMPRESSED_SIGNED_RG_RGTC2, + GPU_COMPRESSED_RED_RGTC1, + GPU_COMPRESSED_SIGNED_RED_RGTC1, #endif - /* Depth Formats */ - GPU_DEPTH_COMPONENT32F, - GPU_DEPTH_COMPONENT24, - GPU_DEPTH_COMPONENT16, + /* Depth Formats */ + GPU_DEPTH_COMPONENT32F, + GPU_DEPTH_COMPONENT24, + GPU_DEPTH_COMPONENT16, } eGPUTextureFormat; typedef enum eGPUDataFormat { - GPU_DATA_FLOAT, - GPU_DATA_INT, - GPU_DATA_UNSIGNED_INT, - GPU_DATA_UNSIGNED_BYTE, - GPU_DATA_UNSIGNED_INT_24_8, - GPU_DATA_10_11_11_REV, + GPU_DATA_FLOAT, + GPU_DATA_INT, + GPU_DATA_UNSIGNED_INT, + GPU_DATA_UNSIGNED_BYTE, + GPU_DATA_UNSIGNED_INT_24_8, + GPU_DATA_10_11_11_REV, } eGPUDataFormat; unsigned int GPU_texture_memory_usage_get(void); /* TODO make it static function again. (create function with eGPUDataFormat exposed) */ -GPUTexture *GPU_texture_create_nD( - int w, int h, int d, int n, const void *pixels, - eGPUTextureFormat tex_format, eGPUDataFormat gpu_data_format, int samples, - const bool can_rescale, char err_out[256]); +GPUTexture *GPU_texture_create_nD(int w, + int h, + int d, + int n, + const void *pixels, + eGPUTextureFormat tex_format, + eGPUDataFormat gpu_data_format, + int samples, + const bool can_rescale, + char err_out[256]); -GPUTexture *GPU_texture_create_1d( - int w, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_1d(int w, + eGPUTextureFormat data_type, + const float *pixels, + char err_out[256]); GPUTexture *GPU_texture_create_1d_array( - int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); + int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_create_2d( - int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_2d_multisample( - int w, int h, eGPUTextureFormat data_type, const float *pixels, int samples, char err_out[256]); + int w, int h, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_2d_multisample(int w, + int h, + eGPUTextureFormat data_type, + const float *pixels, + int samples, + char err_out[256]); GPUTexture *GPU_texture_create_2d_array( - int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); + int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_create_3d( - int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_cube( - int w, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); -GPUTexture *GPU_texture_create_from_vertbuf( - struct GPUVertBuf *vert); -GPUTexture *GPU_texture_create_buffer( - eGPUTextureFormat data_type, const uint buffer); + int w, int h, int d, eGPUTextureFormat data_type, const float *pixels, char err_out[256]); +GPUTexture *GPU_texture_create_cube(int w, + eGPUTextureFormat data_type, + const float *pixels, + char err_out[256]); +GPUTexture *GPU_texture_create_from_vertbuf(struct GPUVertBuf *vert); +GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat data_type, const uint buffer); GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode); -GPUTexture *GPU_texture_from_blender( - struct Image *ima, struct ImageUser *iuser, int textarget, bool is_data); +GPUTexture *GPU_texture_from_blender(struct Image *ima, + struct ImageUser *iuser, + int textarget, + bool is_data); GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap); -void GPU_texture_add_mipmap(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl, const void *pixels); +void GPU_texture_add_mipmap(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + int miplvl, + const void *pixels); void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels); -void GPU_texture_update_sub( - GPUTexture *tex, eGPUDataFormat gpu_data_format, const void *pixels, - int offset_x, int offset_y, int offset_z, int width, int height, int depth); +void GPU_texture_update_sub(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + const void *pixels, + int offset_x, + int offset_y, + int offset_z, + int width, + int height, + int depth); void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl); -void GPU_texture_read_rect( - GPUTexture *tex, eGPUDataFormat gpu_data_format, - const struct rcti *rect, void *r_buf); +void GPU_texture_read_rect(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + const struct rcti *rect, + void *r_buf); void GPU_invalid_tex_init(void); void GPU_invalid_tex_bind(int mode); @@ -206,7 +230,9 @@ void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare); void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter); void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter); void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat); -void GPU_texture_filters(GPUTexture *tex, eGPUFilterFunction min_filter, eGPUFilterFunction mag_filter); +void GPU_texture_filters(GPUTexture *tex, + eGPUFilterFunction min_filter, + eGPUFilterFunction mag_filter); void GPU_texture_attach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb, int attachment); int GPU_texture_detach_framebuffer(GPUTexture *tex, struct GPUFrameBuffer *fb); @@ -229,4 +255,4 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size); } #endif -#endif /* __GPU_TEXTURE_H__ */ +#endif /* __GPU_TEXTURE_H__ */ diff --git a/source/blender/gpu/GPU_uniformbuffer.h b/source/blender/gpu/GPU_uniformbuffer.h index 812a7604142..744bfd932dd 100644 --- a/source/blender/gpu/GPU_uniformbuffer.h +++ b/source/blender/gpu/GPU_uniformbuffer.h @@ -46,4 +46,4 @@ bool GPU_uniformbuffer_is_dirty(GPUUniformBuffer *ubo); #define GPU_UBO_BLOCK_NAME "nodeTree" -#endif /* __GPU_UNIFORMBUFFER_H__ */ +#endif /* __GPU_UNIFORMBUFFER_H__ */ diff --git a/source/blender/gpu/GPU_vertex_buffer.h b/source/blender/gpu/GPU_vertex_buffer.h index c7ef337261f..6d88460964d 100644 --- a/source/blender/gpu/GPU_vertex_buffer.h +++ b/source/blender/gpu/GPU_vertex_buffer.h @@ -40,27 +40,27 @@ /* Is GPUVertBuf always used as part of a GPUBatch? */ typedef enum { - /* can be extended to support more types */ - GPU_USAGE_STREAM, - GPU_USAGE_STATIC, /* do not keep data in memory */ - GPU_USAGE_DYNAMIC, + /* can be extended to support more types */ + GPU_USAGE_STREAM, + GPU_USAGE_STATIC, /* do not keep data in memory */ + GPU_USAGE_DYNAMIC, } GPUUsageType; typedef struct GPUVertBuf { - GPUVertFormat format; - uint vertex_len; /* number of verts we want to draw */ - uint vertex_alloc; /* number of verts data */ - bool dirty; - unsigned char *data; /* NULL indicates data in VRAM (unmapped) */ - uint32_t vbo_id; /* 0 indicates not yet allocated */ - GPUUsageType usage; /* usage hint for GL optimisation */ + GPUVertFormat format; + uint vertex_len; /* number of verts we want to draw */ + uint vertex_alloc; /* number of verts data */ + bool dirty; + unsigned char *data; /* NULL indicates data in VRAM (unmapped) */ + uint32_t vbo_id; /* 0 indicates not yet allocated */ + GPUUsageType usage; /* usage hint for GL optimisation */ } GPUVertBuf; GPUVertBuf *GPU_vertbuf_create(GPUUsageType); GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageType); #define GPU_vertbuf_create_with_format(format) \ - GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC) + GPU_vertbuf_create_with_format_ex(format, GPU_USAGE_STATIC) void GPU_vertbuf_discard(GPUVertBuf *); @@ -68,7 +68,7 @@ void GPU_vertbuf_init(GPUVertBuf *, GPUUsageType); void GPU_vertbuf_init_with_format_ex(GPUVertBuf *, const GPUVertFormat *, GPUUsageType); #define GPU_vertbuf_init_with_format(verts, format) \ - GPU_vertbuf_init_with_format_ex(verts, format, GPU_USAGE_STATIC) + GPU_vertbuf_init_with_format_ex(verts, format, GPU_USAGE_STATIC) uint GPU_vertbuf_size_get(const GPUVertBuf *); void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len); @@ -81,34 +81,36 @@ void GPU_vertbuf_data_len_set(GPUVertBuf *, uint v_len); * should not be a problem. */ void GPU_vertbuf_attr_set(GPUVertBuf *, uint a_idx, uint v_idx, const void *data); -void GPU_vertbuf_attr_fill(GPUVertBuf *, uint a_idx, const void *data); /* tightly packed, non interleaved input data */ +void GPU_vertbuf_attr_fill(GPUVertBuf *, + uint a_idx, + const void *data); /* tightly packed, non interleaved input data */ void GPU_vertbuf_attr_fill_stride(GPUVertBuf *, uint a_idx, uint stride, const void *data); /* For low level access only */ typedef struct GPUVertBufRaw { - uint size; - uint stride; - unsigned char *data; - unsigned char *data_init; + uint size; + uint stride; + unsigned char *data; + unsigned char *data_init; #if TRUST_NO_ONE - /* Only for overflow check */ - unsigned char *_data_end; + /* Only for overflow check */ + unsigned char *_data_end; #endif } GPUVertBufRaw; GPU_INLINE void *GPU_vertbuf_raw_step(GPUVertBufRaw *a) { - unsigned char *data = a->data; - a->data += a->stride; + unsigned char *data = a->data; + a->data += a->stride; #if TRUST_NO_ONE - assert(data < a->_data_end); + assert(data < a->_data_end); #endif - return (void *)data; + return (void *)data; } GPU_INLINE uint GPU_vertbuf_raw_used(GPUVertBufRaw *a) { - return ((a->data - a->data_init) / a->stride); + return ((a->data - a->data_init) / a->stride); } void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *, uint a_idx, GPUVertBufRaw *access); @@ -119,11 +121,12 @@ void GPU_vertbuf_use(GPUVertBuf *); uint GPU_vertbuf_get_memory_usage(void); /* Macros */ -#define GPU_VERTBUF_DISCARD_SAFE(verts) do { \ - if (verts != NULL) { \ - GPU_vertbuf_discard(verts); \ - verts = NULL; \ - } \ -} while (0) +#define GPU_VERTBUF_DISCARD_SAFE(verts) \ + do { \ + if (verts != NULL) { \ + GPU_vertbuf_discard(verts); \ + verts = NULL; \ + } \ + } while (0) #endif /* __GPU_VERTEX_BUFFER_H__ */ diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h index ce70430dcca..021def5b265 100644 --- a/source/blender/gpu/GPU_vertex_format.h +++ b/source/blender/gpu/GPU_vertex_format.h @@ -34,59 +34,59 @@ #define GPU_VERT_ATTR_NAMES_BUF_LEN ((GPU_VERT_ATTR_NAME_AVERAGE_LEN + 1) * GPU_VERT_ATTR_MAX_LEN) typedef enum { - GPU_COMP_I8, - GPU_COMP_U8, - GPU_COMP_I16, - GPU_COMP_U16, - GPU_COMP_I32, - GPU_COMP_U32, + GPU_COMP_I8, + GPU_COMP_U8, + GPU_COMP_I16, + GPU_COMP_U16, + GPU_COMP_I32, + GPU_COMP_U32, - GPU_COMP_F32, + GPU_COMP_F32, - GPU_COMP_I10, + GPU_COMP_I10, } GPUVertCompType; typedef enum { - GPU_FETCH_FLOAT, - GPU_FETCH_INT, - GPU_FETCH_INT_TO_FLOAT_UNIT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */ - GPU_FETCH_INT_TO_FLOAT, /* 127 (any int type) -> 127.0 */ + GPU_FETCH_FLOAT, + GPU_FETCH_INT, + GPU_FETCH_INT_TO_FLOAT_UNIT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */ + GPU_FETCH_INT_TO_FLOAT, /* 127 (any int type) -> 127.0 */ } GPUVertFetchMode; typedef struct GPUVertAttr { - GPUVertFetchMode fetch_mode; - GPUVertCompType comp_type; - uint gl_comp_type; - uint comp_len; /* 1 to 4 or 8 or 12 or 16 */ - uint sz; /* size in bytes, 1 to 64 */ - uint offset; /* from beginning of vertex, in bytes */ - uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */ - const char *name[GPU_VERT_ATTR_MAX_NAMES]; + GPUVertFetchMode fetch_mode; + GPUVertCompType comp_type; + uint gl_comp_type; + uint comp_len; /* 1 to 4 or 8 or 12 or 16 */ + uint sz; /* size in bytes, 1 to 64 */ + uint offset; /* from beginning of vertex, in bytes */ + uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */ + const char *name[GPU_VERT_ATTR_MAX_NAMES]; } GPUVertAttr; typedef struct GPUVertFormat { - /** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */ - uint attr_len; - /** Total count of active vertex attribute. */ - uint name_len; - /** Stride in bytes, 1 to 256. */ - uint stride; - uint name_offset; - bool packed; - char names[GPU_VERT_ATTR_NAMES_BUF_LEN]; - /** TODO: variable-size array */ - GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN]; + /** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */ + uint attr_len; + /** Total count of active vertex attribute. */ + uint name_len; + /** Stride in bytes, 1 to 256. */ + uint stride; + uint name_offset; + bool packed; + char names[GPU_VERT_ATTR_NAMES_BUF_LEN]; + /** TODO: variable-size array */ + GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN]; } GPUVertFormat; struct GPUShaderInterface; void GPU_vertformat_clear(GPUVertFormat *); void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src); -void GPU_vertformat_from_interface(GPUVertFormat *format, const struct GPUShaderInterface *shaderface); +void GPU_vertformat_from_interface(GPUVertFormat *format, + const struct GPUShaderInterface *shaderface); uint GPU_vertformat_attr_add( - GPUVertFormat *, const char *name, - GPUVertCompType, uint comp_len, GPUVertFetchMode); + GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode); void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias); int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name); @@ -103,10 +103,10 @@ void GPU_vertformat_triple_load(GPUVertFormat *format); /* format conversion */ typedef struct GPUPackedNormal { - int x : 10; - int y : 10; - int z : 10; - int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */ + int x : 10; + int y : 10; + int z : 10; + int w : 2; /* 0 by default, can manually set to { -2, -1, 0, 1 } */ } GPUPackedNormal; GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]); diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index d3cff782514..23e5ee28533 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -37,53 +37,53 @@ typedef struct GPUViewport GPUViewport; /* Contains memory pools information */ typedef struct ViewportMemoryPool { - struct BLI_mempool *calls; - struct BLI_mempool *states; - struct BLI_mempool *shgroups; - struct BLI_mempool *uniforms; - struct BLI_mempool *passes; + struct BLI_mempool *calls; + struct BLI_mempool *states; + struct BLI_mempool *shgroups; + struct BLI_mempool *uniforms; + struct BLI_mempool *passes; } ViewportMemoryPool; /* All FramebufferLists are just the same pointers with different names */ typedef struct FramebufferList { - struct GPUFrameBuffer *framebuffers[0]; + struct GPUFrameBuffer *framebuffers[0]; } FramebufferList; typedef struct TextureList { - struct GPUTexture *textures[0]; + struct GPUTexture *textures[0]; } TextureList; typedef struct PassList { - struct DRWPass *passes[0]; + struct DRWPass *passes[0]; } PassList; typedef struct StorageList { - void *storage[0]; /* custom structs from the engine */ + void *storage[0]; /* custom structs from the engine */ } StorageList; typedef struct ViewportEngineData { - void *engine_type; + void *engine_type; - FramebufferList *fbl; - TextureList *txl; - PassList *psl; - StorageList *stl; - char info[GPU_INFO_SIZE]; + FramebufferList *fbl; + TextureList *txl; + PassList *psl; + StorageList *stl; + char info[GPU_INFO_SIZE]; - /* we may want to put this elsewhere */ - struct DRWTextStore *text_draw_cache; + /* we may want to put this elsewhere */ + struct DRWTextStore *text_draw_cache; - /* Profiling data */ - double init_time; - double render_time; - double background_time; + /* Profiling data */ + double init_time; + double render_time; + double background_time; } ViewportEngineData; typedef struct ViewportEngineData_Info { - int fbl_len; - int txl_len; - int psl_len; - int stl_len; + int fbl_len; + int txl_len; + int psl_len; + int stl_len; } ViewportEngineData_Info; GPUViewport *GPU_viewport_create(void); @@ -102,8 +102,8 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type); void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type); void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport); void *GPU_viewport_texture_list_get(GPUViewport *viewport); -void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]); -void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]); +void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]); +void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]); /* Profiling */ double *GPU_viewport_cache_time_get(GPUViewport *viewport); @@ -114,9 +114,10 @@ bool GPU_viewport_do_update(GPUViewport *viewport); GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport); /* Texture pool */ -GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int format); +GPUTexture *GPU_viewport_texture_pool_query( + GPUViewport *viewport, void *engine, int width, int height, int format); bool GPU_viewport_engines_data_validate(GPUViewport *viewport, unsigned int hash); void GPU_viewport_cache_release(GPUViewport *viewport); -#endif // __GPU_VIEWPORT_H__ +#endif // __GPU_VIEWPORT_H__ diff --git a/source/blender/gpu/intern/gpu_attr_binding.c b/source/blender/gpu/intern/gpu_attr_binding.c index 242c157bec1..6cd350df505 100644 --- a/source/blender/gpu/intern/gpu_attr_binding.c +++ b/source/blender/gpu/intern/gpu_attr_binding.c @@ -34,46 +34,48 @@ void AttrBinding_clear(GPUAttrBinding *binding) { - binding->loc_bits = 0; - binding->enabled_bits = 0; + binding->loc_bits = 0; + binding->enabled_bits = 0; } uint read_attr_location(const GPUAttrBinding *binding, uint a_idx) { #if TRUST_NO_ONE - assert(a_idx < GPU_VERT_ATTR_MAX_LEN); - assert(binding->enabled_bits & (1 << a_idx)); + assert(a_idx < GPU_VERT_ATTR_MAX_LEN); + assert(binding->enabled_bits & (1 << a_idx)); #endif - return (binding->loc_bits >> (4 * a_idx)) & 0xF; + return (binding->loc_bits >> (4 * a_idx)) & 0xF; } static void write_attr_location(GPUAttrBinding *binding, uint a_idx, uint location) { #if TRUST_NO_ONE - assert(a_idx < GPU_VERT_ATTR_MAX_LEN); - assert(location < GPU_VERT_ATTR_MAX_LEN); + assert(a_idx < GPU_VERT_ATTR_MAX_LEN); + assert(location < GPU_VERT_ATTR_MAX_LEN); #endif - const uint shift = 4 * a_idx; - const uint64_t mask = ((uint64_t)0xF) << shift; - /* overwrite this attr's previous location */ - binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift); - /* mark this attr as enabled */ - binding->enabled_bits |= 1 << a_idx; + const uint shift = 4 * a_idx; + const uint64_t mask = ((uint64_t)0xF) << shift; + /* overwrite this attr's previous location */ + binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift); + /* mark this attr as enabled */ + binding->enabled_bits |= 1 << a_idx; } -void get_attr_locations(const GPUVertFormat *format, GPUAttrBinding *binding, const GPUShaderInterface *shaderface) +void get_attr_locations(const GPUVertFormat *format, + GPUAttrBinding *binding, + const GPUShaderInterface *shaderface) { - AttrBinding_clear(binding); + AttrBinding_clear(binding); - for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) { - const GPUVertAttr *a = &format->attrs[a_idx]; - for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { - const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]); + for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) { + const GPUVertAttr *a = &format->attrs[a_idx]; + for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { + const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]); #if TRUST_NO_ONE - assert(input != NULL); - /* TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program */ + assert(input != NULL); + /* TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program */ #endif - write_attr_location(binding, a_idx, input->location); - } - } + write_attr_location(binding, a_idx, input->location); + } + } } diff --git a/source/blender/gpu/intern/gpu_attr_binding_private.h b/source/blender/gpu/intern/gpu_attr_binding_private.h index 8615e095197..bcd4ba1dbfc 100644 --- a/source/blender/gpu/intern/gpu_attr_binding_private.h +++ b/source/blender/gpu/intern/gpu_attr_binding_private.h @@ -31,9 +31,9 @@ void AttrBinding_clear(GPUAttrBinding *binding); -void get_attr_locations( - const GPUVertFormat *format, GPUAttrBinding *binding, const GPUShaderInterface *shaderface); -uint read_attr_location( - const GPUAttrBinding *binding, uint a_idx); +void get_attr_locations(const GPUVertFormat *format, + GPUAttrBinding *binding, + const GPUShaderInterface *shaderface); +uint read_attr_location(const GPUAttrBinding *binding, uint a_idx); #endif /* __GPU_ATTR_BINDING_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index ddd1b056ee7..636a48c1623 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -43,642 +43,670 @@ static void batch_update_program_bindings(GPUBatch *batch, uint v_first); void GPU_batch_vao_cache_clear(GPUBatch *batch) { - if (batch->context == NULL) { - return; - } - if (batch->is_dynamic_vao_count) { - for (int i = 0; i < batch->dynamic_vaos.count; ++i) { - if (batch->dynamic_vaos.vao_ids[i]) { - GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); - } - if (batch->dynamic_vaos.interfaces[i]) { - GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->dynamic_vaos.interfaces[i], batch); - } - } - MEM_freeN(batch->dynamic_vaos.interfaces); - MEM_freeN(batch->dynamic_vaos.vao_ids); - } - else { - for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { - if (batch->static_vaos.vao_ids[i]) { - GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context); - } - if (batch->static_vaos.interfaces[i]) { - GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->static_vaos.interfaces[i], batch); - } - } - } - batch->is_dynamic_vao_count = false; - for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { - batch->static_vaos.vao_ids[i] = 0; - batch->static_vaos.interfaces[i] = NULL; - } - gpu_context_remove_batch(batch->context, batch); - batch->context = NULL; -} - -GPUBatch *GPU_batch_create_ex( - GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem, - uint owns_flag) -{ - GPUBatch *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); - GPU_batch_init_ex(batch, prim_type, verts, elem, owns_flag); - return batch; + if (batch->context == NULL) { + return; + } + if (batch->is_dynamic_vao_count) { + for (int i = 0; i < batch->dynamic_vaos.count; ++i) { + if (batch->dynamic_vaos.vao_ids[i]) { + GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); + } + if (batch->dynamic_vaos.interfaces[i]) { + GPU_shaderinterface_remove_batch_ref( + (GPUShaderInterface *)batch->dynamic_vaos.interfaces[i], batch); + } + } + MEM_freeN(batch->dynamic_vaos.interfaces); + MEM_freeN(batch->dynamic_vaos.vao_ids); + } + else { + for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { + if (batch->static_vaos.vao_ids[i]) { + GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context); + } + if (batch->static_vaos.interfaces[i]) { + GPU_shaderinterface_remove_batch_ref( + (GPUShaderInterface *)batch->static_vaos.interfaces[i], batch); + } + } + } + batch->is_dynamic_vao_count = false; + for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { + batch->static_vaos.vao_ids[i] = 0; + batch->static_vaos.interfaces[i] = NULL; + } + gpu_context_remove_batch(batch->context, batch); + batch->context = NULL; +} + +GPUBatch *GPU_batch_create_ex(GPUPrimType prim_type, + GPUVertBuf *verts, + GPUIndexBuf *elem, + uint owns_flag) +{ + GPUBatch *batch = MEM_callocN(sizeof(GPUBatch), "GPUBatch"); + GPU_batch_init_ex(batch, prim_type, verts, elem, owns_flag); + return batch; } void GPU_batch_init_ex( - GPUBatch *batch, GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem, - uint owns_flag) + GPUBatch *batch, GPUPrimType prim_type, GPUVertBuf *verts, GPUIndexBuf *elem, uint owns_flag) { #if TRUST_NO_ONE - assert(verts != NULL); + assert(verts != NULL); #endif - batch->verts[0] = verts; - for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) { - batch->verts[v] = NULL; - } - batch->inst = NULL; - batch->elem = elem; - batch->gl_prim_type = convert_prim_type_to_gl(prim_type); - batch->phase = GPU_BATCH_READY_TO_DRAW; - batch->is_dynamic_vao_count = false; - batch->owns_flag = owns_flag; - batch->free_callback = NULL; + batch->verts[0] = verts; + for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) { + batch->verts[v] = NULL; + } + batch->inst = NULL; + batch->elem = elem; + batch->gl_prim_type = convert_prim_type_to_gl(prim_type); + batch->phase = GPU_BATCH_READY_TO_DRAW; + batch->is_dynamic_vao_count = false; + batch->owns_flag = owns_flag; + batch->free_callback = NULL; } /* This will share the VBOs with the new batch. */ void GPU_batch_copy(GPUBatch *batch_dst, GPUBatch *batch_src) { - GPU_batch_init_ex(batch_dst, GPU_PRIM_POINTS, batch_src->verts[0], batch_src->elem, 0); + GPU_batch_init_ex(batch_dst, GPU_PRIM_POINTS, batch_src->verts[0], batch_src->elem, 0); - batch_dst->gl_prim_type = batch_src->gl_prim_type; - for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) { - batch_dst->verts[v] = batch_src->verts[v]; - } + batch_dst->gl_prim_type = batch_src->gl_prim_type; + for (int v = 1; v < GPU_BATCH_VBO_MAX_LEN; ++v) { + batch_dst->verts[v] = batch_src->verts[v]; + } } void GPU_batch_clear(GPUBatch *batch) { - if (batch->owns_flag & GPU_BATCH_OWNS_INDEX) { - GPU_indexbuf_discard(batch->elem); - } - if (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES) { - GPU_vertbuf_discard(batch->inst); - } - if ((batch->owns_flag & ~GPU_BATCH_OWNS_INDEX) != 0) { - for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) { - if (batch->verts[v] == NULL) { - break; - } - if (batch->owns_flag & (1 << v)) { - GPU_vertbuf_discard(batch->verts[v]); - } - } - } - GPU_batch_vao_cache_clear(batch); + if (batch->owns_flag & GPU_BATCH_OWNS_INDEX) { + GPU_indexbuf_discard(batch->elem); + } + if (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES) { + GPU_vertbuf_discard(batch->inst); + } + if ((batch->owns_flag & ~GPU_BATCH_OWNS_INDEX) != 0) { + for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) { + if (batch->verts[v] == NULL) { + break; + } + if (batch->owns_flag & (1 << v)) { + GPU_vertbuf_discard(batch->verts[v]); + } + } + } + GPU_batch_vao_cache_clear(batch); } void GPU_batch_discard(GPUBatch *batch) { - if (batch->free_callback) { - batch->free_callback(batch, batch->callback_data); - } + if (batch->free_callback) { + batch->free_callback(batch, batch->callback_data); + } - GPU_batch_clear(batch); - MEM_freeN(batch); + GPU_batch_clear(batch); + MEM_freeN(batch); } -void GPU_batch_callback_free_set(GPUBatch *batch, void (*callback)(GPUBatch *, void *), void *user_data) +void GPU_batch_callback_free_set(GPUBatch *batch, + void (*callback)(GPUBatch *, void *), + void *user_data) { - batch->free_callback = callback; - batch->callback_data = user_data; + batch->free_callback = callback; + batch->callback_data = user_data; } void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo) { #if TRUST_NO_ONE - assert(inst != NULL); + assert(inst != NULL); #endif - /* redo the bindings */ - GPU_batch_vao_cache_clear(batch); + /* redo the bindings */ + GPU_batch_vao_cache_clear(batch); - if (batch->inst != NULL && (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES)) { - GPU_vertbuf_discard(batch->inst); - } - batch->inst = inst; + if (batch->inst != NULL && (batch->owns_flag & GPU_BATCH_OWNS_INSTANCES)) { + GPU_vertbuf_discard(batch->inst); + } + batch->inst = inst; - if (own_vbo) { - batch->owns_flag |= GPU_BATCH_OWNS_INSTANCES; - } - else { - batch->owns_flag &= ~GPU_BATCH_OWNS_INSTANCES; - } + if (own_vbo) { + batch->owns_flag |= GPU_BATCH_OWNS_INSTANCES; + } + else { + batch->owns_flag &= ~GPU_BATCH_OWNS_INSTANCES; + } } /* Returns the index of verts in the batch. */ -int GPU_batch_vertbuf_add_ex( - GPUBatch *batch, GPUVertBuf *verts, - bool own_vbo) +int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo) { - /* redo the bindings */ - GPU_batch_vao_cache_clear(batch); + /* redo the bindings */ + GPU_batch_vao_cache_clear(batch); - for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) { - if (batch->verts[v] == NULL) { + for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; ++v) { + if (batch->verts[v] == NULL) { #if TRUST_NO_ONE - /* for now all VertexBuffers must have same vertex_len */ - assert(verts->vertex_len == batch->verts[0]->vertex_len); + /* for now all VertexBuffers must have same vertex_len */ + assert(verts->vertex_len == batch->verts[0]->vertex_len); #endif - batch->verts[v] = verts; - /* TODO: mark dirty so we can keep attribute bindings up-to-date */ - if (own_vbo) - batch->owns_flag |= (1 << v); - return v; - } - } - - /* we only make it this far if there is no room for another GPUVertBuf */ + batch->verts[v] = verts; + /* TODO: mark dirty so we can keep attribute bindings up-to-date */ + if (own_vbo) + batch->owns_flag |= (1 << v); + return v; + } + } + + /* we only make it this far if there is no room for another GPUVertBuf */ #if TRUST_NO_ONE - assert(false); + assert(false); #endif - return -1; + return -1; } static GLuint batch_vao_get(GPUBatch *batch) { - /* Search through cache */ - if (batch->is_dynamic_vao_count) { - for (int i = 0; i < batch->dynamic_vaos.count; ++i) - if (batch->dynamic_vaos.interfaces[i] == batch->interface) - return batch->dynamic_vaos.vao_ids[i]; - } - else { - for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) - if (batch->static_vaos.interfaces[i] == batch->interface) - return batch->static_vaos.vao_ids[i]; - } - - /* Set context of this batch. - * It will be bound to it until GPU_batch_vao_cache_clear is called. - * Until then it can only be drawn with this context. */ - if (batch->context == NULL) { - batch->context = GPU_context_active_get(); - gpu_context_add_batch(batch->context, batch); - } + /* Search through cache */ + if (batch->is_dynamic_vao_count) { + for (int i = 0; i < batch->dynamic_vaos.count; ++i) + if (batch->dynamic_vaos.interfaces[i] == batch->interface) + return batch->dynamic_vaos.vao_ids[i]; + } + else { + for (int i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) + if (batch->static_vaos.interfaces[i] == batch->interface) + return batch->static_vaos.vao_ids[i]; + } + + /* Set context of this batch. + * It will be bound to it until GPU_batch_vao_cache_clear is called. + * Until then it can only be drawn with this context. */ + if (batch->context == NULL) { + batch->context = GPU_context_active_get(); + gpu_context_add_batch(batch->context, batch); + } #if TRUST_NO_ONE - else { - /* Make sure you are not trying to draw this batch in another context. */ - assert(batch->context == GPU_context_active_get()); - } + else { + /* Make sure you are not trying to draw this batch in another context. */ + assert(batch->context == GPU_context_active_get()); + } #endif - /* Cache miss, time to add a new entry! */ - GLuint new_vao = 0; - if (!batch->is_dynamic_vao_count) { - int i; /* find first unused slot */ - for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) - if (batch->static_vaos.vao_ids[i] == 0) - break; - - if (i < GPU_BATCH_VAO_STATIC_LEN) { - batch->static_vaos.interfaces[i] = batch->interface; - batch->static_vaos.vao_ids[i] = new_vao = GPU_vao_alloc(); - } - else { - /* Not enough place switch to dynamic. */ - batch->is_dynamic_vao_count = true; - /* Erase previous entries, they will be added back if drawn again. */ - for (int j = 0; j < GPU_BATCH_VAO_STATIC_LEN; ++j) { - GPU_shaderinterface_remove_batch_ref((GPUShaderInterface *)batch->static_vaos.interfaces[j], batch); - GPU_vao_free(batch->static_vaos.vao_ids[j], batch->context); - } - /* Init dynamic arrays and let the branch below set the values. */ - batch->dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT; - batch->dynamic_vaos.interfaces = MEM_callocN(batch->dynamic_vaos.count * sizeof(GPUShaderInterface *), "dyn vaos interfaces"); - batch->dynamic_vaos.vao_ids = MEM_callocN(batch->dynamic_vaos.count * sizeof(GLuint), "dyn vaos ids"); - } - } - - if (batch->is_dynamic_vao_count) { - int i; /* find first unused slot */ - for (i = 0; i < batch->dynamic_vaos.count; ++i) - if (batch->dynamic_vaos.vao_ids[i] == 0) - break; - - if (i == batch->dynamic_vaos.count) { - /* Not enough place, realloc the array. */ - i = batch->dynamic_vaos.count; - batch->dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT; - batch->dynamic_vaos.interfaces = MEM_recallocN(batch->dynamic_vaos.interfaces, sizeof(GPUShaderInterface *) * batch->dynamic_vaos.count); - batch->dynamic_vaos.vao_ids = MEM_recallocN(batch->dynamic_vaos.vao_ids, sizeof(GLuint) * batch->dynamic_vaos.count); - } - batch->dynamic_vaos.interfaces[i] = batch->interface; - batch->dynamic_vaos.vao_ids[i] = new_vao = GPU_vao_alloc(); - } - - GPU_shaderinterface_add_batch_ref((GPUShaderInterface *)batch->interface, batch); + /* Cache miss, time to add a new entry! */ + GLuint new_vao = 0; + if (!batch->is_dynamic_vao_count) { + int i; /* find first unused slot */ + for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) + if (batch->static_vaos.vao_ids[i] == 0) + break; + + if (i < GPU_BATCH_VAO_STATIC_LEN) { + batch->static_vaos.interfaces[i] = batch->interface; + batch->static_vaos.vao_ids[i] = new_vao = GPU_vao_alloc(); + } + else { + /* Not enough place switch to dynamic. */ + batch->is_dynamic_vao_count = true; + /* Erase previous entries, they will be added back if drawn again. */ + for (int j = 0; j < GPU_BATCH_VAO_STATIC_LEN; ++j) { + GPU_shaderinterface_remove_batch_ref( + (GPUShaderInterface *)batch->static_vaos.interfaces[j], batch); + GPU_vao_free(batch->static_vaos.vao_ids[j], batch->context); + } + /* Init dynamic arrays and let the branch below set the values. */ + batch->dynamic_vaos.count = GPU_BATCH_VAO_DYN_ALLOC_COUNT; + batch->dynamic_vaos.interfaces = MEM_callocN( + batch->dynamic_vaos.count * sizeof(GPUShaderInterface *), "dyn vaos interfaces"); + batch->dynamic_vaos.vao_ids = MEM_callocN(batch->dynamic_vaos.count * sizeof(GLuint), + "dyn vaos ids"); + } + } + + if (batch->is_dynamic_vao_count) { + int i; /* find first unused slot */ + for (i = 0; i < batch->dynamic_vaos.count; ++i) + if (batch->dynamic_vaos.vao_ids[i] == 0) + break; + + if (i == batch->dynamic_vaos.count) { + /* Not enough place, realloc the array. */ + i = batch->dynamic_vaos.count; + batch->dynamic_vaos.count += GPU_BATCH_VAO_DYN_ALLOC_COUNT; + batch->dynamic_vaos.interfaces = MEM_recallocN(batch->dynamic_vaos.interfaces, + sizeof(GPUShaderInterface *) * + batch->dynamic_vaos.count); + batch->dynamic_vaos.vao_ids = MEM_recallocN(batch->dynamic_vaos.vao_ids, + sizeof(GLuint) * batch->dynamic_vaos.count); + } + batch->dynamic_vaos.interfaces[i] = batch->interface; + batch->dynamic_vaos.vao_ids[i] = new_vao = GPU_vao_alloc(); + } + + GPU_shaderinterface_add_batch_ref((GPUShaderInterface *)batch->interface, batch); #if TRUST_NO_ONE - assert(new_vao != 0); + assert(new_vao != 0); #endif - /* We just got a fresh VAO we need to initialize it. */ - glBindVertexArray(new_vao); - batch_update_program_bindings(batch, 0); - glBindVertexArray(0); + /* We just got a fresh VAO we need to initialize it. */ + glBindVertexArray(new_vao); + batch_update_program_bindings(batch, 0); + glBindVertexArray(0); - return new_vao; + return new_vao; } -void GPU_batch_program_set_no_use(GPUBatch *batch, uint32_t program, const GPUShaderInterface *shaderface) +void GPU_batch_program_set_no_use(GPUBatch *batch, + uint32_t program, + const GPUShaderInterface *shaderface) { #if TRUST_NO_ONE - assert(glIsProgram(shaderface->program)); - assert(batch->program_in_use == 0); + assert(glIsProgram(shaderface->program)); + assert(batch->program_in_use == 0); #endif - batch->interface = shaderface; - batch->program = program; - batch->vao_id = batch_vao_get(batch); + batch->interface = shaderface; + batch->program = program; + batch->vao_id = batch_vao_get(batch); } void GPU_batch_program_set(GPUBatch *batch, uint32_t program, const GPUShaderInterface *shaderface) { - GPU_batch_program_set_no_use(batch, program, shaderface); - GPU_batch_program_use_begin(batch); /* hack! to make Batch_Uniform* simpler */ + GPU_batch_program_set_no_use(batch, program, shaderface); + GPU_batch_program_use_begin(batch); /* hack! to make Batch_Uniform* simpler */ } void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface) { - if (batch->is_dynamic_vao_count) { - for (int i = 0; i < batch->dynamic_vaos.count; ++i) { - if (batch->dynamic_vaos.interfaces[i] == interface) { - GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); - batch->dynamic_vaos.vao_ids[i] = 0; - batch->dynamic_vaos.interfaces[i] = NULL; - break; /* cannot have duplicates */ - } - } - } - else { - int i; - for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { - if (batch->static_vaos.interfaces[i] == interface) { - GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context); - batch->static_vaos.vao_ids[i] = 0; - batch->static_vaos.interfaces[i] = NULL; - break; /* cannot have duplicates */ - } - } - } -} - -static void create_bindings( - GPUVertBuf *verts, const GPUShaderInterface *interface, - uint v_first, const bool use_instancing) -{ - const GPUVertFormat *format = &verts->format; - - const uint attr_len = format->attr_len; - const uint stride = format->stride; - - GPU_vertbuf_use(verts); - - for (uint a_idx = 0; a_idx < attr_len; ++a_idx) { - const GPUVertAttr *a = &format->attrs[a_idx]; - const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride; - - for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { - const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]); - - if (input == NULL) continue; - - if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) { + if (batch->is_dynamic_vao_count) { + for (int i = 0; i < batch->dynamic_vaos.count; ++i) { + if (batch->dynamic_vaos.interfaces[i] == interface) { + GPU_vao_free(batch->dynamic_vaos.vao_ids[i], batch->context); + batch->dynamic_vaos.vao_ids[i] = 0; + batch->dynamic_vaos.interfaces[i] = NULL; + break; /* cannot have duplicates */ + } + } + } + else { + int i; + for (i = 0; i < GPU_BATCH_VAO_STATIC_LEN; ++i) { + if (batch->static_vaos.interfaces[i] == interface) { + GPU_vao_free(batch->static_vaos.vao_ids[i], batch->context); + batch->static_vaos.vao_ids[i] = 0; + batch->static_vaos.interfaces[i] = NULL; + break; /* cannot have duplicates */ + } + } + } +} + +static void create_bindings(GPUVertBuf *verts, + const GPUShaderInterface *interface, + uint v_first, + const bool use_instancing) +{ + const GPUVertFormat *format = &verts->format; + + const uint attr_len = format->attr_len; + const uint stride = format->stride; + + GPU_vertbuf_use(verts); + + for (uint a_idx = 0; a_idx < attr_len; ++a_idx) { + const GPUVertAttr *a = &format->attrs[a_idx]; + const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride; + + for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) { + const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]); + + if (input == NULL) + continue; + + if (a->comp_len == 16 || a->comp_len == 12 || a->comp_len == 8) { #if TRUST_NO_ONE - assert(a->fetch_mode == GPU_FETCH_FLOAT); - assert(a->gl_comp_type == GL_FLOAT); + assert(a->fetch_mode == GPU_FETCH_FLOAT); + assert(a->gl_comp_type == GL_FLOAT); #endif - for (int i = 0; i < a->comp_len / 4; ++i) { - glEnableVertexAttribArray(input->location + i); - glVertexAttribDivisor(input->location + i, (use_instancing) ? 1 : 0); - glVertexAttribPointer(input->location + i, 4, a->gl_comp_type, GL_FALSE, stride, - (const GLubyte *)pointer + i * 16); - } - } - else { - glEnableVertexAttribArray(input->location); - glVertexAttribDivisor(input->location, (use_instancing) ? 1 : 0); - - switch (a->fetch_mode) { - case GPU_FETCH_FLOAT: - case GPU_FETCH_INT_TO_FLOAT: - glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); - break; - case GPU_FETCH_INT_TO_FLOAT_UNIT: - glVertexAttribPointer(input->location, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer); - break; - case GPU_FETCH_INT: - glVertexAttribIPointer(input->location, a->comp_len, a->gl_comp_type, stride, pointer); - break; - } - } - } - } + for (int i = 0; i < a->comp_len / 4; ++i) { + glEnableVertexAttribArray(input->location + i); + glVertexAttribDivisor(input->location + i, (use_instancing) ? 1 : 0); + glVertexAttribPointer(input->location + i, + 4, + a->gl_comp_type, + GL_FALSE, + stride, + (const GLubyte *)pointer + i * 16); + } + } + else { + glEnableVertexAttribArray(input->location); + glVertexAttribDivisor(input->location, (use_instancing) ? 1 : 0); + + switch (a->fetch_mode) { + case GPU_FETCH_FLOAT: + case GPU_FETCH_INT_TO_FLOAT: + glVertexAttribPointer( + input->location, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); + break; + case GPU_FETCH_INT_TO_FLOAT_UNIT: + glVertexAttribPointer( + input->location, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer); + break; + case GPU_FETCH_INT: + glVertexAttribIPointer(input->location, a->comp_len, a->gl_comp_type, stride, pointer); + break; + } + } + } + } } static void batch_update_program_bindings(GPUBatch *batch, uint v_first) { - for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) { - create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false); - } - if (batch->inst) { - create_bindings(batch->inst, batch->interface, v_first, true); - } - if (batch->elem) { - GPU_indexbuf_use(batch->elem); - } + for (int v = 0; v < GPU_BATCH_VBO_MAX_LEN && batch->verts[v] != NULL; ++v) { + create_bindings(batch->verts[v], batch->interface, (batch->inst) ? 0 : v_first, false); + } + if (batch->inst) { + create_bindings(batch->inst, batch->interface, v_first, true); + } + if (batch->elem) { + GPU_indexbuf_use(batch->elem); + } } void GPU_batch_program_use_begin(GPUBatch *batch) { - /* NOTE: use_program & done_using_program are fragile, depend on staying in sync with - * the GL context's active program. use_program doesn't mark other programs as "not used". */ - /* TODO: make not fragile (somehow) */ + /* NOTE: use_program & done_using_program are fragile, depend on staying in sync with + * the GL context's active program. use_program doesn't mark other programs as "not used". */ + /* TODO: make not fragile (somehow) */ - if (!batch->program_in_use) { - glUseProgram(batch->program); - batch->program_in_use = true; - } + if (!batch->program_in_use) { + glUseProgram(batch->program); + batch->program_in_use = true; + } } void GPU_batch_program_use_end(GPUBatch *batch) { - if (batch->program_in_use) { + if (batch->program_in_use) { #if PROGRAM_NO_OPTI - glUseProgram(0); + glUseProgram(0); #endif - batch->program_in_use = false; - } + batch->program_in_use = false; + } } #if TRUST_NO_ONE -# define GET_UNIFORM const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); assert(uniform); +# define GET_UNIFORM \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); \ + assert(uniform); #else -# define GET_UNIFORM const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); +# define GET_UNIFORM \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); #endif void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, int value) { - GET_UNIFORM - glUniform1ui(uniform->location, value); + GET_UNIFORM + glUniform1ui(uniform->location, value); } void GPU_batch_uniform_1i(GPUBatch *batch, const char *name, int value) { - GET_UNIFORM - glUniform1i(uniform->location, value); + GET_UNIFORM + glUniform1i(uniform->location, value); } void GPU_batch_uniform_1b(GPUBatch *batch, const char *name, bool value) { - GET_UNIFORM - glUniform1i(uniform->location, value ? GL_TRUE : GL_FALSE); + GET_UNIFORM + glUniform1i(uniform->location, value ? GL_TRUE : GL_FALSE); } void GPU_batch_uniform_2f(GPUBatch *batch, const char *name, float x, float y) { - GET_UNIFORM - glUniform2f(uniform->location, x, y); + GET_UNIFORM + glUniform2f(uniform->location, x, y); } void GPU_batch_uniform_3f(GPUBatch *batch, const char *name, float x, float y, float z) { - GET_UNIFORM - glUniform3f(uniform->location, x, y, z); + GET_UNIFORM + glUniform3f(uniform->location, x, y, z); } void GPU_batch_uniform_4f(GPUBatch *batch, const char *name, float x, float y, float z, float w) { - GET_UNIFORM - glUniform4f(uniform->location, x, y, z, w); + GET_UNIFORM + glUniform4f(uniform->location, x, y, z, w); } void GPU_batch_uniform_1f(GPUBatch *batch, const char *name, float x) { - GET_UNIFORM - glUniform1f(uniform->location, x); + GET_UNIFORM + glUniform1f(uniform->location, x); } void GPU_batch_uniform_2fv(GPUBatch *batch, const char *name, const float data[2]) { - GET_UNIFORM - glUniform2fv(uniform->location, 1, data); + GET_UNIFORM + glUniform2fv(uniform->location, 1, data); } void GPU_batch_uniform_3fv(GPUBatch *batch, const char *name, const float data[3]) { - GET_UNIFORM - glUniform3fv(uniform->location, 1, data); + GET_UNIFORM + glUniform3fv(uniform->location, 1, data); } void GPU_batch_uniform_4fv(GPUBatch *batch, const char *name, const float data[4]) { - GET_UNIFORM - glUniform4fv(uniform->location, 1, data); + GET_UNIFORM + glUniform4fv(uniform->location, 1, data); } -void GPU_batch_uniform_2fv_array(GPUBatch *batch, const char *name, const int len, const float *data) +void GPU_batch_uniform_2fv_array(GPUBatch *batch, + const char *name, + const int len, + const float *data) { - GET_UNIFORM - glUniform2fv(uniform->location, len, data); + GET_UNIFORM + glUniform2fv(uniform->location, len, data); } -void GPU_batch_uniform_4fv_array(GPUBatch *batch, const char *name, const int len, const float *data) +void GPU_batch_uniform_4fv_array(GPUBatch *batch, + const char *name, + const int len, + const float *data) { - GET_UNIFORM - glUniform4fv(uniform->location, len, data); + GET_UNIFORM + glUniform4fv(uniform->location, len, data); } void GPU_batch_uniform_mat4(GPUBatch *batch, const char *name, const float data[4][4]) { - GET_UNIFORM - glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data); + GET_UNIFORM + glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (const float *)data); } static void primitive_restart_enable(const GPUIndexBuf *el) { - // TODO(fclem) Replace by GL_PRIMITIVE_RESTART_FIXED_INDEX when we have ogl 4.3 - glEnable(GL_PRIMITIVE_RESTART); - GLuint restart_index = (GLuint)0xFFFFFFFF; + // TODO(fclem) Replace by GL_PRIMITIVE_RESTART_FIXED_INDEX when we have ogl 4.3 + glEnable(GL_PRIMITIVE_RESTART); + GLuint restart_index = (GLuint)0xFFFFFFFF; #if GPU_TRACK_INDEX_RANGE - if (el->index_type == GPU_INDEX_U8) - restart_index = (GLuint)0xFF; - else if (el->index_type == GPU_INDEX_U16) - restart_index = (GLuint)0xFFFF; + if (el->index_type == GPU_INDEX_U8) + restart_index = (GLuint)0xFF; + else if (el->index_type == GPU_INDEX_U16) + restart_index = (GLuint)0xFFFF; #endif - glPrimitiveRestartIndex(restart_index); + glPrimitiveRestartIndex(restart_index); } static void primitive_restart_disable(void) { - glDisable(GL_PRIMITIVE_RESTART); + glDisable(GL_PRIMITIVE_RESTART); } static void *elem_offset(const GPUIndexBuf *el, int v_first) { #if GPU_TRACK_INDEX_RANGE - if (el->index_type == GPU_INDEX_U8) - return (GLubyte *)0 + v_first; - else if (el->index_type == GPU_INDEX_U16) - return (GLushort *)0 + v_first; - else + if (el->index_type == GPU_INDEX_U8) + return (GLubyte *)0 + v_first; + else if (el->index_type == GPU_INDEX_U16) + return (GLushort *)0 + v_first; + else #endif - return (GLuint *)0 + v_first; + return (GLuint *)0 + v_first; } void GPU_batch_draw(GPUBatch *batch) { #if TRUST_NO_ONE - assert(batch->phase == GPU_BATCH_READY_TO_DRAW); - assert(batch->verts[0]->vbo_id != 0); + assert(batch->phase == GPU_BATCH_READY_TO_DRAW); + assert(batch->verts[0]->vbo_id != 0); #endif - GPU_batch_program_use_begin(batch); - GPU_matrix_bind(batch->interface); // external call. + GPU_batch_program_use_begin(batch); + GPU_matrix_bind(batch->interface); // external call. - GPU_batch_draw_range_ex(batch, 0, 0, false); + GPU_batch_draw_range_ex(batch, 0, 0, false); - GPU_batch_program_use_end(batch); + GPU_batch_program_use_end(batch); } void GPU_batch_draw_range_ex(GPUBatch *batch, int v_first, int v_count, bool force_instance) { #if TRUST_NO_ONE - assert(!(force_instance && (batch->inst == NULL)) || v_count > 0); // we cannot infer length if force_instance + assert(!(force_instance && (batch->inst == NULL)) || + v_count > 0); // we cannot infer length if force_instance #endif - const bool do_instance = (force_instance || batch->inst); - - // If using offset drawing, use the default VAO and redo bindings. - if (v_first != 0 && do_instance) { - glBindVertexArray(GPU_vao_default()); - batch_update_program_bindings(batch, v_first); - } - else { - glBindVertexArray(batch->vao_id); - } - - if (do_instance) { - /* Infer length if vertex count is not given */ - if (v_count == 0) { - v_count = batch->inst->vertex_len; - } - - if (batch->elem) { - const GPUIndexBuf *el = batch->elem; - - if (el->use_prim_restart) { - primitive_restart_enable(el); - } + const bool do_instance = (force_instance || batch->inst); + + // If using offset drawing, use the default VAO and redo bindings. + if (v_first != 0 && do_instance) { + glBindVertexArray(GPU_vao_default()); + batch_update_program_bindings(batch, v_first); + } + else { + glBindVertexArray(batch->vao_id); + } + + if (do_instance) { + /* Infer length if vertex count is not given */ + if (v_count == 0) { + v_count = batch->inst->vertex_len; + } + + if (batch->elem) { + const GPUIndexBuf *el = batch->elem; + + if (el->use_prim_restart) { + primitive_restart_enable(el); + } #if GPU_TRACK_INDEX_RANGE - glDrawElementsInstancedBaseVertex(batch->gl_prim_type, - el->index_len, - el->gl_index_type, - 0, - v_count, - el->base_index); + glDrawElementsInstancedBaseVertex( + batch->gl_prim_type, el->index_len, el->gl_index_type, 0, v_count, el->base_index); #else - glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count); + glDrawElementsInstanced(batch->gl_prim_type, el->index_len, GL_UNSIGNED_INT, 0, v_count); #endif - if (el->use_prim_restart) { - primitive_restart_disable(); - } - } - else { - glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count); - } - } - else { - /* Infer length if vertex count is not given */ - if (v_count == 0) { - v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len; - } - - if (batch->elem) { - const GPUIndexBuf *el = batch->elem; - - if (el->use_prim_restart) { - primitive_restart_enable(el); - } - - void *v_first_ofs = elem_offset(el, v_first); + if (el->use_prim_restart) { + primitive_restart_disable(); + } + } + else { + glDrawArraysInstanced(batch->gl_prim_type, 0, batch->verts[0]->vertex_len, v_count); + } + } + else { + /* Infer length if vertex count is not given */ + if (v_count == 0) { + v_count = (batch->elem) ? batch->elem->index_len : batch->verts[0]->vertex_len; + } + + if (batch->elem) { + const GPUIndexBuf *el = batch->elem; + + if (el->use_prim_restart) { + primitive_restart_enable(el); + } + + void *v_first_ofs = elem_offset(el, v_first); #if GPU_TRACK_INDEX_RANGE - if (el->base_index) { - glDrawRangeElementsBaseVertex( - batch->gl_prim_type, - el->min_index, - el->max_index, - v_count, - el->gl_index_type, - v_first_ofs, - el->base_index); - } - else { - glDrawRangeElements(batch->gl_prim_type, el->min_index, el->max_index, v_count, el->gl_index_type, v_first_ofs); - } + if (el->base_index) { + glDrawRangeElementsBaseVertex(batch->gl_prim_type, + el->min_index, + el->max_index, + v_count, + el->gl_index_type, + v_first_ofs, + el->base_index); + } + else { + glDrawRangeElements(batch->gl_prim_type, + el->min_index, + el->max_index, + v_count, + el->gl_index_type, + v_first_ofs); + } #else - glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, v_first_ofs); + glDrawElements(batch->gl_prim_type, v_count, GL_UNSIGNED_INT, v_first_ofs); #endif - if (el->use_prim_restart) { - primitive_restart_disable(); - } - } - else { - glDrawArrays(batch->gl_prim_type, v_first, v_count); - } - } + if (el->use_prim_restart) { + primitive_restart_disable(); + } + } + else { + glDrawArrays(batch->gl_prim_type, v_first, v_count); + } + } - /* Performance hog if you are drawing with the same vao multiple time. - * Only activate for debugging. */ - // glBindVertexArray(0); + /* Performance hog if you are drawing with the same vao multiple time. + * Only activate for debugging. */ + // glBindVertexArray(0); } /* just draw some vertices and let shader place them where we want. */ void GPU_draw_primitive(GPUPrimType prim_type, int v_count) { - /* we cannot draw without vao ... annoying ... */ - glBindVertexArray(GPU_vao_default()); + /* we cannot draw without vao ... annoying ... */ + glBindVertexArray(GPU_vao_default()); - GLenum type = convert_prim_type_to_gl(prim_type); - glDrawArrays(type, 0, v_count); + GLenum type = convert_prim_type_to_gl(prim_type); + glDrawArrays(type, 0, v_count); - /* Performance hog if you are drawing with the same vao multiple time. - * Only activate for debugging.*/ - // glBindVertexArray(0); + /* Performance hog if you are drawing with the same vao multiple time. + * Only activate for debugging.*/ + // glBindVertexArray(0); } - /* -------------------------------------------------------------------- */ /** \name Utilities * \{ */ void GPU_batch_program_set_shader(GPUBatch *batch, GPUShader *shader) { - GPU_batch_program_set(batch, shader->program, shader->interface); + GPU_batch_program_set(batch, shader->program, shader->interface); } -void GPU_batch_program_set_builtin_with_config( - GPUBatch *batch, eGPUBuiltinShader shader_id, eGPUShaderConfig sh_cfg) +void GPU_batch_program_set_builtin_with_config(GPUBatch *batch, + eGPUBuiltinShader shader_id, + eGPUShaderConfig sh_cfg) { - GPUShader *shader = GPU_shader_get_builtin_shader_with_config(shader_id, sh_cfg); - GPU_batch_program_set(batch, shader->program, shader->interface); + GPUShader *shader = GPU_shader_get_builtin_shader_with_config(shader_id, sh_cfg); + GPU_batch_program_set(batch, shader->program, shader->interface); } void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id) { - GPU_batch_program_set_builtin_with_config(batch, shader_id, GPU_SHADER_CFG_DEFAULT); + GPU_batch_program_set_builtin_with_config(batch, shader_id, GPU_SHADER_CFG_DEFAULT); } /** \} */ @@ -689,12 +717,12 @@ void GPU_batch_program_set_builtin(GPUBatch *batch, eGPUBuiltinShader shader_id) void gpu_batch_init(void) { - gpu_batch_presets_init(); + gpu_batch_presets_init(); } void gpu_batch_exit(void) { - gpu_batch_presets_exit(); + gpu_batch_presets_exit(); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_batch_presets.c b/source/blender/gpu/intern/gpu_batch_presets.c index 8d23d4be297..9018582f6dd 100644 --- a/source/blender/gpu/intern/gpu_batch_presets.c +++ b/source/blender/gpu/intern/gpu_batch_presets.c @@ -31,83 +31,85 @@ #include "GPU_batch.h" #include "GPU_batch_utils.h" -#include "GPU_batch_presets.h" /* own include */ +#include "GPU_batch_presets.h" /* own include */ #include "gpu_shader_private.h" /* Struct to store 3D Batches and their format */ static struct { - struct { - GPUBatch *sphere_high; - GPUBatch *sphere_med; - GPUBatch *sphere_low; - GPUBatch *sphere_wire_low; - GPUBatch *sphere_wire_med; - } batch; + struct { + GPUBatch *sphere_high; + GPUBatch *sphere_med; + GPUBatch *sphere_low; + GPUBatch *sphere_wire_low; + GPUBatch *sphere_wire_med; + } batch; - GPUVertFormat format; + GPUVertFormat format; - struct { - uint pos, nor; - } attr_id; + struct { + uint pos, nor; + } attr_id; - ThreadMutex mutex; + ThreadMutex mutex; } g_presets_3d = {{0}}; static ListBase presets_list = {NULL, NULL}; - /* -------------------------------------------------------------------- */ /** \name 3D Primitives * \{ */ static GPUVertFormat *preset_3d_format(void) { - if (g_presets_3d.format.attr_len == 0) { - GPUVertFormat *format = &g_presets_3d.format; - g_presets_3d.attr_id.pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - g_presets_3d.attr_id.nor = GPU_vertformat_attr_add(format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - } - return &g_presets_3d.format; + if (g_presets_3d.format.attr_len == 0) { + GPUVertFormat *format = &g_presets_3d.format; + g_presets_3d.attr_id.pos = GPU_vertformat_attr_add( + format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + g_presets_3d.attr_id.nor = GPU_vertformat_attr_add( + format, "nor", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + } + return &g_presets_3d.format; } -static void batch_sphere_lat_lon_vert( - GPUVertBufRaw *pos_step, GPUVertBufRaw *nor_step, - float lat, float lon) +static void batch_sphere_lat_lon_vert(GPUVertBufRaw *pos_step, + GPUVertBufRaw *nor_step, + float lat, + float lon) { - float pos[3]; - pos[0] = sinf(lat) * cosf(lon); - pos[1] = cosf(lat); - pos[2] = sinf(lat) * sinf(lon); - copy_v3_v3(GPU_vertbuf_raw_step(pos_step), pos); - copy_v3_v3(GPU_vertbuf_raw_step(nor_step), pos); + float pos[3]; + pos[0] = sinf(lat) * cosf(lon); + pos[1] = cosf(lat); + pos[2] = sinf(lat) * sinf(lon); + copy_v3_v3(GPU_vertbuf_raw_step(pos_step), pos); + copy_v3_v3(GPU_vertbuf_raw_step(nor_step), pos); } GPUBatch *GPU_batch_preset_sphere(int lod) { - BLI_assert(lod >= 0 && lod <= 2); - BLI_assert(BLI_thread_is_main()); - - if (lod == 0) { - return g_presets_3d.batch.sphere_low; - } - else if (lod == 1) { - return g_presets_3d.batch.sphere_med; - } - else { - return g_presets_3d.batch.sphere_high; - } + BLI_assert(lod >= 0 && lod <= 2); + BLI_assert(BLI_thread_is_main()); + + if (lod == 0) { + return g_presets_3d.batch.sphere_low; + } + else if (lod == 1) { + return g_presets_3d.batch.sphere_med; + } + else { + return g_presets_3d.batch.sphere_high; + } } GPUBatch *GPU_batch_preset_sphere_wire(int lod) { - BLI_assert(lod >= 0 && lod <= 1); - BLI_assert(BLI_thread_is_main()); - - if (lod == 0) { - return g_presets_3d.batch.sphere_wire_low; - } - else { - return g_presets_3d.batch.sphere_wire_med; - } + BLI_assert(lod >= 0 && lod <= 1); + BLI_assert(BLI_thread_is_main()); + + if (lod == 0) { + return g_presets_3d.batch.sphere_wire_low; + } + else { + return g_presets_3d.batch.sphere_wire_med; + } } /** \} */ @@ -119,141 +121,141 @@ GPUBatch *GPU_batch_preset_sphere_wire(int lod) /* Replacement for gluSphere */ GPUBatch *gpu_batch_sphere(int lat_res, int lon_res) { - const float lon_inc = 2 * M_PI / lon_res; - const float lat_inc = M_PI / lat_res; - float lon, lat; - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format()); - const uint vbo_len = (lat_res - 1) * lon_res * 6; - GPU_vertbuf_data_alloc(vbo, vbo_len); - - GPUVertBufRaw pos_step, nor_step; - GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step); - GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step); - - lon = 0.0f; - for (int i = 0; i < lon_res; i++, lon += lon_inc) { - lat = 0.0f; - for (int j = 0; j < lat_res; j++, lat += lat_inc) { - if (j != lat_res - 1) { /* Pole */ - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); - } - - if (j != 0) { /* Pole */ - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon + lon_inc); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); - } - } - } - - BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step)); - BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step)); - - return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); + const float lon_inc = 2 * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + float lon, lat; + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format()); + const uint vbo_len = (lat_res - 1) * lon_res * 6; + GPU_vertbuf_data_alloc(vbo, vbo_len); + + GPUVertBufRaw pos_step, nor_step; + GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step); + GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step); + + lon = 0.0f; + for (int i = 0; i < lon_res; i++, lon += lon_inc) { + lat = 0.0f; + for (int j = 0; j < lat_res; j++, lat += lat_inc) { + if (j != lat_res - 1) { /* Pole */ + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); + } + + if (j != 0) { /* Pole */ + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon + lon_inc); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); + } + } + } + + BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step)); + BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step)); + + return GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO); } static GPUBatch *batch_sphere_wire(int lat_res, int lon_res) { - const float lon_inc = 2 * M_PI / lon_res; - const float lat_inc = M_PI / lat_res; - float lon, lat; - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format()); - const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2); - GPU_vertbuf_data_alloc(vbo, vbo_len); - - GPUVertBufRaw pos_step, nor_step; - GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step); - GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step); - - lon = 0.0f; - for (int i = 0; i < lon_res; i++, lon += lon_inc) { - lat = 0.0f; - for (int j = 0; j < lat_res; j++, lat += lat_inc) { - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); - - if (j != lat_res - 1) { /* Pole */ - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); - batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); - } - } - } - - BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step)); - BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step)); - - return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); + const float lon_inc = 2 * M_PI / lon_res; + const float lat_inc = M_PI / lat_res; + float lon, lat; + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(preset_3d_format()); + const uint vbo_len = (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2); + GPU_vertbuf_data_alloc(vbo, vbo_len); + + GPUVertBufRaw pos_step, nor_step; + GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.pos, &pos_step); + GPU_vertbuf_attr_get_raw_data(vbo, g_presets_3d.attr_id.nor, &nor_step); + + lon = 0.0f; + for (int i = 0; i < lon_res; i++, lon += lon_inc) { + lat = 0.0f; + for (int j = 0; j < lat_res; j++, lat += lat_inc) { + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat, lon); + + if (j != lat_res - 1) { /* Pole */ + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(&pos_step, &nor_step, lat + lat_inc, lon); + } + } + } + + BLI_assert(vbo_len == GPU_vertbuf_raw_used(&pos_step)); + BLI_assert(vbo_len == GPU_vertbuf_raw_used(&nor_step)); + + return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); } /** \} */ void gpu_batch_presets_init(void) { - BLI_mutex_init(&g_presets_3d.mutex); + BLI_mutex_init(&g_presets_3d.mutex); - /* Hard coded resolution */ - g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16); - gpu_batch_presets_register(g_presets_3d.batch.sphere_low); + /* Hard coded resolution */ + g_presets_3d.batch.sphere_low = gpu_batch_sphere(8, 16); + gpu_batch_presets_register(g_presets_3d.batch.sphere_low); - g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10); - gpu_batch_presets_register(g_presets_3d.batch.sphere_med); + g_presets_3d.batch.sphere_med = gpu_batch_sphere(16, 10); + gpu_batch_presets_register(g_presets_3d.batch.sphere_med); - g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24); - gpu_batch_presets_register(g_presets_3d.batch.sphere_high); + g_presets_3d.batch.sphere_high = gpu_batch_sphere(32, 24); + gpu_batch_presets_register(g_presets_3d.batch.sphere_high); - g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8); - gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_low); + g_presets_3d.batch.sphere_wire_low = batch_sphere_wire(6, 8); + gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_low); - g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16); - gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med); + g_presets_3d.batch.sphere_wire_med = batch_sphere_wire(8, 16); + gpu_batch_presets_register(g_presets_3d.batch.sphere_wire_med); } void gpu_batch_presets_register(GPUBatch *preset_batch) { - BLI_mutex_lock(&g_presets_3d.mutex); - BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch)); - BLI_mutex_unlock(&g_presets_3d.mutex); + BLI_mutex_lock(&g_presets_3d.mutex); + BLI_addtail(&presets_list, BLI_genericNodeN(preset_batch)); + BLI_mutex_unlock(&g_presets_3d.mutex); } bool gpu_batch_presets_unregister(GPUBatch *preset_batch) { - BLI_mutex_lock(&g_presets_3d.mutex); - for (LinkData *link = presets_list.last; link; link = link->prev) { - if (preset_batch == link->data) { - BLI_remlink(&presets_list, link); - BLI_mutex_unlock(&g_presets_3d.mutex); - MEM_freeN(link); - return true; - } - } - BLI_mutex_unlock(&g_presets_3d.mutex); - return false; + BLI_mutex_lock(&g_presets_3d.mutex); + for (LinkData *link = presets_list.last; link; link = link->prev) { + if (preset_batch == link->data) { + BLI_remlink(&presets_list, link); + BLI_mutex_unlock(&g_presets_3d.mutex); + MEM_freeN(link); + return true; + } + } + BLI_mutex_unlock(&g_presets_3d.mutex); + return false; } void gpu_batch_presets_reset(void) { - BLI_mutex_lock(&g_presets_3d.mutex); - /* Reset vao caches for these every time we switch opengl context. - * This way they will draw correctly for each window. */ - for (LinkData *link = presets_list.first; link; link = link->next) { - GPUBatch *preset = link->data; - GPU_batch_vao_cache_clear(preset); - } - BLI_mutex_unlock(&g_presets_3d.mutex); + BLI_mutex_lock(&g_presets_3d.mutex); + /* Reset vao caches for these every time we switch opengl context. + * This way they will draw correctly for each window. */ + for (LinkData *link = presets_list.first; link; link = link->next) { + GPUBatch *preset = link->data; + GPU_batch_vao_cache_clear(preset); + } + BLI_mutex_unlock(&g_presets_3d.mutex); } void gpu_batch_presets_exit(void) { - LinkData *link; - while ((link = BLI_pophead(&presets_list))) { - GPUBatch *preset = link->data; - GPU_batch_discard(preset); - MEM_freeN(link); - } - - BLI_mutex_end(&g_presets_3d.mutex); + LinkData *link; + while ((link = BLI_pophead(&presets_list))) { + GPUBatch *preset = link->data; + GPU_batch_discard(preset); + MEM_freeN(link); + } + + BLI_mutex_end(&g_presets_3d.mutex); } diff --git a/source/blender/gpu/intern/gpu_batch_utils.c b/source/blender/gpu/intern/gpu_batch_utils.c index 10b7b3c39b5..3a8b392ef1d 100644 --- a/source/blender/gpu/intern/gpu_batch_utils.c +++ b/source/blender/gpu/intern/gpu_batch_utils.c @@ -27,7 +27,7 @@ #include "BLI_sort_utils.h" #include "GPU_batch.h" -#include "GPU_batch_utils.h" /* own include */ +#include "GPU_batch_utils.h" /* own include */ #include "gpu_shader_private.h" /* -------------------------------------------------------------------- */ @@ -43,198 +43,195 @@ * \param polys_flat_len: Length of the array (must be an even number). * \param rect: Optional region to map the byte 0..255 coords to. When not set use -1..1. */ -GPUBatch *GPU_batch_tris_from_poly_2d_encoded( - const uchar *polys_flat, uint polys_flat_len, const rctf *rect) +GPUBatch *GPU_batch_tris_from_poly_2d_encoded(const uchar *polys_flat, + uint polys_flat_len, + const rctf *rect) { - const uchar (*polys)[2] = (const void *)polys_flat; - const uint polys_len = polys_flat_len / 2; - BLI_assert(polys_flat_len == polys_len * 2); - - /* Over alloc in both cases */ - float (*verts)[2] = MEM_mallocN(sizeof(*verts) * polys_len, __func__); - float (*verts_step)[2] = verts; - uint (*tris)[3] = MEM_mallocN(sizeof(*tris) * polys_len, __func__); - uint (*tris_step)[3] = tris; - - const float range_uchar[2] = { - (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f, - (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f, - }; - const float min_uchar[2] = { - (rect ? rect->xmin : -1.0f), - (rect ? rect->ymin : -1.0f), - }; - - uint i_poly = 0; - uint i_vert = 0; - while (i_poly != polys_len) { - for (uint j = 0; j < 2; j++) { - verts[i_vert][j] = min_uchar[j] + ((float)polys[i_poly][j] * range_uchar[j]); - } - i_vert++; - i_poly++; - if (polys[i_poly - 1][0] == polys[i_poly][0] && - polys[i_poly - 1][1] == polys[i_poly][1]) - { - const uint verts_step_len = (&verts[i_vert]) - verts_step; - BLI_assert(verts_step_len >= 3); - const uint tris_len = (verts_step_len - 2); - BLI_polyfill_calc(verts_step, verts_step_len, -1, tris_step); - /* offset indices */ - if (verts_step != verts) { - uint *t = tris_step[0]; - const uint offset = (verts_step - verts); - uint tot = tris_len * 3; - while (tot--) { - *t += offset; - t++; - } - BLI_assert(t == tris_step[tris_len]); - } - verts_step += verts_step_len; - tris_step += tris_len; - i_poly++; - /* ignore the duplicate point */ - } - } - - /* We have vertices and tris, make a batch from this. */ - static GPUVertFormat format = {0}; - static struct { uint pos; } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - - const uint verts_len = (verts_step - verts); - const uint tris_len = (tris_step - tris); - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - GPU_vertbuf_data_alloc(vbo, verts_len); - - GPUVertBufRaw pos_step; - GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); - - for (uint i = 0; i < verts_len; i++) { - copy_v2_v2(GPU_vertbuf_raw_step(&pos_step), verts[i]); - } - - GPUIndexBufBuilder elb; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tris_len, verts_len); - for (uint i = 0; i < tris_len; i++) { - GPU_indexbuf_add_tri_verts(&elb, UNPACK3(tris[i])); - } - GPUIndexBuf *indexbuf = GPU_indexbuf_build(&elb); - - MEM_freeN(tris); - MEM_freeN(verts); - - return GPU_batch_create_ex( - GPU_PRIM_TRIS, vbo, - indexbuf, - GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); + const uchar(*polys)[2] = (const void *)polys_flat; + const uint polys_len = polys_flat_len / 2; + BLI_assert(polys_flat_len == polys_len * 2); + + /* Over alloc in both cases */ + float(*verts)[2] = MEM_mallocN(sizeof(*verts) * polys_len, __func__); + float(*verts_step)[2] = verts; + uint(*tris)[3] = MEM_mallocN(sizeof(*tris) * polys_len, __func__); + uint(*tris_step)[3] = tris; + + const float range_uchar[2] = { + (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f, + (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f, + }; + const float min_uchar[2] = { + (rect ? rect->xmin : -1.0f), + (rect ? rect->ymin : -1.0f), + }; + + uint i_poly = 0; + uint i_vert = 0; + while (i_poly != polys_len) { + for (uint j = 0; j < 2; j++) { + verts[i_vert][j] = min_uchar[j] + ((float)polys[i_poly][j] * range_uchar[j]); + } + i_vert++; + i_poly++; + if (polys[i_poly - 1][0] == polys[i_poly][0] && polys[i_poly - 1][1] == polys[i_poly][1]) { + const uint verts_step_len = (&verts[i_vert]) - verts_step; + BLI_assert(verts_step_len >= 3); + const uint tris_len = (verts_step_len - 2); + BLI_polyfill_calc(verts_step, verts_step_len, -1, tris_step); + /* offset indices */ + if (verts_step != verts) { + uint *t = tris_step[0]; + const uint offset = (verts_step - verts); + uint tot = tris_len * 3; + while (tot--) { + *t += offset; + t++; + } + BLI_assert(t == tris_step[tris_len]); + } + verts_step += verts_step_len; + tris_step += tris_len; + i_poly++; + /* ignore the duplicate point */ + } + } + + /* We have vertices and tris, make a batch from this. */ + static GPUVertFormat format = {0}; + static struct { + uint pos; + } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + const uint verts_len = (verts_step - verts); + const uint tris_len = (tris_step - tris); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, verts_len); + + GPUVertBufRaw pos_step; + GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + + for (uint i = 0; i < verts_len; i++) { + copy_v2_v2(GPU_vertbuf_raw_step(&pos_step), verts[i]); + } + + GPUIndexBufBuilder elb; + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tris_len, verts_len); + for (uint i = 0; i < tris_len; i++) { + GPU_indexbuf_add_tri_verts(&elb, UNPACK3(tris[i])); + } + GPUIndexBuf *indexbuf = GPU_indexbuf_build(&elb); + + MEM_freeN(tris); + MEM_freeN(verts); + + return GPU_batch_create_ex( + GPU_PRIM_TRIS, vbo, indexbuf, GPU_BATCH_OWNS_VBO | GPU_BATCH_OWNS_INDEX); } -GPUBatch *GPU_batch_wire_from_poly_2d_encoded( - const uchar *polys_flat, uint polys_flat_len, const rctf *rect) +GPUBatch *GPU_batch_wire_from_poly_2d_encoded(const uchar *polys_flat, + uint polys_flat_len, + const rctf *rect) { - const uchar (*polys)[2] = (const void *)polys_flat; - const uint polys_len = polys_flat_len / 2; - BLI_assert(polys_flat_len == polys_len * 2); - - /* Over alloc */ - /* Lines are pairs of (x, y) byte locations packed into an int32_t. */ - int32_t *lines = MEM_mallocN(sizeof(*lines) * polys_len, __func__); - int32_t *lines_step = lines; - - const float range_uchar[2] = { - (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f, - (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f, - }; - const float min_uchar[2] = { - (rect ? rect->xmin : -1.0f), - (rect ? rect->ymin : -1.0f), - }; - - uint i_poly_prev = 0; - uint i_poly = 0; - while (i_poly != polys_len) { - i_poly++; - if (polys[i_poly - 1][0] == polys[i_poly][0] && - polys[i_poly - 1][1] == polys[i_poly][1]) - { - const uchar (*polys_step)[2] = polys + i_poly_prev; - const uint polys_step_len = i_poly - i_poly_prev; - BLI_assert(polys_step_len >= 2); - for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) { - union { - uint8_t as_u8[4]; - uint16_t as_u16[2]; - uint32_t as_u32; - } data; - data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]); - data.as_u16[1] = *((const uint16_t *)polys_step[i]); - if (data.as_u16[0] > data.as_u16[1]) { - SWAP(uint16_t, data.as_u16[0], data.as_u16[1]); - } - *lines_step = data.as_u32; - lines_step++; - } - i_poly++; - i_poly_prev = i_poly; - /* ignore the duplicate point */ - } - } - - uint lines_len = lines_step - lines; - - /* Hide Lines (we could make optional) */ - { - qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int); - lines_step = lines; - for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) { - if (lines[i] != lines[i_prev]) { - *lines_step++ = lines[i_prev]; - } - else { - i++; - } - } - *lines_step++ = lines[lines_len - 1]; - lines_len = lines_step - lines; - } - - /* We have vertices and tris, make a batch from this. */ - static GPUVertFormat format = {0}; - static struct { uint pos; } attr_id; - if (format.attr_len == 0) { - attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - } - - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); - const uint vbo_len_capacity = lines_len * 2; - GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); - - GPUVertBufRaw pos_step; - GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); - - for (uint i = 0; i < lines_len; i++) { - union { - uint8_t as_u8_pair[2][2]; - uint32_t as_u32; - } data; - data.as_u32 = lines[i]; - for (uint k = 0; k < 2; k++) { - float *pos_v2 = GPU_vertbuf_raw_step(&pos_step); - for (uint j = 0; j < 2; j++) { - pos_v2[j] = min_uchar[j] + ((float)data.as_u8_pair[k][j] * range_uchar[j]); - } - } - } - BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step)); - MEM_freeN(lines); - return GPU_batch_create_ex( - GPU_PRIM_LINES, vbo, - NULL, - GPU_BATCH_OWNS_VBO); + const uchar(*polys)[2] = (const void *)polys_flat; + const uint polys_len = polys_flat_len / 2; + BLI_assert(polys_flat_len == polys_len * 2); + + /* Over alloc */ + /* Lines are pairs of (x, y) byte locations packed into an int32_t. */ + int32_t *lines = MEM_mallocN(sizeof(*lines) * polys_len, __func__); + int32_t *lines_step = lines; + + const float range_uchar[2] = { + (rect ? (rect->xmax - rect->xmin) : 2.0f) / 255.0f, + (rect ? (rect->ymax - rect->ymin) : 2.0f) / 255.0f, + }; + const float min_uchar[2] = { + (rect ? rect->xmin : -1.0f), + (rect ? rect->ymin : -1.0f), + }; + + uint i_poly_prev = 0; + uint i_poly = 0; + while (i_poly != polys_len) { + i_poly++; + if (polys[i_poly - 1][0] == polys[i_poly][0] && polys[i_poly - 1][1] == polys[i_poly][1]) { + const uchar(*polys_step)[2] = polys + i_poly_prev; + const uint polys_step_len = i_poly - i_poly_prev; + BLI_assert(polys_step_len >= 2); + for (uint i_prev = polys_step_len - 1, i = 0; i < polys_step_len; i_prev = i++) { + union { + uint8_t as_u8[4]; + uint16_t as_u16[2]; + uint32_t as_u32; + } data; + data.as_u16[0] = *((const uint16_t *)polys_step[i_prev]); + data.as_u16[1] = *((const uint16_t *)polys_step[i]); + if (data.as_u16[0] > data.as_u16[1]) { + SWAP(uint16_t, data.as_u16[0], data.as_u16[1]); + } + *lines_step = data.as_u32; + lines_step++; + } + i_poly++; + i_poly_prev = i_poly; + /* ignore the duplicate point */ + } + } + + uint lines_len = lines_step - lines; + + /* Hide Lines (we could make optional) */ + { + qsort(lines, lines_len, sizeof(int32_t), BLI_sortutil_cmp_int); + lines_step = lines; + for (uint i_prev = 0, i = 1; i < lines_len; i_prev = i++) { + if (lines[i] != lines[i_prev]) { + *lines_step++ = lines[i_prev]; + } + else { + i++; + } + } + *lines_step++ = lines[lines_len - 1]; + lines_len = lines_step - lines; + } + + /* We have vertices and tris, make a batch from this. */ + static GPUVertFormat format = {0}; + static struct { + uint pos; + } attr_id; + if (format.attr_len == 0) { + attr_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + } + + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + const uint vbo_len_capacity = lines_len * 2; + GPU_vertbuf_data_alloc(vbo, vbo_len_capacity); + + GPUVertBufRaw pos_step; + GPU_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); + + for (uint i = 0; i < lines_len; i++) { + union { + uint8_t as_u8_pair[2][2]; + uint32_t as_u32; + } data; + data.as_u32 = lines[i]; + for (uint k = 0; k < 2; k++) { + float *pos_v2 = GPU_vertbuf_raw_step(&pos_step); + for (uint j = 0; j < 2; j++) { + pos_v2[j] = min_uchar[j] + ((float)data.as_u8_pair[k][j] * range_uchar[j]); + } + } + } + BLI_assert(vbo_len_capacity == GPU_vertbuf_raw_used(&pos_step)); + MEM_freeN(lines); + return GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO); } /** \} */ diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index edf5eb7e7d1..0b5b2e469a0 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -53,45 +53,45 @@ * drawing and doesn't interact at all with the buffer code above */ struct GPU_PBVH_Buffers { - GPUIndexBuf *index_buf, *index_buf_fast; - GPUIndexBuf *index_lines_buf, *index_lines_buf_fast; - GPUVertBuf *vert_buf; + GPUIndexBuf *index_buf, *index_buf_fast; + GPUIndexBuf *index_lines_buf, *index_lines_buf_fast; + GPUVertBuf *vert_buf; - GPUBatch *lines; - GPUBatch *lines_fast; - GPUBatch *triangles; - GPUBatch *triangles_fast; + GPUBatch *lines; + GPUBatch *lines_fast; + GPUBatch *triangles; + GPUBatch *triangles_fast; - /* mesh pointers in case buffer allocation fails */ - const MPoly *mpoly; - const MLoop *mloop; - const MLoopTri *looptri; - const MVert *mvert; + /* mesh pointers in case buffer allocation fails */ + const MPoly *mpoly; + const MLoop *mloop; + const MLoopTri *looptri; + const MVert *mvert; - const int *face_indices; - int face_indices_len; + const int *face_indices; + int face_indices_len; - /* grid pointers */ - CCGKey gridkey; - CCGElem **grids; - const DMFlagMat *grid_flag_mats; - BLI_bitmap * const *grid_hidden; - const int *grid_indices; - int totgrid; + /* grid pointers */ + CCGKey gridkey; + CCGElem **grids; + const DMFlagMat *grid_flag_mats; + BLI_bitmap *const *grid_hidden; + const int *grid_indices; + int totgrid; - bool use_bmesh; + bool use_bmesh; - uint tot_tri, tot_quad; + uint tot_tri, tot_quad; - /* The PBVH ensures that either all faces in the node are - * smooth-shaded or all faces are flat-shaded */ - bool smooth; + /* The PBVH ensures that either all faces in the node are + * smooth-shaded or all faces are flat-shaded */ + bool smooth; - bool show_mask; + bool show_mask; }; static struct { - uint pos, nor, msk; + uint pos, nor, msk; } g_vbo_id = {0}; /** \} */ @@ -104,916 +104,915 @@ static struct { * Return is false it indicates that the memory map failed. */ static bool gpu_pbvh_vert_buf_data_set(GPU_PBVH_Buffers *buffers, uint vert_len) { - if (buffers->vert_buf == NULL) { - /* Initialize vertex buffer */ - /* match 'VertexBufferFormat' */ - - static GPUVertFormat format = {0}; - if (format.attr_len == 0) { - g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - g_vbo_id.nor = GPU_vertformat_attr_add(&format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); - g_vbo_id.msk = GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - } + if (buffers->vert_buf == NULL) { + /* Initialize vertex buffer */ + /* match 'VertexBufferFormat' */ + + static GPUVertFormat format = {0}; + if (format.attr_len == 0) { + g_vbo_id.pos = GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + g_vbo_id.nor = GPU_vertformat_attr_add( + &format, "nor", GPU_COMP_I16, 3, GPU_FETCH_INT_TO_FLOAT_UNIT); + g_vbo_id.msk = GPU_vertformat_attr_add(&format, "msk", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + } #if 0 - buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DYNAMIC); - GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); - } - else if (vert_len != buffers->vert_buf->vertex_len) { - GPU_vertbuf_data_resize(buffers->vert_buf, vert_len); - } + buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_DYNAMIC); + GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); + } + else if (vert_len != buffers->vert_buf->vertex_len) { + GPU_vertbuf_data_resize(buffers->vert_buf, vert_len); + } #else - buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC); - } - GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); + buffers->vert_buf = GPU_vertbuf_create_with_format_ex(&format, GPU_USAGE_STATIC); + } + GPU_vertbuf_data_alloc(buffers->vert_buf, vert_len); #endif - return buffers->vert_buf->data != NULL; -} - -static void gpu_pbvh_batch_init(GPU_PBVH_Buffers *buffers, GPUPrimType prim) -{ - /* force flushing to the GPU */ - if (buffers->vert_buf->data) { - GPU_vertbuf_use(buffers->vert_buf); - } - - if (buffers->triangles == NULL) { - buffers->triangles = GPU_batch_create( - prim, buffers->vert_buf, - /* can be NULL */ - buffers->index_buf); - } - - if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { - buffers->triangles_fast = GPU_batch_create( - prim, buffers->vert_buf, - buffers->index_buf_fast); - } - - if (buffers->lines == NULL) { - BLI_assert(buffers->index_lines_buf != NULL); - buffers->lines = GPU_batch_create( - GPU_PRIM_LINES, buffers->vert_buf, - buffers->index_lines_buf); - } - - if ((buffers->lines_fast == NULL) && buffers->index_lines_buf_fast) { - buffers->lines_fast = GPU_batch_create( - GPU_PRIM_LINES, buffers->vert_buf, - buffers->index_lines_buf_fast); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Mesh PBVH + return buffers->vert_buf->data != NULL; + } + + static void gpu_pbvh_batch_init(GPU_PBVH_Buffers * buffers, GPUPrimType prim) + { + /* force flushing to the GPU */ + if (buffers->vert_buf->data) { + GPU_vertbuf_use(buffers->vert_buf); + } + + if (buffers->triangles == NULL) { + buffers->triangles = GPU_batch_create(prim, + buffers->vert_buf, + /* can be NULL */ + buffers->index_buf); + } + + if ((buffers->triangles_fast == NULL) && buffers->index_buf_fast) { + buffers->triangles_fast = GPU_batch_create(prim, buffers->vert_buf, buffers->index_buf_fast); + } + + if (buffers->lines == NULL) { + BLI_assert(buffers->index_lines_buf != NULL); + buffers->lines = GPU_batch_create( + GPU_PRIM_LINES, buffers->vert_buf, buffers->index_lines_buf); + } + + if ((buffers->lines_fast == NULL) && buffers->index_lines_buf_fast) { + buffers->lines_fast = GPU_batch_create( + GPU_PRIM_LINES, buffers->vert_buf, buffers->index_lines_buf_fast); + } + } + + /** \} */ + + /* -------------------------------------------------------------------- */ + /** \name Mesh PBVH * \{ */ -void GPU_pbvh_mesh_buffers_update( - GPU_PBVH_Buffers *buffers, const MVert *mvert, - const int *vert_indices, int totvert, const float *vmask, - const int (*face_vert_indices)[3], - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - bool empty_mask = true; - - { - int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); - - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) { - /* Vertex data is shared if smooth-shaded, but separate - * copies are made for flat shading because normals - * shouldn't be shared. */ - if (buffers->smooth) { - for (uint i = 0; i < totvert; ++i) { - const MVert *v = &mvert[vert_indices[i]]; - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no); - } - - if (vmask && show_mask) { - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - for (uint j = 0; j < 3; j++) { - int vidx = face_vert_indices[i][j]; - int v_index = buffers->mloop[lt->tri[j]].v; - float fmask = vmask[v_index]; - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vidx, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); - } - } - } - } - else { - /* calculate normal for each polygon only once */ - uint mpoly_prev = UINT_MAX; - short no[3]; - int vbo_index = 0; - - for (uint i = 0; i < buffers->face_indices_len; i++) { - const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; - const uint vtri[3] = { - buffers->mloop[lt->tri[0]].v, - buffers->mloop[lt->tri[1]].v, - buffers->mloop[lt->tri[2]].v, - }; - - if (paint_is_face_hidden(lt, mvert, buffers->mloop)) - continue; - - /* Face normal and mask */ - if (lt->poly != mpoly_prev) { - const MPoly *mp = &buffers->mpoly[lt->poly]; - float fno[3]; - BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno); - normal_float_to_short_v3(no, fno); - mpoly_prev = lt->poly; - } - - float fmask = 0.0f; - if (vmask && show_mask) { - fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; - } - - for (uint j = 0; j < 3; j++) { - const MVert *v = &mvert[vtri[j]]; - - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); - - vbo_index++; - } - - empty_mask = empty_mask && (fmask == 0.0f); - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - } - - buffers->show_mask = !empty_mask; - buffers->mvert = mvert; -} - -GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build( - const int (*face_vert_indices)[3], - const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri, - const MVert *mvert, - const int *face_indices, - const int face_indices_len) -{ - GPU_PBVH_Buffers *buffers; - int i, tottri; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - - /* smooth or flat for all */ - buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; - - buffers->show_mask = false; - - /* Count the number of visible triangles */ - for (i = 0, tottri = 0; i < face_indices_len; ++i) { - const MLoopTri *lt = &looptri[face_indices[i]]; - if (!paint_is_face_hidden(lt, mvert, mloop)) - tottri++; - } - - if (tottri == 0) { - buffers->tot_tri = 0; - - buffers->mpoly = mpoly; - buffers->mloop = mloop; - buffers->looptri = looptri; - buffers->face_indices = face_indices; - buffers->face_indices_len = 0; - - return buffers; - } - - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - - /* An element index buffer is used for smooth shading, but flat - * shading requires separate vertex normals so an index buffer - * can't be used there. */ - if (buffers->smooth) { - /* Fill the triangle and line buffers. */ - GPUIndexBufBuilder elb, elb_lines; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, INT_MAX); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX); - - for (i = 0; i < face_indices_len; ++i) { - const MLoopTri *lt = &looptri[face_indices[i]]; - - /* Skip hidden faces */ - if (paint_is_face_hidden(lt, mvert, mloop)) - continue; - - GPU_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i])); - - /* TODO skip "non-real" edges. */ - GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][0], face_vert_indices[i][1]); - GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][1], face_vert_indices[i][2]); - GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][2], face_vert_indices[i][0]); - } - buffers->index_buf = GPU_indexbuf_build(&elb); - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - } - else { - /* Fill the only the line buffer. */ - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX); - - for (i = 0; i < face_indices_len; ++i) { - const MLoopTri *lt = &looptri[face_indices[i]]; - - /* Skip hidden faces */ - if (paint_is_face_hidden(lt, mvert, mloop)) - continue; - - /* TODO skip "non-real" edges. */ - GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 0, i * 3 + 1); - GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 1, i * 3 + 2); - GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 2, i * 3 + 0); - } - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - } - - buffers->tot_tri = tottri; - - buffers->mpoly = mpoly; - buffers->mloop = mloop; - buffers->looptri = looptri; - - buffers->face_indices = face_indices; - buffers->face_indices_len = face_indices_len; - - return buffers; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Grid PBVH + void GPU_pbvh_mesh_buffers_update(GPU_PBVH_Buffers * buffers, + const MVert *mvert, + const int *vert_indices, + int totvert, + const float *vmask, + const int(*face_vert_indices)[3], + const int update_flags) + { + const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; + bool empty_mask = true; + + { + int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3)); + + /* Build VBO */ + if (gpu_pbvh_vert_buf_data_set(buffers, totelem)) { + /* Vertex data is shared if smooth-shaded, but separate + * copies are made for flat shading because normals + * shouldn't be shared. */ + if (buffers->smooth) { + for (uint i = 0; i < totvert; ++i) { + const MVert *v = &mvert[vert_indices[i]]; + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, i, v->co); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, i, v->no); + } + + if (vmask && show_mask) { + for (uint i = 0; i < buffers->face_indices_len; i++) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; + for (uint j = 0; j < 3; j++) { + int vidx = face_vert_indices[i][j]; + int v_index = buffers->mloop[lt->tri[j]].v; + float fmask = vmask[v_index]; + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vidx, &fmask); + empty_mask = empty_mask && (fmask == 0.0f); + } + } + } + } + else { + /* calculate normal for each polygon only once */ + uint mpoly_prev = UINT_MAX; + short no[3]; + int vbo_index = 0; + + for (uint i = 0; i < buffers->face_indices_len; i++) { + const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]]; + const uint vtri[3] = { + buffers->mloop[lt->tri[0]].v, + buffers->mloop[lt->tri[1]].v, + buffers->mloop[lt->tri[2]].v, + }; + + if (paint_is_face_hidden(lt, mvert, buffers->mloop)) + continue; + + /* Face normal and mask */ + if (lt->poly != mpoly_prev) { + const MPoly *mp = &buffers->mpoly[lt->poly]; + float fno[3]; + BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno); + normal_float_to_short_v3(no, fno); + mpoly_prev = lt->poly; + } + + float fmask = 0.0f; + if (vmask && show_mask) { + fmask = (vmask[vtri[0]] + vmask[vtri[1]] + vmask[vtri[2]]) / 3.0f; + } + + for (uint j = 0; j < 3; j++) { + const MVert *v = &mvert[vtri[j]]; + + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, v->co); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); + + vbo_index++; + } + + empty_mask = empty_mask && (fmask == 0.0f); + } + } + + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); + } + } + + buffers->show_mask = !empty_mask; + buffers->mvert = mvert; + } + + GPU_PBVH_Buffers *GPU_pbvh_mesh_buffers_build(const int(*face_vert_indices)[3], + const MPoly *mpoly, + const MLoop *mloop, + const MLoopTri *looptri, + const MVert *mvert, + const int *face_indices, + const int face_indices_len) + { + GPU_PBVH_Buffers *buffers; + int i, tottri; + + buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); + + /* smooth or flat for all */ + buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH; + + buffers->show_mask = false; + + /* Count the number of visible triangles */ + for (i = 0, tottri = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; + if (!paint_is_face_hidden(lt, mvert, mloop)) + tottri++; + } + + if (tottri == 0) { + buffers->tot_tri = 0; + + buffers->mpoly = mpoly; + buffers->mloop = mloop; + buffers->looptri = looptri; + buffers->face_indices = face_indices; + buffers->face_indices_len = 0; + + return buffers; + } + + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + + /* An element index buffer is used for smooth shading, but flat + * shading requires separate vertex normals so an index buffer + * can't be used there. */ + if (buffers->smooth) { + /* Fill the triangle and line buffers. */ + GPUIndexBufBuilder elb, elb_lines; + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, INT_MAX); + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX); + + for (i = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; + + /* Skip hidden faces */ + if (paint_is_face_hidden(lt, mvert, mloop)) + continue; + + GPU_indexbuf_add_tri_verts(&elb, UNPACK3(face_vert_indices[i])); + + /* TODO skip "non-real" edges. */ + GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][0], face_vert_indices[i][1]); + GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][1], face_vert_indices[i][2]); + GPU_indexbuf_add_line_verts(&elb_lines, face_vert_indices[i][2], face_vert_indices[i][0]); + } + buffers->index_buf = GPU_indexbuf_build(&elb); + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + } + else { + /* Fill the only the line buffer. */ + GPUIndexBufBuilder elb_lines; + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, INT_MAX); + + for (i = 0; i < face_indices_len; ++i) { + const MLoopTri *lt = &looptri[face_indices[i]]; + + /* Skip hidden faces */ + if (paint_is_face_hidden(lt, mvert, mloop)) + continue; + + /* TODO skip "non-real" edges. */ + GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 0, i * 3 + 1); + GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 1, i * 3 + 2); + GPU_indexbuf_add_line_verts(&elb_lines, i * 3 + 2, i * 3 + 0); + } + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + } + + buffers->tot_tri = tottri; + + buffers->mpoly = mpoly; + buffers->mloop = mloop; + buffers->looptri = looptri; + + buffers->face_indices = face_indices; + buffers->face_indices_len = face_indices_len; + + return buffers; + } + + /** \} */ + + /* -------------------------------------------------------------------- */ + /** \name Grid PBVH * \{ */ -static void gpu_pbvh_grid_fill_index_buffers( - GPU_PBVH_Buffers *buffers, - int *grid_indices, - uint visible_quad_len, - int totgrid, - int gridsize) -{ - GPUIndexBufBuilder elb, elb_lines; - GPUIndexBufBuilder elb_fast, elb_lines_fast; - - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX); - GPU_indexbuf_init(&elb_fast, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX); - GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); - - if (buffers->smooth) { - uint offset = 0; - const uint grid_vert_len = gridsize * gridsize; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - uint v0, v1, v2, v3; - bool grid_visible = false; - - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - for (int j = 0; j < gridsize - 1; ++j) { - for (int k = 0; k < gridsize - 1; ++k) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden( - gh, gridsize, k, j)) - { - continue; - } - /* Indices in a Clockwise QUAD disposition. */ - v0 = offset + j * gridsize + k; - v1 = v0 + 1; - v2 = v1 + gridsize; - v3 = v2 - 1; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + gridsize - 1; - v2 = offset + grid_vert_len - 1; - v3 = offset + grid_vert_len - gridsize; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - else { - uint offset = 0; - const uint grid_vert_len = SQUARE(gridsize - 1) * 4; - for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { - bool grid_visible = false; - - BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; - - uint v0, v1, v2, v3; - for (int j = 0; j < gridsize - 1; j++) { - for (int k = 0; k < gridsize - 1; k++) { - /* Skip hidden grid face */ - if (gh && paint_is_grid_face_hidden( - gh, gridsize, k, j)) - { - continue; - } - /* VBO data are in a Clockwise QUAD disposition. */ - v0 = offset + (j * (gridsize - 1) + k) * 4; - v1 = v0 + 1; - v2 = v0 + 2; - v3 = v0 + 3; - - GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); - - if (j + 2 == gridsize) { - GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); - } - grid_visible = true; - } - GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); - } - - if (grid_visible) { - /* Grid corners */ - v0 = offset; - v1 = offset + (gridsize - 1) * 4 - 3; - v2 = offset + grid_vert_len - 2; - v3 = offset + grid_vert_len - (gridsize - 1) * 4 + 3; - - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); - GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); - - GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); - GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); - } - } - } - - buffers->index_buf = GPU_indexbuf_build(&elb); - buffers->index_buf_fast = GPU_indexbuf_build(&elb_fast); - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast); -} - -void GPU_pbvh_grid_buffers_update( - GPU_PBVH_Buffers *buffers, CCGElem **grids, - const DMFlagMat *grid_flag_mats, int *grid_indices, - int totgrid, const CCGKey *key, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - bool empty_mask = true; - int i, j, k, x, y; - - const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; - - /* Build VBO */ - const int has_mask = key->has_mask; - - uint vert_per_grid = (smooth) ? key->grid_area : (SQUARE(key->grid_size - 1) * 4); - uint vert_count = totgrid * vert_per_grid; - - if (buffers->smooth != smooth) { - buffers->smooth = smooth; - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - } - - if (buffers->index_buf == NULL) { - uint visible_quad_len = BKE_pbvh_count_grid_quads((BLI_bitmap **)buffers->grid_hidden, - grid_indices, - totgrid, - key->grid_size); - - /* totally hidden node, return here to avoid BufferData with zero below. */ - if (visible_quad_len == 0) { - return; - } - - gpu_pbvh_grid_fill_index_buffers(buffers, grid_indices, visible_quad_len, totgrid, key->grid_size); - } - - uint vbo_index_offset = 0; - /* Build VBO */ - if (gpu_pbvh_vert_buf_data_set(buffers, vert_count)) { - GPUIndexBufBuilder elb_lines; - - if (buffers->index_lines_buf == NULL) { - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); - } - - for (i = 0; i < totgrid; ++i) { - CCGElem *grid = grids[grid_indices[i]]; - int vbo_index = vbo_index_offset; - - if (buffers->smooth) { - for (y = 0; y < key->grid_size; y++) { - for (x = 0; x < key->grid_size; x++) { - CCGElem *elem = CCG_grid_elem(key, grid, x, y); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem)); - - short no_short[3]; - normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); - - if (has_mask && show_mask) { - float fmask = *CCG_elem_mask(key, elem); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); - } - vbo_index += 1; - } - } - vbo_index_offset += key->grid_area; - } - else { - for (j = 0; j < key->grid_size - 1; j++) { - for (k = 0; k < key->grid_size - 1; k++) { - CCGElem *elems[4] = { - CCG_grid_elem(key, grid, k, j), - CCG_grid_elem(key, grid, k + 1, j), - CCG_grid_elem(key, grid, k + 1, j + 1), - CCG_grid_elem(key, grid, k, j + 1), - }; - float *co[4] = { - CCG_elem_co(key, elems[0]), - CCG_elem_co(key, elems[1]), - CCG_elem_co(key, elems[2]), - CCG_elem_co(key, elems[3]), - }; - - float fno[3]; - short no_short[3]; - /* Note: Clockwise indices ordering, that's why we invert order here. */ - normal_quad_v3(fno, co[3], co[2], co[1], co[0]); - normal_float_to_short_v3(no_short, fno); - - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 0, co[0]); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 0, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 1, co[1]); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 1, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 2, co[2]); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 2, no_short); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 3, co[3]); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 3, no_short); - - if (has_mask && show_mask) { - float fmask = (*CCG_elem_mask(key, elems[0]) + - *CCG_elem_mask(key, elems[1]) + - *CCG_elem_mask(key, elems[2]) + - *CCG_elem_mask(key, elems[3])) * 0.25f; - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 0, &fmask); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 1, &fmask); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 2, &fmask); - GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fmask); - empty_mask = empty_mask && (fmask == 0.0f); - } - vbo_index += 4; - } - } - vbo_index_offset += SQUARE(key->grid_size - 1) * 4; - } - } - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); - } - - buffers->grids = grids; - buffers->grid_indices = grid_indices; - buffers->totgrid = totgrid; - buffers->grid_flag_mats = grid_flag_mats; - buffers->gridkey = *key; - buffers->show_mask = !empty_mask; - - //printf("node updated %p\n", buffers); -} - -GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build( - int totgrid, - BLI_bitmap **grid_hidden) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->grid_hidden = grid_hidden; - buffers->totgrid = totgrid; - - buffers->show_mask = false; - - return buffers; -} + static void gpu_pbvh_grid_fill_index_buffers(GPU_PBVH_Buffers * buffers, + int *grid_indices, + uint visible_quad_len, + int totgrid, + int gridsize) + { + GPUIndexBufBuilder elb, elb_lines; + GPUIndexBufBuilder elb_fast, elb_lines_fast; + + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, 2 * visible_quad_len, INT_MAX); + GPU_indexbuf_init(&elb_fast, GPU_PRIM_TRIS, 2 * totgrid, INT_MAX); + GPU_indexbuf_init( + &elb_lines, GPU_PRIM_LINES, 2 * totgrid * gridsize * (gridsize - 1), INT_MAX); + GPU_indexbuf_init(&elb_lines_fast, GPU_PRIM_LINES, 4 * totgrid, INT_MAX); + + if (buffers->smooth) { + uint offset = 0; + const uint grid_vert_len = gridsize * gridsize; + for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { + uint v0, v1, v2, v3; + bool grid_visible = false; + + BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; + + for (int j = 0; j < gridsize - 1; ++j) { + for (int k = 0; k < gridsize - 1; ++k) { + /* Skip hidden grid face */ + if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { + continue; + } + /* Indices in a Clockwise QUAD disposition. */ + v0 = offset + j * gridsize + k; + v1 = v0 + 1; + v2 = v1 + gridsize; + v3 = v2 - 1; + + GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); + + if (j + 2 == gridsize) { + GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); + } + grid_visible = true; + } + GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); + } + + if (grid_visible) { + /* Grid corners */ + v0 = offset; + v1 = offset + gridsize - 1; + v2 = offset + grid_vert_len - 1; + v3 = offset + grid_vert_len - gridsize; + + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); + } + } + } + else { + uint offset = 0; + const uint grid_vert_len = SQUARE(gridsize - 1) * 4; + for (int i = 0; i < totgrid; i++, offset += grid_vert_len) { + bool grid_visible = false; + + BLI_bitmap *gh = buffers->grid_hidden[grid_indices[i]]; + + uint v0, v1, v2, v3; + for (int j = 0; j < gridsize - 1; j++) { + for (int k = 0; k < gridsize - 1; k++) { + /* Skip hidden grid face */ + if (gh && paint_is_grid_face_hidden(gh, gridsize, k, j)) { + continue; + } + /* VBO data are in a Clockwise QUAD disposition. */ + v0 = offset + (j * (gridsize - 1) + k) * 4; + v1 = v0 + 1; + v2 = v0 + 2; + v3 = v0 + 3; + + GPU_indexbuf_add_tri_verts(&elb, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines, v0, v3); + + if (j + 2 == gridsize) { + GPU_indexbuf_add_line_verts(&elb_lines, v2, v3); + } + grid_visible = true; + } + GPU_indexbuf_add_line_verts(&elb_lines, v1, v2); + } + + if (grid_visible) { + /* Grid corners */ + v0 = offset; + v1 = offset + (gridsize - 1) * 4 - 3; + v2 = offset + grid_vert_len - 2; + v3 = offset + grid_vert_len - (gridsize - 1) * 4 + 3; + + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v2, v1); + GPU_indexbuf_add_tri_verts(&elb_fast, v0, v3, v2); + + GPU_indexbuf_add_line_verts(&elb_lines_fast, v0, v1); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v1, v2); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v2, v3); + GPU_indexbuf_add_line_verts(&elb_lines_fast, v3, v0); + } + } + } + + buffers->index_buf = GPU_indexbuf_build(&elb); + buffers->index_buf_fast = GPU_indexbuf_build(&elb_fast); + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + buffers->index_lines_buf_fast = GPU_indexbuf_build(&elb_lines_fast); + } + + void GPU_pbvh_grid_buffers_update(GPU_PBVH_Buffers * buffers, + CCGElem * *grids, + const DMFlagMat *grid_flag_mats, + int *grid_indices, + int totgrid, + const CCGKey *key, + const int update_flags) + { + const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; + bool empty_mask = true; + int i, j, k, x, y; + + const bool smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH; + + /* Build VBO */ + const int has_mask = key->has_mask; + + uint vert_per_grid = (smooth) ? key->grid_area : (SQUARE(key->grid_size - 1) * 4); + uint vert_count = totgrid * vert_per_grid; + + if (buffers->smooth != smooth) { + buffers->smooth = smooth; + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); + + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); + } + + if (buffers->index_buf == NULL) { + uint visible_quad_len = BKE_pbvh_count_grid_quads( + (BLI_bitmap **)buffers->grid_hidden, grid_indices, totgrid, key->grid_size); + + /* totally hidden node, return here to avoid BufferData with zero below. */ + if (visible_quad_len == 0) { + return; + } + + gpu_pbvh_grid_fill_index_buffers( + buffers, grid_indices, visible_quad_len, totgrid, key->grid_size); + } + + uint vbo_index_offset = 0; + /* Build VBO */ + if (gpu_pbvh_vert_buf_data_set(buffers, vert_count)) { + GPUIndexBufBuilder elb_lines; + + if (buffers->index_lines_buf == NULL) { + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, totgrid * key->grid_area * 2, vert_count); + } + + for (i = 0; i < totgrid; ++i) { + CCGElem *grid = grids[grid_indices[i]]; + int vbo_index = vbo_index_offset; + + if (buffers->smooth) { + for (y = 0; y < key->grid_size; y++) { + for (x = 0; x < key->grid_size; x++) { + CCGElem *elem = CCG_grid_elem(key, grid, x, y); + GPU_vertbuf_attr_set( + buffers->vert_buf, g_vbo_id.pos, vbo_index, CCG_elem_co(key, elem)); + + short no_short[3]; + normal_float_to_short_v3(no_short, CCG_elem_no(key, elem)); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index, no_short); + + if (has_mask && show_mask) { + float fmask = *CCG_elem_mask(key, elem); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index, &fmask); + empty_mask = empty_mask && (fmask == 0.0f); + } + vbo_index += 1; + } + } + vbo_index_offset += key->grid_area; + } + else { + for (j = 0; j < key->grid_size - 1; j++) { + for (k = 0; k < key->grid_size - 1; k++) { + CCGElem *elems[4] = { + CCG_grid_elem(key, grid, k, j), + CCG_grid_elem(key, grid, k + 1, j), + CCG_grid_elem(key, grid, k + 1, j + 1), + CCG_grid_elem(key, grid, k, j + 1), + }; + float *co[4] = { + CCG_elem_co(key, elems[0]), + CCG_elem_co(key, elems[1]), + CCG_elem_co(key, elems[2]), + CCG_elem_co(key, elems[3]), + }; + + float fno[3]; + short no_short[3]; + /* Note: Clockwise indices ordering, that's why we invert order here. */ + normal_quad_v3(fno, co[3], co[2], co[1], co[0]); + normal_float_to_short_v3(no_short, fno); + + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 0, co[0]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 0, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 1, co[1]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 1, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 2, co[2]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 2, no_short); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.pos, vbo_index + 3, co[3]); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.nor, vbo_index + 3, no_short); + + if (has_mask && show_mask) { + float fmask = (*CCG_elem_mask(key, elems[0]) + *CCG_elem_mask(key, elems[1]) + + *CCG_elem_mask(key, elems[2]) + *CCG_elem_mask(key, elems[3])) * + 0.25f; + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 0, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 1, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 2, &fmask); + GPU_vertbuf_attr_set(buffers->vert_buf, g_vbo_id.msk, vbo_index + 3, &fmask); + empty_mask = empty_mask && (fmask == 0.0f); + } + vbo_index += 4; + } + } + vbo_index_offset += SQUARE(key->grid_size - 1) * 4; + } + } + + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); + } + + buffers->grids = grids; + buffers->grid_indices = grid_indices; + buffers->totgrid = totgrid; + buffers->grid_flag_mats = grid_flag_mats; + buffers->gridkey = *key; + buffers->show_mask = !empty_mask; + + //printf("node updated %p\n", buffers); + } + + GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hidden) + { + GPU_PBVH_Buffers *buffers; + + buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); + buffers->grid_hidden = grid_hidden; + buffers->totgrid = totgrid; + + buffers->show_mask = false; + + return buffers; + } #undef FILL_QUAD_BUFFER -/** \} */ + /** \} */ -/* -------------------------------------------------------------------- */ -/** \name BMesh PBVH + /* -------------------------------------------------------------------- */ + /** \name BMesh PBVH * \{ */ -/* Output a BMVert into a VertexBufferFormat array + /* Output a BMVert into a VertexBufferFormat array * * The vertex is skipped if hidden, otherwise the output goes into * index '*v_index' in the 'vert_data' array and '*v_index' is * incremented. */ -static void gpu_bmesh_vert_to_buffer_copy__gwn( - BMVert *v, - GPUVertBuf *vert_buf, - int *v_index, - const float fno[3], - const float *fmask, - const int cd_vert_mask_offset, - const bool show_mask, - bool *empty_mask) -{ - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { - - /* Set coord, normal, and mask */ - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co); - - short no_short[3]; - normal_float_to_short_v3(no_short, fno ? fno : v->no); - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short); - - if (show_mask) { - float effective_mask = fmask ? *fmask - : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); - GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, *v_index, &effective_mask); - *empty_mask = *empty_mask && (effective_mask == 0.0f); - } - - /* Assign index for use in the triangle index buffer */ - /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ - BM_elem_index_set(v, (*v_index)); /* set_dirty! */ - - (*v_index)++; - } -} - -/* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */ -static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts, - GSet *bm_other_verts) -{ - GSetIterator gs_iter; - int totvert = 0; - - GSET_ITER (gs_iter, bm_unique_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) - totvert++; - } - GSET_ITER (gs_iter, bm_other_verts) { - BMVert *v = BLI_gsetIterator_getKey(&gs_iter); - if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) - totvert++; - } - - return totvert; -} - -/* Return the total number of visible faces */ -static int gpu_bmesh_face_visible_count(GSet *bm_faces) -{ - GSetIterator gh_iter; - int totface = 0; - - GSET_ITER (gh_iter, bm_faces) { - BMFace *f = BLI_gsetIterator_getKey(&gh_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) - totface++; - } - - return totface; -} - -/* Creates a vertex buffer (coordinate, normal, color) and, if smooth + static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert * v, + GPUVertBuf * vert_buf, + int *v_index, + const float fno[3], + const float *fmask, + const int cd_vert_mask_offset, + const bool show_mask, + bool *empty_mask) + { + if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) { + + /* Set coord, normal, and mask */ + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co); + + short no_short[3]; + normal_float_to_short_v3(no_short, fno ? fno : v->no); + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short); + + if (show_mask) { + float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset); + GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, *v_index, &effective_mask); + *empty_mask = *empty_mask && (effective_mask == 0.0f); + } + + /* Assign index for use in the triangle index buffer */ + /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ + BM_elem_index_set(v, (*v_index)); /* set_dirty! */ + + (*v_index)++; + } + } + + /* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */ + static int gpu_bmesh_vert_visible_count(GSet * bm_unique_verts, GSet * bm_other_verts) + { + GSetIterator gs_iter; + int totvert = 0; + + GSET_ITER (gs_iter, bm_unique_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); + if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) + totvert++; + } + GSET_ITER (gs_iter, bm_other_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); + if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) + totvert++; + } + + return totvert; + } + + /* Return the total number of visible faces */ + static int gpu_bmesh_face_visible_count(GSet * bm_faces) + { + GSetIterator gh_iter; + int totface = 0; + + GSET_ITER (gh_iter, bm_faces) { + BMFace *f = BLI_gsetIterator_getKey(&gh_iter); + + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) + totface++; + } + + return totface; + } + + /* Creates a vertex buffer (coordinate, normal, color) and, if smooth * shading, an element index buffer. */ -void GPU_pbvh_bmesh_buffers_update( - GPU_PBVH_Buffers *buffers, - BMesh *bm, - GSet *bm_faces, - GSet *bm_unique_verts, - GSet *bm_other_verts, - const int update_flags) -{ - const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; - int tottri, totvert, maxvert = 0; - bool empty_mask = true; - - /* TODO, make mask layer optional for bmesh buffer */ - const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); - - /* Count visible triangles */ - tottri = gpu_bmesh_face_visible_count(bm_faces); - - if (buffers->smooth) { - /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */ - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - /* Count visible vertices */ - totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts); - } - else { - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - totvert = tottri * 3; - } - - if (!tottri) { - buffers->tot_tri = 0; - return; - } - - /* Fill vertex buffer */ - if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) { - int v_index = 0; - - if (buffers->smooth) { - GSetIterator gs_iter; - - /* Vertices get an index assigned for use in the triangle - * index buffer */ - bm->elem_index_dirty |= BM_VERT; - - GSET_ITER (gs_iter, bm_unique_verts) { - gpu_bmesh_vert_to_buffer_copy__gwn( - BLI_gsetIterator_getKey(&gs_iter), - buffers->vert_buf, &v_index, NULL, NULL, - cd_vert_mask_offset, - show_mask, &empty_mask); - } - - GSET_ITER (gs_iter, bm_other_verts) { - gpu_bmesh_vert_to_buffer_copy__gwn( - BLI_gsetIterator_getKey(&gs_iter), - buffers->vert_buf, &v_index, NULL, NULL, - cd_vert_mask_offset, - show_mask, &empty_mask); - } - - maxvert = v_index; - } - else { - GSetIterator gs_iter; - - GPUIndexBufBuilder elb_lines; - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); - - GSET_ITER (gs_iter, bm_faces) { - BMFace *f = BLI_gsetIterator_getKey(&gs_iter); - - BLI_assert(f->len == 3); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - float fmask = 0.0f; - int i; - - BM_face_as_array_vert_tri(f, v); - - /* Average mask value */ - for (i = 0; i < 3; i++) { - fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); - } - fmask /= 3.0f; - - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); - GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); - - for (i = 0; i < 3; i++) { - gpu_bmesh_vert_to_buffer_copy__gwn( - v[i], buffers->vert_buf, - &v_index, f->no, &fmask, - cd_vert_mask_offset, - show_mask, &empty_mask); - } - } - } - - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - buffers->tot_tri = tottri; - } - - /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */ - bm->elem_index_dirty |= BM_VERT; - } - else { - /* Memory map failed */ - return; - } - - if (buffers->smooth) { - /* Fill the triangle buffer */ - GPUIndexBufBuilder elb, elb_lines; - GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert); - GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, maxvert); - - /* Fill triangle index buffer */ - { - GSetIterator gs_iter; - - GSET_ITER (gs_iter, bm_faces) { - BMFace *f = BLI_gsetIterator_getKey(&gs_iter); - - if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { - BMVert *v[3]; - - BM_face_as_array_vert_tri(f, v); - - uint idx[3] = {BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])}; - GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); - - GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); - GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); - } - } - - buffers->tot_tri = tottri; - - if (buffers->index_buf == NULL) { - buffers->index_buf = GPU_indexbuf_build(&elb); - } - else { - GPU_indexbuf_build_in_place(&elb, buffers->index_buf); - } - - buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); - } - } - - buffers->show_mask = !empty_mask; - - gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Generic + void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers * buffers, + BMesh * bm, + GSet * bm_faces, + GSet * bm_unique_verts, + GSet * bm_other_verts, + const int update_flags) + { + const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0; + int tottri, totvert, maxvert = 0; + bool empty_mask = true; + + /* TODO, make mask layer optional for bmesh buffer */ + const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK); + + /* Count visible triangles */ + tottri = gpu_bmesh_face_visible_count(bm_faces); + + if (buffers->smooth) { + /* Smooth needs to recreate index buffer, so we have to invalidate the batch. */ + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + /* Count visible vertices */ + totvert = gpu_bmesh_vert_visible_count(bm_unique_verts, bm_other_verts); + } + else { + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + totvert = tottri * 3; + } + + if (!tottri) { + buffers->tot_tri = 0; + return; + } + + /* Fill vertex buffer */ + if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) { + int v_index = 0; + + if (buffers->smooth) { + GSetIterator gs_iter; + + /* Vertices get an index assigned for use in the triangle + * index buffer */ + bm->elem_index_dirty |= BM_VERT; + + GSET_ITER (gs_iter, bm_unique_verts) { + gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter), + buffers->vert_buf, + &v_index, + NULL, + NULL, + cd_vert_mask_offset, + show_mask, + &empty_mask); + } + + GSET_ITER (gs_iter, bm_other_verts) { + gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter), + buffers->vert_buf, + &v_index, + NULL, + NULL, + cd_vert_mask_offset, + show_mask, + &empty_mask); + } + + maxvert = v_index; + } + else { + GSetIterator gs_iter; + + GPUIndexBufBuilder elb_lines; + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert); + + GSET_ITER (gs_iter, bm_faces) { + BMFace *f = BLI_gsetIterator_getKey(&gs_iter); + + BLI_assert(f->len == 3); + + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + BMVert *v[3]; + float fmask = 0.0f; + int i; + + BM_face_as_array_vert_tri(f, v); + + /* Average mask value */ + for (i = 0; i < 3; i++) { + fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset); + } + fmask /= 3.0f; + + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1); + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2); + GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0); + + for (i = 0; i < 3; i++) { + gpu_bmesh_vert_to_buffer_copy__gwn(v[i], + buffers->vert_buf, + &v_index, + f->no, + &fmask, + cd_vert_mask_offset, + show_mask, + &empty_mask); + } + } + } + + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + buffers->tot_tri = tottri; + } + + /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */ + bm->elem_index_dirty |= BM_VERT; + } + else { + /* Memory map failed */ + return; + } + + if (buffers->smooth) { + /* Fill the triangle buffer */ + GPUIndexBufBuilder elb, elb_lines; + GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert); + GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, maxvert); + + /* Fill triangle index buffer */ + { + GSetIterator gs_iter; + + GSET_ITER (gs_iter, bm_faces) { + BMFace *f = BLI_gsetIterator_getKey(&gs_iter); + + if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) { + BMVert *v[3]; + + BM_face_as_array_vert_tri(f, v); + + uint idx[3] = { + BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])}; + GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]); + + GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]); + GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]); + GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]); + } + } + + buffers->tot_tri = tottri; + + if (buffers->index_buf == NULL) { + buffers->index_buf = GPU_indexbuf_build(&elb); + } + else { + GPU_indexbuf_build_in_place(&elb, buffers->index_buf); + } + + buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines); + } + } + + buffers->show_mask = !empty_mask; + + gpu_pbvh_batch_init(buffers, GPU_PRIM_TRIS); + } + + /** \} */ + + /* -------------------------------------------------------------------- */ + /** \name Generic * \{ */ -GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) -{ - GPU_PBVH_Buffers *buffers; - - buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); - buffers->use_bmesh = true; - buffers->smooth = smooth_shading; - buffers->show_mask = true; - - return buffers; -} - -GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers *buffers, bool fast, bool wires) -{ - if (wires) { - return (fast && buffers->lines_fast) ? - buffers->lines_fast : buffers->lines; - } - else { - return (fast && buffers->triangles_fast) ? - buffers->triangles_fast : buffers->triangles; - } -} - -bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers *buffers) -{ - return buffers->show_mask; -} - -void GPU_pbvh_buffers_free(GPU_PBVH_Buffers *buffers) -{ - if (buffers) { - GPU_BATCH_DISCARD_SAFE(buffers->lines); - GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); - GPU_BATCH_DISCARD_SAFE(buffers->triangles); - GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); - GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); - GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); - - MEM_freeN(buffers); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Debug + GPU_PBVH_Buffers *GPU_pbvh_bmesh_buffers_build(bool smooth_shading) + { + GPU_PBVH_Buffers *buffers; + + buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers"); + buffers->use_bmesh = true; + buffers->smooth = smooth_shading; + buffers->show_mask = true; + + return buffers; + } + + GPUBatch *GPU_pbvh_buffers_batch_get(GPU_PBVH_Buffers * buffers, bool fast, bool wires) + { + if (wires) { + return (fast && buffers->lines_fast) ? buffers->lines_fast : buffers->lines; + } + else { + return (fast && buffers->triangles_fast) ? buffers->triangles_fast : buffers->triangles; + } + } + + bool GPU_pbvh_buffers_has_mask(GPU_PBVH_Buffers * buffers) + { + return buffers->show_mask; + } + + void GPU_pbvh_buffers_free(GPU_PBVH_Buffers * buffers) + { + if (buffers) { + GPU_BATCH_DISCARD_SAFE(buffers->lines); + GPU_BATCH_DISCARD_SAFE(buffers->lines_fast); + GPU_BATCH_DISCARD_SAFE(buffers->triangles); + GPU_BATCH_DISCARD_SAFE(buffers->triangles_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_lines_buf); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf_fast); + GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf); + GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf); + + MEM_freeN(buffers); + } + } + + /** \} */ + + /* -------------------------------------------------------------------- */ + /** \name Debug * \{ */ -/* debug function, draws the pbvh BB */ -void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, uint pos) -{ - if (leaf) - immUniformColor4f(0.0, 1.0, 0.0, 0.5); - else - immUniformColor4f(1.0, 0.0, 0.0, 0.5); + /* debug function, draws the pbvh BB */ + void GPU_pbvh_BB_draw(float min[3], float max[3], bool leaf, uint pos) + { + if (leaf) + immUniformColor4f(0.0, 1.0, 0.0, 0.5); + else + immUniformColor4f(1.0, 0.0, 0.0, 0.5); - /* TODO(merwin): revisit this after we have mutable VertexBuffers - * could keep a static batch & index buffer, change the VBO contents per draw - */ + /* TODO(merwin): revisit this after we have mutable VertexBuffers + * could keep a static batch & index buffer, change the VBO contents per draw + */ - immBegin(GPU_PRIM_LINES, 24); + immBegin(GPU_PRIM_LINES, 24); - /* top */ - immVertex3f(pos, min[0], min[1], max[2]); - immVertex3f(pos, min[0], max[1], max[2]); + /* top */ + immVertex3f(pos, min[0], min[1], max[2]); + immVertex3f(pos, min[0], max[1], max[2]); - immVertex3f(pos, min[0], max[1], max[2]); - immVertex3f(pos, max[0], max[1], max[2]); + immVertex3f(pos, min[0], max[1], max[2]); + immVertex3f(pos, max[0], max[1], max[2]); - immVertex3f(pos, max[0], max[1], max[2]); - immVertex3f(pos, max[0], min[1], max[2]); + immVertex3f(pos, max[0], max[1], max[2]); + immVertex3f(pos, max[0], min[1], max[2]); - immVertex3f(pos, max[0], min[1], max[2]); - immVertex3f(pos, min[0], min[1], max[2]); + immVertex3f(pos, max[0], min[1], max[2]); + immVertex3f(pos, min[0], min[1], max[2]); - /* bottom */ - immVertex3f(pos, min[0], min[1], min[2]); - immVertex3f(pos, min[0], max[1], min[2]); + /* bottom */ + immVertex3f(pos, min[0], min[1], min[2]); + immVertex3f(pos, min[0], max[1], min[2]); - immVertex3f(pos, min[0], max[1], min[2]); - immVertex3f(pos, max[0], max[1], min[2]); + immVertex3f(pos, min[0], max[1], min[2]); + immVertex3f(pos, max[0], max[1], min[2]); - immVertex3f(pos, max[0], max[1], min[2]); - immVertex3f(pos, max[0], min[1], min[2]); + immVertex3f(pos, max[0], max[1], min[2]); + immVertex3f(pos, max[0], min[1], min[2]); - immVertex3f(pos, max[0], min[1], min[2]); - immVertex3f(pos, min[0], min[1], min[2]); + immVertex3f(pos, max[0], min[1], min[2]); + immVertex3f(pos, min[0], min[1], min[2]); - /* sides */ - immVertex3f(pos, min[0], min[1], min[2]); - immVertex3f(pos, min[0], min[1], max[2]); + /* sides */ + immVertex3f(pos, min[0], min[1], min[2]); + immVertex3f(pos, min[0], min[1], max[2]); - immVertex3f(pos, min[0], max[1], min[2]); - immVertex3f(pos, min[0], max[1], max[2]); + immVertex3f(pos, min[0], max[1], min[2]); + immVertex3f(pos, min[0], max[1], max[2]); - immVertex3f(pos, max[0], max[1], min[2]); - immVertex3f(pos, max[0], max[1], max[2]); + immVertex3f(pos, max[0], max[1], min[2]); + immVertex3f(pos, max[0], max[1], max[2]); - immVertex3f(pos, max[0], min[1], min[2]); - immVertex3f(pos, max[0], min[1], max[2]); + immVertex3f(pos, max[0], min[1], min[2]); + immVertex3f(pos, max[0], min[1], max[2]); - immEnd(); -} + immEnd(); + } -/** \} */ + /** \} */ -void GPU_pbvh_fix_linking() -{ -} + void GPU_pbvh_fix_linking() + { + } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 84164045984..458c0d5da85 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -72,81 +72,100 @@ static SpinLock pass_cache_spin; static uint32_t gpu_pass_hash(const char *frag_gen, const char *defs, GPUVertAttrLayers *attrs) { - BLI_HashMurmur2A hm2a; - BLI_hash_mm2a_init(&hm2a, 0); - BLI_hash_mm2a_add(&hm2a, (uchar *)frag_gen, strlen(frag_gen)); - if (attrs) { - for (int att_idx = 0; att_idx < attrs->totlayer; att_idx++) { - char *name = attrs->layer[att_idx].name; - BLI_hash_mm2a_add(&hm2a, (uchar *)name, strlen(name)); - } - } - if (defs) - BLI_hash_mm2a_add(&hm2a, (uchar *)defs, strlen(defs)); - - return BLI_hash_mm2a_end(&hm2a); + BLI_HashMurmur2A hm2a; + BLI_hash_mm2a_init(&hm2a, 0); + BLI_hash_mm2a_add(&hm2a, (uchar *)frag_gen, strlen(frag_gen)); + if (attrs) { + for (int att_idx = 0; att_idx < attrs->totlayer; att_idx++) { + char *name = attrs->layer[att_idx].name; + BLI_hash_mm2a_add(&hm2a, (uchar *)name, strlen(name)); + } + } + if (defs) + BLI_hash_mm2a_add(&hm2a, (uchar *)defs, strlen(defs)); + + return BLI_hash_mm2a_end(&hm2a); } /* Search by hash only. Return first pass with the same hash. * There is hash collision if (pass->next && pass->next->hash == hash) */ static GPUPass *gpu_pass_cache_lookup(uint32_t hash) { - BLI_spin_lock(&pass_cache_spin); - /* Could be optimized with a Lookup table. */ - for (GPUPass *pass = pass_cache; pass; pass = pass->next) { - if (pass->hash == hash) { - BLI_spin_unlock(&pass_cache_spin); - return pass; - } - } - BLI_spin_unlock(&pass_cache_spin); - return NULL; + BLI_spin_lock(&pass_cache_spin); + /* Could be optimized with a Lookup table. */ + for (GPUPass *pass = pass_cache; pass; pass = pass->next) { + if (pass->hash == hash) { + BLI_spin_unlock(&pass_cache_spin); + return pass; + } + } + BLI_spin_unlock(&pass_cache_spin); + return NULL; } /* Check all possible passes with the same hash. */ -static GPUPass *gpu_pass_cache_resolve_collision( - GPUPass *pass, const char *vert, const char *geom, const char *frag, const char *defs, uint32_t hash) +static GPUPass *gpu_pass_cache_resolve_collision(GPUPass *pass, + const char *vert, + const char *geom, + const char *frag, + const char *defs, + uint32_t hash) { - BLI_spin_lock(&pass_cache_spin); - /* Collision, need to strcmp the whole shader. */ - for (; pass && (pass->hash == hash); pass = pass->next) { - if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ } - else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ } - else if ((strcmp(pass->fragmentcode, frag) == 0) && - (strcmp(pass->vertexcode, vert) == 0)) - { - BLI_spin_unlock(&pass_cache_spin); - return pass; - } - } - BLI_spin_unlock(&pass_cache_spin); - return NULL; + BLI_spin_lock(&pass_cache_spin); + /* Collision, need to strcmp the whole shader. */ + for (; pass && (pass->hash == hash); pass = pass->next) { + if ((defs != NULL) && (strcmp(pass->defines, defs) != 0)) { /* Pass */ + } + else if ((geom != NULL) && (strcmp(pass->geometrycode, geom) != 0)) { /* Pass */ + } + else if ((strcmp(pass->fragmentcode, frag) == 0) && (strcmp(pass->vertexcode, vert) == 0)) { + BLI_spin_unlock(&pass_cache_spin); + return pass; + } + } + BLI_spin_unlock(&pass_cache_spin); + return NULL; } /* -------------------- GPU Codegen ------------------ */ /* type definitions and constants */ -#define MAX_FUNCTION_NAME 64 -#define MAX_PARAMETER 32 +#define MAX_FUNCTION_NAME 64 +#define MAX_PARAMETER 32 typedef enum { - FUNCTION_QUAL_IN, - FUNCTION_QUAL_OUT, - FUNCTION_QUAL_INOUT, + FUNCTION_QUAL_IN, + FUNCTION_QUAL_OUT, + FUNCTION_QUAL_INOUT, } GPUFunctionQual; typedef struct GPUFunction { - char name[MAX_FUNCTION_NAME]; - eGPUType paramtype[MAX_PARAMETER]; - GPUFunctionQual paramqual[MAX_PARAMETER]; - int totparam; + char name[MAX_FUNCTION_NAME]; + eGPUType paramtype[MAX_PARAMETER]; + GPUFunctionQual paramqual[MAX_PARAMETER]; + int totparam; } GPUFunction; /* Indices match the eGPUType enum */ static const char *GPU_DATATYPE_STR[17] = { - "", "float", "vec2", "vec3", "vec4", - NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4", + "", + "float", + "vec2", + "vec3", + "vec4", + NULL, + NULL, + NULL, + NULL, + "mat3", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + "mat4", }; /* GLSL code parsing for finding function definitions. @@ -160,219 +179,219 @@ static GPUShader *FUNCTION_LIB = NULL; static int gpu_str_prefix(const char *str, const char *prefix) { - while (*str && *prefix) { - if (*str != *prefix) - return 0; + while (*str && *prefix) { + if (*str != *prefix) + return 0; - str++; - prefix++; - } + str++; + prefix++; + } - return (*prefix == '\0'); + return (*prefix == '\0'); } static char *gpu_str_skip_token(char *str, char *token, int max) { - int len = 0; - - /* skip a variable/function name */ - while (*str) { - if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r')) - break; - else { - if (token && len < max - 1) { - *token = *str; - token++; - len++; - } - str++; - } - } - - if (token) - *token = '\0'; - - /* skip the next special characters: - * note the missing ')' */ - while (*str) { - if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r')) - str++; - else - break; - } - - return str; + int len = 0; + + /* skip a variable/function name */ + while (*str) { + if (ELEM(*str, ' ', '(', ')', ',', ';', '\t', '\n', '\r')) + break; + else { + if (token && len < max - 1) { + *token = *str; + token++; + len++; + } + str++; + } + } + + if (token) + *token = '\0'; + + /* skip the next special characters: + * note the missing ')' */ + while (*str) { + if (ELEM(*str, ' ', '(', ',', ';', '\t', '\n', '\r')) + str++; + else + break; + } + + return str; } static void gpu_parse_functions_string(GHash *hash, char *code) { - GPUFunction *function; - eGPUType type; - GPUFunctionQual qual; - int i; - - while ((code = strstr(code, "void "))) { - function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); - - code = gpu_str_skip_token(code, NULL, 0); - code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); - - /* get parameters */ - while (*code && *code != ')') { - /* test if it's an input or output */ - qual = FUNCTION_QUAL_IN; - if (gpu_str_prefix(code, "out ")) - qual = FUNCTION_QUAL_OUT; - if (gpu_str_prefix(code, "inout ")) - qual = FUNCTION_QUAL_INOUT; - if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) - code = gpu_str_skip_token(code, NULL, 0); - - /* test for type */ - type = GPU_NONE; - for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) { - if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { - type = i; - break; - } - } - - if (!type && gpu_str_prefix(code, "samplerCube")) { - type = GPU_TEXCUBE; - } - if (!type && gpu_str_prefix(code, "sampler2DShadow")) { - type = GPU_SHADOW2D; - } - if (!type && gpu_str_prefix(code, "sampler1DArray")) { - type = GPU_TEX1D_ARRAY; - } - if (!type && gpu_str_prefix(code, "sampler2D")) { - type = GPU_TEX2D; - } - if (!type && gpu_str_prefix(code, "sampler3D")) { - type = GPU_TEX3D; - } - - if (!type && gpu_str_prefix(code, "Closure")) { - type = GPU_CLOSURE; - } - - if (type) { - /* add parameter */ - code = gpu_str_skip_token(code, NULL, 0); - code = gpu_str_skip_token(code, NULL, 0); - function->paramqual[function->totparam] = qual; - function->paramtype[function->totparam] = type; - function->totparam++; - } - else { - fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name); - break; - } - } - - if (function->name[0] == '\0' || function->totparam == 0) { - fprintf(stderr, "GPU functions parse error.\n"); - MEM_freeN(function); - break; - } - - BLI_ghash_insert(hash, function->name, function); - } + GPUFunction *function; + eGPUType type; + GPUFunctionQual qual; + int i; + + while ((code = strstr(code, "void "))) { + function = MEM_callocN(sizeof(GPUFunction), "GPUFunction"); + + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, function->name, MAX_FUNCTION_NAME); + + /* get parameters */ + while (*code && *code != ')') { + /* test if it's an input or output */ + qual = FUNCTION_QUAL_IN; + if (gpu_str_prefix(code, "out ")) + qual = FUNCTION_QUAL_OUT; + if (gpu_str_prefix(code, "inout ")) + qual = FUNCTION_QUAL_INOUT; + if ((qual != FUNCTION_QUAL_IN) || gpu_str_prefix(code, "in ")) + code = gpu_str_skip_token(code, NULL, 0); + + /* test for type */ + type = GPU_NONE; + for (i = 1; i < ARRAY_SIZE(GPU_DATATYPE_STR); i++) { + if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) { + type = i; + break; + } + } + + if (!type && gpu_str_prefix(code, "samplerCube")) { + type = GPU_TEXCUBE; + } + if (!type && gpu_str_prefix(code, "sampler2DShadow")) { + type = GPU_SHADOW2D; + } + if (!type && gpu_str_prefix(code, "sampler1DArray")) { + type = GPU_TEX1D_ARRAY; + } + if (!type && gpu_str_prefix(code, "sampler2D")) { + type = GPU_TEX2D; + } + if (!type && gpu_str_prefix(code, "sampler3D")) { + type = GPU_TEX3D; + } + + if (!type && gpu_str_prefix(code, "Closure")) { + type = GPU_CLOSURE; + } + + if (type) { + /* add parameter */ + code = gpu_str_skip_token(code, NULL, 0); + code = gpu_str_skip_token(code, NULL, 0); + function->paramqual[function->totparam] = qual; + function->paramtype[function->totparam] = type; + function->totparam++; + } + else { + fprintf(stderr, "GPU invalid function parameter in %s.\n", function->name); + break; + } + } + + if (function->name[0] == '\0' || function->totparam == 0) { + fprintf(stderr, "GPU functions parse error.\n"); + MEM_freeN(function); + break; + } + + BLI_ghash_insert(hash, function->name, function); + } } #if 0 static char *gpu_generate_function_prototyps(GHash *hash) { - DynStr *ds = BLI_dynstr_new(); - GHashIterator *ghi; - GPUFunction *function; - char *name, *prototypes; - int a; - - /* automatically generate function prototypes to add to the top of the - * generated code, to avoid have to add the actual code & recompile all */ - ghi = BLI_ghashIterator_new(hash); - - for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) { - name = BLI_ghashIterator_getValue(ghi); - function = BLI_ghashIterator_getValue(ghi); - - BLI_dynstr_appendf(ds, "void %s(", name); - for (a = 0; a < function->totparam; a++) { - if (function->paramqual[a] == FUNCTION_QUAL_OUT) - BLI_dynstr_append(ds, "out "); - else if (function->paramqual[a] == FUNCTION_QUAL_INOUT) - BLI_dynstr_append(ds, "inout "); - - if (function->paramtype[a] == GPU_TEX2D) - BLI_dynstr_append(ds, "sampler2D"); - else if (function->paramtype[a] == GPU_SHADOW2D) - BLI_dynstr_append(ds, "sampler2DShadow"); - else - BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); + DynStr *ds = BLI_dynstr_new(); + GHashIterator *ghi; + GPUFunction *function; + char *name, *prototypes; + int a; + + /* automatically generate function prototypes to add to the top of the + * generated code, to avoid have to add the actual code & recompile all */ + ghi = BLI_ghashIterator_new(hash); + + for (; !BLI_ghashIterator_done(ghi); BLI_ghashIterator_step(ghi)) { + name = BLI_ghashIterator_getValue(ghi); + function = BLI_ghashIterator_getValue(ghi); + + BLI_dynstr_appendf(ds, "void %s(", name); + for (a = 0; a < function->totparam; a++) { + if (function->paramqual[a] == FUNCTION_QUAL_OUT) + BLI_dynstr_append(ds, "out "); + else if (function->paramqual[a] == FUNCTION_QUAL_INOUT) + BLI_dynstr_append(ds, "inout "); + + if (function->paramtype[a] == GPU_TEX2D) + BLI_dynstr_append(ds, "sampler2D"); + else if (function->paramtype[a] == GPU_SHADOW2D) + BLI_dynstr_append(ds, "sampler2DShadow"); + else + BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); # if 0 - BLI_dynstr_appendf(ds, " param%d", a); + BLI_dynstr_appendf(ds, " param%d", a); # endif - if (a != function->totparam - 1) - BLI_dynstr_append(ds, ", "); - } - BLI_dynstr_append(ds, ");\n"); - } + if (a != function->totparam - 1) + BLI_dynstr_append(ds, ", "); + } + BLI_dynstr_append(ds, ");\n"); + } - BLI_dynstr_append(ds, "\n"); + BLI_dynstr_append(ds, "\n"); - prototypes = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); + prototypes = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); - return prototypes; + return prototypes; } #endif static GPUFunction *gpu_lookup_function(const char *name) { - if (!FUNCTION_HASH) { - FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); - gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library); - } + if (!FUNCTION_HASH) { + FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh"); + gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library); + } - return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name); + return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name); } void gpu_codegen_init(void) { - GPU_code_generate_glsl_lib(); + GPU_code_generate_glsl_lib(); } void gpu_codegen_exit(void) { - extern Material defmaterial; /* render module abuse... */ + extern Material defmaterial; /* render module abuse... */ - if (defmaterial.gpumaterial.first) - GPU_material_free(&defmaterial.gpumaterial); + if (defmaterial.gpumaterial.first) + GPU_material_free(&defmaterial.gpumaterial); - if (FUNCTION_HASH) { - BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN); - FUNCTION_HASH = NULL; - } + if (FUNCTION_HASH) { + BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN); + FUNCTION_HASH = NULL; + } - GPU_shader_free_builtin_shaders(); + GPU_shader_free_builtin_shaders(); - if (glsl_material_library) { - MEM_freeN(glsl_material_library); - glsl_material_library = NULL; - } + if (glsl_material_library) { + MEM_freeN(glsl_material_library); + glsl_material_library = NULL; + } #if 0 - if (FUNCTION_PROTOTYPES) { - MEM_freeN(FUNCTION_PROTOTYPES); - FUNCTION_PROTOTYPES = NULL; - } - if (FUNCTION_LIB) { - GPU_shader_free(FUNCTION_LIB); - FUNCTION_LIB = NULL; - } + if (FUNCTION_PROTOTYPES) { + MEM_freeN(FUNCTION_PROTOTYPES); + FUNCTION_PROTOTYPES = NULL; + } + if (FUNCTION_LIB) { + GPU_shader_free(FUNCTION_LIB); + FUNCTION_LIB = NULL; + } #endif } @@ -380,189 +399,189 @@ void gpu_codegen_exit(void) static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *tmp, int id) { - char name[1024]; - - BLI_snprintf(name, sizeof(name), "%s%d", tmp, id); - - if (from == to) { - BLI_dynstr_append(ds, name); - } - else if (to == GPU_FLOAT) { - if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name); - else if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name); - else if (from == GPU_VEC2) - BLI_dynstr_appendf(ds, "%s.r", name); - } - else if (to == GPU_VEC2) { - if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name); - else if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name); - else if (from == GPU_FLOAT) - BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name); - } - else if (to == GPU_VEC3) { - if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "%s.rgb", name); - else if (from == GPU_VEC2) - BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); - else if (from == GPU_FLOAT) - BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name); - } - else if (to == GPU_VEC4) { - if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name); - else if (from == GPU_VEC2) - BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); - else if (from == GPU_FLOAT) - BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); - } - else if (to == GPU_CLOSURE) { - if (from == GPU_VEC4) - BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); - else if (from == GPU_VEC3) - BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); - else if (from == GPU_VEC2) - BLI_dynstr_appendf(ds, "closure_emission(%s.rrr)", name); - else if (from == GPU_FLOAT) - BLI_dynstr_appendf(ds, "closure_emission(vec3(%s, %s, %s))", name, name, name); - } - else { - BLI_dynstr_append(ds, name); - } + char name[1024]; + + BLI_snprintf(name, sizeof(name), "%s%d", tmp, id); + + if (from == to) { + BLI_dynstr_append(ds, name); + } + else if (to == GPU_FLOAT) { + if (from == GPU_VEC4) + BLI_dynstr_appendf(ds, "convert_rgba_to_float(%s)", name); + else if (from == GPU_VEC3) + BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name); + else if (from == GPU_VEC2) + BLI_dynstr_appendf(ds, "%s.r", name); + } + else if (to == GPU_VEC2) { + if (from == GPU_VEC4) + BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name); + else if (from == GPU_VEC3) + BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name); + } + else if (to == GPU_VEC3) { + if (from == GPU_VEC4) + BLI_dynstr_appendf(ds, "%s.rgb", name); + else if (from == GPU_VEC2) + BLI_dynstr_appendf(ds, "vec3(%s.r, %s.r, %s.r)", name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_appendf(ds, "vec3(%s, %s, %s)", name, name, name); + } + else if (to == GPU_VEC4) { + if (from == GPU_VEC3) + BLI_dynstr_appendf(ds, "vec4(%s, 1.0)", name); + else if (from == GPU_VEC2) + BLI_dynstr_appendf(ds, "vec4(%s.r, %s.r, %s.r, %s.g)", name, name, name, name); + else if (from == GPU_FLOAT) + BLI_dynstr_appendf(ds, "vec4(%s, %s, %s, 1.0)", name, name, name); + } + else if (to == GPU_CLOSURE) { + if (from == GPU_VEC4) + BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); + else if (from == GPU_VEC3) + BLI_dynstr_appendf(ds, "closure_emission(%s.rgb)", name); + else if (from == GPU_VEC2) + BLI_dynstr_appendf(ds, "closure_emission(%s.rrr)", name); + else if (from == GPU_FLOAT) + BLI_dynstr_appendf(ds, "closure_emission(vec3(%s, %s, %s))", name, name, name); + } + else { + BLI_dynstr_append(ds, name); + } } static void codegen_print_datatype(DynStr *ds, const eGPUType type, float *data) { - int i; + int i; - BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); + BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); - for (i = 0; i < type; i++) { - BLI_dynstr_appendf(ds, "%.12f", data[i]); - if (i == type - 1) - BLI_dynstr_append(ds, ")"); - else - BLI_dynstr_append(ds, ", "); - } + for (i = 0; i < type; i++) { + BLI_dynstr_appendf(ds, "%.12f", data[i]); + if (i == type - 1) + BLI_dynstr_append(ds, ")"); + else + BLI_dynstr_append(ds, ", "); + } } static int codegen_input_has_texture(GPUInput *input) { - if (input->link) - return 0; - else - return (input->source == GPU_SOURCE_TEX); + if (input->link) + return 0; + else + return (input->source == GPU_SOURCE_TEX); } const char *GPU_builtin_name(eGPUBuiltin builtin) { - if (builtin == GPU_VIEW_MATRIX) - return "unfviewmat"; - else if (builtin == GPU_OBJECT_MATRIX) - return "unfobmat"; - else if (builtin == GPU_INVERSE_VIEW_MATRIX) - return "unfinvviewmat"; - else if (builtin == GPU_INVERSE_OBJECT_MATRIX) - return "unfinvobmat"; - else if (builtin == GPU_INVERSE_NORMAL_MATRIX) - return "unfinvnormat"; - else if (builtin == GPU_LOC_TO_VIEW_MATRIX) - return "unflocaltoviewmat"; - else if (builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX) - return "unfinvlocaltoviewmat"; - else if (builtin == GPU_VIEW_POSITION) - return "varposition"; - else if (builtin == GPU_VIEW_NORMAL) - return "varnormal"; - else if (builtin == GPU_OBCOLOR) - return "unfobcolor"; - else if (builtin == GPU_AUTO_BUMPSCALE) - return "unfobautobumpscale"; - else if (builtin == GPU_CAMERA_TEXCO_FACTORS) - return "unfcameratexfactors"; - else if (builtin == GPU_PARTICLE_SCALAR_PROPS) - return "unfparticlescalarprops"; - else if (builtin == GPU_PARTICLE_LOCATION) - return "unfparticleco"; - else if (builtin == GPU_PARTICLE_VELOCITY) - return "unfparticlevel"; - else if (builtin == GPU_PARTICLE_ANG_VELOCITY) - return "unfparticleangvel"; - else if (builtin == GPU_OBJECT_INFO) - return "unfobjectinfo"; - else if (builtin == GPU_VOLUME_DENSITY) - return "sampdensity"; - else if (builtin == GPU_VOLUME_FLAME) - return "sampflame"; - else if (builtin == GPU_VOLUME_TEMPERATURE) - return "unftemperature"; - else if (builtin == GPU_BARYCENTRIC_TEXCO) - return "unfbarycentrictex"; - else if (builtin == GPU_BARYCENTRIC_DIST) - return "unfbarycentricdist"; - else - return ""; + if (builtin == GPU_VIEW_MATRIX) + return "unfviewmat"; + else if (builtin == GPU_OBJECT_MATRIX) + return "unfobmat"; + else if (builtin == GPU_INVERSE_VIEW_MATRIX) + return "unfinvviewmat"; + else if (builtin == GPU_INVERSE_OBJECT_MATRIX) + return "unfinvobmat"; + else if (builtin == GPU_INVERSE_NORMAL_MATRIX) + return "unfinvnormat"; + else if (builtin == GPU_LOC_TO_VIEW_MATRIX) + return "unflocaltoviewmat"; + else if (builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX) + return "unfinvlocaltoviewmat"; + else if (builtin == GPU_VIEW_POSITION) + return "varposition"; + else if (builtin == GPU_VIEW_NORMAL) + return "varnormal"; + else if (builtin == GPU_OBCOLOR) + return "unfobcolor"; + else if (builtin == GPU_AUTO_BUMPSCALE) + return "unfobautobumpscale"; + else if (builtin == GPU_CAMERA_TEXCO_FACTORS) + return "unfcameratexfactors"; + else if (builtin == GPU_PARTICLE_SCALAR_PROPS) + return "unfparticlescalarprops"; + else if (builtin == GPU_PARTICLE_LOCATION) + return "unfparticleco"; + else if (builtin == GPU_PARTICLE_VELOCITY) + return "unfparticlevel"; + else if (builtin == GPU_PARTICLE_ANG_VELOCITY) + return "unfparticleangvel"; + else if (builtin == GPU_OBJECT_INFO) + return "unfobjectinfo"; + else if (builtin == GPU_VOLUME_DENSITY) + return "sampdensity"; + else if (builtin == GPU_VOLUME_FLAME) + return "sampflame"; + else if (builtin == GPU_VOLUME_TEMPERATURE) + return "unftemperature"; + else if (builtin == GPU_BARYCENTRIC_TEXCO) + return "unfbarycentrictex"; + else if (builtin == GPU_BARYCENTRIC_DIST) + return "unfbarycentricdist"; + else + return ""; } /* assign only one texid per buffer to avoid sampling the same texture twice */ static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key) { - if (BLI_ghash_haskey(bindhash, key)) { - /* Reuse existing texid */ - input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, key)); - } - else { - /* Allocate new texid */ - input->texid = *texid; - (*texid)++; - input->bindtex = true; - BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid)); - } + if (BLI_ghash_haskey(bindhash, key)) { + /* Reuse existing texid */ + input->texid = POINTER_AS_INT(BLI_ghash_lookup(bindhash, key)); + } + else { + /* Allocate new texid */ + input->texid = *texid; + (*texid)++; + input->bindtex = true; + BLI_ghash_insert(bindhash, key, POINTER_FROM_INT(input->texid)); + } } static void codegen_set_unique_ids(ListBase *nodes) { - GHash *bindhash; - GPUNode *node; - GPUInput *input; - GPUOutput *output; - int id = 1, texid = 0; - - bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - /* set id for unique names of uniform variables */ - input->id = id++; - - /* set texid used for settings texture slot */ - if (codegen_input_has_texture(input)) { - input->bindtex = false; - if (input->ima) { - /* input is texture from image */ - codegen_set_texid(bindhash, input, &texid, input->ima); - } - else if (input->coba) { - /* input is color band texture, check coba pointer */ - codegen_set_texid(bindhash, input, &texid, input->coba); - } - else { - /* Either input->ima or input->coba should be non-NULL. */ - BLI_assert(0); - } - } - } - - for (output = node->outputs.first; output; output = output->next) { - /* set id for unique names of tmp variables storing output */ - output->id = id++; - } - } - - BLI_ghash_free(bindhash, NULL, NULL); + GHash *bindhash; + GPUNode *node; + GPUInput *input; + GPUOutput *output; + int id = 1, texid = 0; + + bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh"); + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + /* set id for unique names of uniform variables */ + input->id = id++; + + /* set texid used for settings texture slot */ + if (codegen_input_has_texture(input)) { + input->bindtex = false; + if (input->ima) { + /* input is texture from image */ + codegen_set_texid(bindhash, input, &texid, input->ima); + } + else if (input->coba) { + /* input is color band texture, check coba pointer */ + codegen_set_texid(bindhash, input, &texid, input->coba); + } + else { + /* Either input->ima or input->coba should be non-NULL. */ + BLI_assert(0); + } + } + } + + for (output = node->outputs.first; output; output = output->next) { + /* set id for unique names of tmp variables storing output */ + output->id = id++; + } + } + + BLI_ghash_free(bindhash, NULL, NULL); } /** @@ -570,1511 +589,1518 @@ static void codegen_set_unique_ids(ListBase *nodes) */ static int codegen_process_uniforms_functions(GPUMaterial *material, DynStr *ds, ListBase *nodes) { - GPUNode *node; - GPUInput *input; - const char *name; - int builtins = 0; - ListBase ubo_inputs = {NULL, NULL}; - - /* print uniforms */ - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_TEX) { - /* create exactly one sampler for each texture */ - if (codegen_input_has_texture(input) && input->bindtex) { - BLI_dynstr_appendf( - ds, "uniform %s samp%d;\n", - (input->coba) ? "sampler1DArray" : "sampler2D", - input->texid); - } - } - else if (input->source == GPU_SOURCE_BUILTIN) { - /* only define each builtin uniform/varying once */ - if (!(builtins & input->builtin)) { - builtins |= input->builtin; - name = GPU_builtin_name(input->builtin); - - if (gpu_str_prefix(name, "samp")) { - if ((input->builtin == GPU_VOLUME_DENSITY) || - (input->builtin == GPU_VOLUME_FLAME)) - { - BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name); - } - } - else if (gpu_str_prefix(name, "unf")) { - BLI_dynstr_appendf( - ds, "uniform %s %s;\n", - GPU_DATATYPE_STR[input->type], name); - } - else { - BLI_dynstr_appendf( - ds, "in %s %s;\n", - GPU_DATATYPE_STR[input->type], name); - } - } - } - else if (input->source == GPU_SOURCE_STRUCT) { - /* Add other struct here if needed. */ - BLI_dynstr_appendf(ds, "Closure strct%d = CLOSURE_DEFAULT;\n", input->id); - } - else if (input->source == GPU_SOURCE_UNIFORM) { - if (!input->link) { - /* We handle the UBOuniforms separately. */ - BLI_addtail(&ubo_inputs, BLI_genericNodeN(input)); - } - } - else if (input->source == GPU_SOURCE_CONSTANT) { - BLI_dynstr_appendf( - ds, "const %s cons%d = ", - GPU_DATATYPE_STR[input->type], input->id); - codegen_print_datatype(ds, input->type, input->vec); - BLI_dynstr_append(ds, ";\n"); - } - else if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - BLI_dynstr_appendf( - ds, "in %s var%d;\n", - GPU_DATATYPE_STR[input->type], input->attr_id); - } - } - } - - /* Handle the UBO block separately. */ - if ((material != NULL) && !BLI_listbase_is_empty(&ubo_inputs)) { - GPU_material_uniform_buffer_create(material, &ubo_inputs); - - /* Inputs are sorted */ - BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME); - - for (LinkData *link = ubo_inputs.first; link; link = link->next) { - input = link->data; - BLI_dynstr_appendf( - ds, "\t%s unf%d;\n", - GPU_DATATYPE_STR[input->type], input->id); - } - BLI_dynstr_append(ds, "};\n"); - BLI_freelistN(&ubo_inputs); - } - - BLI_dynstr_append(ds, "\n"); - - return builtins; + GPUNode *node; + GPUInput *input; + const char *name; + int builtins = 0; + ListBase ubo_inputs = {NULL, NULL}; + + /* print uniforms */ + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_TEX) { + /* create exactly one sampler for each texture */ + if (codegen_input_has_texture(input) && input->bindtex) { + BLI_dynstr_appendf(ds, + "uniform %s samp%d;\n", + (input->coba) ? "sampler1DArray" : "sampler2D", + input->texid); + } + } + else if (input->source == GPU_SOURCE_BUILTIN) { + /* only define each builtin uniform/varying once */ + if (!(builtins & input->builtin)) { + builtins |= input->builtin; + name = GPU_builtin_name(input->builtin); + + if (gpu_str_prefix(name, "samp")) { + if ((input->builtin == GPU_VOLUME_DENSITY) || (input->builtin == GPU_VOLUME_FLAME)) { + BLI_dynstr_appendf(ds, "uniform sampler3D %s;\n", name); + } + } + else if (gpu_str_prefix(name, "unf")) { + BLI_dynstr_appendf(ds, "uniform %s %s;\n", GPU_DATATYPE_STR[input->type], name); + } + else { + BLI_dynstr_appendf(ds, "in %s %s;\n", GPU_DATATYPE_STR[input->type], name); + } + } + } + else if (input->source == GPU_SOURCE_STRUCT) { + /* Add other struct here if needed. */ + BLI_dynstr_appendf(ds, "Closure strct%d = CLOSURE_DEFAULT;\n", input->id); + } + else if (input->source == GPU_SOURCE_UNIFORM) { + if (!input->link) { + /* We handle the UBOuniforms separately. */ + BLI_addtail(&ubo_inputs, BLI_genericNodeN(input)); + } + } + else if (input->source == GPU_SOURCE_CONSTANT) { + BLI_dynstr_appendf(ds, "const %s cons%d = ", GPU_DATATYPE_STR[input->type], input->id); + codegen_print_datatype(ds, input->type, input->vec); + BLI_dynstr_append(ds, ";\n"); + } + else if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + BLI_dynstr_appendf(ds, "in %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attr_id); + } + } + } + + /* Handle the UBO block separately. */ + if ((material != NULL) && !BLI_listbase_is_empty(&ubo_inputs)) { + GPU_material_uniform_buffer_create(material, &ubo_inputs); + + /* Inputs are sorted */ + BLI_dynstr_appendf(ds, "\nlayout (std140) uniform %s {\n", GPU_UBO_BLOCK_NAME); + + for (LinkData *link = ubo_inputs.first; link; link = link->next) { + input = link->data; + BLI_dynstr_appendf(ds, "\t%s unf%d;\n", GPU_DATATYPE_STR[input->type], input->id); + } + BLI_dynstr_append(ds, "};\n"); + BLI_freelistN(&ubo_inputs); + } + + BLI_dynstr_append(ds, "\n"); + + return builtins; } static void codegen_declare_tmps(DynStr *ds, ListBase *nodes) { - GPUNode *node; - GPUOutput *output; - - for (node = nodes->first; node; node = node->next) { - /* declare temporary variables for node output storage */ - for (output = node->outputs.first; output; output = output->next) { - if (output->type == GPU_CLOSURE) { - BLI_dynstr_appendf( - ds, "\tClosure tmp%d;\n", output->id); - } - else { - BLI_dynstr_appendf( - ds, "\t%s tmp%d;\n", - GPU_DATATYPE_STR[output->type], output->id); - } - } - } - - BLI_dynstr_append(ds, "\n"); + GPUNode *node; + GPUOutput *output; + + for (node = nodes->first; node; node = node->next) { + /* declare temporary variables for node output storage */ + for (output = node->outputs.first; output; output = output->next) { + if (output->type == GPU_CLOSURE) { + BLI_dynstr_appendf(ds, "\tClosure tmp%d;\n", output->id); + } + else { + BLI_dynstr_appendf(ds, "\t%s tmp%d;\n", GPU_DATATYPE_STR[output->type], output->id); + } + } + } + + BLI_dynstr_append(ds, "\n"); } static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *finaloutput) { - GPUNode *node; - GPUInput *input; - GPUOutput *output; - - for (node = nodes->first; node; node = node->next) { - BLI_dynstr_appendf(ds, "\t%s(", node->name); - - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_TEX) { - BLI_dynstr_appendf(ds, "samp%d", input->texid); - } - else if (input->source == GPU_SOURCE_OUTPUT) { - codegen_convert_datatype( - ds, input->link->output->type, input->type, - "tmp", input->link->output->id); - } - else if (input->source == GPU_SOURCE_BUILTIN) { - /* TODO(fclem) get rid of that. */ - if (input->builtin == GPU_INVERSE_VIEW_MATRIX) - BLI_dynstr_append(ds, "viewinv"); - else if (input->builtin == GPU_VIEW_MATRIX) - BLI_dynstr_append(ds, "viewmat"); - else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS) - BLI_dynstr_append(ds, "camtexfac"); - else if (input->builtin == GPU_LOC_TO_VIEW_MATRIX) - BLI_dynstr_append(ds, "localtoviewmat"); - else if (input->builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX) - BLI_dynstr_append(ds, "invlocaltoviewmat"); - else if (input->builtin == GPU_BARYCENTRIC_DIST) - BLI_dynstr_append(ds, "barycentricDist"); - else if (input->builtin == GPU_BARYCENTRIC_TEXCO) - BLI_dynstr_append(ds, "barytexco"); - else if (input->builtin == GPU_OBJECT_MATRIX) - BLI_dynstr_append(ds, "objmat"); - else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) - BLI_dynstr_append(ds, "objinv"); - else if (input->builtin == GPU_INVERSE_NORMAL_MATRIX) - BLI_dynstr_append(ds, "norinv"); - else if (input->builtin == GPU_VIEW_POSITION) - BLI_dynstr_append(ds, "viewposition"); - else if (input->builtin == GPU_VIEW_NORMAL) - BLI_dynstr_append(ds, "facingnormal"); - else - BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); - } - else if (input->source == GPU_SOURCE_STRUCT) { - BLI_dynstr_appendf(ds, "strct%d", input->id); - } - else if (input->source == GPU_SOURCE_UNIFORM) { - BLI_dynstr_appendf(ds, "unf%d", input->id); - } - else if (input->source == GPU_SOURCE_CONSTANT) { - BLI_dynstr_appendf(ds, "cons%d", input->id); - } - else if (input->source == GPU_SOURCE_ATTR) { - BLI_dynstr_appendf(ds, "var%d", input->attr_id); - } - - BLI_dynstr_append(ds, ", "); - } - - for (output = node->outputs.first; output; output = output->next) { - BLI_dynstr_appendf(ds, "tmp%d", output->id); - if (output->next) - BLI_dynstr_append(ds, ", "); - } - - BLI_dynstr_append(ds, ");\n"); - } - - BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id); - BLI_dynstr_append(ds, ";\n"); + GPUNode *node; + GPUInput *input; + GPUOutput *output; + + for (node = nodes->first; node; node = node->next) { + BLI_dynstr_appendf(ds, "\t%s(", node->name); + + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_TEX) { + BLI_dynstr_appendf(ds, "samp%d", input->texid); + } + else if (input->source == GPU_SOURCE_OUTPUT) { + codegen_convert_datatype( + ds, input->link->output->type, input->type, "tmp", input->link->output->id); + } + else if (input->source == GPU_SOURCE_BUILTIN) { + /* TODO(fclem) get rid of that. */ + if (input->builtin == GPU_INVERSE_VIEW_MATRIX) + BLI_dynstr_append(ds, "viewinv"); + else if (input->builtin == GPU_VIEW_MATRIX) + BLI_dynstr_append(ds, "viewmat"); + else if (input->builtin == GPU_CAMERA_TEXCO_FACTORS) + BLI_dynstr_append(ds, "camtexfac"); + else if (input->builtin == GPU_LOC_TO_VIEW_MATRIX) + BLI_dynstr_append(ds, "localtoviewmat"); + else if (input->builtin == GPU_INVERSE_LOC_TO_VIEW_MATRIX) + BLI_dynstr_append(ds, "invlocaltoviewmat"); + else if (input->builtin == GPU_BARYCENTRIC_DIST) + BLI_dynstr_append(ds, "barycentricDist"); + else if (input->builtin == GPU_BARYCENTRIC_TEXCO) + BLI_dynstr_append(ds, "barytexco"); + else if (input->builtin == GPU_OBJECT_MATRIX) + BLI_dynstr_append(ds, "objmat"); + else if (input->builtin == GPU_INVERSE_OBJECT_MATRIX) + BLI_dynstr_append(ds, "objinv"); + else if (input->builtin == GPU_INVERSE_NORMAL_MATRIX) + BLI_dynstr_append(ds, "norinv"); + else if (input->builtin == GPU_VIEW_POSITION) + BLI_dynstr_append(ds, "viewposition"); + else if (input->builtin == GPU_VIEW_NORMAL) + BLI_dynstr_append(ds, "facingnormal"); + else + BLI_dynstr_append(ds, GPU_builtin_name(input->builtin)); + } + else if (input->source == GPU_SOURCE_STRUCT) { + BLI_dynstr_appendf(ds, "strct%d", input->id); + } + else if (input->source == GPU_SOURCE_UNIFORM) { + BLI_dynstr_appendf(ds, "unf%d", input->id); + } + else if (input->source == GPU_SOURCE_CONSTANT) { + BLI_dynstr_appendf(ds, "cons%d", input->id); + } + else if (input->source == GPU_SOURCE_ATTR) { + BLI_dynstr_appendf(ds, "var%d", input->attr_id); + } + + BLI_dynstr_append(ds, ", "); + } + + for (output = node->outputs.first; output; output = output->next) { + BLI_dynstr_appendf(ds, "tmp%d", output->id); + if (output->next) + BLI_dynstr_append(ds, ", "); + } + + BLI_dynstr_append(ds, ");\n"); + } + + BLI_dynstr_appendf(ds, "\n\treturn tmp%d", finaloutput->id); + BLI_dynstr_append(ds, ";\n"); } -static char *code_generate_fragment(GPUMaterial *material, ListBase *nodes, GPUOutput *output, int *rbuiltins) +static char *code_generate_fragment(GPUMaterial *material, + ListBase *nodes, + GPUOutput *output, + int *rbuiltins) { - DynStr *ds = BLI_dynstr_new(); - char *code; - int builtins; + DynStr *ds = BLI_dynstr_new(); + char *code; + int builtins; #if 0 - BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); + BLI_dynstr_append(ds, FUNCTION_PROTOTYPES); #endif - codegen_set_unique_ids(nodes); - *rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes); - - if (builtins & GPU_BARYCENTRIC_TEXCO) - BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n"); - - if (builtins & GPU_BARYCENTRIC_DIST) - BLI_dynstr_append(ds, "flat in vec3 barycentricDist;\n"); - - BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n"); - - if (builtins & GPU_BARYCENTRIC_TEXCO) { - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); - BLI_dynstr_append(ds, "\tvec2 barytexco = vec2((fract(barycentricTexCo.y) != 0.0)\n" - "\t ? barycentricTexCo.x\n" - "\t : 1.0 - barycentricTexCo.x,\n" - "\t 0.0);\n"); - BLI_dynstr_append(ds, "#else\n"); - BLI_dynstr_append(ds, "\tvec2 barytexco = barycentricTexCo;\n"); - BLI_dynstr_append(ds, "#endif\n"); - } - /* TODO(fclem) get rid of that. */ - if (builtins & GPU_VIEW_MATRIX) - BLI_dynstr_append(ds, "\t#define viewmat ViewMatrix\n"); - if (builtins & GPU_CAMERA_TEXCO_FACTORS) - BLI_dynstr_append(ds, "\t#define camtexfac CameraTexCoFactors\n"); - if (builtins & GPU_OBJECT_MATRIX) - BLI_dynstr_append(ds, "\t#define objmat ModelMatrix\n"); - if (builtins & GPU_INVERSE_OBJECT_MATRIX) - BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n"); - if (builtins & GPU_INVERSE_NORMAL_MATRIX) - BLI_dynstr_append(ds, "\t#define norinv NormalMatrixInverse\n"); - if (builtins & GPU_INVERSE_VIEW_MATRIX) - BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n"); - if (builtins & GPU_LOC_TO_VIEW_MATRIX) - BLI_dynstr_append(ds, "\t#define localtoviewmat ModelViewMatrix\n"); - if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) - BLI_dynstr_append(ds, "\t#define invlocaltoviewmat ModelViewMatrixInverse\n"); - if (builtins & GPU_VIEW_NORMAL) - BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n"); - if (builtins & GPU_VIEW_POSITION) - BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n"); - - codegen_declare_tmps(ds, nodes); - codegen_call_functions(ds, nodes, output); - - BLI_dynstr_append(ds, "}\n"); - - /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */ - /* Old glsl mode compat. */ - BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n"); - BLI_dynstr_append(ds, "out vec4 fragColor;\n"); - BLI_dynstr_append(ds, "void main()\n"); - BLI_dynstr_append(ds, "{\n"); - BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n"); - BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n"); - BLI_dynstr_append(ds, "}\n"); - BLI_dynstr_append(ds, "#endif\n\n"); - - /* create shader */ - code = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); + codegen_set_unique_ids(nodes); + *rbuiltins = builtins = codegen_process_uniforms_functions(material, ds, nodes); + + if (builtins & GPU_BARYCENTRIC_TEXCO) + BLI_dynstr_append(ds, "in vec2 barycentricTexCo;\n"); + + if (builtins & GPU_BARYCENTRIC_DIST) + BLI_dynstr_append(ds, "flat in vec3 barycentricDist;\n"); + + BLI_dynstr_append(ds, "Closure nodetree_exec(void)\n{\n"); + + if (builtins & GPU_BARYCENTRIC_TEXCO) { + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + BLI_dynstr_append(ds, + "\tvec2 barytexco = vec2((fract(barycentricTexCo.y) != 0.0)\n" + "\t ? barycentricTexCo.x\n" + "\t : 1.0 - barycentricTexCo.x,\n" + "\t 0.0);\n"); + BLI_dynstr_append(ds, "#else\n"); + BLI_dynstr_append(ds, "\tvec2 barytexco = barycentricTexCo;\n"); + BLI_dynstr_append(ds, "#endif\n"); + } + /* TODO(fclem) get rid of that. */ + if (builtins & GPU_VIEW_MATRIX) + BLI_dynstr_append(ds, "\t#define viewmat ViewMatrix\n"); + if (builtins & GPU_CAMERA_TEXCO_FACTORS) + BLI_dynstr_append(ds, "\t#define camtexfac CameraTexCoFactors\n"); + if (builtins & GPU_OBJECT_MATRIX) + BLI_dynstr_append(ds, "\t#define objmat ModelMatrix\n"); + if (builtins & GPU_INVERSE_OBJECT_MATRIX) + BLI_dynstr_append(ds, "\t#define objinv ModelMatrixInverse\n"); + if (builtins & GPU_INVERSE_NORMAL_MATRIX) + BLI_dynstr_append(ds, "\t#define norinv NormalMatrixInverse\n"); + if (builtins & GPU_INVERSE_VIEW_MATRIX) + BLI_dynstr_append(ds, "\t#define viewinv ViewMatrixInverse\n"); + if (builtins & GPU_LOC_TO_VIEW_MATRIX) + BLI_dynstr_append(ds, "\t#define localtoviewmat ModelViewMatrix\n"); + if (builtins & GPU_INVERSE_LOC_TO_VIEW_MATRIX) + BLI_dynstr_append(ds, "\t#define invlocaltoviewmat ModelViewMatrixInverse\n"); + if (builtins & GPU_VIEW_NORMAL) + BLI_dynstr_append(ds, "\tvec3 facingnormal = gl_FrontFacing? viewNormal: -viewNormal;\n"); + if (builtins & GPU_VIEW_POSITION) + BLI_dynstr_append(ds, "\t#define viewposition viewPosition\n"); + + codegen_declare_tmps(ds, nodes); + codegen_call_functions(ds, nodes, output); + + BLI_dynstr_append(ds, "}\n"); + + /* XXX This cannot go into gpu_shader_material.glsl because main() would be parsed and generate error */ + /* Old glsl mode compat. */ + BLI_dynstr_append(ds, "#ifndef NODETREE_EXEC\n"); + BLI_dynstr_append(ds, "out vec4 fragColor;\n"); + BLI_dynstr_append(ds, "void main()\n"); + BLI_dynstr_append(ds, "{\n"); + BLI_dynstr_append(ds, "\tClosure cl = nodetree_exec();\n"); + BLI_dynstr_append(ds, "\tfragColor = vec4(cl.radiance, cl.opacity);\n"); + BLI_dynstr_append(ds, "}\n"); + BLI_dynstr_append(ds, "#endif\n\n"); + + /* create shader */ + code = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); #if 0 - if (G.debug & G_DEBUG) printf("%s\n", code); + if (G.debug & G_DEBUG) printf("%s\n", code); #endif - return code; + return code; } static const char *attr_prefix_get(CustomDataType type) { - switch (type) { - case CD_ORCO: return "orco"; - case CD_MTFACE: return "u"; - case CD_TANGENT: return "t"; - case CD_MCOL: return "c"; - case CD_AUTO_FROM_NAME: return "a"; - default: BLI_assert(false && "GPUVertAttr Prefix type not found : This should not happen!"); return ""; - } + switch (type) { + case CD_ORCO: + return "orco"; + case CD_MTFACE: + return "u"; + case CD_TANGENT: + return "t"; + case CD_MCOL: + return "c"; + case CD_AUTO_FROM_NAME: + return "a"; + default: + BLI_assert(false && "GPUVertAttr Prefix type not found : This should not happen!"); + return ""; + } } static char *code_generate_vertex(ListBase *nodes, const char *vert_code, bool use_geom) { - DynStr *ds = BLI_dynstr_new(); - GPUNode *node; - GPUInput *input; - char *code; - int builtins = 0; - - /* Hairs uv and col attributes are passed by bufferTextures. */ - BLI_dynstr_append( - ds, - "#ifdef HAIR_SHADER\n" - "#define DEFINE_ATTR(type, attr) uniform samplerBuffer attr\n" - "#else\n" - "#define DEFINE_ATTR(type, attr) in type attr\n" - "#endif\n" - ); - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_BUILTIN) { - builtins |= input->builtin; - } - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - /* XXX FIXME : see notes in mesh_render_data_create() */ - /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ - if (input->attr_type == CD_ORCO) { - /* OPTI : orco is computed from local positions, but only if no modifier is present. */ - BLI_dynstr_append(ds, "uniform vec3 OrcoTexCoFactors[2];\n"); - BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); - } - else if (input->attr_name[0] == '\0') { - BLI_dynstr_appendf(ds, "DEFINE_ATTR(%s, %s);\n", GPU_DATATYPE_STR[input->type], attr_prefix_get(input->attr_type)); - BLI_dynstr_appendf(ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type)); - } - else { - uint hash = BLI_ghashutil_strhash_p(input->attr_name); - BLI_dynstr_appendf( - ds, "DEFINE_ATTR(%s, %s%u);\n", - GPU_DATATYPE_STR[input->type], attr_prefix_get(input->attr_type), hash); - BLI_dynstr_appendf( - ds, "#define att%d %s%u\n", - input->attr_id, attr_prefix_get(input->attr_type), hash); - /* Auto attribute can be vertex color byte buffer. - * We need to know and convert them to linear space in VS. */ - if (input->attr_type == CD_AUTO_FROM_NAME) { - BLI_dynstr_appendf(ds, "uniform bool ba%u;\n", hash); - BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attr_id, hash); - } - } - BLI_dynstr_appendf( - ds, "out %s var%d%s;\n", - GPU_DATATYPE_STR[input->type], input->attr_id, use_geom ? "g" : ""); - } - } - } - - if (builtins & GPU_BARYCENTRIC_TEXCO) { - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); - BLI_dynstr_appendf( - ds, "out vec2 barycentricTexCo%s;\n", - use_geom ? "g" : ""); - BLI_dynstr_append(ds, "#endif\n"); - } - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "out vec3 barycentricPosg;\n"); - } - - - BLI_dynstr_append(ds, "\n"); - - BLI_dynstr_append( - ds, - "#define USE_ATTR\n" - "uniform mat3 NormalMatrix;\n" - "uniform mat4 ModelMatrixInverse;\n" - "uniform mat4 ModelMatrix;\n" - "vec3 srgb_to_linear_attr(vec3 c) {\n" - "\tc = max(c, vec3(0.0));\n" - "\tvec3 c1 = c * (1.0 / 12.92);\n" - "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n" - "\treturn mix(c1, c2, step(vec3(0.04045), c));\n" - "}\n\n" - ); - - /* Prototype because defined later. */ - BLI_dynstr_append( - ds, - "vec2 hair_get_customdata_vec2(const samplerBuffer);\n" - "vec3 hair_get_customdata_vec3(const samplerBuffer);\n" - "vec4 hair_get_customdata_vec4(const samplerBuffer);\n" - "vec3 hair_get_strand_pos(void);\n" - "int hair_get_base_id(void);\n" - "\n" - ); - - BLI_dynstr_append(ds, "void pass_attr(in vec3 position) {\n"); - - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); - - if (builtins & GPU_BARYCENTRIC_TEXCO) { - /* To match cycles without breaking into individual segment we encode if we need to invert - * the first component into the second component. We invert if the barycentricTexCo.y - * is NOT 0.0 or 1.0. */ - BLI_dynstr_append( - ds, "\tint _base_id = hair_get_base_id();\n"); - BLI_dynstr_appendf( - ds, "\tbarycentricTexCo%s.x = float((_base_id %% 2) == 1);\n", - use_geom ? "g" : ""); - BLI_dynstr_appendf( - ds, "\tbarycentricTexCo%s.y = float(((_base_id %% 4) %% 3) > 0);\n", - use_geom ? "g" : ""); - } - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n"); - } - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - if (input->attr_type == CD_TANGENT) { - /* Not supported by hairs */ - BLI_dynstr_appendf( - ds, "\tvar%d%s = vec4(0.0);\n", - input->attr_id, use_geom ? "g" : ""); - } - else if (input->attr_type == CD_ORCO) { - BLI_dynstr_appendf( - ds, "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n", - input->attr_id, use_geom ? "g" : ""); - /* TODO: fix ORCO with modifiers. */ - } - else { - BLI_dynstr_appendf( - ds, "\tvar%d%s = hair_get_customdata_%s(att%d);\n", - input->attr_id, use_geom ? "g" : "", GPU_DATATYPE_STR[input->type], input->attr_id); - } - } - } - } - - BLI_dynstr_append(ds, "#else /* MESH_SHADER */\n"); - - /* GPU_BARYCENTRIC_TEXCO cannot be computed based on gl_VertexID - * for MESH_SHADER because of indexed drawing. In this case a - * geometry shader is needed. */ - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n"); - } - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - if (input->attr_type == CD_TANGENT) { /* silly exception */ - BLI_dynstr_appendf( - ds, "\tvar%d%s.xyz = NormalMatrix * att%d.xyz;\n", - input->attr_id, use_geom ? "g" : "", input->attr_id); - BLI_dynstr_appendf( - ds, "\tvar%d%s.w = att%d.w;\n", - input->attr_id, use_geom ? "g" : "", input->attr_id); - /* Normalize only if vector is not null. */ - BLI_dynstr_appendf( - ds, "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n", - input->attr_id, input->attr_id, use_geom ? "g" : "", input->attr_id, use_geom ? "g" : ""); - BLI_dynstr_appendf( - ds, "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n", - input->attr_id, use_geom ? "g" : "", input->attr_id, input->attr_id); - } - else if (input->attr_type == CD_ORCO) { - BLI_dynstr_appendf( - ds, "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n", - input->attr_id, use_geom ? "g" : ""); - /* See mesh_create_loop_orco() for explanation. */ - BLI_dynstr_appendf( - ds, "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n", - input->attr_id, use_geom ? "g" : ""); - } - else if (input->attr_type == CD_MCOL) { - BLI_dynstr_appendf( - ds, "\tvar%d%s = srgb_to_linear_attr(att%d);\n", - input->attr_id, use_geom ? "g" : "", input->attr_id); - } - else if (input->attr_type == CD_AUTO_FROM_NAME) { - BLI_dynstr_appendf( - ds, "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attr(att%d) : att%d;\n", - input->attr_id, use_geom ? "g" : "", - input->attr_id, input->attr_id, input->attr_id); - } - else { - BLI_dynstr_appendf( - ds, "\tvar%d%s = att%d;\n", - input->attr_id, use_geom ? "g" : "", input->attr_id); - } - } - } - } - BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n"); - - BLI_dynstr_append(ds, "}\n"); - - if (use_geom) { - /* XXX HACK: Eevee specific. */ - char *vert_new, *vert_new2; - vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong"); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong"); - MEM_freeN(vert_new2); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg"); - MEM_freeN(vert_new2); - vert_new2 = vert_new; - vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg"); - MEM_freeN(vert_new2); - - BLI_dynstr_append(ds, vert_new); - - MEM_freeN(vert_new); - } - else { - BLI_dynstr_append(ds, vert_code); - } - - code = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); + DynStr *ds = BLI_dynstr_new(); + GPUNode *node; + GPUInput *input; + char *code; + int builtins = 0; + + /* Hairs uv and col attributes are passed by bufferTextures. */ + BLI_dynstr_append(ds, + "#ifdef HAIR_SHADER\n" + "#define DEFINE_ATTR(type, attr) uniform samplerBuffer attr\n" + "#else\n" + "#define DEFINE_ATTR(type, attr) in type attr\n" + "#endif\n"); + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_BUILTIN) { + builtins |= input->builtin; + } + if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + /* XXX FIXME : see notes in mesh_render_data_create() */ + /* NOTE : Replicate changes to mesh_render_data_create() in draw_cache_impl_mesh.c */ + if (input->attr_type == CD_ORCO) { + /* OPTI : orco is computed from local positions, but only if no modifier is present. */ + BLI_dynstr_append(ds, "uniform vec3 OrcoTexCoFactors[2];\n"); + BLI_dynstr_append(ds, "DEFINE_ATTR(vec4, orco);\n"); + } + else if (input->attr_name[0] == '\0') { + BLI_dynstr_appendf(ds, + "DEFINE_ATTR(%s, %s);\n", + GPU_DATATYPE_STR[input->type], + attr_prefix_get(input->attr_type)); + BLI_dynstr_appendf( + ds, "#define att%d %s\n", input->attr_id, attr_prefix_get(input->attr_type)); + } + else { + uint hash = BLI_ghashutil_strhash_p(input->attr_name); + BLI_dynstr_appendf(ds, + "DEFINE_ATTR(%s, %s%u);\n", + GPU_DATATYPE_STR[input->type], + attr_prefix_get(input->attr_type), + hash); + BLI_dynstr_appendf( + ds, "#define att%d %s%u\n", input->attr_id, attr_prefix_get(input->attr_type), hash); + /* Auto attribute can be vertex color byte buffer. + * We need to know and convert them to linear space in VS. */ + if (input->attr_type == CD_AUTO_FROM_NAME) { + BLI_dynstr_appendf(ds, "uniform bool ba%u;\n", hash); + BLI_dynstr_appendf(ds, "#define att%d_is_srgb ba%u\n", input->attr_id, hash); + } + } + BLI_dynstr_appendf(ds, + "out %s var%d%s;\n", + GPU_DATATYPE_STR[input->type], + input->attr_id, + use_geom ? "g" : ""); + } + } + } + + if (builtins & GPU_BARYCENTRIC_TEXCO) { + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + BLI_dynstr_appendf(ds, "out vec2 barycentricTexCo%s;\n", use_geom ? "g" : ""); + BLI_dynstr_append(ds, "#endif\n"); + } + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, "out vec3 barycentricPosg;\n"); + } + + BLI_dynstr_append(ds, "\n"); + + BLI_dynstr_append(ds, + "#define USE_ATTR\n" + "uniform mat3 NormalMatrix;\n" + "uniform mat4 ModelMatrixInverse;\n" + "uniform mat4 ModelMatrix;\n" + "vec3 srgb_to_linear_attr(vec3 c) {\n" + "\tc = max(c, vec3(0.0));\n" + "\tvec3 c1 = c * (1.0 / 12.92);\n" + "\tvec3 c2 = pow((c + 0.055) * (1.0 / 1.055), vec3(2.4));\n" + "\treturn mix(c1, c2, step(vec3(0.04045), c));\n" + "}\n\n"); + + /* Prototype because defined later. */ + BLI_dynstr_append(ds, + "vec2 hair_get_customdata_vec2(const samplerBuffer);\n" + "vec3 hair_get_customdata_vec3(const samplerBuffer);\n" + "vec4 hair_get_customdata_vec4(const samplerBuffer);\n" + "vec3 hair_get_strand_pos(void);\n" + "int hair_get_base_id(void);\n" + "\n"); + + BLI_dynstr_append(ds, "void pass_attr(in vec3 position) {\n"); + + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + + if (builtins & GPU_BARYCENTRIC_TEXCO) { + /* To match cycles without breaking into individual segment we encode if we need to invert + * the first component into the second component. We invert if the barycentricTexCo.y + * is NOT 0.0 or 1.0. */ + BLI_dynstr_append(ds, "\tint _base_id = hair_get_base_id();\n"); + BLI_dynstr_appendf( + ds, "\tbarycentricTexCo%s.x = float((_base_id %% 2) == 1);\n", use_geom ? "g" : ""); + BLI_dynstr_appendf( + ds, "\tbarycentricTexCo%s.y = float(((_base_id %% 4) %% 3) > 0);\n", use_geom ? "g" : ""); + } + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, "\tbarycentricPosg = position;\n"); + } + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + if (input->attr_type == CD_TANGENT) { + /* Not supported by hairs */ + BLI_dynstr_appendf(ds, "\tvar%d%s = vec4(0.0);\n", input->attr_id, use_geom ? "g" : ""); + } + else if (input->attr_type == CD_ORCO) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = OrcoTexCoFactors[0] + (ModelMatrixInverse * " + "vec4(hair_get_strand_pos(), 1.0)).xyz * OrcoTexCoFactors[1];\n", + input->attr_id, + use_geom ? "g" : ""); + /* TODO: fix ORCO with modifiers. */ + } + else { + BLI_dynstr_appendf(ds, + "\tvar%d%s = hair_get_customdata_%s(att%d);\n", + input->attr_id, + use_geom ? "g" : "", + GPU_DATATYPE_STR[input->type], + input->attr_id); + } + } + } + } + + BLI_dynstr_append(ds, "#else /* MESH_SHADER */\n"); + + /* GPU_BARYCENTRIC_TEXCO cannot be computed based on gl_VertexID + * for MESH_SHADER because of indexed drawing. In this case a + * geometry shader is needed. */ + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, "\tbarycentricPosg = (ModelMatrix * vec4(position, 1.0)).xyz;\n"); + } + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + if (input->attr_type == CD_TANGENT) { /* silly exception */ + BLI_dynstr_appendf(ds, + "\tvar%d%s.xyz = NormalMatrix * att%d.xyz;\n", + input->attr_id, + use_geom ? "g" : "", + input->attr_id); + BLI_dynstr_appendf( + ds, "\tvar%d%s.w = att%d.w;\n", input->attr_id, use_geom ? "g" : "", input->attr_id); + /* Normalize only if vector is not null. */ + BLI_dynstr_appendf(ds, + "\tfloat lvar%d = dot(var%d%s.xyz, var%d%s.xyz);\n", + input->attr_id, + input->attr_id, + use_geom ? "g" : "", + input->attr_id, + use_geom ? "g" : ""); + BLI_dynstr_appendf(ds, + "\tvar%d%s.xyz *= (lvar%d > 0.0) ? inversesqrt(lvar%d) : 1.0;\n", + input->attr_id, + use_geom ? "g" : "", + input->attr_id, + input->attr_id); + } + else if (input->attr_type == CD_ORCO) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = OrcoTexCoFactors[0] + position * OrcoTexCoFactors[1];\n", + input->attr_id, + use_geom ? "g" : ""); + /* See mesh_create_loop_orco() for explanation. */ + BLI_dynstr_appendf(ds, + "\tif (orco.w == 0.0) { var%d%s = orco.xyz * 0.5 + 0.5; }\n", + input->attr_id, + use_geom ? "g" : ""); + } + else if (input->attr_type == CD_MCOL) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = srgb_to_linear_attr(att%d);\n", + input->attr_id, + use_geom ? "g" : "", + input->attr_id); + } + else if (input->attr_type == CD_AUTO_FROM_NAME) { + BLI_dynstr_appendf(ds, + "\tvar%d%s = (att%d_is_srgb) ? srgb_to_linear_attr(att%d) : att%d;\n", + input->attr_id, + use_geom ? "g" : "", + input->attr_id, + input->attr_id, + input->attr_id); + } + else { + BLI_dynstr_appendf( + ds, "\tvar%d%s = att%d;\n", input->attr_id, use_geom ? "g" : "", input->attr_id); + } + } + } + } + BLI_dynstr_append(ds, "#endif /* HAIR_SHADER */\n"); + + BLI_dynstr_append(ds, "}\n"); + + if (use_geom) { + /* XXX HACK: Eevee specific. */ + char *vert_new, *vert_new2; + vert_new = BLI_str_replaceN(vert_code, "worldPosition", "worldPositiong"); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "viewPosition", "viewPositiong"); + MEM_freeN(vert_new2); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "worldNormal", "worldNormalg"); + MEM_freeN(vert_new2); + vert_new2 = vert_new; + vert_new = BLI_str_replaceN(vert_new2, "viewNormal", "viewNormalg"); + MEM_freeN(vert_new2); + + BLI_dynstr_append(ds, vert_new); + + MEM_freeN(vert_new); + } + else { + BLI_dynstr_append(ds, vert_code); + } + + code = BLI_dynstr_get_cstring(ds); + + BLI_dynstr_free(ds); #if 0 - if (G.debug & G_DEBUG) printf("%s\n", code); + if (G.debug & G_DEBUG) printf("%s\n", code); #endif - return code; + return code; } static char *code_generate_geometry(ListBase *nodes, const char *geom_code, const char *defines) { - DynStr *ds = BLI_dynstr_new(); - GPUNode *node; - GPUInput *input; - char *code; - int builtins = 0; - - /* XXX we should not make specific eevee cases here. */ - bool is_hair_shader = (strstr(defines, "HAIR_SHADER") != NULL); - - /* Create prototype because attributes cannot be declared before layout. */ - BLI_dynstr_append(ds, "void pass_attr(in int vert);\n"); - BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2);\n"); - BLI_dynstr_append(ds, "#define USE_ATTR\n"); - - /* Generate varying declarations. */ - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_BUILTIN) { - builtins |= input->builtin; - } - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - BLI_dynstr_appendf( - ds, "in %s var%dg[];\n", - GPU_DATATYPE_STR[input->type], - input->attr_id); - BLI_dynstr_appendf( - ds, "out %s var%d;\n", - GPU_DATATYPE_STR[input->type], - input->attr_id); - } - } - } - - if (builtins & GPU_BARYCENTRIC_TEXCO) { - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); - BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n"); - BLI_dynstr_append(ds, "#endif\n"); - - BLI_dynstr_append(ds, "out vec2 barycentricTexCo;\n"); - } - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "in vec3 barycentricPosg[];\n"); - BLI_dynstr_append(ds, "flat out vec3 barycentricDist;\n"); - } - - if (geom_code == NULL) { - /* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used. - * Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */ - if ((builtins & (GPU_BARYCENTRIC_DIST | GPU_BARYCENTRIC_TEXCO)) == 0 || is_hair_shader) { - /* Early out */ - BLI_dynstr_free(ds); - return NULL; - } - else { - /* Force geom shader usage */ - /* TODO put in external file. */ - BLI_dynstr_append(ds, "layout(triangles) in;\n"); - BLI_dynstr_append(ds, "layout(triangle_strip, max_vertices=3) out;\n"); - - BLI_dynstr_append(ds, "in vec3 worldPositiong[];\n"); - BLI_dynstr_append(ds, "in vec3 viewPositiong[];\n"); - BLI_dynstr_append(ds, "in vec3 worldNormalg[];\n"); - BLI_dynstr_append(ds, "in vec3 viewNormalg[];\n"); - - BLI_dynstr_append(ds, "out vec3 worldPosition;\n"); - BLI_dynstr_append(ds, "out vec3 viewPosition;\n"); - BLI_dynstr_append(ds, "out vec3 worldNormal;\n"); - BLI_dynstr_append(ds, "out vec3 viewNormal;\n"); - - BLI_dynstr_append(ds, "void main(){\n"); - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "\tcalc_barycentric_distances(barycentricPosg[0], barycentricPosg[1], barycentricPosg[2]);\n"); - } - - BLI_dynstr_append(ds, "\tgl_Position = gl_in[0].gl_Position;\n"); - BLI_dynstr_append(ds, "\tpass_attr(0);\n"); - BLI_dynstr_append(ds, "\tEmitVertex();\n"); - - BLI_dynstr_append(ds, "\tgl_Position = gl_in[1].gl_Position;\n"); - BLI_dynstr_append(ds, "\tpass_attr(1);\n"); - BLI_dynstr_append(ds, "\tEmitVertex();\n"); - - BLI_dynstr_append(ds, "\tgl_Position = gl_in[2].gl_Position;\n"); - BLI_dynstr_append(ds, "\tpass_attr(2);\n"); - BLI_dynstr_append(ds, "\tEmitVertex();\n"); - BLI_dynstr_append(ds, "};\n"); - } - } - else { - BLI_dynstr_append(ds, geom_code); - } - - if (builtins & GPU_BARYCENTRIC_DIST) { - BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2) {\n"); - BLI_dynstr_append(ds, "\tvec3 edge21 = pos2 - pos1;\n"); - BLI_dynstr_append(ds, "\tvec3 edge10 = pos1 - pos0;\n"); - BLI_dynstr_append(ds, "\tvec3 edge02 = pos0 - pos2;\n"); - BLI_dynstr_append(ds, "\tvec3 d21 = normalize(edge21);\n"); - BLI_dynstr_append(ds, "\tvec3 d10 = normalize(edge10);\n"); - BLI_dynstr_append(ds, "\tvec3 d02 = normalize(edge02);\n"); - - BLI_dynstr_append(ds, "\tfloat d = dot(d21, edge02);\n"); - BLI_dynstr_append(ds, "\tbarycentricDist.x = sqrt(dot(edge02, edge02) - d * d);\n"); - BLI_dynstr_append(ds, "\td = dot(d02, edge10);\n"); - BLI_dynstr_append(ds, "\tbarycentricDist.y = sqrt(dot(edge10, edge10) - d * d);\n"); - BLI_dynstr_append(ds, "\td = dot(d10, edge21);\n"); - BLI_dynstr_append(ds, "\tbarycentricDist.z = sqrt(dot(edge21, edge21) - d * d);\n"); - BLI_dynstr_append(ds, "}\n"); - } - - /* Generate varying assignments. */ - BLI_dynstr_append(ds, "void pass_attr(in int vert) {\n"); - - /* XXX HACK: Eevee specific. */ - if (geom_code == NULL) { - BLI_dynstr_append(ds, "\tworldPosition = worldPositiong[vert];\n"); - BLI_dynstr_append(ds, "\tviewPosition = viewPositiong[vert];\n"); - BLI_dynstr_append(ds, "\tworldNormal = worldNormalg[vert];\n"); - BLI_dynstr_append(ds, "\tviewNormal = viewNormalg[vert];\n"); - } - - if (builtins & GPU_BARYCENTRIC_TEXCO) { - BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); - BLI_dynstr_append(ds, "\tbarycentricTexCo = barycentricTexCog[vert];\n"); - BLI_dynstr_append(ds, "#else\n"); - BLI_dynstr_append(ds, "\tbarycentricTexCo.x = float((vert % 3) == 0);\n"); - BLI_dynstr_append(ds, "\tbarycentricTexCo.y = float((vert % 3) == 1);\n"); - BLI_dynstr_append(ds, "#endif\n"); - } - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR && input->attr_first) { - /* TODO let shader choose what to do depending on what the attribute is. */ - BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attr_id, input->attr_id); - } - } - } - BLI_dynstr_append(ds, "}\n"); - - code = BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - - return code; + DynStr *ds = BLI_dynstr_new(); + GPUNode *node; + GPUInput *input; + char *code; + int builtins = 0; + + /* XXX we should not make specific eevee cases here. */ + bool is_hair_shader = (strstr(defines, "HAIR_SHADER") != NULL); + + /* Create prototype because attributes cannot be declared before layout. */ + BLI_dynstr_append(ds, "void pass_attr(in int vert);\n"); + BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2);\n"); + BLI_dynstr_append(ds, "#define USE_ATTR\n"); + + /* Generate varying declarations. */ + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_BUILTIN) { + builtins |= input->builtin; + } + if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + BLI_dynstr_appendf(ds, "in %s var%dg[];\n", GPU_DATATYPE_STR[input->type], input->attr_id); + BLI_dynstr_appendf(ds, "out %s var%d;\n", GPU_DATATYPE_STR[input->type], input->attr_id); + } + } + } + + if (builtins & GPU_BARYCENTRIC_TEXCO) { + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + BLI_dynstr_append(ds, "in vec2 barycentricTexCog[];\n"); + BLI_dynstr_append(ds, "#endif\n"); + + BLI_dynstr_append(ds, "out vec2 barycentricTexCo;\n"); + } + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, "in vec3 barycentricPosg[];\n"); + BLI_dynstr_append(ds, "flat out vec3 barycentricDist;\n"); + } + + if (geom_code == NULL) { + /* Force geometry usage if GPU_BARYCENTRIC_DIST or GPU_BARYCENTRIC_TEXCO are used. + * Note: GPU_BARYCENTRIC_TEXCO only requires it if the shader is not drawing hairs. */ + if ((builtins & (GPU_BARYCENTRIC_DIST | GPU_BARYCENTRIC_TEXCO)) == 0 || is_hair_shader) { + /* Early out */ + BLI_dynstr_free(ds); + return NULL; + } + else { + /* Force geom shader usage */ + /* TODO put in external file. */ + BLI_dynstr_append(ds, "layout(triangles) in;\n"); + BLI_dynstr_append(ds, "layout(triangle_strip, max_vertices=3) out;\n"); + + BLI_dynstr_append(ds, "in vec3 worldPositiong[];\n"); + BLI_dynstr_append(ds, "in vec3 viewPositiong[];\n"); + BLI_dynstr_append(ds, "in vec3 worldNormalg[];\n"); + BLI_dynstr_append(ds, "in vec3 viewNormalg[];\n"); + + BLI_dynstr_append(ds, "out vec3 worldPosition;\n"); + BLI_dynstr_append(ds, "out vec3 viewPosition;\n"); + BLI_dynstr_append(ds, "out vec3 worldNormal;\n"); + BLI_dynstr_append(ds, "out vec3 viewNormal;\n"); + + BLI_dynstr_append(ds, "void main(){\n"); + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, + "\tcalc_barycentric_distances(barycentricPosg[0], barycentricPosg[1], " + "barycentricPosg[2]);\n"); + } + + BLI_dynstr_append(ds, "\tgl_Position = gl_in[0].gl_Position;\n"); + BLI_dynstr_append(ds, "\tpass_attr(0);\n"); + BLI_dynstr_append(ds, "\tEmitVertex();\n"); + + BLI_dynstr_append(ds, "\tgl_Position = gl_in[1].gl_Position;\n"); + BLI_dynstr_append(ds, "\tpass_attr(1);\n"); + BLI_dynstr_append(ds, "\tEmitVertex();\n"); + + BLI_dynstr_append(ds, "\tgl_Position = gl_in[2].gl_Position;\n"); + BLI_dynstr_append(ds, "\tpass_attr(2);\n"); + BLI_dynstr_append(ds, "\tEmitVertex();\n"); + BLI_dynstr_append(ds, "};\n"); + } + } + else { + BLI_dynstr_append(ds, geom_code); + } + + if (builtins & GPU_BARYCENTRIC_DIST) { + BLI_dynstr_append(ds, "void calc_barycentric_distances(vec3 pos0, vec3 pos1, vec3 pos2) {\n"); + BLI_dynstr_append(ds, "\tvec3 edge21 = pos2 - pos1;\n"); + BLI_dynstr_append(ds, "\tvec3 edge10 = pos1 - pos0;\n"); + BLI_dynstr_append(ds, "\tvec3 edge02 = pos0 - pos2;\n"); + BLI_dynstr_append(ds, "\tvec3 d21 = normalize(edge21);\n"); + BLI_dynstr_append(ds, "\tvec3 d10 = normalize(edge10);\n"); + BLI_dynstr_append(ds, "\tvec3 d02 = normalize(edge02);\n"); + + BLI_dynstr_append(ds, "\tfloat d = dot(d21, edge02);\n"); + BLI_dynstr_append(ds, "\tbarycentricDist.x = sqrt(dot(edge02, edge02) - d * d);\n"); + BLI_dynstr_append(ds, "\td = dot(d02, edge10);\n"); + BLI_dynstr_append(ds, "\tbarycentricDist.y = sqrt(dot(edge10, edge10) - d * d);\n"); + BLI_dynstr_append(ds, "\td = dot(d10, edge21);\n"); + BLI_dynstr_append(ds, "\tbarycentricDist.z = sqrt(dot(edge21, edge21) - d * d);\n"); + BLI_dynstr_append(ds, "}\n"); + } + + /* Generate varying assignments. */ + BLI_dynstr_append(ds, "void pass_attr(in int vert) {\n"); + + /* XXX HACK: Eevee specific. */ + if (geom_code == NULL) { + BLI_dynstr_append(ds, "\tworldPosition = worldPositiong[vert];\n"); + BLI_dynstr_append(ds, "\tviewPosition = viewPositiong[vert];\n"); + BLI_dynstr_append(ds, "\tworldNormal = worldNormalg[vert];\n"); + BLI_dynstr_append(ds, "\tviewNormal = viewNormalg[vert];\n"); + } + + if (builtins & GPU_BARYCENTRIC_TEXCO) { + BLI_dynstr_append(ds, "#ifdef HAIR_SHADER\n"); + BLI_dynstr_append(ds, "\tbarycentricTexCo = barycentricTexCog[vert];\n"); + BLI_dynstr_append(ds, "#else\n"); + BLI_dynstr_append(ds, "\tbarycentricTexCo.x = float((vert % 3) == 0);\n"); + BLI_dynstr_append(ds, "\tbarycentricTexCo.y = float((vert % 3) == 1);\n"); + BLI_dynstr_append(ds, "#endif\n"); + } + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTR && input->attr_first) { + /* TODO let shader choose what to do depending on what the attribute is. */ + BLI_dynstr_appendf(ds, "\tvar%d = var%dg[vert];\n", input->attr_id, input->attr_id); + } + } + } + BLI_dynstr_append(ds, "}\n"); + + code = BLI_dynstr_get_cstring(ds); + BLI_dynstr_free(ds); + + return code; } void GPU_code_generate_glsl_lib(void) { - DynStr *ds; + DynStr *ds; - /* only initialize the library once */ - if (glsl_material_library) - return; + /* only initialize the library once */ + if (glsl_material_library) + return; - ds = BLI_dynstr_new(); + ds = BLI_dynstr_new(); - BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl); + BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl); + glsl_material_library = BLI_dynstr_get_cstring(ds); - glsl_material_library = BLI_dynstr_get_cstring(ds); - - BLI_dynstr_free(ds); + BLI_dynstr_free(ds); } - /* GPU pass binding/unbinding */ GPUShader *GPU_pass_shader_get(GPUPass *pass) { - return pass->shader; + return pass->shader; } void GPU_nodes_extract_dynamic_inputs(GPUShader *shader, ListBase *inputs, ListBase *nodes) { - GPUNode *node; - GPUInput *next, *input; - - BLI_listbase_clear(inputs); - - if (!shader) - return; - - for (node = nodes->first; node; node = node->next) { - int z = 0; - for (input = node->inputs.first; input; input = next, z++) { - next = input->next; - - /* attributes don't need to be bound, they already have - * an id that the drawing functions will use. Builtins have - * constant names. */ - if (ELEM(input->source, GPU_SOURCE_ATTR, GPU_SOURCE_BUILTIN)) { - continue; - } - - if (input->source == GPU_SOURCE_TEX) - BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); - else { - BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); - } - - if (input->source == GPU_SOURCE_TEX) { - if (input->bindtex) { - input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername); - /* extract nodes */ - BLI_remlink(&node->inputs, input); - BLI_addtail(inputs, input); - } - } - } - } + GPUNode *node; + GPUInput *next, *input; + + BLI_listbase_clear(inputs); + + if (!shader) + return; + + for (node = nodes->first; node; node = node->next) { + int z = 0; + for (input = node->inputs.first; input; input = next, z++) { + next = input->next; + + /* attributes don't need to be bound, they already have + * an id that the drawing functions will use. Builtins have + * constant names. */ + if (ELEM(input->source, GPU_SOURCE_ATTR, GPU_SOURCE_BUILTIN)) { + continue; + } + + if (input->source == GPU_SOURCE_TEX) + BLI_snprintf(input->shadername, sizeof(input->shadername), "samp%d", input->texid); + else { + BLI_snprintf(input->shadername, sizeof(input->shadername), "unf%d", input->id); + } + + if (input->source == GPU_SOURCE_TEX) { + if (input->bindtex) { + input->shaderloc = GPU_shader_get_uniform_ensure(shader, input->shadername); + /* extract nodes */ + BLI_remlink(&node->inputs, input); + BLI_addtail(inputs, input); + } + } + } + } } /* Node Link Functions */ static GPUNodeLink *GPU_node_link_create(void) { - GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink"); - link->users++; + GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink"); + link->users++; - return link; + return link; } static void gpu_node_link_free(GPUNodeLink *link) { - link->users--; + link->users--; - if (link->users < 0) - fprintf(stderr, "GPU_node_link_free: negative refcount\n"); + if (link->users < 0) + fprintf(stderr, "GPU_node_link_free: negative refcount\n"); - if (link->users == 0) { - if (link->output) - link->output->link = NULL; - MEM_freeN(link); - } + if (link->users == 0) { + if (link->output) + link->output->link = NULL; + MEM_freeN(link); + } } /* Node Functions */ static GPUNode *GPU_node_begin(const char *name) { - GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); + GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode"); - node->name = name; + node->name = name; - return node; + return node; } static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const eGPUType type) { - GPUInput *input; - GPUNode *outnode; - const char *name; - - if (link->link_type == GPU_NODE_LINK_OUTPUT) { - outnode = link->output->node; - name = outnode->name; - input = outnode->inputs.first; - - if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && - (input->type == type)) - { - input = MEM_dupallocN(outnode->inputs.first); - if (input->link) - input->link->users++; - BLI_addtail(&node->inputs, input); - return; - } - } - - input = MEM_callocN(sizeof(GPUInput), "GPUInput"); - input->node = node; - input->type = type; - - switch (link->link_type) { - case GPU_NODE_LINK_BUILTIN: - input->source = GPU_SOURCE_BUILTIN; - input->builtin = link->builtin; - break; - case GPU_NODE_LINK_OUTPUT: - input->source = GPU_SOURCE_OUTPUT; - input->link = link; - link->users++; - break; - case GPU_NODE_LINK_COLORBAND: - input->source = GPU_SOURCE_TEX; - input->coba = link->coba; - break; - case GPU_NODE_LINK_IMAGE_BLENDER: - input->source = GPU_SOURCE_TEX; - input->ima = link->ima; - input->iuser = link->iuser; - input->image_isdata = link->image_isdata; - break; - case GPU_NODE_LINK_ATTR: - input->source = GPU_SOURCE_ATTR; - input->attr_type = link->attr_type; - BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name)); - break; - case GPU_NODE_LINK_CONSTANT: - input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT; - break; - case GPU_NODE_LINK_UNIFORM: - input->source = GPU_SOURCE_UNIFORM; - break; - default: - break; - } - - if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) { - memcpy(input->vec, link->data, type * sizeof(float)); - } - - if (link->link_type != GPU_NODE_LINK_OUTPUT) { - MEM_freeN(link); - } - BLI_addtail(&node->inputs, input); + GPUInput *input; + GPUNode *outnode; + const char *name; + + if (link->link_type == GPU_NODE_LINK_OUTPUT) { + outnode = link->output->node; + name = outnode->name; + input = outnode->inputs.first; + + if ((STR_ELEM(name, "set_value", "set_rgb", "set_rgba")) && (input->type == type)) { + input = MEM_dupallocN(outnode->inputs.first); + if (input->link) + input->link->users++; + BLI_addtail(&node->inputs, input); + return; + } + } + + input = MEM_callocN(sizeof(GPUInput), "GPUInput"); + input->node = node; + input->type = type; + + switch (link->link_type) { + case GPU_NODE_LINK_BUILTIN: + input->source = GPU_SOURCE_BUILTIN; + input->builtin = link->builtin; + break; + case GPU_NODE_LINK_OUTPUT: + input->source = GPU_SOURCE_OUTPUT; + input->link = link; + link->users++; + break; + case GPU_NODE_LINK_COLORBAND: + input->source = GPU_SOURCE_TEX; + input->coba = link->coba; + break; + case GPU_NODE_LINK_IMAGE_BLENDER: + input->source = GPU_SOURCE_TEX; + input->ima = link->ima; + input->iuser = link->iuser; + input->image_isdata = link->image_isdata; + break; + case GPU_NODE_LINK_ATTR: + input->source = GPU_SOURCE_ATTR; + input->attr_type = link->attr_type; + BLI_strncpy(input->attr_name, link->attr_name, sizeof(input->attr_name)); + break; + case GPU_NODE_LINK_CONSTANT: + input->source = (type == GPU_CLOSURE) ? GPU_SOURCE_STRUCT : GPU_SOURCE_CONSTANT; + break; + case GPU_NODE_LINK_UNIFORM: + input->source = GPU_SOURCE_UNIFORM; + break; + default: + break; + } + + if (ELEM(input->source, GPU_SOURCE_CONSTANT, GPU_SOURCE_UNIFORM)) { + memcpy(input->vec, link->data, type * sizeof(float)); + } + + if (link->link_type != GPU_NODE_LINK_OUTPUT) { + MEM_freeN(link); + } + BLI_addtail(&node->inputs, input); } - static const char *gpu_uniform_set_function_from_type(eNodeSocketDatatype type) { - switch (type) { - /* For now INT is supported as float. */ - case SOCK_INT: - case SOCK_FLOAT: - return "set_value"; - case SOCK_VECTOR: - return "set_rgb"; - case SOCK_RGBA: - return "set_rgba"; - default: - BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype"); - return NULL; - } + switch (type) { + /* For now INT is supported as float. */ + case SOCK_INT: + case SOCK_FLOAT: + return "set_value"; + case SOCK_VECTOR: + return "set_rgb"; + case SOCK_RGBA: + return "set_rgba"; + default: + BLI_assert(!"No gpu function for non-supported eNodeSocketDatatype"); + return NULL; + } } /** * Link stack uniform buffer. * This is called for the input/output sockets that are note connected. */ -static GPUNodeLink *gpu_uniformbuffer_link( - GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index, const eNodeSocketInOut in_out) +static GPUNodeLink *gpu_uniformbuffer_link(GPUMaterial *mat, + bNode *node, + GPUNodeStack *stack, + const int index, + const eNodeSocketInOut in_out) { - bNodeSocket *socket; - - if (in_out == SOCK_IN) { - socket = BLI_findlink(&node->inputs, index); - } - else { - socket = BLI_findlink(&node->outputs, index); - } - - BLI_assert(socket != NULL); - BLI_assert(socket->in_out == in_out); - - if ((socket->flag & SOCK_HIDE_VALUE) == 0) { - GPUNodeLink *link; - switch (socket->type) { - case SOCK_FLOAT: - { - bNodeSocketValueFloat *socket_data = socket->default_value; - link = GPU_uniform(&socket_data->value); - break; - } - case SOCK_VECTOR: - { - bNodeSocketValueVector *socket_data = socket->default_value; - link = GPU_uniform(socket_data->value); - break; - } - case SOCK_RGBA: - { - bNodeSocketValueRGBA *socket_data = socket->default_value; - link = GPU_uniform(socket_data->value); - break; - } - default: - return NULL; - break; - } - - if (in_out == SOCK_IN) { - GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link); - } - return link; - } - return NULL; + bNodeSocket *socket; + + if (in_out == SOCK_IN) { + socket = BLI_findlink(&node->inputs, index); + } + else { + socket = BLI_findlink(&node->outputs, index); + } + + BLI_assert(socket != NULL); + BLI_assert(socket->in_out == in_out); + + if ((socket->flag & SOCK_HIDE_VALUE) == 0) { + GPUNodeLink *link; + switch (socket->type) { + case SOCK_FLOAT: { + bNodeSocketValueFloat *socket_data = socket->default_value; + link = GPU_uniform(&socket_data->value); + break; + } + case SOCK_VECTOR: { + bNodeSocketValueVector *socket_data = socket->default_value; + link = GPU_uniform(socket_data->value); + break; + } + case SOCK_RGBA: { + bNodeSocketValueRGBA *socket_data = socket->default_value; + link = GPU_uniform(socket_data->value); + break; + } + default: + return NULL; + break; + } + + if (in_out == SOCK_IN) { + GPU_link(mat, gpu_uniform_set_function_from_type(socket->type), link, &stack->link); + } + return link; + } + return NULL; } -static void gpu_node_input_socket(GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index) +static void gpu_node_input_socket( + GPUMaterial *material, bNode *bnode, GPUNode *node, GPUNodeStack *sock, const int index) { - if (sock->link) { - gpu_node_input_link(node, sock->link, sock->type); - } - else if ((material != NULL) && (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) { - gpu_node_input_link(node, sock->link, sock->type); - } - else { - gpu_node_input_link(node, GPU_constant(sock->vec), sock->type); - } + if (sock->link) { + gpu_node_input_link(node, sock->link, sock->type); + } + else if ((material != NULL) && + (gpu_uniformbuffer_link(material, bnode, sock, index, SOCK_IN) != NULL)) { + gpu_node_input_link(node, sock->link, sock->type); + } + else { + gpu_node_input_link(node, GPU_constant(sock->vec), sock->type); + } } static void gpu_node_output(GPUNode *node, const eGPUType type, GPUNodeLink **link) { - GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput"); + GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput"); - output->type = type; - output->node = node; + output->type = type; + output->node = node; - if (link) { - *link = output->link = GPU_node_link_create(); - output->link->link_type = GPU_NODE_LINK_OUTPUT; - output->link->output = output; + if (link) { + *link = output->link = GPU_node_link_create(); + output->link->link_type = GPU_NODE_LINK_OUTPUT; + output->link->output = output; - /* note: the caller owns the reference to the link, GPUOutput - * merely points to it, and if the node is destroyed it will - * set that pointer to NULL */ - } + /* note: the caller owns the reference to the link, GPUOutput + * merely points to it, and if the node is destroyed it will + * set that pointer to NULL */ + } - BLI_addtail(&node->outputs, output); + BLI_addtail(&node->outputs, output); } void GPU_inputs_free(ListBase *inputs) { - GPUInput *input; + GPUInput *input; - for (input = inputs->first; input; input = input->next) { - if (input->link) - gpu_node_link_free(input->link); - } + for (input = inputs->first; input; input = input->next) { + if (input->link) + gpu_node_link_free(input->link); + } - BLI_freelistN(inputs); + BLI_freelistN(inputs); } static void gpu_node_free(GPUNode *node) { - GPUOutput *output; + GPUOutput *output; - GPU_inputs_free(&node->inputs); + GPU_inputs_free(&node->inputs); - for (output = node->outputs.first; output; output = output->next) - if (output->link) { - output->link->output = NULL; - gpu_node_link_free(output->link); - } + for (output = node->outputs.first; output; output = output->next) + if (output->link) { + output->link->output = NULL; + gpu_node_link_free(output->link); + } - BLI_freelistN(&node->outputs); - MEM_freeN(node); + BLI_freelistN(&node->outputs); + MEM_freeN(node); } static void gpu_nodes_free(ListBase *nodes) { - GPUNode *node; + GPUNode *node; - while ((node = BLI_pophead(nodes))) { - gpu_node_free(node); - } + while ((node = BLI_pophead(nodes))) { + gpu_node_free(node); + } } /* vertex attributes */ void GPU_nodes_get_vertex_attrs(ListBase *nodes, GPUVertAttrLayers *attrs) { - GPUNode *node; - GPUInput *input; - int a; - - /* convert attributes requested by node inputs to an array of layers, - * checking for duplicates and assigning id's starting from zero. */ - - memset(attrs, 0, sizeof(*attrs)); - - for (node = nodes->first; node; node = node->next) { - for (input = node->inputs.first; input; input = input->next) { - if (input->source == GPU_SOURCE_ATTR) { - for (a = 0; a < attrs->totlayer; a++) { - if (attrs->layer[a].type == input->attr_type && - STREQ(attrs->layer[a].name, input->attr_name)) - { - break; - } - } - - if (a < GPU_MAX_ATTR) { - if (a == attrs->totlayer) { - input->attr_id = attrs->totlayer++; - input->attr_first = true; - - attrs->layer[a].type = input->attr_type; - attrs->layer[a].attr_id = input->attr_id; - BLI_strncpy( - attrs->layer[a].name, input->attr_name, - sizeof(attrs->layer[a].name)); - } - else { - input->attr_id = attrs->layer[a].attr_id; - } - } - } - } - } + GPUNode *node; + GPUInput *input; + int a; + + /* convert attributes requested by node inputs to an array of layers, + * checking for duplicates and assigning id's starting from zero. */ + + memset(attrs, 0, sizeof(*attrs)); + + for (node = nodes->first; node; node = node->next) { + for (input = node->inputs.first; input; input = input->next) { + if (input->source == GPU_SOURCE_ATTR) { + for (a = 0; a < attrs->totlayer; a++) { + if (attrs->layer[a].type == input->attr_type && + STREQ(attrs->layer[a].name, input->attr_name)) { + break; + } + } + + if (a < GPU_MAX_ATTR) { + if (a == attrs->totlayer) { + input->attr_id = attrs->totlayer++; + input->attr_first = true; + + attrs->layer[a].type = input->attr_type; + attrs->layer[a].attr_id = input->attr_id; + BLI_strncpy(attrs->layer[a].name, input->attr_name, sizeof(attrs->layer[a].name)); + } + else { + input->attr_id = attrs->layer[a].attr_id; + } + } + } + } + } } /* varargs linking */ GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_ATTR; - link->attr_name = name; - /* Fall back to the UV layer, which matches old behavior. */ - if (type == CD_AUTO_FROM_NAME && name[0] == '\0') { - link->attr_type = CD_MTFACE; - } - else { - link->attr_type = type; - } - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_ATTR; + link->attr_name = name; + /* Fall back to the UV layer, which matches old behavior. */ + if (type == CD_AUTO_FROM_NAME && name[0] == '\0') { + link->attr_type = CD_MTFACE; + } + else { + link->attr_type = type; + } + return link; } GPUNodeLink *GPU_constant(float *num) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_CONSTANT; - link->data = num; - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_CONSTANT; + link->data = num; + return link; } GPUNodeLink *GPU_uniform(float *num) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_UNIFORM; - link->data = num; - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_UNIFORM; + link->data = num; + return link; } GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_IMAGE_BLENDER; - link->ima = ima; - link->iuser = iuser; - link->image_isdata = is_data; - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_IMAGE_BLENDER; + link->ima = ima; + link->iuser = iuser; + link->image_isdata = is_data; + return link; } GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *row) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_COLORBAND; - link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row); - MEM_freeN(pixels); - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_COLORBAND; + link->coba = gpu_material_ramp_texture_row_set(mat, size, pixels, row); + MEM_freeN(pixels); + return link; } GPUNodeLink *GPU_builtin(eGPUBuiltin builtin) { - GPUNodeLink *link = GPU_node_link_create(); - link->link_type = GPU_NODE_LINK_BUILTIN; - link->builtin = builtin; - return link; + GPUNodeLink *link = GPU_node_link_create(); + link->link_type = GPU_NODE_LINK_BUILTIN; + link->builtin = builtin; + return link; } bool GPU_link(GPUMaterial *mat, const char *name, ...) { - GPUNode *node; - GPUFunction *function; - GPUNodeLink *link, **linkptr; - va_list params; - int i; - - function = gpu_lookup_function(name); - if (!function) { - fprintf(stderr, "GPU failed to find function %s\n", name); - return false; - } - - node = GPU_node_begin(name); - - va_start(params, name); - for (i = 0; i < function->totparam; i++) { - if (function->paramqual[i] != FUNCTION_QUAL_IN) { - linkptr = va_arg(params, GPUNodeLink **); - gpu_node_output(node, function->paramtype[i], linkptr); - } - else { - link = va_arg(params, GPUNodeLink *); - gpu_node_input_link(node, link, function->paramtype[i]); - } - } - va_end(params); - - gpu_material_add_node(mat, node); - - return true; + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i; + + function = gpu_lookup_function(name); + if (!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return false; + } + + node = GPU_node_begin(name); + + va_start(params, name); + for (i = 0; i < function->totparam; i++) { + if (function->paramqual[i] != FUNCTION_QUAL_IN) { + linkptr = va_arg(params, GPUNodeLink **); + gpu_node_output(node, function->paramtype[i], linkptr); + } + else { + link = va_arg(params, GPUNodeLink *); + gpu_node_input_link(node, link, function->paramtype[i]); + } + } + va_end(params); + + gpu_material_add_node(mat, node); + + return true; } -bool GPU_stack_link(GPUMaterial *material, bNode *bnode, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...) +bool GPU_stack_link(GPUMaterial *material, + bNode *bnode, + const char *name, + GPUNodeStack *in, + GPUNodeStack *out, + ...) { - GPUNode *node; - GPUFunction *function; - GPUNodeLink *link, **linkptr; - va_list params; - int i, totin, totout; - - function = gpu_lookup_function(name); - if (!function) { - fprintf(stderr, "GPU failed to find function %s\n", name); - return false; - } - - node = GPU_node_begin(name); - totin = 0; - totout = 0; - - if (in) { - for (i = 0; !in[i].end; i++) { - if (in[i].type != GPU_NONE) { - gpu_node_input_socket(material, bnode, node, &in[i], i); - totin++; - } - } - } - - if (out) { - for (i = 0; !out[i].end; i++) { - if (out[i].type != GPU_NONE) { - gpu_node_output(node, out[i].type, &out[i].link); - totout++; - } - } - } - - va_start(params, out); - for (i = 0; i < function->totparam; i++) { - if (function->paramqual[i] != FUNCTION_QUAL_IN) { - if (totout == 0) { - linkptr = va_arg(params, GPUNodeLink **); - gpu_node_output(node, function->paramtype[i], linkptr); - } - else - totout--; - } - else { - if (totin == 0) { - link = va_arg(params, GPUNodeLink *); - if (link->socket) - gpu_node_input_socket(NULL, NULL, node, link->socket, -1); - else - gpu_node_input_link(node, link, function->paramtype[i]); - } - else - totin--; - } - } - va_end(params); - - gpu_material_add_node(material, node); - - return true; + GPUNode *node; + GPUFunction *function; + GPUNodeLink *link, **linkptr; + va_list params; + int i, totin, totout; + + function = gpu_lookup_function(name); + if (!function) { + fprintf(stderr, "GPU failed to find function %s\n", name); + return false; + } + + node = GPU_node_begin(name); + totin = 0; + totout = 0; + + if (in) { + for (i = 0; !in[i].end; i++) { + if (in[i].type != GPU_NONE) { + gpu_node_input_socket(material, bnode, node, &in[i], i); + totin++; + } + } + } + + if (out) { + for (i = 0; !out[i].end; i++) { + if (out[i].type != GPU_NONE) { + gpu_node_output(node, out[i].type, &out[i].link); + totout++; + } + } + } + + va_start(params, out); + for (i = 0; i < function->totparam; i++) { + if (function->paramqual[i] != FUNCTION_QUAL_IN) { + if (totout == 0) { + linkptr = va_arg(params, GPUNodeLink **); + gpu_node_output(node, function->paramtype[i], linkptr); + } + else + totout--; + } + else { + if (totin == 0) { + link = va_arg(params, GPUNodeLink *); + if (link->socket) + gpu_node_input_socket(NULL, NULL, node, link->socket, -1); + else + gpu_node_input_link(node, link, function->paramtype[i]); + } + else + totin--; + } + } + va_end(params); + + gpu_material_add_node(material, node); + + return true; } -GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat, bNode *node, GPUNodeStack *stack, const int index) +GPUNodeLink *GPU_uniformbuffer_link_out(GPUMaterial *mat, + bNode *node, + GPUNodeStack *stack, + const int index) { - return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT); + return gpu_uniformbuffer_link(mat, node, stack, index, SOCK_OUT); } /* Pass create/free */ static void gpu_nodes_tag(GPUNodeLink *link) { - GPUNode *node; - GPUInput *input; + GPUNode *node; + GPUInput *input; - if (!link->output) - return; + if (!link->output) + return; - node = link->output->node; - if (node->tag) - return; + node = link->output->node; + if (node->tag) + return; - node->tag = true; - for (input = node->inputs.first; input; input = input->next) - if (input->link) - gpu_nodes_tag(input->link); + node->tag = true; + for (input = node->inputs.first; input; input = input->next) + if (input->link) + gpu_nodes_tag(input->link); } void GPU_nodes_prune(ListBase *nodes, GPUNodeLink *outlink) { - GPUNode *node, *next; + GPUNode *node, *next; - for (node = nodes->first; node; node = node->next) - node->tag = false; + for (node = nodes->first; node; node = node->next) + node->tag = false; - gpu_nodes_tag(outlink); + gpu_nodes_tag(outlink); - for (node = nodes->first; node; node = next) { - next = node->next; + for (node = nodes->first; node; node = next) { + next = node->next; - if (!node->tag) { - BLI_remlink(nodes, node); - gpu_node_free(node); - } - } + if (!node->tag) { + BLI_remlink(nodes, node); + gpu_node_free(node); + } + } } static bool gpu_pass_is_valid(GPUPass *pass) { - /* Shader is not null if compilation is successful. */ - return (pass->compiled == false || pass->shader != NULL); + /* Shader is not null if compilation is successful. */ + return (pass->compiled == false || pass->shader != NULL); } -GPUPass *GPU_generate_pass( - GPUMaterial *material, - GPUNodeLink *frag_outlink, - struct GPUVertAttrLayers *attrs, - ListBase *nodes, - int *builtins, - const char *vert_code, - const char *geom_code, - const char *frag_lib, - const char *defines) +GPUPass *GPU_generate_pass(GPUMaterial *material, + GPUNodeLink *frag_outlink, + struct GPUVertAttrLayers *attrs, + ListBase *nodes, + int *builtins, + const char *vert_code, + const char *geom_code, + const char *frag_lib, + const char *defines) { - char *vertexcode, *geometrycode, *fragmentcode; - GPUPass *pass = NULL, *pass_hash = NULL; - - /* prune unused nodes */ - GPU_nodes_prune(nodes, frag_outlink); - - GPU_nodes_get_vertex_attrs(nodes, attrs); - - /* generate code */ - char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, builtins); - - /* Cache lookup: Reuse shaders already compiled */ - uint32_t hash = gpu_pass_hash(fragmentgen, defines, attrs); - pass_hash = gpu_pass_cache_lookup(hash); - - if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) { - /* No collision, just return the pass. */ - MEM_freeN(fragmentgen); - if (!gpu_pass_is_valid(pass_hash)) { - /* Shader has already been created but failed to compile. */ - return NULL; - } - pass_hash->refcount += 1; - return pass_hash; - } - - /* Either the shader is not compiled or there is a hash collision... - * continue generating the shader strings. */ - char *tmp = BLI_strdupcat(frag_lib, glsl_material_library); - - geometrycode = code_generate_geometry(nodes, geom_code, defines); - vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL)); - fragmentcode = BLI_strdupcat(tmp, fragmentgen); - - MEM_freeN(fragmentgen); - MEM_freeN(tmp); - - if (pass_hash) { - /* Cache lookup: Reuse shaders already compiled */ - pass = gpu_pass_cache_resolve_collision(pass_hash, vertexcode, geometrycode, fragmentcode, defines, hash); - } - - if (pass) { - /* Cache hit. Reuse the same GPUPass and GPUShader. */ - if (!gpu_pass_is_valid(pass)) { - /* Shader has already been created but failed to compile. */ - return NULL; - } - - MEM_SAFE_FREE(vertexcode); - MEM_SAFE_FREE(fragmentcode); - MEM_SAFE_FREE(geometrycode); - - pass->refcount += 1; - } - else { - /* We still create a pass even if shader compilation - * fails to avoid trying to compile again and again. */ - pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); - pass->shader = NULL; - pass->refcount = 1; - pass->hash = hash; - pass->vertexcode = vertexcode; - pass->fragmentcode = fragmentcode; - pass->geometrycode = geometrycode; - pass->defines = (defines) ? BLI_strdup(defines) : NULL; - pass->compiled = false; - - BLI_spin_lock(&pass_cache_spin); - if (pass_hash != NULL) { - /* Add after the first pass having the same hash. */ - pass->next = pass_hash->next; - pass_hash->next = pass; - } - else { - /* No other pass have same hash, just prepend to the list. */ - BLI_LINKS_PREPEND(pass_cache, pass); - } - BLI_spin_unlock(&pass_cache_spin); - } - - return pass; + char *vertexcode, *geometrycode, *fragmentcode; + GPUPass *pass = NULL, *pass_hash = NULL; + + /* prune unused nodes */ + GPU_nodes_prune(nodes, frag_outlink); + + GPU_nodes_get_vertex_attrs(nodes, attrs); + + /* generate code */ + char *fragmentgen = code_generate_fragment(material, nodes, frag_outlink->output, builtins); + + /* Cache lookup: Reuse shaders already compiled */ + uint32_t hash = gpu_pass_hash(fragmentgen, defines, attrs); + pass_hash = gpu_pass_cache_lookup(hash); + + if (pass_hash && (pass_hash->next == NULL || pass_hash->next->hash != hash)) { + /* No collision, just return the pass. */ + MEM_freeN(fragmentgen); + if (!gpu_pass_is_valid(pass_hash)) { + /* Shader has already been created but failed to compile. */ + return NULL; + } + pass_hash->refcount += 1; + return pass_hash; + } + + /* Either the shader is not compiled or there is a hash collision... + * continue generating the shader strings. */ + char *tmp = BLI_strdupcat(frag_lib, glsl_material_library); + + geometrycode = code_generate_geometry(nodes, geom_code, defines); + vertexcode = code_generate_vertex(nodes, vert_code, (geometrycode != NULL)); + fragmentcode = BLI_strdupcat(tmp, fragmentgen); + + MEM_freeN(fragmentgen); + MEM_freeN(tmp); + + if (pass_hash) { + /* Cache lookup: Reuse shaders already compiled */ + pass = gpu_pass_cache_resolve_collision( + pass_hash, vertexcode, geometrycode, fragmentcode, defines, hash); + } + + if (pass) { + /* Cache hit. Reuse the same GPUPass and GPUShader. */ + if (!gpu_pass_is_valid(pass)) { + /* Shader has already been created but failed to compile. */ + return NULL; + } + + MEM_SAFE_FREE(vertexcode); + MEM_SAFE_FREE(fragmentcode); + MEM_SAFE_FREE(geometrycode); + + pass->refcount += 1; + } + else { + /* We still create a pass even if shader compilation + * fails to avoid trying to compile again and again. */ + pass = MEM_callocN(sizeof(GPUPass), "GPUPass"); + pass->shader = NULL; + pass->refcount = 1; + pass->hash = hash; + pass->vertexcode = vertexcode; + pass->fragmentcode = fragmentcode; + pass->geometrycode = geometrycode; + pass->defines = (defines) ? BLI_strdup(defines) : NULL; + pass->compiled = false; + + BLI_spin_lock(&pass_cache_spin); + if (pass_hash != NULL) { + /* Add after the first pass having the same hash. */ + pass->next = pass_hash->next; + pass_hash->next = pass; + } + else { + /* No other pass have same hash, just prepend to the list. */ + BLI_LINKS_PREPEND(pass_cache, pass); + } + BLI_spin_unlock(&pass_cache_spin); + } + + return pass; } static int count_active_texture_sampler(GPUShader *shader, char *source) { - char *code = source; - int samplers_id[64]; /* Remember this is per stage. */ - int sampler_len = 0; - - while ((code = strstr(code, "uniform "))) { - /* Move past "uniform". */ - code += 7; - /* Skip following spaces. */ - while (*code == ' ') { code++; } - /* Skip "i" from potential isamplers. */ - if (*code == 'i') { code++; } - /* Skip following spaces. */ - if (gpu_str_prefix(code, "sampler")) { - /* Move past "uniform". */ - code += 7; - /* Skip sampler type suffix. */ - while (*code != ' ' && *code != '\0') { code++; } - /* Skip following spaces. */ - while (*code == ' ') { code++; } - - if (*code != '\0') { - char sampler_name[64]; - code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name)); - int id = GPU_shader_get_uniform_ensure(shader, sampler_name); - - if (id == -1) { - continue; - } - /* Catch duplicates. */ - bool is_duplicate = false; - for (int i = 0; i < sampler_len; ++i) { - if (samplers_id[i] == id) { - is_duplicate = true; - } - } - - if (!is_duplicate) { - samplers_id[sampler_len] = id; - sampler_len++; - } - } - } - } - - return sampler_len; + char *code = source; + int samplers_id[64]; /* Remember this is per stage. */ + int sampler_len = 0; + + while ((code = strstr(code, "uniform "))) { + /* Move past "uniform". */ + code += 7; + /* Skip following spaces. */ + while (*code == ' ') { + code++; + } + /* Skip "i" from potential isamplers. */ + if (*code == 'i') { + code++; + } + /* Skip following spaces. */ + if (gpu_str_prefix(code, "sampler")) { + /* Move past "uniform". */ + code += 7; + /* Skip sampler type suffix. */ + while (*code != ' ' && *code != '\0') { + code++; + } + /* Skip following spaces. */ + while (*code == ' ') { + code++; + } + + if (*code != '\0') { + char sampler_name[64]; + code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name)); + int id = GPU_shader_get_uniform_ensure(shader, sampler_name); + + if (id == -1) { + continue; + } + /* Catch duplicates. */ + bool is_duplicate = false; + for (int i = 0; i < sampler_len; ++i) { + if (samplers_id[i] == id) { + is_duplicate = true; + } + } + + if (!is_duplicate) { + samplers_id[sampler_len] = id; + sampler_len++; + } + } + } + } + + return sampler_len; } static bool gpu_pass_shader_validate(GPUPass *pass) { - if (pass->shader == NULL) { - return false; - } - - /* NOTE: The only drawback of this method is that it will count a sampler - * used in the fragment shader and only declared (but not used) in the vertex - * shader as used by both. But this corner case is not happening for now. */ - int vert_samplers_len = count_active_texture_sampler(pass->shader, pass->vertexcode); - int frag_samplers_len = count_active_texture_sampler(pass->shader, pass->fragmentcode); - - int total_samplers_len = vert_samplers_len + frag_samplers_len; - - /* Validate against opengl limit. */ - if ((frag_samplers_len > GPU_max_textures_frag()) || - (vert_samplers_len > GPU_max_textures_vert())) - { - return false; - } - - if (pass->geometrycode) { - int geom_samplers_len = count_active_texture_sampler(pass->shader, pass->geometrycode); - total_samplers_len += geom_samplers_len; - if (geom_samplers_len > GPU_max_textures_geom()) { - return false; - } - } - - return (total_samplers_len <= GPU_max_textures()); + if (pass->shader == NULL) { + return false; + } + + /* NOTE: The only drawback of this method is that it will count a sampler + * used in the fragment shader and only declared (but not used) in the vertex + * shader as used by both. But this corner case is not happening for now. */ + int vert_samplers_len = count_active_texture_sampler(pass->shader, pass->vertexcode); + int frag_samplers_len = count_active_texture_sampler(pass->shader, pass->fragmentcode); + + int total_samplers_len = vert_samplers_len + frag_samplers_len; + + /* Validate against opengl limit. */ + if ((frag_samplers_len > GPU_max_textures_frag()) || + (vert_samplers_len > GPU_max_textures_vert())) { + return false; + } + + if (pass->geometrycode) { + int geom_samplers_len = count_active_texture_sampler(pass->shader, pass->geometrycode); + total_samplers_len += geom_samplers_len; + if (geom_samplers_len > GPU_max_textures_geom()) { + return false; + } + } + + return (total_samplers_len <= GPU_max_textures()); } void GPU_pass_compile(GPUPass *pass, const char *shname) { - if (!pass->compiled) { - pass->shader = GPU_shader_create( - pass->vertexcode, - pass->fragmentcode, - pass->geometrycode, - NULL, - pass->defines, - shname); - - /* NOTE: Some drivers / gpu allows more active samplers than the opengl limit. - * We need to make sure to count active samplers to avoid undefined behavior. */ - if (!gpu_pass_shader_validate(pass)) { - if (pass->shader != NULL) { - fprintf(stderr, "GPUShader: error: too many samplers in shader.\n"); - GPU_shader_free(pass->shader); - } - pass->shader = NULL; - } - else if (!BLI_thread_is_main()) { - /* For some Intel drivers, you must use the program at least once - * in the rendering context that it is linked. */ - glUseProgram(GPU_shader_get_program(pass->shader)); - glUseProgram(0); - } - - pass->compiled = true; - } + if (!pass->compiled) { + pass->shader = GPU_shader_create( + pass->vertexcode, pass->fragmentcode, pass->geometrycode, NULL, pass->defines, shname); + + /* NOTE: Some drivers / gpu allows more active samplers than the opengl limit. + * We need to make sure to count active samplers to avoid undefined behavior. */ + if (!gpu_pass_shader_validate(pass)) { + if (pass->shader != NULL) { + fprintf(stderr, "GPUShader: error: too many samplers in shader.\n"); + GPU_shader_free(pass->shader); + } + pass->shader = NULL; + } + else if (!BLI_thread_is_main()) { + /* For some Intel drivers, you must use the program at least once + * in the rendering context that it is linked. */ + glUseProgram(GPU_shader_get_program(pass->shader)); + glUseProgram(0); + } + + pass->compiled = true; + } } void GPU_pass_release(GPUPass *pass) { - BLI_assert(pass->refcount > 0); - pass->refcount--; + BLI_assert(pass->refcount > 0); + pass->refcount--; } static void gpu_pass_free(GPUPass *pass) { - BLI_assert(pass->refcount == 0); - if (pass->shader) { - GPU_shader_free(pass->shader); - } - MEM_SAFE_FREE(pass->fragmentcode); - MEM_SAFE_FREE(pass->geometrycode); - MEM_SAFE_FREE(pass->vertexcode); - MEM_SAFE_FREE(pass->defines); - MEM_freeN(pass); + BLI_assert(pass->refcount == 0); + if (pass->shader) { + GPU_shader_free(pass->shader); + } + MEM_SAFE_FREE(pass->fragmentcode); + MEM_SAFE_FREE(pass->geometrycode); + MEM_SAFE_FREE(pass->vertexcode); + MEM_SAFE_FREE(pass->defines); + MEM_freeN(pass); } void GPU_pass_free_nodes(ListBase *nodes) { - gpu_nodes_free(nodes); + gpu_nodes_free(nodes); } void GPU_pass_cache_garbage_collect(void) { - static int lasttime = 0; - const int shadercollectrate = 60; /* hardcoded for now. */ - int ctime = (int)PIL_check_seconds_timer(); - - if (ctime < shadercollectrate + lasttime) - return; - - lasttime = ctime; - - BLI_spin_lock(&pass_cache_spin); - GPUPass *next, **prev_pass = &pass_cache; - for (GPUPass *pass = pass_cache; pass; pass = next) { - next = pass->next; - if (pass->refcount == 0) { - /* Remove from list */ - *prev_pass = next; - gpu_pass_free(pass); - } - else { - prev_pass = &pass->next; - } - } - BLI_spin_unlock(&pass_cache_spin); + static int lasttime = 0; + const int shadercollectrate = 60; /* hardcoded for now. */ + int ctime = (int)PIL_check_seconds_timer(); + + if (ctime < shadercollectrate + lasttime) + return; + + lasttime = ctime; + + BLI_spin_lock(&pass_cache_spin); + GPUPass *next, **prev_pass = &pass_cache; + for (GPUPass *pass = pass_cache; pass; pass = next) { + next = pass->next; + if (pass->refcount == 0) { + /* Remove from list */ + *prev_pass = next; + gpu_pass_free(pass); + } + else { + prev_pass = &pass->next; + } + } + BLI_spin_unlock(&pass_cache_spin); } void GPU_pass_cache_init(void) { - BLI_spin_init(&pass_cache_spin); + BLI_spin_init(&pass_cache_spin); } void GPU_pass_cache_free(void) { - BLI_spin_lock(&pass_cache_spin); - while (pass_cache) { - GPUPass *next = pass_cache->next; - gpu_pass_free(pass_cache); - pass_cache = next; - } - BLI_spin_unlock(&pass_cache_spin); - - BLI_spin_end(&pass_cache_spin); + BLI_spin_lock(&pass_cache_spin); + while (pass_cache) { + GPUPass *next = pass_cache->next; + gpu_pass_free(pass_cache); + pass_cache = next; + } + BLI_spin_unlock(&pass_cache_spin); + + BLI_spin_end(&pass_cache_spin); } diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h index 181bcde9120..73155c3aafa 100644 --- a/source/blender/gpu/intern/gpu_codegen.h +++ b/source/blender/gpu/intern/gpu_codegen.h @@ -21,7 +21,6 @@ * \ingroup gpu */ - #ifndef __GPU_CODEGEN_H__ #define __GPU_CODEGEN_H__ @@ -44,140 +43,143 @@ struct PreviewImage; */ typedef enum eGPUDataSource { - GPU_SOURCE_OUTPUT, - GPU_SOURCE_CONSTANT, - GPU_SOURCE_UNIFORM, - GPU_SOURCE_ATTR, - GPU_SOURCE_BUILTIN, - GPU_SOURCE_STRUCT, - GPU_SOURCE_TEX, + GPU_SOURCE_OUTPUT, + GPU_SOURCE_CONSTANT, + GPU_SOURCE_UNIFORM, + GPU_SOURCE_ATTR, + GPU_SOURCE_BUILTIN, + GPU_SOURCE_STRUCT, + GPU_SOURCE_TEX, } eGPUDataSource; typedef enum { - GPU_NODE_LINK_NONE = 0, - GPU_NODE_LINK_ATTR, - GPU_NODE_LINK_BUILTIN, - GPU_NODE_LINK_COLORBAND, - GPU_NODE_LINK_CONSTANT, - GPU_NODE_LINK_IMAGE_BLENDER, - GPU_NODE_LINK_OUTPUT, - GPU_NODE_LINK_UNIFORM, + GPU_NODE_LINK_NONE = 0, + GPU_NODE_LINK_ATTR, + GPU_NODE_LINK_BUILTIN, + GPU_NODE_LINK_COLORBAND, + GPU_NODE_LINK_CONSTANT, + GPU_NODE_LINK_IMAGE_BLENDER, + GPU_NODE_LINK_OUTPUT, + GPU_NODE_LINK_UNIFORM, } GPUNodeLinkType; struct GPUNode { - struct GPUNode *next, *prev; + struct GPUNode *next, *prev; - const char *name; + const char *name; - /* Internal flag to mark nodes during pruning */ - bool tag; + /* Internal flag to mark nodes during pruning */ + bool tag; - ListBase inputs; - ListBase outputs; + ListBase inputs; + ListBase outputs; }; struct GPUNodeLink { - GPUNodeStack *socket; - - GPUNodeLinkType link_type; - int users; /* Refcount */ - - union { - /* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */ - float *data; - /* GPU_NODE_LINK_BUILTIN */ - eGPUBuiltin builtin; - /* GPU_NODE_LINK_COLORBAND */ - struct GPUTexture **coba; - /* GPU_NODE_LINK_OUTPUT */ - struct GPUOutput *output; - /* GPU_NODE_LINK_ATTR */ - struct { - const char *attr_name; - CustomDataType attr_type; - }; - /* GPU_NODE_LINK_IMAGE_BLENDER */ - struct { - struct Image *ima; - struct ImageUser *iuser; - bool image_isdata; - }; - }; + GPUNodeStack *socket; + + GPUNodeLinkType link_type; + int users; /* Refcount */ + + union { + /* GPU_NODE_LINK_CONSTANT | GPU_NODE_LINK_UNIFORM */ + float *data; + /* GPU_NODE_LINK_BUILTIN */ + eGPUBuiltin builtin; + /* GPU_NODE_LINK_COLORBAND */ + struct GPUTexture **coba; + /* GPU_NODE_LINK_OUTPUT */ + struct GPUOutput *output; + /* GPU_NODE_LINK_ATTR */ + struct { + const char *attr_name; + CustomDataType attr_type; + }; + /* GPU_NODE_LINK_IMAGE_BLENDER */ + struct { + struct Image *ima; + struct ImageUser *iuser; + bool image_isdata; + }; + }; }; typedef struct GPUOutput { - struct GPUOutput *next, *prev; + struct GPUOutput *next, *prev; - GPUNode *node; - eGPUType type; /* data type = length of vector/matrix */ - GPUNodeLink *link; /* output link */ - int id; /* unique id as created by code generator */ + GPUNode *node; + eGPUType type; /* data type = length of vector/matrix */ + GPUNodeLink *link; /* output link */ + int id; /* unique id as created by code generator */ } GPUOutput; typedef struct GPUInput { - struct GPUInput *next, *prev; - - GPUNode *node; - eGPUType type; /* datatype */ - GPUNodeLink *link; - int id; /* unique id as created by code generator */ - - eGPUDataSource source; /* data source */ - - int shaderloc; /* id from opengl */ - char shadername[32]; /* name in shader */ - - /* Content based on eGPUDataSource */ - union { - /* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */ - float vec[16]; /* vector data */ - /* GPU_SOURCE_BUILTIN */ - eGPUBuiltin builtin; /* builtin uniform */ - /* GPU_SOURCE_TEX */ - struct { - struct GPUTexture **coba; /* input texture, only set at runtime */ - struct Image *ima; /* image */ - struct ImageUser *iuser; /* image user */ - bool image_isdata; /* image does not contain color data */ - bool bindtex; /* input is responsible for binding the texture? */ - int texid; /* number for multitexture, starting from zero */ - eGPUType textype; /* texture type (2D, 1D Array ...) */ - }; - /* GPU_SOURCE_ATTR */ - struct { - /** Attribute name. */ - char attr_name[MAX_CUSTOMDATA_LAYER_NAME]; - /** ID for vertex attributes. */ - int attr_id; - /** This is the first one that is bound. */ - bool attr_first; - /** Attribute type. */ - CustomDataType attr_type; - }; - }; + struct GPUInput *next, *prev; + + GPUNode *node; + eGPUType type; /* datatype */ + GPUNodeLink *link; + int id; /* unique id as created by code generator */ + + eGPUDataSource source; /* data source */ + + int shaderloc; /* id from opengl */ + char shadername[32]; /* name in shader */ + + /* Content based on eGPUDataSource */ + union { + /* GPU_SOURCE_CONSTANT | GPU_SOURCE_UNIFORM */ + float vec[16]; /* vector data */ + /* GPU_SOURCE_BUILTIN */ + eGPUBuiltin builtin; /* builtin uniform */ + /* GPU_SOURCE_TEX */ + struct { + struct GPUTexture **coba; /* input texture, only set at runtime */ + struct Image *ima; /* image */ + struct ImageUser *iuser; /* image user */ + bool image_isdata; /* image does not contain color data */ + bool bindtex; /* input is responsible for binding the texture? */ + int texid; /* number for multitexture, starting from zero */ + eGPUType textype; /* texture type (2D, 1D Array ...) */ + }; + /* GPU_SOURCE_ATTR */ + struct { + /** Attribute name. */ + char attr_name[MAX_CUSTOMDATA_LAYER_NAME]; + /** ID for vertex attributes. */ + int attr_id; + /** This is the first one that is bound. */ + bool attr_first; + /** Attribute type. */ + CustomDataType attr_type; + }; + }; } GPUInput; struct GPUPass { - struct GPUPass *next; - - struct GPUShader *shader; - char *fragmentcode; - char *geometrycode; - char *vertexcode; - char *defines; - uint refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */ - uint32_t hash; /* Identity hash generated from all GLSL code. */ - bool compiled; /* Did we already tried to compile the attached GPUShader. */ + struct GPUPass *next; + + struct GPUShader *shader; + char *fragmentcode; + char *geometrycode; + char *vertexcode; + char *defines; + uint refcount; /* Orphaned GPUPasses gets freed by the garbage collector. */ + uint32_t hash; /* Identity hash generated from all GLSL code. */ + bool compiled; /* Did we already tried to compile the attached GPUShader. */ }; typedef struct GPUPass GPUPass; -GPUPass *GPU_generate_pass( - GPUMaterial *material, - GPUNodeLink *frag_outlink, struct GPUVertAttrLayers *attrs, - ListBase *nodes, int *builtins, - const char *vert_code, const char *geom_code, - const char *frag_lib, const char *defines); +GPUPass *GPU_generate_pass(GPUMaterial *material, + GPUNodeLink *frag_outlink, + struct GPUVertAttrLayers *attrs, + ListBase *nodes, + int *builtins, + const char *vert_code, + const char *geom_code, + const char *frag_lib, + const char *defines); struct GPUShader *GPU_pass_shader_get(GPUPass *pass); @@ -198,6 +200,9 @@ void gpu_codegen_exit(void); const char *GPU_builtin_name(eGPUBuiltin builtin); void gpu_material_add_node(struct GPUMaterial *material, struct GPUNode *node); -struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row); +struct GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, + int size, + float *pixels, + float *row); #endif diff --git a/source/blender/gpu/intern/gpu_context.cpp b/source/blender/gpu/intern/gpu_context.cpp index 77a69999bf6..8e489fbac39 100644 --- a/source/blender/gpu/intern/gpu_context.cpp +++ b/source/blender/gpu/intern/gpu_context.cpp @@ -44,16 +44,16 @@ #include #if TRUST_NO_ONE -#if 0 +# if 0 extern "C" { extern int BLI_thread_is_main(void); /* Blender-specific function */ } static bool thread_is_main() { - /* "main" here means the GL context's thread */ - return BLI_thread_is_main(); + /* "main" here means the GL context's thread */ + return BLI_thread_is_main(); } -#endif +# endif #endif static std::vector orphaned_buffer_ids; @@ -62,30 +62,32 @@ static std::vector orphaned_texture_ids; static std::mutex orphans_mutex; struct GPUContext { - GLuint default_vao; - GPUFrameBuffer *current_fbo; - std::unordered_set batches; /* Batches that have VAOs from this context */ + GLuint default_vao; + GPUFrameBuffer *current_fbo; + std::unordered_set batches; /* Batches that have VAOs from this context */ #ifdef DEBUG - std::unordered_set framebuffers; /* Framebuffers that have FBO from this context */ + std::unordered_set + framebuffers; /* Framebuffers that have FBO from this context */ #endif - std::vector orphaned_vertarray_ids; - std::vector orphaned_framebuffer_ids; - std::mutex orphans_mutex; /* todo: try spinlock instead */ + std::vector orphaned_vertarray_ids; + std::vector orphaned_framebuffer_ids; + std::mutex orphans_mutex; /* todo: try spinlock instead */ #if TRUST_NO_ONE - pthread_t thread; /* Thread on which this context is active. */ - bool thread_is_used; + pthread_t thread; /* Thread on which this context is active. */ + bool thread_is_used; #endif - GPUContext() { + GPUContext() + { #if TRUST_NO_ONE - thread_is_used = false; + thread_is_used = false; #endif - current_fbo = 0; - } + current_fbo = 0; + } }; #if defined(_MSC_VER) && (_MSC_VER == 1800) -#define thread_local __declspec(thread) +# define thread_local __declspec(thread) thread_local GPUContext *active_ctx = NULL; #else static thread_local GPUContext *active_ctx = NULL; @@ -93,181 +95,183 @@ static thread_local GPUContext *active_ctx = NULL; static void orphans_add(GPUContext *ctx, std::vector *orphan_list, GLuint id) { - std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex; + std::mutex *mutex = (ctx) ? &ctx->orphans_mutex : &orphans_mutex; - mutex->lock(); - orphan_list->emplace_back(id); - mutex->unlock(); + mutex->lock(); + orphan_list->emplace_back(id); + mutex->unlock(); } static void orphans_clear(GPUContext *ctx) { - BLI_assert(ctx); /* need at least an active context */ - BLI_assert(pthread_equal(pthread_self(), ctx->thread)); /* context has been activated by another thread! */ - - ctx->orphans_mutex.lock(); - if (!ctx->orphaned_vertarray_ids.empty()) { - uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size(); - glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data()); - ctx->orphaned_vertarray_ids.clear(); - } - if (!ctx->orphaned_framebuffer_ids.empty()) { - uint orphan_len = (uint)ctx->orphaned_framebuffer_ids.size(); - glDeleteFramebuffers(orphan_len, ctx->orphaned_framebuffer_ids.data()); - ctx->orphaned_framebuffer_ids.clear(); - } - - ctx->orphans_mutex.unlock(); - - orphans_mutex.lock(); - if (!orphaned_buffer_ids.empty()) { - uint orphan_len = (uint)orphaned_buffer_ids.size(); - glDeleteBuffers(orphan_len, orphaned_buffer_ids.data()); - orphaned_buffer_ids.clear(); - } - if (!orphaned_texture_ids.empty()) { - uint orphan_len = (uint)orphaned_texture_ids.size(); - glDeleteTextures(orphan_len, orphaned_texture_ids.data()); - orphaned_texture_ids.clear(); - } - orphans_mutex.unlock(); + BLI_assert(ctx); /* need at least an active context */ + BLI_assert(pthread_equal(pthread_self(), + ctx->thread)); /* context has been activated by another thread! */ + + ctx->orphans_mutex.lock(); + if (!ctx->orphaned_vertarray_ids.empty()) { + uint orphan_len = (uint)ctx->orphaned_vertarray_ids.size(); + glDeleteVertexArrays(orphan_len, ctx->orphaned_vertarray_ids.data()); + ctx->orphaned_vertarray_ids.clear(); + } + if (!ctx->orphaned_framebuffer_ids.empty()) { + uint orphan_len = (uint)ctx->orphaned_framebuffer_ids.size(); + glDeleteFramebuffers(orphan_len, ctx->orphaned_framebuffer_ids.data()); + ctx->orphaned_framebuffer_ids.clear(); + } + + ctx->orphans_mutex.unlock(); + + orphans_mutex.lock(); + if (!orphaned_buffer_ids.empty()) { + uint orphan_len = (uint)orphaned_buffer_ids.size(); + glDeleteBuffers(orphan_len, orphaned_buffer_ids.data()); + orphaned_buffer_ids.clear(); + } + if (!orphaned_texture_ids.empty()) { + uint orphan_len = (uint)orphaned_texture_ids.size(); + glDeleteTextures(orphan_len, orphaned_texture_ids.data()); + orphaned_texture_ids.clear(); + } + orphans_mutex.unlock(); } GPUContext *GPU_context_create(void) { - /* BLI_assert(thread_is_main()); */ - GPUContext *ctx = new GPUContext; - glGenVertexArrays(1, &ctx->default_vao); - GPU_context_active_set(ctx); - return ctx; + /* BLI_assert(thread_is_main()); */ + GPUContext *ctx = new GPUContext; + glGenVertexArrays(1, &ctx->default_vao); + GPU_context_active_set(ctx); + return ctx; } /* to be called after GPU_context_active_set(ctx_to_destroy) */ void GPU_context_discard(GPUContext *ctx) { - /* Make sure no other thread has locked it. */ - BLI_assert(ctx == active_ctx); - BLI_assert(pthread_equal(pthread_self(), ctx->thread)); - BLI_assert(ctx->orphaned_vertarray_ids.empty()); + /* Make sure no other thread has locked it. */ + BLI_assert(ctx == active_ctx); + BLI_assert(pthread_equal(pthread_self(), ctx->thread)); + BLI_assert(ctx->orphaned_vertarray_ids.empty()); #ifdef DEBUG - /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */ - BLI_assert(ctx->framebuffers.empty()); + /* For now don't allow GPUFrameBuffers to be reuse in another ctx. */ + BLI_assert(ctx->framebuffers.empty()); #endif - /* delete remaining vaos */ - while (!ctx->batches.empty()) { - /* this removes the array entry */ - GPU_batch_vao_cache_clear(*ctx->batches.begin()); - } - glDeleteVertexArrays(1, &ctx->default_vao); - delete ctx; - active_ctx = NULL; + /* delete remaining vaos */ + while (!ctx->batches.empty()) { + /* this removes the array entry */ + GPU_batch_vao_cache_clear(*ctx->batches.begin()); + } + glDeleteVertexArrays(1, &ctx->default_vao); + delete ctx; + active_ctx = NULL; } /* ctx can be NULL */ void GPU_context_active_set(GPUContext *ctx) { #if TRUST_NO_ONE - if (active_ctx) { - active_ctx->thread_is_used = false; - } - /* Make sure no other context is already bound to this thread. */ - if (ctx) { - /* Make sure no other thread has locked it. */ - assert(ctx->thread_is_used == false); - ctx->thread = pthread_self(); - ctx->thread_is_used = true; - } + if (active_ctx) { + active_ctx->thread_is_used = false; + } + /* Make sure no other context is already bound to this thread. */ + if (ctx) { + /* Make sure no other thread has locked it. */ + assert(ctx->thread_is_used == false); + ctx->thread = pthread_self(); + ctx->thread_is_used = true; + } #endif - if (ctx) { - orphans_clear(ctx); - } - active_ctx = ctx; + if (ctx) { + orphans_clear(ctx); + } + active_ctx = ctx; } GPUContext *GPU_context_active_get(void) { - return active_ctx; + return active_ctx; } GLuint GPU_vao_default(void) { - BLI_assert(active_ctx); /* need at least an active context */ - BLI_assert(pthread_equal(pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ - return active_ctx->default_vao; + BLI_assert(active_ctx); /* need at least an active context */ + BLI_assert(pthread_equal( + pthread_self(), active_ctx->thread)); /* context has been activated by another thread! */ + return active_ctx->default_vao; } GLuint GPU_vao_alloc(void) { - GLuint new_vao_id = 0; - orphans_clear(active_ctx); - glGenVertexArrays(1, &new_vao_id); - return new_vao_id; + GLuint new_vao_id = 0; + orphans_clear(active_ctx); + glGenVertexArrays(1, &new_vao_id); + return new_vao_id; } GLuint GPU_fbo_alloc(void) { - GLuint new_fbo_id = 0; - orphans_clear(active_ctx); - glGenFramebuffers(1, &new_fbo_id); - return new_fbo_id; + GLuint new_fbo_id = 0; + orphans_clear(active_ctx); + glGenFramebuffers(1, &new_fbo_id); + return new_fbo_id; } GLuint GPU_buf_alloc(void) { - GLuint new_buffer_id = 0; - orphans_clear(active_ctx); - glGenBuffers(1, &new_buffer_id); - return new_buffer_id; + GLuint new_buffer_id = 0; + orphans_clear(active_ctx); + glGenBuffers(1, &new_buffer_id); + return new_buffer_id; } GLuint GPU_tex_alloc(void) { - GLuint new_texture_id = 0; - orphans_clear(active_ctx); - glGenTextures(1, &new_texture_id); - return new_texture_id; + GLuint new_texture_id = 0; + orphans_clear(active_ctx); + glGenTextures(1, &new_texture_id); + return new_texture_id; } void GPU_vao_free(GLuint vao_id, GPUContext *ctx) { - BLI_assert(ctx); - if (ctx == active_ctx) { - glDeleteVertexArrays(1, &vao_id); - } - else { - orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id); - } + BLI_assert(ctx); + if (ctx == active_ctx) { + glDeleteVertexArrays(1, &vao_id); + } + else { + orphans_add(ctx, &ctx->orphaned_vertarray_ids, vao_id); + } } void GPU_fbo_free(GLuint fbo_id, GPUContext *ctx) { - BLI_assert(ctx); - if (ctx == active_ctx) { - glDeleteFramebuffers(1, &fbo_id); - } - else { - orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id); - } + BLI_assert(ctx); + if (ctx == active_ctx) { + glDeleteFramebuffers(1, &fbo_id); + } + else { + orphans_add(ctx, &ctx->orphaned_framebuffer_ids, fbo_id); + } } void GPU_buf_free(GLuint buf_id) { - if (active_ctx) { - glDeleteBuffers(1, &buf_id); - } - else { - orphans_add(NULL, &orphaned_buffer_ids, buf_id); - } + if (active_ctx) { + glDeleteBuffers(1, &buf_id); + } + else { + orphans_add(NULL, &orphaned_buffer_ids, buf_id); + } } void GPU_tex_free(GLuint tex_id) { - if (active_ctx) { - glDeleteTextures(1, &tex_id); - } - else { - orphans_add(NULL, &orphaned_texture_ids, tex_id); - } + if (active_ctx) { + glDeleteTextures(1, &tex_id); + } + else { + orphans_add(NULL, &orphaned_texture_ids, tex_id); + } } /* GPUBatch & GPUFrameBuffer contains respectively VAO & FBO indices @@ -276,50 +280,50 @@ void GPU_tex_free(GLuint tex_id) void gpu_context_add_batch(GPUContext *ctx, GPUBatch *batch) { - BLI_assert(ctx); - ctx->orphans_mutex.lock(); - ctx->batches.emplace(batch); - ctx->orphans_mutex.unlock(); + BLI_assert(ctx); + ctx->orphans_mutex.lock(); + ctx->batches.emplace(batch); + ctx->orphans_mutex.unlock(); } void gpu_context_remove_batch(GPUContext *ctx, GPUBatch *batch) { - BLI_assert(ctx); - ctx->orphans_mutex.lock(); - ctx->batches.erase(batch); - ctx->orphans_mutex.unlock(); + BLI_assert(ctx); + ctx->orphans_mutex.lock(); + ctx->batches.erase(batch); + ctx->orphans_mutex.unlock(); } void gpu_context_add_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb) { #ifdef DEBUG - BLI_assert(ctx); - ctx->orphans_mutex.lock(); - ctx->framebuffers.emplace(fb); - ctx->orphans_mutex.unlock(); + BLI_assert(ctx); + ctx->orphans_mutex.lock(); + ctx->framebuffers.emplace(fb); + ctx->orphans_mutex.unlock(); #else - UNUSED_VARS(ctx, fb); + UNUSED_VARS(ctx, fb); #endif } void gpu_context_remove_framebuffer(GPUContext *ctx, GPUFrameBuffer *fb) { #ifdef DEBUG - BLI_assert(ctx); - ctx->orphans_mutex.lock(); - ctx->framebuffers.erase(fb); - ctx->orphans_mutex.unlock(); + BLI_assert(ctx); + ctx->orphans_mutex.lock(); + ctx->framebuffers.erase(fb); + ctx->orphans_mutex.unlock(); #else - UNUSED_VARS(ctx, fb); + UNUSED_VARS(ctx, fb); #endif } void gpu_context_active_framebuffer_set(GPUContext *ctx, GPUFrameBuffer *fb) { - ctx->current_fbo = fb; + ctx->current_fbo = fb; } GPUFrameBuffer *gpu_context_active_framebuffer_get(GPUContext *ctx) { - return ctx->current_fbo; + return ctx->current_fbo; } diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index 71f318f3a56..d8eaab424a9 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -49,94 +49,122 @@ # define APIENTRY # endif - static const char *source_name(GLenum source) { - switch (source) { - case GL_DEBUG_SOURCE_API: return "API"; - case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "window system"; - case GL_DEBUG_SOURCE_SHADER_COMPILER: return "shader compiler"; - case GL_DEBUG_SOURCE_THIRD_PARTY: return "3rd party"; - case GL_DEBUG_SOURCE_APPLICATION: return "application"; - case GL_DEBUG_SOURCE_OTHER: return "other"; - default: return "???"; - } + switch (source) { + case GL_DEBUG_SOURCE_API: + return "API"; + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + return "window system"; + case GL_DEBUG_SOURCE_SHADER_COMPILER: + return "shader compiler"; + case GL_DEBUG_SOURCE_THIRD_PARTY: + return "3rd party"; + case GL_DEBUG_SOURCE_APPLICATION: + return "application"; + case GL_DEBUG_SOURCE_OTHER: + return "other"; + default: + return "???"; + } } static const char *message_type_name(GLenum message) { - switch (message) { - case GL_DEBUG_TYPE_ERROR: return "error"; - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "deprecated behavior"; - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "undefined behavior"; - case GL_DEBUG_TYPE_PORTABILITY: return "portability"; - case GL_DEBUG_TYPE_PERFORMANCE: return "performance"; - case GL_DEBUG_TYPE_OTHER: return "other"; - case GL_DEBUG_TYPE_MARKER: return "marker"; /* KHR has this, ARB does not */ - default: return "???"; - } + switch (message) { + case GL_DEBUG_TYPE_ERROR: + return "error"; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + return "deprecated behavior"; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + return "undefined behavior"; + case GL_DEBUG_TYPE_PORTABILITY: + return "portability"; + case GL_DEBUG_TYPE_PERFORMANCE: + return "performance"; + case GL_DEBUG_TYPE_OTHER: + return "other"; + case GL_DEBUG_TYPE_MARKER: + return "marker"; /* KHR has this, ARB does not */ + default: + return "???"; + } } -static void APIENTRY gpu_debug_proc( - GLenum source, GLenum type, GLuint UNUSED(id), - GLenum severity, GLsizei UNUSED(length), - const GLchar *message, const GLvoid *UNUSED(userParm)) +static void APIENTRY gpu_debug_proc(GLenum source, + GLenum type, + GLuint UNUSED(id), + GLenum severity, + GLsizei UNUSED(length), + const GLchar *message, + const GLvoid *UNUSED(userParm)) { - bool backtrace = false; - - switch (severity) { - case GL_DEBUG_SEVERITY_HIGH: - backtrace = true; - ATTR_FALLTHROUGH; - case GL_DEBUG_SEVERITY_MEDIUM: - case GL_DEBUG_SEVERITY_LOW: - case GL_DEBUG_SEVERITY_NOTIFICATION: /* KHR has this, ARB does not */ - fprintf(stderr, "GL %s %s: %s\n", source_name(source), message_type_name(type), message); - } - - if (backtrace) { - BLI_system_backtrace(stderr); - fflush(stderr); - } + bool backtrace = false; + + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH: + backtrace = true; + ATTR_FALLTHROUGH; + case GL_DEBUG_SEVERITY_MEDIUM: + case GL_DEBUG_SEVERITY_LOW: + case GL_DEBUG_SEVERITY_NOTIFICATION: /* KHR has this, ARB does not */ + fprintf(stderr, "GL %s %s: %s\n", source_name(source), message_type_name(type), message); + } + + if (backtrace) { + BLI_system_backtrace(stderr); + fflush(stderr); + } } # if LEGACY_DEBUG static const char *category_name_amd(GLenum category) { - switch (category) { - case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error"; - case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: return "window system"; - case GL_DEBUG_CATEGORY_DEPRECATION_AMD: return "deprecated behavior"; - case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: return "undefined behavior"; - case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: return "performance"; - case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: return "shader compiler"; - case GL_DEBUG_CATEGORY_APPLICATION_AMD: return "application"; - case GL_DEBUG_CATEGORY_OTHER_AMD: return "other"; - default: return "???"; - } + switch (category) { + case GL_DEBUG_CATEGORY_API_ERROR_AMD: + return "API error"; + case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD: + return "window system"; + case GL_DEBUG_CATEGORY_DEPRECATION_AMD: + return "deprecated behavior"; + case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD: + return "undefined behavior"; + case GL_DEBUG_CATEGORY_PERFORMANCE_AMD: + return "performance"; + case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD: + return "shader compiler"; + case GL_DEBUG_CATEGORY_APPLICATION_AMD: + return "application"; + case GL_DEBUG_CATEGORY_OTHER_AMD: + return "other"; + default: + return "???"; + } } -static void APIENTRY gpu_debug_proc_amd( - GLuint UNUSED(id), GLenum category, - GLenum severity, GLsizei UNUSED(length), - const GLchar *message, GLvoid *UNUSED(userParm)) +static void APIENTRY gpu_debug_proc_amd(GLuint UNUSED(id), + GLenum category, + GLenum severity, + GLsizei UNUSED(length), + const GLchar *message, + GLvoid *UNUSED(userParm)) { - bool backtrace = false; - - switch (severity) { - case GL_DEBUG_SEVERITY_HIGH: - backtrace = true; - ATTR_FALLTHROUGH; - case GL_DEBUG_SEVERITY_MEDIUM: - case GL_DEBUG_SEVERITY_LOW: - fprintf(stderr, "GL %s: %s\n", category_name_amd(category), message); - } - - if (backtrace) { - BLI_system_backtrace(stderr); - fflush(stderr); - } + bool backtrace = false; + + switch (severity) { + case GL_DEBUG_SEVERITY_HIGH: + backtrace = true; + ATTR_FALLTHROUGH; + case GL_DEBUG_SEVERITY_MEDIUM: + case GL_DEBUG_SEVERITY_LOW: + fprintf(stderr, "GL %s: %s\n", category_name_amd(category), message); + } + + if (backtrace) { + BLI_system_backtrace(stderr); + fflush(stderr); + } } # endif /* LEGACY_DEBUG */ @@ -146,53 +174,54 @@ static void APIENTRY gpu_debug_proc_amd( void gpu_debug_init(void) { #ifdef __APPLE__ - fprintf(stderr, "OpenGL debug callback is not available on Apple.\n"); + fprintf(stderr, "OpenGL debug callback is not available on Apple.\n"); #else /* not Apple */ - const char success[] = "Successfully hooked OpenGL debug callback."; - - if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { - fprintf(stderr, "Using %s\n", GLEW_VERSION_4_3 ? "OpenGL 4.3 debug facilities" : "KHR_debug extension"); - glEnable(GL_DEBUG_OUTPUT); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, NULL); - glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(success); - } - else if (GLEW_ARB_debug_output) { - fprintf(stderr, "Using ARB_debug_output extension\n"); - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, NULL); - glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(success); - } + const char success[] = "Successfully hooked OpenGL debug callback."; + + if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { + fprintf(stderr, + "Using %s\n", + GLEW_VERSION_4_3 ? "OpenGL 4.3 debug facilities" : "KHR_debug extension"); + glEnable(GL_DEBUG_OUTPUT); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallback((GLDEBUGPROC)gpu_debug_proc, NULL); + glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); + GPU_string_marker(success); + } + else if (GLEW_ARB_debug_output) { + fprintf(stderr, "Using ARB_debug_output extension\n"); + glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); + glDebugMessageCallbackARB((GLDEBUGPROCARB)gpu_debug_proc, NULL); + glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); + GPU_string_marker(success); + } # if LEGACY_DEBUG - else if (GLEW_AMD_debug_output) { - fprintf(stderr, "Using AMD_debug_output extension\n"); - glDebugMessageCallbackAMD(gpu_debug_proc_amd, NULL); - glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); - GPU_string_marker(success); - } + else if (GLEW_AMD_debug_output) { + fprintf(stderr, "Using AMD_debug_output extension\n"); + glDebugMessageCallbackAMD(gpu_debug_proc_amd, NULL); + glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); + GPU_string_marker(success); + } # endif - else { - fprintf(stderr, "Failed to hook OpenGL debug callback.\n"); - } + else { + fprintf(stderr, "Failed to hook OpenGL debug callback.\n"); + } #endif /* not Apple */ } - void gpu_debug_exit(void) { #ifndef __APPLE__ - if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { - glDebugMessageCallback(NULL, NULL); - } - else if (GLEW_ARB_debug_output) { - glDebugMessageCallbackARB(NULL, NULL); - } + if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { + glDebugMessageCallback(NULL, NULL); + } + else if (GLEW_ARB_debug_output) { + glDebugMessageCallbackARB(NULL, NULL); + } # if LEGACY_DEBUG - else if (GLEW_AMD_debug_output) { - glDebugMessageCallbackAMD(NULL, NULL); - } + else if (GLEW_AMD_debug_output) { + glDebugMessageCallbackAMD(NULL, NULL); + } # endif #endif } @@ -200,30 +229,35 @@ void gpu_debug_exit(void) void GPU_string_marker(const char *buf) { #ifdef __APPLE__ - UNUSED_VARS(buf); + UNUSED_VARS(buf); #else /* not Apple */ - if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { - glDebugMessageInsert( - GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, - GL_DEBUG_SEVERITY_NOTIFICATION, -1, buf); - } - else if (GLEW_ARB_debug_output) { - glDebugMessageInsertARB( - GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, - GL_DEBUG_SEVERITY_LOW_ARB, -1, buf); - } + if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { + glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, + GL_DEBUG_TYPE_MARKER, + 0, + GL_DEBUG_SEVERITY_NOTIFICATION, + -1, + buf); + } + else if (GLEW_ARB_debug_output) { + glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB, + GL_DEBUG_TYPE_OTHER_ARB, + 0, + GL_DEBUG_SEVERITY_LOW_ARB, + -1, + buf); + } # if LEGACY_DEBUG - else if (GLEW_AMD_debug_output) { - glDebugMessageInsertAMD( - GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, - 0, buf); - } + else if (GLEW_AMD_debug_output) { + glDebugMessageInsertAMD( + GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, 0, buf); + } # endif #endif /* not Apple */ } void GPU_print_error_debug(const char *str) { - if (G.debug & G_DEBUG) - fprintf(stderr, "GPU: %s\n", str); + if (G.debug & G_DEBUG) + fprintf(stderr, "GPU: %s\n", str); } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index c9989703d5b..fec96b18dac 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -81,442 +81,441 @@ static void gpu_free_image_immediate(Image *ima); #ifdef WITH_DDS static bool is_power_of_2_resolution(int w, int h) { - return is_power_of_2_i(w) && is_power_of_2_i(h); + return is_power_of_2_i(w) && is_power_of_2_i(h); } #endif static bool is_over_resolution_limit(GLenum textarget, int w, int h) { - int size = (textarget == GL_TEXTURE_2D) ? - GPU_max_texture_size() : GPU_max_cube_map_size(); - int reslimit = (U.glreslimit != 0) ? - min_ii(U.glreslimit, size) : size; + int size = (textarget == GL_TEXTURE_2D) ? GPU_max_texture_size() : GPU_max_cube_map_size(); + int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, size) : size; - return (w > reslimit || h > reslimit); + return (w > reslimit || h > reslimit); } static int smaller_power_of_2_limit(int num) { - int reslimit = (U.glreslimit != 0) ? - min_ii(U.glreslimit, GPU_max_texture_size()) : - GPU_max_texture_size(); - /* take texture clamping into account */ - if (num > reslimit) - return reslimit; - - return power_of_2_min_i(num); + int reslimit = (U.glreslimit != 0) ? min_ii(U.glreslimit, GPU_max_texture_size()) : + GPU_max_texture_size(); + /* take texture clamping into account */ + if (num > reslimit) + return reslimit; + + return power_of_2_min_i(num); } /* Current OpenGL state caching for GPU_set_tpage */ static struct GPUTextureState { - /* also controls min/mag filtering */ - bool domipmap; - /* only use when 'domipmap' is set */ - bool linearmipmap; - /* store this so that new images created while texture painting won't be set to mipmapped */ - bool texpaint; - - float anisotropic; + /* also controls min/mag filtering */ + bool domipmap; + /* only use when 'domipmap' is set */ + bool linearmipmap; + /* store this so that new images created while texture painting won't be set to mipmapped */ + bool texpaint; + + float anisotropic; } GTS = {1, 0, 0, 1.0f}; /* Mipmap settings */ void GPU_set_mipmap(Main *bmain, bool mipmap) { - if (GTS.domipmap != mipmap) { - GPU_free_images(bmain); - GTS.domipmap = mipmap; - } + if (GTS.domipmap != mipmap) { + GPU_free_images(bmain); + GTS.domipmap = mipmap; + } } void GPU_set_linear_mipmap(bool linear) { - if (GTS.linearmipmap != linear) { - GTS.linearmipmap = linear; - } + if (GTS.linearmipmap != linear) { + GTS.linearmipmap = linear; + } } bool GPU_get_mipmap(void) { - return GTS.domipmap && !GTS.texpaint; + return GTS.domipmap && !GTS.texpaint; } bool GPU_get_linear_mipmap(void) { - return GTS.linearmipmap; + return GTS.linearmipmap; } static GLenum gpu_get_mipmap_filter(bool mag) { - /* linearmipmap is off by default *when mipmapping is off, - * use unfiltered display */ - if (mag) { - if (GTS.domipmap) - return GL_LINEAR; - else - return GL_NEAREST; - } - else { - if (GTS.domipmap) { - if (GTS.linearmipmap) { - return GL_LINEAR_MIPMAP_LINEAR; - } - else { - return GL_LINEAR_MIPMAP_NEAREST; - } - } - else { - return GL_NEAREST; - } - } + /* linearmipmap is off by default *when mipmapping is off, + * use unfiltered display */ + if (mag) { + if (GTS.domipmap) + return GL_LINEAR; + else + return GL_NEAREST; + } + else { + if (GTS.domipmap) { + if (GTS.linearmipmap) { + return GL_LINEAR_MIPMAP_LINEAR; + } + else { + return GL_LINEAR_MIPMAP_NEAREST; + } + } + else { + return GL_NEAREST; + } + } } /* Anisotropic filtering settings */ void GPU_set_anisotropic(Main *bmain, float value) { - if (GTS.anisotropic != value) { - GPU_free_images(bmain); + if (GTS.anisotropic != value) { + GPU_free_images(bmain); - /* Clamp value to the maximum value the graphics card supports */ - const float max = GPU_max_texture_anisotropy(); - if (value > max) - value = max; + /* Clamp value to the maximum value the graphics card supports */ + const float max = GPU_max_texture_anisotropy(); + if (value > max) + value = max; - GTS.anisotropic = value; - } + GTS.anisotropic = value; + } } float GPU_get_anisotropic(void) { - return GTS.anisotropic; + return GTS.anisotropic; } /* Set OpenGL state for an MTFace */ static GPUTexture **gpu_get_image_gputexture(Image *ima, GLenum textarget) { - if (textarget == GL_TEXTURE_2D) - return &ima->gputexture[TEXTARGET_TEXTURE_2D]; - else if (textarget == GL_TEXTURE_CUBE_MAP) - return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; + if (textarget == GL_TEXTURE_2D) + return &ima->gputexture[TEXTARGET_TEXTURE_2D]; + else if (textarget == GL_TEXTURE_CUBE_MAP) + return &ima->gputexture[TEXTARGET_TEXTURE_CUBE_MAP]; - return NULL; + return NULL; } typedef struct VerifyThreadData { - ImBuf *ibuf; - float *srgb_frect; + ImBuf *ibuf; + float *srgb_frect; } VerifyThreadData; -static void gpu_verify_high_bit_srgb_buffer_slice( - float *srgb_frect, - ImBuf *ibuf, - const int start_line, - const int height) +static void gpu_verify_high_bit_srgb_buffer_slice(float *srgb_frect, + ImBuf *ibuf, + const int start_line, + const int height) { - size_t offset = ibuf->channels * start_line * ibuf->x; - float *current_srgb_frect = srgb_frect + offset; - float *current_rect_float = ibuf->rect_float + offset; - IMB_buffer_float_from_float( - current_srgb_frect, - current_rect_float, - ibuf->channels, - IB_PROFILE_SRGB, - IB_PROFILE_LINEAR_RGB, true, - ibuf->x, height, - ibuf->x, ibuf->x); - IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height); + size_t offset = ibuf->channels * start_line * ibuf->x; + float *current_srgb_frect = srgb_frect + offset; + float *current_rect_float = ibuf->rect_float + offset; + IMB_buffer_float_from_float(current_srgb_frect, + current_rect_float, + ibuf->channels, + IB_PROFILE_SRGB, + IB_PROFILE_LINEAR_RGB, + true, + ibuf->x, + height, + ibuf->x, + ibuf->x); + IMB_buffer_float_unpremultiply(current_srgb_frect, ibuf->x, height); } -static void verify_thread_do( - void *data_v, - int start_scanline, - int num_scanlines) +static void verify_thread_do(void *data_v, int start_scanline, int num_scanlines) { - VerifyThreadData *data = (VerifyThreadData *)data_v; - gpu_verify_high_bit_srgb_buffer_slice( - data->srgb_frect, - data->ibuf, - start_scanline, - num_scanlines); + VerifyThreadData *data = (VerifyThreadData *)data_v; + gpu_verify_high_bit_srgb_buffer_slice( + data->srgb_frect, data->ibuf, start_scanline, num_scanlines); } -static void gpu_verify_high_bit_srgb_buffer( - float *srgb_frect, - ImBuf *ibuf) +static void gpu_verify_high_bit_srgb_buffer(float *srgb_frect, ImBuf *ibuf) { - if (ibuf->y < 64) { - gpu_verify_high_bit_srgb_buffer_slice( - srgb_frect, - ibuf, - 0, ibuf->y); - } - else { - VerifyThreadData data; - data.ibuf = ibuf; - data.srgb_frect = srgb_frect; - IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data); - } + if (ibuf->y < 64) { + gpu_verify_high_bit_srgb_buffer_slice(srgb_frect, ibuf, 0, ibuf->y); + } + else { + VerifyThreadData data; + data.ibuf = ibuf; + data.srgb_frect = srgb_frect; + IMB_processor_apply_threaded_scanlines(ibuf->y, verify_thread_do, &data); + } } -GPUTexture *GPU_texture_from_blender( - Image *ima, - ImageUser *iuser, - int textarget, - bool is_data) +GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, int textarget, bool is_data) { - if (ima == NULL) { - return NULL; - } - - /* currently, gpu refresh tagging is used by ima sequences */ - if (ima->gpuflag & IMA_GPU_REFRESH) { - gpu_free_image_immediate(ima); - ima->gpuflag &= ~IMA_GPU_REFRESH; - } - - /* Test if we already have a texture. */ - GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); - if (*tex) { - return *tex; - } - - /* Check if we have a valid image. If not, we return a dummy - * texture with zero bindcode so we don't keep trying. */ - uint bindcode = 0; - if (ima->ok == 0) { - *tex = GPU_texture_from_bindcode(textarget, bindcode); - return *tex; - } - - /* check if we have a valid image buffer */ - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - if (ibuf == NULL) { - *tex = GPU_texture_from_bindcode(textarget, bindcode); - return *tex; - } - - /* flag to determine whether deep format is used */ - bool use_high_bit_depth = false, do_color_management = false; - - if (ibuf->rect_float) { - use_high_bit_depth = true; - - /* TODO unneeded when float images are correctly treated as linear always */ - if (!is_data) { - do_color_management = true; - } - } - - const int rectw = ibuf->x; - const int recth = ibuf->y; - uint *rect = ibuf->rect; - float *frect = NULL; - float *srgb_frect = NULL; - - if (use_high_bit_depth) { - if (do_color_management) { - frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor"); - gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf); - } - else { - frect = ibuf->rect_float; - } - } - - const bool mipmap = GPU_get_mipmap(); + if (ima == NULL) { + return NULL; + } + + /* currently, gpu refresh tagging is used by ima sequences */ + if (ima->gpuflag & IMA_GPU_REFRESH) { + gpu_free_image_immediate(ima); + ima->gpuflag &= ~IMA_GPU_REFRESH; + } + + /* Test if we already have a texture. */ + GPUTexture **tex = gpu_get_image_gputexture(ima, textarget); + if (*tex) { + return *tex; + } + + /* Check if we have a valid image. If not, we return a dummy + * texture with zero bindcode so we don't keep trying. */ + uint bindcode = 0; + if (ima->ok == 0) { + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; + } + + /* check if we have a valid image buffer */ + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + if (ibuf == NULL) { + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; + } + + /* flag to determine whether deep format is used */ + bool use_high_bit_depth = false, do_color_management = false; + + if (ibuf->rect_float) { + use_high_bit_depth = true; + + /* TODO unneeded when float images are correctly treated as linear always */ + if (!is_data) { + do_color_management = true; + } + } + + const int rectw = ibuf->x; + const int recth = ibuf->y; + uint *rect = ibuf->rect; + float *frect = NULL; + float *srgb_frect = NULL; + + if (use_high_bit_depth) { + if (do_color_management) { + frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, + "floar_buf_col_cor"); + gpu_verify_high_bit_srgb_buffer(srgb_frect, ibuf); + } + else { + frect = ibuf->rect_float; + } + } + + const bool mipmap = GPU_get_mipmap(); #ifdef WITH_DDS - if (ibuf->ftype == IMB_FTYPE_DDS) { - GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); - } - else + if (ibuf->ftype == IMB_FTYPE_DDS) { + GPU_create_gl_tex_compressed(&bindcode, rect, rectw, recth, textarget, mipmap, ima, ibuf); + } + else #endif - { - GPU_create_gl_tex(&bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); - } - - /* mark as non-color data texture */ - if (bindcode) { - if (is_data) - ima->gpuflag |= IMA_GPU_IS_DATA; - else - ima->gpuflag &= ~IMA_GPU_IS_DATA; - } - - /* clean up */ - if (srgb_frect) - MEM_freeN(srgb_frect); - - BKE_image_release_ibuf(ima, ibuf, NULL); - - *tex = GPU_texture_from_bindcode(textarget, bindcode); - return *tex; + { + GPU_create_gl_tex( + &bindcode, rect, frect, rectw, recth, textarget, mipmap, use_high_bit_depth, ima); + } + + /* mark as non-color data texture */ + if (bindcode) { + if (is_data) + ima->gpuflag |= IMA_GPU_IS_DATA; + else + ima->gpuflag &= ~IMA_GPU_IS_DATA; + } + + /* clean up */ + if (srgb_frect) + MEM_freeN(srgb_frect); + + BKE_image_release_ibuf(ima, ibuf, NULL); + + *tex = GPU_texture_from_bindcode(textarget, bindcode); + return *tex; } -static void **gpu_gen_cube_map(uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) +static void **gpu_gen_cube_map( + uint *rect, float *frect, int rectw, int recth, bool use_high_bit_depth) { - size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]); - void **sides = NULL; - int h = recth / 2; - int w = rectw / 3; - - if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) - return sides; - - /* PosX, NegX, PosY, NegY, PosZ, NegZ */ - sides = MEM_mallocN(sizeof(void *) * 6, ""); - for (int i = 0; i < 6; i++) - sides[i] = MEM_mallocN(block_size * w * h, ""); - - /* divide image into six parts */ - /* ______________________ - * | | | | - * | NegX | NegY | PosX | - * |______|______|______| - * | | | | - * | NegZ | PosZ | PosY | - * |______|______|______| - */ - if (use_high_bit_depth) { - float (*frectb)[4] = (float(*)[4])frect; - float (**fsides)[4] = (float(**)[4])sides; - - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - memcpy(&fsides[0][x * h + y], &frectb[(recth - y - 1) * rectw + 2 * w + x], block_size); - memcpy(&fsides[1][x * h + y], &frectb[(y + h) * rectw + w - 1 - x], block_size); - memcpy(&fsides[3][y * w + x], &frectb[(recth - y - 1) * rectw + 2 * w - 1 - x], block_size); - memcpy(&fsides[5][y * w + x], &frectb[(h - y - 1) * rectw + w - 1 - x], block_size); - } - memcpy(&fsides[2][y * w], frectb[y * rectw + 2 * w], block_size * w); - memcpy(&fsides[4][y * w], frectb[y * rectw + w], block_size * w); - } - } - else { - uint **isides = (uint **)sides; - - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - isides[0][x * h + y] = rect[(recth - y - 1) * rectw + 2 * w + x]; - isides[1][x * h + y] = rect[(y + h) * rectw + w - 1 - x]; - isides[3][y * w + x] = rect[(recth - y - 1) * rectw + 2 * w - 1 - x]; - isides[5][y * w + x] = rect[(h - y - 1) * rectw + w - 1 - x]; - } - memcpy(&isides[2][y * w], &rect[y * rectw + 2 * w], block_size * w); - memcpy(&isides[4][y * w], &rect[y * rectw + w], block_size * w); - } - } - - return sides; + size_t block_size = use_high_bit_depth ? sizeof(float[4]) : sizeof(uchar[4]); + void **sides = NULL; + int h = recth / 2; + int w = rectw / 3; + + if ((use_high_bit_depth && frect == NULL) || (!use_high_bit_depth && rect == NULL) || w != h) + return sides; + + /* PosX, NegX, PosY, NegY, PosZ, NegZ */ + sides = MEM_mallocN(sizeof(void *) * 6, ""); + for (int i = 0; i < 6; i++) + sides[i] = MEM_mallocN(block_size * w * h, ""); + + /* divide image into six parts */ + /* ______________________ + * | | | | + * | NegX | NegY | PosX | + * |______|______|______| + * | | | | + * | NegZ | PosZ | PosY | + * |______|______|______| + */ + if (use_high_bit_depth) { + float(*frectb)[4] = (float(*)[4])frect; + float(**fsides)[4] = (float(**)[4])sides; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + memcpy(&fsides[0][x * h + y], &frectb[(recth - y - 1) * rectw + 2 * w + x], block_size); + memcpy(&fsides[1][x * h + y], &frectb[(y + h) * rectw + w - 1 - x], block_size); + memcpy( + &fsides[3][y * w + x], &frectb[(recth - y - 1) * rectw + 2 * w - 1 - x], block_size); + memcpy(&fsides[5][y * w + x], &frectb[(h - y - 1) * rectw + w - 1 - x], block_size); + } + memcpy(&fsides[2][y * w], frectb[y * rectw + 2 * w], block_size * w); + memcpy(&fsides[4][y * w], frectb[y * rectw + w], block_size * w); + } + } + else { + uint **isides = (uint **)sides; + + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + isides[0][x * h + y] = rect[(recth - y - 1) * rectw + 2 * w + x]; + isides[1][x * h + y] = rect[(y + h) * rectw + w - 1 - x]; + isides[3][y * w + x] = rect[(recth - y - 1) * rectw + 2 * w - 1 - x]; + isides[5][y * w + x] = rect[(h - y - 1) * rectw + w - 1 - x]; + } + memcpy(&isides[2][y * w], &rect[y * rectw + 2 * w], block_size * w); + memcpy(&isides[4][y * w], &rect[y * rectw + w], block_size * w); + } + } + + return sides; } static void gpu_del_cube_map(void **cube_map) { - int i; - if (cube_map == NULL) - return; - for (i = 0; i < 6; i++) - MEM_freeN(cube_map[i]); - MEM_freeN(cube_map); + int i; + if (cube_map == NULL) + return; + for (i = 0; i < 6; i++) + MEM_freeN(cube_map[i]); + MEM_freeN(cube_map); } /* Image *ima can be NULL */ -void GPU_create_gl_tex( - uint *bind, uint *rect, float *frect, int rectw, int recth, - int textarget, bool mipmap, bool use_high_bit_depth, Image *ima) +void GPU_create_gl_tex(uint *bind, + uint *rect, + float *frect, + int rectw, + int recth, + int textarget, + bool mipmap, + bool use_high_bit_depth, + Image *ima) { - ImBuf *ibuf = NULL; - - if (textarget == GL_TEXTURE_2D && - is_over_resolution_limit(textarget, rectw, recth)) - { - int tpx = rectw; - int tpy = recth; - rectw = smaller_power_of_2_limit(rectw); - recth = smaller_power_of_2_limit(recth); - - if (use_high_bit_depth) { - ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); - IMB_scaleImBuf(ibuf, rectw, recth); - - frect = ibuf->rect_float; - } - else { - ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); - IMB_scaleImBuf(ibuf, rectw, recth); - - rect = ibuf->rect; - } - } - - /* create image */ - glGenTextures(1, (GLuint *)bind); - glBindTexture(textarget, *bind); - - if (textarget == GL_TEXTURE_2D) { - if (use_high_bit_depth) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); - } - else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - - if (GPU_get_mipmap() && mipmap) { - glGenerateMipmap(GL_TEXTURE_2D); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - if (ima) - ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; - } - else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - } - else if (textarget == GL_TEXTURE_CUBE_MAP) { - int w = rectw / 3, h = recth / 2; - - if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) { - void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth); - GLenum informat = use_high_bit_depth ? GL_RGBA16F : GL_RGBA8; - GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE; - - if (cube_map) - for (int i = 0; i < 6; i++) - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, informat, w, h, 0, GL_RGBA, type, cube_map[i]); - - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - - if (GPU_get_mipmap() && mipmap) { - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - - if (ima) - ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; - } - else { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - } - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - gpu_del_cube_map(cube_map); - } - else { - printf("Incorrect envmap size\n"); - } - } - - if (GLEW_EXT_texture_filter_anisotropic) - glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - - glBindTexture(textarget, 0); - - if (ibuf) - IMB_freeImBuf(ibuf); + ImBuf *ibuf = NULL; + + if (textarget == GL_TEXTURE_2D && is_over_resolution_limit(textarget, rectw, recth)) { + int tpx = rectw; + int tpy = recth; + rectw = smaller_power_of_2_limit(rectw); + recth = smaller_power_of_2_limit(recth); + + if (use_high_bit_depth) { + ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy); + IMB_scaleImBuf(ibuf, rectw, recth); + + frect = ibuf->rect_float; + } + else { + ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy); + IMB_scaleImBuf(ibuf, rectw, recth); + + rect = ibuf->rect; + } + } + + /* create image */ + glGenTextures(1, (GLuint *)bind); + glBindTexture(textarget, *bind); + + if (textarget == GL_TEXTURE_2D) { + if (use_high_bit_depth) { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect); + } + else { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + if (GPU_get_mipmap() && mipmap) { + glGenerateMipmap(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + if (ima) + ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; + } + else { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + } + else if (textarget == GL_TEXTURE_CUBE_MAP) { + int w = rectw / 3, h = recth / 2; + + if (h == w && is_power_of_2_i(h) && !is_over_resolution_limit(textarget, h, w)) { + void **cube_map = gpu_gen_cube_map(rect, frect, rectw, recth, use_high_bit_depth); + GLenum informat = use_high_bit_depth ? GL_RGBA16F : GL_RGBA8; + GLenum type = use_high_bit_depth ? GL_FLOAT : GL_UNSIGNED_BYTE; + + if (cube_map) + for (int i = 0; i < 6; i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + 0, + informat, + w, + h, + 0, + GL_RGBA, + type, + cube_map[i]); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + if (GPU_get_mipmap() && mipmap) { + glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + + if (ima) + ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE; + } + else { + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + gpu_del_cube_map(cube_map); + } + else { + printf("Incorrect envmap size\n"); + } + } + + if (GLEW_EXT_texture_filter_anisotropic) + glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); + + glBindTexture(textarget, 0); + + if (ibuf) + IMB_freeImBuf(ibuf); } /** @@ -527,83 +526,83 @@ void GPU_create_gl_tex( bool GPU_upload_dxt_texture(ImBuf *ibuf) { #ifdef WITH_DDS - GLint format = 0; - int blocksize, height, width, i, size, offset = 0; - - width = ibuf->x; - height = ibuf->y; - - if (GLEW_EXT_texture_compression_s3tc) { - if (ibuf->dds_data.fourcc == FOURCC_DXT1) - format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - else if (ibuf->dds_data.fourcc == FOURCC_DXT3) - format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - else if (ibuf->dds_data.fourcc == FOURCC_DXT5) - format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - } - - if (format == 0) { - fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n"); - return false; - } - - if (!is_power_of_2_resolution(width, height)) { - fprintf(stderr, "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n"); - return false; - } - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - - if (GLEW_EXT_texture_filter_anisotropic) - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); - - blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16; - for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); ++i) { - if (width == 0) - width = 1; - if (height == 0) - height = 1; - - size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize; - - glCompressedTexImage2D( - GL_TEXTURE_2D, i, format, width, height, - 0, size, ibuf->dds_data.data + offset); - - offset += size; - width >>= 1; - height >>= 1; - } - - /* set number of mipmap levels we have, needed in case they don't go down to 1x1 */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1); - - return true; + GLint format = 0; + int blocksize, height, width, i, size, offset = 0; + + width = ibuf->x; + height = ibuf->y; + + if (GLEW_EXT_texture_compression_s3tc) { + if (ibuf->dds_data.fourcc == FOURCC_DXT1) + format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT3) + format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + else if (ibuf->dds_data.fourcc == FOURCC_DXT5) + format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + } + + if (format == 0) { + fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n"); + return false; + } + + if (!is_power_of_2_resolution(width, height)) { + fprintf( + stderr, + "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n"); + return false; + } + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + + if (GLEW_EXT_texture_filter_anisotropic) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); + + blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16; + for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); ++i) { + if (width == 0) + width = 1; + if (height == 0) + height = 1; + + size = ((width + 3) / 4) * ((height + 3) / 4) * blocksize; + + glCompressedTexImage2D( + GL_TEXTURE_2D, i, format, width, height, 0, size, ibuf->dds_data.data + offset); + + offset += size; + width >>= 1; + height >>= 1; + } + + /* set number of mipmap levels we have, needed in case they don't go down to 1x1 */ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1); + + return true; #else - (void)ibuf; - return false; + (void)ibuf; + return false; #endif } void GPU_create_gl_tex_compressed( - uint *bind, uint *pix, int x, int y, - int textarget, int mipmap, Image *ima, ImBuf *ibuf) + uint *bind, uint *pix, int x, int y, int textarget, int mipmap, Image *ima, ImBuf *ibuf) { #ifndef WITH_DDS - (void)ibuf; - /* Fall back to uncompressed if DDS isn't enabled */ - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + (void)ibuf; + /* Fall back to uncompressed if DDS isn't enabled */ + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); #else - glGenTextures(1, (GLuint *)bind); - glBindTexture(textarget, *bind); + glGenTextures(1, (GLuint *)bind); + glBindTexture(textarget, *bind); - if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) { - glDeleteTextures(1, (GLuint *)bind); - GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); - } + if (textarget == GL_TEXTURE_2D && GPU_upload_dxt_texture(ibuf) == 0) { + glDeleteTextures(1, (GLuint *)bind); + GPU_create_gl_tex(bind, pix, NULL, x, y, textarget, mipmap, 0, ima); + } - glBindTexture(textarget, 0); + glBindTexture(textarget, 0); #endif } @@ -613,208 +612,201 @@ void GPU_create_gl_tex_compressed( * re-uploaded to OpenGL */ void GPU_paint_set_mipmap(Main *bmain, bool mipmap) { - if (!GTS.domipmap) - return; - - GTS.texpaint = !mipmap; - - if (mipmap) { - for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { - if (BKE_image_has_opengl_texture(ima)) { - if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) { - if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - } - } - else - GPU_free_image(ima); - } - else - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - } - else { - for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { - if (BKE_image_has_opengl_texture(ima)) { - if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - } - } - else - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - } + if (!GTS.domipmap) + return; + + GTS.texpaint = !mipmap; + + if (mipmap) { + for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { + if (BKE_image_has_opengl_texture(ima)) { + if (ima->gpuflag & IMA_GPU_MIPMAP_COMPLETE) { + if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + } + } + else + GPU_free_image(ima); + } + else + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + } + else { + for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { + if (BKE_image_has_opengl_texture(ima)) { + if (ima->gputexture[TEXTARGET_TEXTURE_2D]) { + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1)); + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + } + } + else + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + } } - /* check if image has been downscaled and do scaled partial update */ -static bool gpu_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) +static bool gpu_check_scaled_image( + ImBuf *ibuf, Image *ima, float *frect, int x, int y, int w, int h) { - if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) { - int x_limit = smaller_power_of_2_limit(ibuf->x); - int y_limit = smaller_power_of_2_limit(ibuf->y); - - float xratio = x_limit / (float)ibuf->x; - float yratio = y_limit / (float)ibuf->y; - - /* find new width, height and x,y gpu texture coordinates */ - - /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */ - int rectw = (int)ceil(xratio * w); - int recth = (int)ceil(yratio * h); - - x *= xratio; - y *= yratio; - - /* ...but take back if we are over the limit! */ - if (rectw + x > x_limit) rectw--; - if (recth + y > y_limit) recth--; - - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - - /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */ - if (frect) { - ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h); - IMB_scaleImBuf(ibuf_scale, rectw, recth); - - glTexSubImage2D( - GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, - GL_FLOAT, ibuf_scale->rect_float); - - IMB_freeImBuf(ibuf_scale); - } - /* byte images are not continuous in memory so do manual interpolation */ - else { - uchar *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect"); - uint *p = (uint *)scalerect; - int i, j; - float inv_xratio = 1.0f / xratio; - float inv_yratio = 1.0f / yratio; - for (i = 0; i < rectw; i++) { - float u = (x + i) * inv_xratio; - for (j = 0; j < recth; j++) { - float v = (y + j) * inv_yratio; - bilinear_interpolation_color_wrap(ibuf, (uchar *)(p + i + j * (rectw)), NULL, u, v); - } - } - - glTexSubImage2D( - GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, - GL_UNSIGNED_BYTE, scalerect); - - MEM_freeN(scalerect); - } - - if (GPU_get_mipmap()) { - glGenerateMipmap(GL_TEXTURE_2D); - } - else { - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - - return true; - } - - return false; + if (is_over_resolution_limit(GL_TEXTURE_2D, ibuf->x, ibuf->y)) { + int x_limit = smaller_power_of_2_limit(ibuf->x); + int y_limit = smaller_power_of_2_limit(ibuf->y); + + float xratio = x_limit / (float)ibuf->x; + float yratio = y_limit / (float)ibuf->y; + + /* find new width, height and x,y gpu texture coordinates */ + + /* take ceiling because we will be losing 1 pixel due to rounding errors in x,y... */ + int rectw = (int)ceil(xratio * w); + int recth = (int)ceil(yratio * h); + + x *= xratio; + y *= yratio; + + /* ...but take back if we are over the limit! */ + if (rectw + x > x_limit) + rectw--; + if (recth + y > y_limit) + recth--; + + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + + /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */ + if (frect) { + ImBuf *ibuf_scale = IMB_allocFromBuffer(NULL, frect, w, h); + IMB_scaleImBuf(ibuf_scale, rectw, recth); + + glTexSubImage2D( + GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_FLOAT, ibuf_scale->rect_float); + + IMB_freeImBuf(ibuf_scale); + } + /* byte images are not continuous in memory so do manual interpolation */ + else { + uchar *scalerect = MEM_mallocN(rectw * recth * sizeof(*scalerect) * 4, "scalerect"); + uint *p = (uint *)scalerect; + int i, j; + float inv_xratio = 1.0f / xratio; + float inv_yratio = 1.0f / yratio; + for (i = 0; i < rectw; i++) { + float u = (x + i) * inv_xratio; + for (j = 0; j < recth; j++) { + float v = (y + j) * inv_yratio; + bilinear_interpolation_color_wrap(ibuf, (uchar *)(p + i + j * (rectw)), NULL, u, v); + } + } + + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, scalerect); + + MEM_freeN(scalerect); + } + + if (GPU_get_mipmap()) { + glGenerateMipmap(GL_TEXTURE_2D); + } + else { + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + + return true; + } + + return false; } void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h) { - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); - - if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || - (ibuf == NULL) || - (w == 0) || (h == 0)) - { - /* these cases require full reload still */ - GPU_free_image(ima); - } - else { - /* for the special case, we can do a partial update - * which is much quicker for painting */ - GLint row_length, skip_pixels, skip_rows; - - /* if color correction is needed, we must update the part that needs updating. */ - if (ibuf->rect_float) { - float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf"); - bool is_data = (ima->gpuflag & IMA_GPU_IS_DATA) != 0; - IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); - - if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { - MEM_freeN(buffer); - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); - - MEM_freeN(buffer); - - if (GPU_get_mipmap()) { - glGenerateMipmap(GL_TEXTURE_2D); - } - else { - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - return; - } - - GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); - - glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); - glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); - glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); - glPixelStorei(GL_UNPACK_SKIP_ROWS, y); - - glTexSubImage2D( - GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, - GL_UNSIGNED_BYTE, ibuf->rect); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); - glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); - glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); - - /* see comment above as to why we are using gpu mipmap generation here */ - if (GPU_get_mipmap()) { - glGenerateMipmap(GL_TEXTURE_2D); - } - else { - ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; - } - - GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); - } - - BKE_image_release_ibuf(ima, ibuf, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL); + + if ((ima->gputexture[TEXTARGET_TEXTURE_2D] == NULL) || (ibuf == NULL) || (w == 0) || (h == 0)) { + /* these cases require full reload still */ + GPU_free_image(ima); + } + else { + /* for the special case, we can do a partial update + * which is much quicker for painting */ + GLint row_length, skip_pixels, skip_rows; + + /* if color correction is needed, we must update the part that needs updating. */ + if (ibuf->rect_float) { + float *buffer = MEM_mallocN(w * h * sizeof(float) * 4, "temp_texpaint_float_buf"); + bool is_data = (ima->gpuflag & IMA_GPU_IS_DATA) != 0; + IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h, is_data); + + if (gpu_check_scaled_image(ibuf, ima, buffer, x, y, w, h)) { + MEM_freeN(buffer); + BKE_image_release_ibuf(ima, ibuf, NULL); + return; + } + + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer); + + MEM_freeN(buffer); + + if (GPU_get_mipmap()) { + glGenerateMipmap(GL_TEXTURE_2D); + } + else { + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + + BKE_image_release_ibuf(ima, ibuf, NULL); + return; + } + + if (gpu_check_scaled_image(ibuf, ima, NULL, x, y, w, h)) { + BKE_image_release_ibuf(ima, ibuf, NULL); + return; + } + + GPU_texture_bind(ima->gputexture[TEXTARGET_TEXTURE_2D], 0); + + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, x); + glPixelStorei(GL_UNPACK_SKIP_ROWS, y); + + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows); + + /* see comment above as to why we are using gpu mipmap generation here */ + if (GPU_get_mipmap()) { + glGenerateMipmap(GL_TEXTURE_2D); + } + else { + ima->gpuflag &= ~IMA_GPU_MIPMAP_COMPLETE; + } + + GPU_texture_unbind(ima->gputexture[TEXTARGET_TEXTURE_2D]); + } + + BKE_image_release_ibuf(ima, ibuf, NULL); } /* *************************** Transfer functions *************************** */ enum { - TFUNC_FLAME_SPECTRUM = 0, - TFUNC_COLOR_RAMP = 1, + TFUNC_FLAME_SPECTRUM = 0, + TFUNC_COLOR_RAMP = 1, }; #define TFUNC_WIDTH 256 @@ -822,436 +814,481 @@ enum { #ifdef WITH_SMOKE static void create_flame_spectrum_texture(float *data) { -#define FIRE_THRESH 7 -#define MAX_FIRE_ALPHA 0.06f -#define FULL_ON_FIRE 100 - - float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels"); - - blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000); - - for (int i = 0; i < 16; i++) { - for (int j = 0; j < 16; j++) { - for (int k = 0; k < TFUNC_WIDTH; k++) { - int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4; - if (k >= FIRE_THRESH) { - spec_pixels[index] = (data[k * 4]); - spec_pixels[index + 1] = (data[k * 4 + 1]); - spec_pixels[index + 2] = (data[k * 4 + 2]); - spec_pixels[index + 3] = MAX_FIRE_ALPHA * ( - (k > FULL_ON_FIRE) ? 1.0f : (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); - } - else { - zero_v4(&spec_pixels[index]); - } - } - } - } - - memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH); - - MEM_freeN(spec_pixels); - -#undef FIRE_THRESH -#undef MAX_FIRE_ALPHA -#undef FULL_ON_FIRE +# define FIRE_THRESH 7 +# define MAX_FIRE_ALPHA 0.06f +# define FULL_ON_FIRE 100 + + float *spec_pixels = MEM_mallocN(TFUNC_WIDTH * 4 * 16 * 16 * sizeof(float), "spec_pixels"); + + blackbody_temperature_to_rgb_table(data, TFUNC_WIDTH, 1500, 3000); + + for (int i = 0; i < 16; i++) { + for (int j = 0; j < 16; j++) { + for (int k = 0; k < TFUNC_WIDTH; k++) { + int index = (j * TFUNC_WIDTH * 16 + i * TFUNC_WIDTH + k) * 4; + if (k >= FIRE_THRESH) { + spec_pixels[index] = (data[k * 4]); + spec_pixels[index + 1] = (data[k * 4 + 1]); + spec_pixels[index + 2] = (data[k * 4 + 2]); + spec_pixels[index + 3] = MAX_FIRE_ALPHA * + ((k > FULL_ON_FIRE) ? + 1.0f : + (k - FIRE_THRESH) / ((float)FULL_ON_FIRE - FIRE_THRESH)); + } + else { + zero_v4(&spec_pixels[index]); + } + } + } + } + + memcpy(data, spec_pixels, sizeof(float) * 4 * TFUNC_WIDTH); + + MEM_freeN(spec_pixels); + +# undef FIRE_THRESH +# undef MAX_FIRE_ALPHA +# undef FULL_ON_FIRE } static void create_color_ramp(const ColorBand *coba, float *data) { - for (int i = 0; i < TFUNC_WIDTH; i++) { - BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]); - } + for (int i = 0; i < TFUNC_WIDTH; i++) { + BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]); + } } static GPUTexture *create_transfer_function(int type, const ColorBand *coba) { - float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__); + float *data = MEM_mallocN(sizeof(float) * 4 * TFUNC_WIDTH, __func__); - switch (type) { - case TFUNC_FLAME_SPECTRUM: - create_flame_spectrum_texture(data); - break; - case TFUNC_COLOR_RAMP: - create_color_ramp(coba, data); - break; - } + switch (type) { + case TFUNC_FLAME_SPECTRUM: + create_flame_spectrum_texture(data); + break; + case TFUNC_COLOR_RAMP: + create_color_ramp(coba, data); + break; + } - GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_RGBA8, data, NULL); + GPUTexture *tex = GPU_texture_create_1d(TFUNC_WIDTH, GPU_RGBA8, data, NULL); - MEM_freeN(data); + MEM_freeN(data); - return tex; + return tex; } static void swizzle_texture_channel_rrrr(GPUTexture *tex) { - GPU_texture_bind(tex, 0); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED); - GPU_texture_unbind(tex); + GPU_texture_bind(tex, 0); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_R, GL_RED); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_G, GL_RED); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_B, GL_RED); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, GL_RED); + GPU_texture_unbind(tex); } static GPUTexture *create_field_texture(SmokeDomainSettings *sds) { - float *field = NULL; - - switch (sds->coba_field) { - case FLUID_FIELD_DENSITY: field = smoke_get_density(sds->fluid); break; - case FLUID_FIELD_HEAT: field = smoke_get_heat(sds->fluid); break; - case FLUID_FIELD_FUEL: field = smoke_get_fuel(sds->fluid); break; - case FLUID_FIELD_REACT: field = smoke_get_react(sds->fluid); break; - case FLUID_FIELD_FLAME: field = smoke_get_flame(sds->fluid); break; - case FLUID_FIELD_VELOCITY_X: field = smoke_get_velocity_x(sds->fluid); break; - case FLUID_FIELD_VELOCITY_Y: field = smoke_get_velocity_y(sds->fluid); break; - case FLUID_FIELD_VELOCITY_Z: field = smoke_get_velocity_z(sds->fluid); break; - case FLUID_FIELD_COLOR_R: field = smoke_get_color_r(sds->fluid); break; - case FLUID_FIELD_COLOR_G: field = smoke_get_color_g(sds->fluid); break; - case FLUID_FIELD_COLOR_B: field = smoke_get_color_b(sds->fluid); break; - case FLUID_FIELD_FORCE_X: field = smoke_get_force_x(sds->fluid); break; - case FLUID_FIELD_FORCE_Y: field = smoke_get_force_y(sds->fluid); break; - case FLUID_FIELD_FORCE_Z: field = smoke_get_force_z(sds->fluid); break; - default: return NULL; - } - - GPUTexture *tex = GPU_texture_create_nD( - sds->res[0], sds->res[1], sds->res[2], 3, - field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); - - swizzle_texture_channel_rrrr(tex); - return tex; + float *field = NULL; + + switch (sds->coba_field) { + case FLUID_FIELD_DENSITY: + field = smoke_get_density(sds->fluid); + break; + case FLUID_FIELD_HEAT: + field = smoke_get_heat(sds->fluid); + break; + case FLUID_FIELD_FUEL: + field = smoke_get_fuel(sds->fluid); + break; + case FLUID_FIELD_REACT: + field = smoke_get_react(sds->fluid); + break; + case FLUID_FIELD_FLAME: + field = smoke_get_flame(sds->fluid); + break; + case FLUID_FIELD_VELOCITY_X: + field = smoke_get_velocity_x(sds->fluid); + break; + case FLUID_FIELD_VELOCITY_Y: + field = smoke_get_velocity_y(sds->fluid); + break; + case FLUID_FIELD_VELOCITY_Z: + field = smoke_get_velocity_z(sds->fluid); + break; + case FLUID_FIELD_COLOR_R: + field = smoke_get_color_r(sds->fluid); + break; + case FLUID_FIELD_COLOR_G: + field = smoke_get_color_g(sds->fluid); + break; + case FLUID_FIELD_COLOR_B: + field = smoke_get_color_b(sds->fluid); + break; + case FLUID_FIELD_FORCE_X: + field = smoke_get_force_x(sds->fluid); + break; + case FLUID_FIELD_FORCE_Y: + field = smoke_get_force_y(sds->fluid); + break; + case FLUID_FIELD_FORCE_Z: + field = smoke_get_force_z(sds->fluid); + break; + default: + return NULL; + } + + GPUTexture *tex = GPU_texture_create_nD( + sds->res[0], sds->res[1], sds->res[2], 3, field, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); + + swizzle_texture_channel_rrrr(tex); + return tex; } static GPUTexture *create_density_texture(SmokeDomainSettings *sds, int highres) { - float *data = NULL, *source; - int cell_count = (highres) ? smoke_turbulence_get_cells(sds->wt) : sds->total_cells; - const bool has_color = (highres) ? smoke_turbulence_has_colors(sds->wt) : smoke_has_colors(sds->fluid); - int *dim = (highres) ? sds->res_wt : sds->res; - eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8; - - if (has_color) { - data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture"); - } - - if (highres) { - if (has_color) { - smoke_turbulence_get_rgba(sds->wt, data, 0); - } - else { - source = smoke_turbulence_get_density(sds->wt); - } - } - else { - if (has_color) { - smoke_get_rgba(sds->fluid, data, 0); - } - else { - source = smoke_get_density(sds->fluid); - } - } - - GPUTexture *tex = GPU_texture_create_nD( - dim[0], dim[1], dim[2], 3, - (has_color) ? data : source, - format, GPU_DATA_FLOAT, 0, true, NULL); - if (data) { - MEM_freeN(data); - } - - if (format == GPU_R8) { - /* Swizzle the RGBA components to read the Red channel so - * that the shader stay the same for colored and non color - * density textures. */ - swizzle_texture_channel_rrrr(tex); - } - return tex; + float *data = NULL, *source; + int cell_count = (highres) ? smoke_turbulence_get_cells(sds->wt) : sds->total_cells; + const bool has_color = (highres) ? smoke_turbulence_has_colors(sds->wt) : + smoke_has_colors(sds->fluid); + int *dim = (highres) ? sds->res_wt : sds->res; + eGPUTextureFormat format = (has_color) ? GPU_RGBA8 : GPU_R8; + + if (has_color) { + data = MEM_callocN(sizeof(float) * cell_count * 4, "smokeColorTexture"); + } + + if (highres) { + if (has_color) { + smoke_turbulence_get_rgba(sds->wt, data, 0); + } + else { + source = smoke_turbulence_get_density(sds->wt); + } + } + else { + if (has_color) { + smoke_get_rgba(sds->fluid, data, 0); + } + else { + source = smoke_get_density(sds->fluid); + } + } + + GPUTexture *tex = GPU_texture_create_nD(dim[0], + dim[1], + dim[2], + 3, + (has_color) ? data : source, + format, + GPU_DATA_FLOAT, + 0, + true, + NULL); + if (data) { + MEM_freeN(data); + } + + if (format == GPU_R8) { + /* Swizzle the RGBA components to read the Red channel so + * that the shader stay the same for colored and non color + * density textures. */ + swizzle_texture_channel_rrrr(tex); + } + return tex; } static GPUTexture *create_flame_texture(SmokeDomainSettings *sds, int highres) { - float *source = NULL; - const bool has_fuel = (highres) ? smoke_turbulence_has_fuel(sds->wt) : smoke_has_fuel(sds->fluid); - int *dim = (highres) ? sds->res_wt : sds->res; + float *source = NULL; + const bool has_fuel = (highres) ? smoke_turbulence_has_fuel(sds->wt) : + smoke_has_fuel(sds->fluid); + int *dim = (highres) ? sds->res_wt : sds->res; - if (!has_fuel) - return NULL; + if (!has_fuel) + return NULL; - if (highres) { - source = smoke_turbulence_get_flame(sds->wt); - } - else { - source = smoke_get_flame(sds->fluid); - } + if (highres) { + source = smoke_turbulence_get_flame(sds->wt); + } + else { + source = smoke_get_flame(sds->fluid); + } - GPUTexture *tex = GPU_texture_create_nD( - dim[0], dim[1], dim[2], 3, - source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); + GPUTexture *tex = GPU_texture_create_nD( + dim[0], dim[1], dim[2], 3, source, GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); - swizzle_texture_channel_rrrr(tex); + swizzle_texture_channel_rrrr(tex); - return tex; + return tex; } -#endif /* WITH_SMOKE */ +#endif /* WITH_SMOKE */ void GPU_free_smoke(SmokeModifierData *smd) { - if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { - if (smd->domain->tex) - GPU_texture_free(smd->domain->tex); - smd->domain->tex = NULL; - - if (smd->domain->tex_shadow) - GPU_texture_free(smd->domain->tex_shadow); - smd->domain->tex_shadow = NULL; - - if (smd->domain->tex_flame) - GPU_texture_free(smd->domain->tex_flame); - smd->domain->tex_flame = NULL; - - if (smd->domain->tex_flame_coba) - GPU_texture_free(smd->domain->tex_flame_coba); - smd->domain->tex_flame_coba = NULL; - - if (smd->domain->tex_coba) - GPU_texture_free(smd->domain->tex_coba); - smd->domain->tex_coba = NULL; - - if (smd->domain->tex_field) - GPU_texture_free(smd->domain->tex_field); - smd->domain->tex_field = NULL; - } + if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { + if (smd->domain->tex) + GPU_texture_free(smd->domain->tex); + smd->domain->tex = NULL; + + if (smd->domain->tex_shadow) + GPU_texture_free(smd->domain->tex_shadow); + smd->domain->tex_shadow = NULL; + + if (smd->domain->tex_flame) + GPU_texture_free(smd->domain->tex_flame); + smd->domain->tex_flame = NULL; + + if (smd->domain->tex_flame_coba) + GPU_texture_free(smd->domain->tex_flame_coba); + smd->domain->tex_flame_coba = NULL; + + if (smd->domain->tex_coba) + GPU_texture_free(smd->domain->tex_coba); + smd->domain->tex_coba = NULL; + + if (smd->domain->tex_field) + GPU_texture_free(smd->domain->tex_field); + smd->domain->tex_field = NULL; + } } void GPU_create_smoke_coba_field(SmokeModifierData *smd) { #ifdef WITH_SMOKE - if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - SmokeDomainSettings *sds = smd->domain; - - if (!sds->tex_field) { - sds->tex_field = create_field_texture(sds); - } - if (!sds->tex_coba) { - sds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, sds->coba); - } - } -#else // WITH_SMOKE - smd->domain->tex_field = NULL; -#endif // WITH_SMOKE + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + SmokeDomainSettings *sds = smd->domain; + + if (!sds->tex_field) { + sds->tex_field = create_field_texture(sds); + } + if (!sds->tex_coba) { + sds->tex_coba = create_transfer_function(TFUNC_COLOR_RAMP, sds->coba); + } + } +#else // WITH_SMOKE + smd->domain->tex_field = NULL; +#endif // WITH_SMOKE } void GPU_create_smoke(SmokeModifierData *smd, int highres) { #ifdef WITH_SMOKE - if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - SmokeDomainSettings *sds = smd->domain; - - if (!sds->tex) { - sds->tex = create_density_texture(sds, highres); - } - if (!sds->tex_flame) { - sds->tex_flame = create_flame_texture(sds, highres); - } - if (!sds->tex_flame_coba && sds->tex_flame) { - sds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL); - } - if (!sds->tex_shadow) { - sds->tex_shadow = GPU_texture_create_nD( - sds->res[0], sds->res[1], sds->res[2], 3, - sds->shadow, - GPU_R8, GPU_DATA_FLOAT, 0, true, NULL); - } - } -#else // WITH_SMOKE - (void)highres; - smd->domain->tex = NULL; - smd->domain->tex_flame = NULL; - smd->domain->tex_flame_coba = NULL; - smd->domain->tex_shadow = NULL; -#endif // WITH_SMOKE + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + SmokeDomainSettings *sds = smd->domain; + + if (!sds->tex) { + sds->tex = create_density_texture(sds, highres); + } + if (!sds->tex_flame) { + sds->tex_flame = create_flame_texture(sds, highres); + } + if (!sds->tex_flame_coba && sds->tex_flame) { + sds->tex_flame_coba = create_transfer_function(TFUNC_FLAME_SPECTRUM, NULL); + } + if (!sds->tex_shadow) { + sds->tex_shadow = GPU_texture_create_nD(sds->res[0], + sds->res[1], + sds->res[2], + 3, + sds->shadow, + GPU_R8, + GPU_DATA_FLOAT, + 0, + true, + NULL); + } + } +#else // WITH_SMOKE + (void)highres; + smd->domain->tex = NULL; + smd->domain->tex_flame = NULL; + smd->domain->tex_flame_coba = NULL; + smd->domain->tex_shadow = NULL; +#endif // WITH_SMOKE } void GPU_create_smoke_velocity(SmokeModifierData *smd) { #ifdef WITH_SMOKE - if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { - SmokeDomainSettings *sds = smd->domain; - - const float *vel_x = smoke_get_velocity_x(sds->fluid); - const float *vel_y = smoke_get_velocity_y(sds->fluid); - const float *vel_z = smoke_get_velocity_z(sds->fluid); - - if (ELEM(NULL, vel_x, vel_y, vel_z)) { - return; - } - - if (!sds->tex_velocity_x) { - sds->tex_velocity_x = GPU_texture_create_3d(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_x, NULL); - sds->tex_velocity_y = GPU_texture_create_3d(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_y, NULL); - sds->tex_velocity_z = GPU_texture_create_3d(sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_z, NULL); - } - } -#else // WITH_SMOKE - smd->domain->tex_velocity_x = NULL; - smd->domain->tex_velocity_y = NULL; - smd->domain->tex_velocity_z = NULL; -#endif // WITH_SMOKE + if (smd->type & MOD_SMOKE_TYPE_DOMAIN) { + SmokeDomainSettings *sds = smd->domain; + + const float *vel_x = smoke_get_velocity_x(sds->fluid); + const float *vel_y = smoke_get_velocity_y(sds->fluid); + const float *vel_z = smoke_get_velocity_z(sds->fluid); + + if (ELEM(NULL, vel_x, vel_y, vel_z)) { + return; + } + + if (!sds->tex_velocity_x) { + sds->tex_velocity_x = GPU_texture_create_3d( + sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_x, NULL); + sds->tex_velocity_y = GPU_texture_create_3d( + sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_y, NULL); + sds->tex_velocity_z = GPU_texture_create_3d( + sds->res[0], sds->res[1], sds->res[2], GPU_R16F, vel_z, NULL); + } + } +#else // WITH_SMOKE + smd->domain->tex_velocity_x = NULL; + smd->domain->tex_velocity_y = NULL; + smd->domain->tex_velocity_z = NULL; +#endif // WITH_SMOKE } /* TODO Unify with the other GPU_free_smoke. */ void GPU_free_smoke_velocity(SmokeModifierData *smd) { - if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { - if (smd->domain->tex_velocity_x) - GPU_texture_free(smd->domain->tex_velocity_x); + if (smd->type & MOD_SMOKE_TYPE_DOMAIN && smd->domain) { + if (smd->domain->tex_velocity_x) + GPU_texture_free(smd->domain->tex_velocity_x); - if (smd->domain->tex_velocity_y) - GPU_texture_free(smd->domain->tex_velocity_y); + if (smd->domain->tex_velocity_y) + GPU_texture_free(smd->domain->tex_velocity_y); - if (smd->domain->tex_velocity_z) - GPU_texture_free(smd->domain->tex_velocity_z); + if (smd->domain->tex_velocity_z) + GPU_texture_free(smd->domain->tex_velocity_z); - smd->domain->tex_velocity_x = NULL; - smd->domain->tex_velocity_y = NULL; - smd->domain->tex_velocity_z = NULL; - } + smd->domain->tex_velocity_x = NULL; + smd->domain->tex_velocity_y = NULL; + smd->domain->tex_velocity_z = NULL; + } } static LinkNode *image_free_queue = NULL; static void gpu_queue_image_for_free(Image *ima) { - BLI_thread_lock(LOCK_OPENGL); - BLI_linklist_prepend(&image_free_queue, ima); - BLI_thread_unlock(LOCK_OPENGL); + BLI_thread_lock(LOCK_OPENGL); + BLI_linklist_prepend(&image_free_queue, ima); + BLI_thread_unlock(LOCK_OPENGL); } void GPU_free_unused_buffers(Main *bmain) { - if (!BLI_thread_is_main()) - return; + if (!BLI_thread_is_main()) + return; - BLI_thread_lock(LOCK_OPENGL); + BLI_thread_lock(LOCK_OPENGL); - /* images */ - for (LinkNode *node = image_free_queue; node; node = node->next) { - Image *ima = node->link; + /* images */ + for (LinkNode *node = image_free_queue; node; node = node->next) { + Image *ima = node->link; - /* check in case it was freed in the meantime */ - if (bmain && BLI_findindex(&bmain->images, ima) != -1) - GPU_free_image(ima); - } + /* check in case it was freed in the meantime */ + if (bmain && BLI_findindex(&bmain->images, ima) != -1) + GPU_free_image(ima); + } - BLI_linklist_free(image_free_queue, NULL); - image_free_queue = NULL; + BLI_linklist_free(image_free_queue, NULL); + image_free_queue = NULL; - BLI_thread_unlock(LOCK_OPENGL); + BLI_thread_unlock(LOCK_OPENGL); } static void gpu_free_image_immediate(Image *ima) { - for (int i = 0; i < TEXTARGET_COUNT; i++) { - /* free glsl image binding */ - if (ima->gputexture[i]) { - GPU_texture_free(ima->gputexture[i]); - ima->gputexture[i] = NULL; - } - } - - ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE | IMA_GPU_IS_DATA); + for (int i = 0; i < TEXTARGET_COUNT; i++) { + /* free glsl image binding */ + if (ima->gputexture[i]) { + GPU_texture_free(ima->gputexture[i]); + ima->gputexture[i] = NULL; + } + } + + ima->gpuflag &= ~(IMA_GPU_MIPMAP_COMPLETE | IMA_GPU_IS_DATA); } void GPU_free_image(Image *ima) { - if (!BLI_thread_is_main()) { - gpu_queue_image_for_free(ima); - return; - } + if (!BLI_thread_is_main()) { + gpu_queue_image_for_free(ima); + return; + } - gpu_free_image_immediate(ima); + gpu_free_image_immediate(ima); } void GPU_free_images(Main *bmain) { - if (bmain) { - for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { - GPU_free_image(ima); - } - } + if (bmain) { + for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { + GPU_free_image(ima); + } + } } /* same as above but only free animated images */ void GPU_free_images_anim(Main *bmain) { - if (bmain) { - for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { - if (BKE_image_is_animated(ima)) { - GPU_free_image(ima); - } - } - } + if (bmain) { + for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { + if (BKE_image_is_animated(ima)) { + GPU_free_image(ima); + } + } + } } - void GPU_free_images_old(Main *bmain) { - static int lasttime = 0; - int ctime = (int)PIL_check_seconds_timer(); - - /* - * Run garbage collector once for every collecting period of time - * if textimeout is 0, that's the option to NOT run the collector - */ - if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) - return; - - /* of course not! */ - if (G.is_rendering) - return; - - lasttime = ctime; - - Image *ima = bmain->images.first; - while (ima) { - if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { - /* If it's in GL memory, deallocate and set time tag to current time - * This gives textures a "second chance" to be used before dying. */ - if (BKE_image_has_opengl_texture(ima)) { - GPU_free_image(ima); - ima->lastused = ctime; - } - /* Otherwise, just kill the buffers */ - else { - BKE_image_free_buffers(ima); - } - } - ima = ima->id.next; - } + static int lasttime = 0; + int ctime = (int)PIL_check_seconds_timer(); + + /* + * Run garbage collector once for every collecting period of time + * if textimeout is 0, that's the option to NOT run the collector + */ + if (U.textimeout == 0 || ctime % U.texcollectrate || ctime == lasttime) + return; + + /* of course not! */ + if (G.is_rendering) + return; + + lasttime = ctime; + + Image *ima = bmain->images.first; + while (ima) { + if ((ima->flag & IMA_NOCOLLECT) == 0 && ctime - ima->lastused > U.textimeout) { + /* If it's in GL memory, deallocate and set time tag to current time + * This gives textures a "second chance" to be used before dying. */ + if (BKE_image_has_opengl_texture(ima)) { + GPU_free_image(ima); + ima->lastused = ctime; + } + /* Otherwise, just kill the buffers */ + else { + BKE_image_free_buffers(ima); + } + } + ima = ima->id.next; + } } static void gpu_disable_multisample(void) { #ifdef __linux__ - /* changing multisample from the default (enabled) causes problems on some - * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */ - bool toggle_ok = true; + /* changing multisample from the default (enabled) causes problems on some + * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */ + bool toggle_ok = true; - if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) { - int samples = 0; - glGetIntegerv(GL_SAMPLES, &samples); + if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) { + int samples = 0; + glGetIntegerv(GL_SAMPLES, &samples); - if (samples == 0) - toggle_ok = false; - } + if (samples == 0) + toggle_ok = false; + } - if (toggle_ok) { - glDisable(GL_MULTISAMPLE); - } + if (toggle_ok) { + glDisable(GL_MULTISAMPLE); + } #else - glDisable(GL_MULTISAMPLE); + glDisable(GL_MULTISAMPLE); #endif } @@ -1264,85 +1301,84 @@ static void gpu_disable_multisample(void) void GPU_state_init(void) { - GPU_disable_program_point_size(); + GPU_disable_program_point_size(); - glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LEQUAL); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_COLOR_LOGIC_OP); - glDisable(GL_STENCIL_TEST); + glDisable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + glDisable(GL_COLOR_LOGIC_OP); + glDisable(GL_STENCIL_TEST); - glDepthRange(0.0, 1.0); + glDepthRange(0.0, 1.0); - glFrontFace(GL_CCW); - glCullFace(GL_BACK); - glDisable(GL_CULL_FACE); + glFrontFace(GL_CCW); + glCullFace(GL_BACK); + glDisable(GL_CULL_FACE); - gpu_disable_multisample(); + gpu_disable_multisample(); } void GPU_enable_program_point_size(void) { - glEnable(GL_PROGRAM_POINT_SIZE); + glEnable(GL_PROGRAM_POINT_SIZE); } void GPU_disable_program_point_size(void) { - glDisable(GL_PROGRAM_POINT_SIZE); + glDisable(GL_PROGRAM_POINT_SIZE); } /** \name Framebuffer color depth, for selection codes * \{ */ - #define STATE_STACK_DEPTH 16 typedef struct { - eGPUAttrMask mask; - - /* GL_ENABLE_BIT */ - uint is_blend : 1; - uint is_cull_face : 1; - uint is_depth_test : 1; - uint is_dither : 1; - uint is_lighting : 1; - uint is_line_smooth : 1; - uint is_color_logic_op : 1; - uint is_multisample : 1; - uint is_polygon_offset_line : 1; - uint is_polygon_offset_fill : 1; - uint is_polygon_smooth : 1; - uint is_sample_alpha_to_coverage : 1; - uint is_scissor_test : 1; - uint is_stencil_test : 1; - - bool is_clip_plane[6]; - - /* GL_DEPTH_BUFFER_BIT */ - /* uint is_depth_test : 1; */ - int depth_func; - double depth_clear_value; - bool depth_write_mask; - - /* GL_SCISSOR_BIT */ - int scissor_box[4]; - /* uint is_scissor_test : 1; */ - - /* GL_VIEWPORT_BIT */ - int viewport[4]; - double near_far[2]; -} GPUAttrValues; + eGPUAttrMask mask; + + /* GL_ENABLE_BIT */ + uint is_blend : 1; + uint is_cull_face : 1; + uint is_depth_test : 1; + uint is_dither : 1; + uint is_lighting : 1; + uint is_line_smooth : 1; + uint is_color_logic_op : 1; + uint is_multisample : 1; + uint is_polygon_offset_line : 1; + uint is_polygon_offset_fill : 1; + uint is_polygon_smooth : 1; + uint is_sample_alpha_to_coverage : 1; + uint is_scissor_test : 1; + uint is_stencil_test : 1; + + bool is_clip_plane[6]; + + /* GL_DEPTH_BUFFER_BIT */ + /* uint is_depth_test : 1; */ + int depth_func; + double depth_clear_value; + bool depth_write_mask; + + /* GL_SCISSOR_BIT */ + int scissor_box[4]; + /* uint is_scissor_test : 1; */ + + /* GL_VIEWPORT_BIT */ + int viewport[4]; + double near_far[2]; +} GPUAttrValues; typedef struct { - GPUAttrValues attr_stack[STATE_STACK_DEPTH]; - uint top; + GPUAttrValues attr_stack[STATE_STACK_DEPTH]; + uint top; } GPUAttrStack; static GPUAttrStack state = { - .top = 0, + .top = 0, }; #define AttrStack state @@ -1356,112 +1392,112 @@ static GPUAttrStack state = { */ void gpuPushAttr(eGPUAttrMask mask) { - Attr.mask = mask; - - if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { - Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST); - glGetIntegerv(GL_DEPTH_FUNC, &Attr.depth_func); - glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attr.depth_clear_value); - glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attr.depth_write_mask); - } - - if ((mask & GPU_ENABLE_BIT) != 0) { - Attr.is_blend = glIsEnabled(GL_BLEND); - - for (int i = 0; i < 6; i++) { - Attr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i); - } - - Attr.is_cull_face = glIsEnabled(GL_CULL_FACE); - Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST); - Attr.is_dither = glIsEnabled(GL_DITHER); - Attr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH); - Attr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP); - Attr.is_multisample = glIsEnabled(GL_MULTISAMPLE); - Attr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE); - Attr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL); - Attr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH); - Attr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); - Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - Attr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST); - } - - if ((mask & GPU_SCISSOR_BIT) != 0) { - Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); - glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attr.scissor_box); - } - - if ((mask & GPU_VIEWPORT_BIT) != 0) { - glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far); - glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport); - } - - if ((mask & GPU_BLEND_BIT) != 0) { - Attr.is_blend = glIsEnabled(GL_BLEND); - } - - BLI_assert(AttrStack.top < STATE_STACK_DEPTH); - AttrStack.top++; + Attr.mask = mask; + + if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { + Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST); + glGetIntegerv(GL_DEPTH_FUNC, &Attr.depth_func); + glGetDoublev(GL_DEPTH_CLEAR_VALUE, &Attr.depth_clear_value); + glGetBooleanv(GL_DEPTH_WRITEMASK, (GLboolean *)&Attr.depth_write_mask); + } + + if ((mask & GPU_ENABLE_BIT) != 0) { + Attr.is_blend = glIsEnabled(GL_BLEND); + + for (int i = 0; i < 6; i++) { + Attr.is_clip_plane[i] = glIsEnabled(GL_CLIP_PLANE0 + i); + } + + Attr.is_cull_face = glIsEnabled(GL_CULL_FACE); + Attr.is_depth_test = glIsEnabled(GL_DEPTH_TEST); + Attr.is_dither = glIsEnabled(GL_DITHER); + Attr.is_line_smooth = glIsEnabled(GL_LINE_SMOOTH); + Attr.is_color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP); + Attr.is_multisample = glIsEnabled(GL_MULTISAMPLE); + Attr.is_polygon_offset_line = glIsEnabled(GL_POLYGON_OFFSET_LINE); + Attr.is_polygon_offset_fill = glIsEnabled(GL_POLYGON_OFFSET_FILL); + Attr.is_polygon_smooth = glIsEnabled(GL_POLYGON_SMOOTH); + Attr.is_sample_alpha_to_coverage = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); + Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + Attr.is_stencil_test = glIsEnabled(GL_STENCIL_TEST); + } + + if ((mask & GPU_SCISSOR_BIT) != 0) { + Attr.is_scissor_test = glIsEnabled(GL_SCISSOR_TEST); + glGetIntegerv(GL_SCISSOR_BOX, (GLint *)&Attr.scissor_box); + } + + if ((mask & GPU_VIEWPORT_BIT) != 0) { + glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far); + glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport); + } + + if ((mask & GPU_BLEND_BIT) != 0) { + Attr.is_blend = glIsEnabled(GL_BLEND); + } + + BLI_assert(AttrStack.top < STATE_STACK_DEPTH); + AttrStack.top++; } static void restore_mask(GLenum cap, const bool value) { - if (value) { - glEnable(cap); - } - else { - glDisable(cap); - } + if (value) { + glEnable(cap); + } + else { + glDisable(cap); + } } void gpuPopAttr(void) { - BLI_assert(AttrStack.top > 0); - AttrStack.top--; - - GLint mask = Attr.mask; - - if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { - restore_mask(GL_DEPTH_TEST, Attr.is_depth_test); - glDepthFunc(Attr.depth_func); - glClearDepth(Attr.depth_clear_value); - glDepthMask(Attr.depth_write_mask); - } - - if ((mask & GPU_ENABLE_BIT) != 0) { - restore_mask(GL_BLEND, Attr.is_blend); - - for (int i = 0; i < 6; i++) { - restore_mask(GL_CLIP_PLANE0 + i, Attr.is_clip_plane[i]); - } - - restore_mask(GL_CULL_FACE, Attr.is_cull_face); - restore_mask(GL_DEPTH_TEST, Attr.is_depth_test); - restore_mask(GL_DITHER, Attr.is_dither); - restore_mask(GL_LINE_SMOOTH, Attr.is_line_smooth); - restore_mask(GL_COLOR_LOGIC_OP, Attr.is_color_logic_op); - restore_mask(GL_MULTISAMPLE, Attr.is_multisample); - restore_mask(GL_POLYGON_OFFSET_LINE, Attr.is_polygon_offset_line); - restore_mask(GL_POLYGON_OFFSET_FILL, Attr.is_polygon_offset_fill); - restore_mask(GL_POLYGON_SMOOTH, Attr.is_polygon_smooth); - restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attr.is_sample_alpha_to_coverage); - restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test); - restore_mask(GL_STENCIL_TEST, Attr.is_stencil_test); - } - - if ((mask & GPU_VIEWPORT_BIT) != 0) { - glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]); - glDepthRange(Attr.near_far[0], Attr.near_far[1]); - } - - if ((mask & GPU_SCISSOR_BIT) != 0) { - restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test); - glScissor(Attr.scissor_box[0], Attr.scissor_box[1], Attr.scissor_box[2], Attr.scissor_box[3]); - } - - if ((mask & GPU_BLEND_BIT) != 0) { - restore_mask(GL_BLEND, Attr.is_blend); - } + BLI_assert(AttrStack.top > 0); + AttrStack.top--; + + GLint mask = Attr.mask; + + if ((mask & GPU_DEPTH_BUFFER_BIT) != 0) { + restore_mask(GL_DEPTH_TEST, Attr.is_depth_test); + glDepthFunc(Attr.depth_func); + glClearDepth(Attr.depth_clear_value); + glDepthMask(Attr.depth_write_mask); + } + + if ((mask & GPU_ENABLE_BIT) != 0) { + restore_mask(GL_BLEND, Attr.is_blend); + + for (int i = 0; i < 6; i++) { + restore_mask(GL_CLIP_PLANE0 + i, Attr.is_clip_plane[i]); + } + + restore_mask(GL_CULL_FACE, Attr.is_cull_face); + restore_mask(GL_DEPTH_TEST, Attr.is_depth_test); + restore_mask(GL_DITHER, Attr.is_dither); + restore_mask(GL_LINE_SMOOTH, Attr.is_line_smooth); + restore_mask(GL_COLOR_LOGIC_OP, Attr.is_color_logic_op); + restore_mask(GL_MULTISAMPLE, Attr.is_multisample); + restore_mask(GL_POLYGON_OFFSET_LINE, Attr.is_polygon_offset_line); + restore_mask(GL_POLYGON_OFFSET_FILL, Attr.is_polygon_offset_fill); + restore_mask(GL_POLYGON_SMOOTH, Attr.is_polygon_smooth); + restore_mask(GL_SAMPLE_ALPHA_TO_COVERAGE, Attr.is_sample_alpha_to_coverage); + restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test); + restore_mask(GL_STENCIL_TEST, Attr.is_stencil_test); + } + + if ((mask & GPU_VIEWPORT_BIT) != 0) { + glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]); + glDepthRange(Attr.near_far[0], Attr.near_far[1]); + } + + if ((mask & GPU_SCISSOR_BIT) != 0) { + restore_mask(GL_SCISSOR_TEST, Attr.is_scissor_test); + glScissor(Attr.scissor_box[0], Attr.scissor_box[1], Attr.scissor_box[2], Attr.scissor_box[3]); + } + + if ((mask & GPU_BLEND_BIT) != 0) { + restore_mask(GL_BLEND, Attr.is_blend); + } } #undef Attr diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c index 2c80fff75a6..9fcc9821227 100644 --- a/source/blender/gpu/intern/gpu_element.c +++ b/source/blender/gpu/intern/gpu_element.c @@ -35,128 +35,134 @@ static GLenum convert_index_type_to_gl(GPUIndexBufType type) { - static const GLenum table[] = { - [GPU_INDEX_U8] = GL_UNSIGNED_BYTE, /* GL has this, Vulkan does not */ - [GPU_INDEX_U16] = GL_UNSIGNED_SHORT, - [GPU_INDEX_U32] = GL_UNSIGNED_INT, - }; - return table[type]; + static const GLenum table[] = { + [GPU_INDEX_U8] = GL_UNSIGNED_BYTE, /* GL has this, Vulkan does not */ + [GPU_INDEX_U16] = GL_UNSIGNED_SHORT, + [GPU_INDEX_U32] = GL_UNSIGNED_INT, + }; + return table[type]; } uint GPU_indexbuf_size_get(const GPUIndexBuf *elem) { #if GPU_TRACK_INDEX_RANGE - static const uint table[] = { - [GPU_INDEX_U8] = sizeof(GLubyte), /* GL has this, Vulkan does not */ - [GPU_INDEX_U16] = sizeof(GLushort), - [GPU_INDEX_U32] = sizeof(GLuint), - }; - return elem->index_len * table[elem->index_type]; + static const uint table[] = { + [GPU_INDEX_U8] = sizeof(GLubyte), /* GL has this, Vulkan does not */ + [GPU_INDEX_U16] = sizeof(GLushort), + [GPU_INDEX_U32] = sizeof(GLuint), + }; + return elem->index_len * table[elem->index_type]; #else - return elem->index_len * sizeof(GLuint); + return elem->index_len * sizeof(GLuint); #endif } int GPU_indexbuf_primitive_len(GPUPrimType prim_type) { - switch (prim_type) { - case GPU_PRIM_POINTS: - return 1; - case GPU_PRIM_LINES: - return 2; - case GPU_PRIM_TRIS: - return 3; - case GPU_PRIM_LINES_ADJ: - return 4; - default: - break; - } + switch (prim_type) { + case GPU_PRIM_POINTS: + return 1; + case GPU_PRIM_LINES: + return 2; + case GPU_PRIM_TRIS: + return 3; + case GPU_PRIM_LINES_ADJ: + return 4; + default: + break; + } #if TRUST_NO_ONE - assert(false); + assert(false); #endif - return -1; + return -1; } -void GPU_indexbuf_init_ex( - GPUIndexBufBuilder *builder, GPUPrimType prim_type, - uint index_len, uint vertex_len, bool use_prim_restart) +void GPU_indexbuf_init_ex(GPUIndexBufBuilder *builder, + GPUPrimType prim_type, + uint index_len, + uint vertex_len, + bool use_prim_restart) { - builder->use_prim_restart = use_prim_restart; - builder->max_allowed_index = vertex_len - 1; - builder->max_index_len = index_len; - builder->index_len = 0; // start empty - builder->prim_type = prim_type; - builder->data = MEM_callocN(builder->max_index_len * sizeof(uint), "GPUIndexBuf data"); + builder->use_prim_restart = use_prim_restart; + builder->max_allowed_index = vertex_len - 1; + builder->max_index_len = index_len; + builder->index_len = 0; // start empty + builder->prim_type = prim_type; + builder->data = MEM_callocN(builder->max_index_len * sizeof(uint), "GPUIndexBuf data"); } -void GPU_indexbuf_init(GPUIndexBufBuilder *builder, GPUPrimType prim_type, uint prim_len, uint vertex_len) +void GPU_indexbuf_init(GPUIndexBufBuilder *builder, + GPUPrimType prim_type, + uint prim_len, + uint vertex_len) { - int verts_per_prim = GPU_indexbuf_primitive_len(prim_type); + int verts_per_prim = GPU_indexbuf_primitive_len(prim_type); #if TRUST_NO_ONE - assert(verts_per_prim != -1); + assert(verts_per_prim != -1); #endif - GPU_indexbuf_init_ex(builder, prim_type, prim_len * (uint)verts_per_prim, vertex_len, false); + GPU_indexbuf_init_ex(builder, prim_type, prim_len * (uint)verts_per_prim, vertex_len, false); } void GPU_indexbuf_add_generic_vert(GPUIndexBufBuilder *builder, uint v) { #if TRUST_NO_ONE - assert(builder->data != NULL); - assert(builder->index_len < builder->max_index_len); - assert(v <= builder->max_allowed_index); + assert(builder->data != NULL); + assert(builder->index_len < builder->max_index_len); + assert(v <= builder->max_allowed_index); #endif - builder->data[builder->index_len++] = v; + builder->data[builder->index_len++] = v; } void GPU_indexbuf_add_primitive_restart(GPUIndexBufBuilder *builder) { #if TRUST_NO_ONE - assert(builder->data != NULL); - assert(builder->index_len < builder->max_index_len); - assert(builder->use_prim_restart); + assert(builder->data != NULL); + assert(builder->index_len < builder->max_index_len); + assert(builder->use_prim_restart); #endif - builder->data[builder->index_len++] = GPU_PRIM_RESTART; + builder->data[builder->index_len++] = GPU_PRIM_RESTART; } void GPU_indexbuf_add_point_vert(GPUIndexBufBuilder *builder, uint v) { #if TRUST_NO_ONE - assert(builder->prim_type == GPU_PRIM_POINTS); + assert(builder->prim_type == GPU_PRIM_POINTS); #endif - GPU_indexbuf_add_generic_vert(builder, v); + GPU_indexbuf_add_generic_vert(builder, v); } void GPU_indexbuf_add_line_verts(GPUIndexBufBuilder *builder, uint v1, uint v2) { #if TRUST_NO_ONE - assert(builder->prim_type == GPU_PRIM_LINES); - assert(v1 != v2); + assert(builder->prim_type == GPU_PRIM_LINES); + assert(v1 != v2); #endif - GPU_indexbuf_add_generic_vert(builder, v1); - GPU_indexbuf_add_generic_vert(builder, v2); + GPU_indexbuf_add_generic_vert(builder, v1); + GPU_indexbuf_add_generic_vert(builder, v2); } void GPU_indexbuf_add_tri_verts(GPUIndexBufBuilder *builder, uint v1, uint v2, uint v3) { #if TRUST_NO_ONE - assert(builder->prim_type == GPU_PRIM_TRIS); - assert(v1 != v2 && v2 != v3 && v3 != v1); + assert(builder->prim_type == GPU_PRIM_TRIS); + assert(v1 != v2 && v2 != v3 && v3 != v1); #endif - GPU_indexbuf_add_generic_vert(builder, v1); - GPU_indexbuf_add_generic_vert(builder, v2); - GPU_indexbuf_add_generic_vert(builder, v3); + GPU_indexbuf_add_generic_vert(builder, v1); + GPU_indexbuf_add_generic_vert(builder, v2); + GPU_indexbuf_add_generic_vert(builder, v3); } -void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *builder, uint v1, uint v2, uint v3, uint v4) +void GPU_indexbuf_add_line_adj_verts( + GPUIndexBufBuilder *builder, uint v1, uint v2, uint v3, uint v4) { #if TRUST_NO_ONE - assert(builder->prim_type == GPU_PRIM_LINES_ADJ); - assert(v2 != v3); /* only the line need diff indices */ + assert(builder->prim_type == GPU_PRIM_LINES_ADJ); + assert(v2 != v3); /* only the line need diff indices */ #endif - GPU_indexbuf_add_generic_vert(builder, v1); - GPU_indexbuf_add_generic_vert(builder, v2); - GPU_indexbuf_add_generic_vert(builder, v3); - GPU_indexbuf_add_generic_vert(builder, v4); + GPU_indexbuf_add_generic_vert(builder, v1); + GPU_indexbuf_add_generic_vert(builder, v2); + GPU_indexbuf_add_generic_vert(builder, v3); + GPU_indexbuf_add_generic_vert(builder, v4); } #if GPU_TRACK_INDEX_RANGE @@ -165,154 +171,154 @@ void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *builder, uint v1, uint static uint index_range(const uint values[], uint value_len, uint *min_out, uint *max_out) { - if (value_len == 0) { - *min_out = 0; - *max_out = 0; - return 0; - } - uint min_value = values[0]; - uint max_value = values[0]; - for (uint i = 1; i < value_len; ++i) { - const uint value = values[i]; - if (value == GPU_PRIM_RESTART) - continue; - else if (value < min_value) - min_value = value; - else if (value > max_value) - max_value = value; - } - *min_out = min_value; - *max_out = max_value; - return max_value - min_value; + if (value_len == 0) { + *min_out = 0; + *max_out = 0; + return 0; + } + uint min_value = values[0]; + uint max_value = values[0]; + for (uint i = 1; i < value_len; ++i) { + const uint value = values[i]; + if (value == GPU_PRIM_RESTART) + continue; + else if (value < min_value) + min_value = value; + else if (value > max_value) + max_value = value; + } + *min_out = min_value; + *max_out = max_value; + return max_value - min_value; } static void squeeze_indices_byte(GPUIndexBufBuilder *builder, GPUIndexBuf *elem) { - const uint *values = builder->data; - const uint index_len = elem->index_len; - - /* data will never be *larger* than builder->data... - * converting in place to avoid extra allocation */ - GLubyte *data = (GLubyte *)builder->data; - - if (elem->max_index > 0xFF) { - const uint base = elem->min_index; - elem->base_index = base; - elem->min_index = 0; - elem->max_index -= base; - for (uint i = 0; i < index_len; ++i) { - data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base); - } - } - else { - elem->base_index = 0; - for (uint i = 0; i < index_len; ++i) { - data[i] = (GLubyte)(values[i]); - } - } + const uint *values = builder->data; + const uint index_len = elem->index_len; + + /* data will never be *larger* than builder->data... + * converting in place to avoid extra allocation */ + GLubyte *data = (GLubyte *)builder->data; + + if (elem->max_index > 0xFF) { + const uint base = elem->min_index; + elem->base_index = base; + elem->min_index = 0; + elem->max_index -= base; + for (uint i = 0; i < index_len; ++i) { + data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFF : (GLubyte)(values[i] - base); + } + } + else { + elem->base_index = 0; + for (uint i = 0; i < index_len; ++i) { + data[i] = (GLubyte)(values[i]); + } + } } static void squeeze_indices_short(GPUIndexBufBuilder *builder, GPUIndexBuf *elem) { - const uint *values = builder->data; - const uint index_len = elem->index_len; - - /* data will never be *larger* than builder->data... - * converting in place to avoid extra allocation */ - GLushort *data = (GLushort *)builder->data; - - if (elem->max_index > 0xFFFF) { - const uint base = elem->min_index; - elem->base_index = base; - elem->min_index = 0; - elem->max_index -= base; - for (uint i = 0; i < index_len; ++i) { - data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base); - } - } - else { - elem->base_index = 0; - for (uint i = 0; i < index_len; ++i) { - data[i] = (GLushort)(values[i]); - } - } + const uint *values = builder->data; + const uint index_len = elem->index_len; + + /* data will never be *larger* than builder->data... + * converting in place to avoid extra allocation */ + GLushort *data = (GLushort *)builder->data; + + if (elem->max_index > 0xFFFF) { + const uint base = elem->min_index; + elem->base_index = base; + elem->min_index = 0; + elem->max_index -= base; + for (uint i = 0; i < index_len; ++i) { + data[i] = (values[i] == GPU_PRIM_RESTART) ? 0xFFFF : (GLushort)(values[i] - base); + } + } + else { + elem->base_index = 0; + for (uint i = 0; i < index_len; ++i) { + data[i] = (GLushort)(values[i]); + } + } } #endif /* GPU_TRACK_INDEX_RANGE */ GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *builder) { - GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf"); - GPU_indexbuf_build_in_place(builder, elem); - return elem; + GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf"); + GPU_indexbuf_build_in_place(builder, elem); + return elem; } void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *builder, GPUIndexBuf *elem) { #if TRUST_NO_ONE - assert(builder->data != NULL); + assert(builder->data != NULL); #endif - elem->index_len = builder->index_len; - elem->use_prim_restart = builder->use_prim_restart; - elem->ibo_id = 0; /* Created at first use. */ + elem->index_len = builder->index_len; + elem->use_prim_restart = builder->use_prim_restart; + elem->ibo_id = 0; /* Created at first use. */ #if GPU_TRACK_INDEX_RANGE - uint range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index); - - /* count the primitive restart index. */ - if (elem->use_prim_restart) { - range += 1; - } - - if (range <= 0xFF) { - elem->index_type = GPU_INDEX_U8; - squeeze_indices_byte(builder, elem); - } - else if (range <= 0xFFFF) { - elem->index_type = GPU_INDEX_U16; - squeeze_indices_short(builder, elem); - } - else { - elem->index_type = GPU_INDEX_U32; - elem->base_index = 0; - } - elem->gl_index_type = convert_index_type_to_gl(elem->index_type); + uint range = index_range(builder->data, builder->index_len, &elem->min_index, &elem->max_index); + + /* count the primitive restart index. */ + if (elem->use_prim_restart) { + range += 1; + } + + if (range <= 0xFF) { + elem->index_type = GPU_INDEX_U8; + squeeze_indices_byte(builder, elem); + } + else if (range <= 0xFFFF) { + elem->index_type = GPU_INDEX_U16; + squeeze_indices_short(builder, elem); + } + else { + elem->index_type = GPU_INDEX_U32; + elem->base_index = 0; + } + elem->gl_index_type = convert_index_type_to_gl(elem->index_type); #endif - /* Transfer data ownership to GPUIndexBuf. - * It will be uploaded upon first use. */ - elem->data = builder->data; - builder->data = NULL; - /* other fields are safe to leave */ + /* Transfer data ownership to GPUIndexBuf. + * It will be uploaded upon first use. */ + elem->data = builder->data; + builder->data = NULL; + /* other fields are safe to leave */ } static void indexbuf_upload_data(GPUIndexBuf *elem) { - /* send data to GPU */ - glBufferData(GL_ELEMENT_ARRAY_BUFFER, GPU_indexbuf_size_get(elem), elem->data, GL_STATIC_DRAW); - /* No need to keep copy of data in system memory. */ - MEM_freeN(elem->data); - elem->data = NULL; + /* send data to GPU */ + glBufferData(GL_ELEMENT_ARRAY_BUFFER, GPU_indexbuf_size_get(elem), elem->data, GL_STATIC_DRAW); + /* No need to keep copy of data in system memory. */ + MEM_freeN(elem->data); + elem->data = NULL; } void GPU_indexbuf_use(GPUIndexBuf *elem) { - if (elem->ibo_id == 0) { - elem->ibo_id = GPU_buf_alloc(); - } - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->ibo_id); - if (elem->data != NULL) { - indexbuf_upload_data(elem); - } + if (elem->ibo_id == 0) { + elem->ibo_id = GPU_buf_alloc(); + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->ibo_id); + if (elem->data != NULL) { + indexbuf_upload_data(elem); + } } void GPU_indexbuf_discard(GPUIndexBuf *elem) { - if (elem->ibo_id) { - GPU_buf_free(elem->ibo_id); - } - if (elem->data) { - MEM_freeN(elem->data); - } - MEM_freeN(elem); + if (elem->ibo_id) { + GPU_buf_free(elem->ibo_id); + } + if (elem->data) { + MEM_freeN(elem->data); + } + MEM_freeN(elem); } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 282b9dfc388..860a64a1297 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -58,368 +58,356 @@ */ static struct GPUGlobal { - GLint maxtexsize; - GLint maxtexlayers; - GLint maxcubemapsize; - GLint maxtextures; - GLint maxtexturesfrag; - GLint maxtexturesgeom; - GLint maxtexturesvert; - GLint maxubosize; - GLint maxubobinds; - int samples_color_texture_max; - eGPUDeviceType device; - eGPUOSType os; - eGPUDriverType driver; - float line_width_range[2]; - /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers - * calculate dfdy in shader differently when drawing to an offscreen buffer. First - * number is factor on screen and second is off-screen */ - float dfdyfactors[2]; - float max_anisotropy; - /* Some Intel drivers have issues with using mips as framebuffer targets if - * GL_TEXTURE_MAX_LEVEL is higher than the target mip. - * We need a workaround in this cases. */ - bool mip_render_workaround; - /* There is an issue with the glBlitFramebuffer on MacOS with radeon pro graphics. - * Blitting depth with GL_DEPTH24_STENCIL8 is buggy so the workaround is to use - * GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will - * still be broken. */ - bool depth_blitting_workaround; - /* Crappy driver don't know how to map framebuffer slot to output vars... - * We need to have no "holes" in the output buffer slots. */ - bool unused_fb_slot_workaround; + GLint maxtexsize; + GLint maxtexlayers; + GLint maxcubemapsize; + GLint maxtextures; + GLint maxtexturesfrag; + GLint maxtexturesgeom; + GLint maxtexturesvert; + GLint maxubosize; + GLint maxubobinds; + int samples_color_texture_max; + eGPUDeviceType device; + eGPUOSType os; + eGPUDriverType driver; + float line_width_range[2]; + /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers + * calculate dfdy in shader differently when drawing to an offscreen buffer. First + * number is factor on screen and second is off-screen */ + float dfdyfactors[2]; + float max_anisotropy; + /* Some Intel drivers have issues with using mips as framebuffer targets if + * GL_TEXTURE_MAX_LEVEL is higher than the target mip. + * We need a workaround in this cases. */ + bool mip_render_workaround; + /* There is an issue with the glBlitFramebuffer on MacOS with radeon pro graphics. + * Blitting depth with GL_DEPTH24_STENCIL8 is buggy so the workaround is to use + * GPU_DEPTH32F_STENCIL8. Then Blitting depth will work but blitting stencil will + * still be broken. */ + bool depth_blitting_workaround; + /* Crappy driver don't know how to map framebuffer slot to output vars... + * We need to have no "holes" in the output buffer slots. */ + bool unused_fb_slot_workaround; } GG = {1, 0}; - static void gpu_detect_mip_render_workaround(void) { - int cube_size = 2; - float *source_pix = MEM_callocN(sizeof(float) * 4 * 6 * cube_size * cube_size, __func__); - float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f}; - - GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL); - MEM_freeN(source_pix); - - GPU_texture_bind(tex, 0); - GPU_texture_generate_mipmap(tex); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0); - GPU_texture_unbind(tex); - - GPUFrameBuffer *fb = GPU_framebuffer_create(); - GPU_framebuffer_texture_attach(fb, tex, 0, 1); - GPU_framebuffer_bind(fb); - GPU_framebuffer_clear_color(fb, clear_color); - GPU_framebuffer_restore(); - GPU_framebuffer_free(fb); - - float *data = GPU_texture_read(tex, GPU_DATA_FLOAT, 1); - GG.mip_render_workaround = !equals_v4v4(clear_color, data); - - MEM_freeN(data); - GPU_texture_free(tex); + int cube_size = 2; + float *source_pix = MEM_callocN(sizeof(float) * 4 * 6 * cube_size * cube_size, __func__); + float clear_color[4] = {1.0f, 0.5f, 0.0f, 0.0f}; + + GPUTexture *tex = GPU_texture_create_cube(cube_size, GPU_RGBA16F, source_pix, NULL); + MEM_freeN(source_pix); + + GPU_texture_bind(tex, 0); + GPU_texture_generate_mipmap(tex); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, 0); + GPU_texture_unbind(tex); + + GPUFrameBuffer *fb = GPU_framebuffer_create(); + GPU_framebuffer_texture_attach(fb, tex, 0, 1); + GPU_framebuffer_bind(fb); + GPU_framebuffer_clear_color(fb, clear_color); + GPU_framebuffer_restore(); + GPU_framebuffer_free(fb); + + float *data = GPU_texture_read(tex, GPU_DATA_FLOAT, 1); + GG.mip_render_workaround = !equals_v4v4(clear_color, data); + + MEM_freeN(data); + GPU_texture_free(tex); } /* GPU Types */ bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver) { - return (GG.device & device) && (GG.os & os) && (GG.driver & driver); + return (GG.device & device) && (GG.os & os) && (GG.driver & driver); } /* GPU Extensions */ int GPU_max_texture_size(void) { - return GG.maxtexsize; + return GG.maxtexsize; } int GPU_max_texture_layers(void) { - return GG.maxtexlayers; + return GG.maxtexlayers; } int GPU_max_textures(void) { - return GG.maxtextures; + return GG.maxtextures; } int GPU_max_textures_frag(void) { - return GG.maxtexturesfrag; + return GG.maxtexturesfrag; } int GPU_max_textures_geom(void) { - return GG.maxtexturesgeom; + return GG.maxtexturesgeom; } int GPU_max_textures_vert(void) { - return GG.maxtexturesvert; + return GG.maxtexturesvert; } float GPU_max_texture_anisotropy(void) { - return GG.max_anisotropy; + return GG.max_anisotropy; } int GPU_max_color_texture_samples(void) { - return GG.samples_color_texture_max; + return GG.samples_color_texture_max; } int GPU_max_cube_map_size(void) { - return GG.maxcubemapsize; + return GG.maxcubemapsize; } int GPU_max_ubo_binds(void) { - return GG.maxubobinds; + return GG.maxubobinds; } int GPU_max_ubo_size(void) { - return GG.maxubosize; + return GG.maxubosize; } float GPU_max_line_width(void) { - return GG.line_width_range[1]; + return GG.line_width_range[1]; } void GPU_get_dfdy_factors(float fac[2]) { - copy_v2_v2(fac, GG.dfdyfactors); + copy_v2_v2(fac, GG.dfdyfactors); } bool GPU_mip_render_workaround(void) { - return GG.mip_render_workaround; + return GG.mip_render_workaround; } bool GPU_depth_blitting_workaround(void) { - return GG.depth_blitting_workaround; + return GG.depth_blitting_workaround; } bool GPU_unused_fb_slot_workaround(void) { - return GG.unused_fb_slot_workaround; + return GG.unused_fb_slot_workaround; } bool GPU_crappy_amd_driver(void) { - /* Currently are the same drivers with the `unused_fb_slot` problem. */ - return GPU_unused_fb_slot_workaround(); + /* Currently are the same drivers with the `unused_fb_slot` problem. */ + return GPU_unused_fb_slot_workaround(); } void gpu_extensions_init(void) { - /* during 2.8 development each platform has its own OpenGL minimum requirements - * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions - * see developer.blender.org/T49012 for details - */ - BLI_assert(GLEW_VERSION_3_3); + /* during 2.8 development each platform has its own OpenGL minimum requirements + * final 2.8 release will be unified on OpenGL 3.3 core profile, no required extensions + * see developer.blender.org/T49012 for details + */ + BLI_assert(GLEW_VERSION_3_3); - glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag); - glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert); - glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom); - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesfrag); + glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &GG.maxtexturesvert); + glGetIntegerv(GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &GG.maxtexturesgeom); + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &GG.maxtextures); - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); - glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers); - glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &GG.maxtexsize); + glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &GG.maxtexlayers); + glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &GG.maxcubemapsize); - if (GLEW_EXT_texture_filter_anisotropic) - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy); - else - GG.max_anisotropy = 1.0f; + if (GLEW_EXT_texture_filter_anisotropic) + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &GG.max_anisotropy); + else + GG.max_anisotropy = 1.0f; - glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds); - glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize); + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_BLOCKS, &GG.maxubobinds); + glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &GG.maxubosize); - glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, GG.line_width_range); + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, GG.line_width_range); #ifndef NDEBUG - GLint ret; - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret); - /* We expect FRONT_LEFT to be the default buffer. */ - BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT); + GLint ret; + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glGetFramebufferAttachmentParameteriv( + GL_FRAMEBUFFER, GL_FRONT_LEFT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &ret); + /* We expect FRONT_LEFT to be the default buffer. */ + BLI_assert(ret == GL_FRAMEBUFFER_DEFAULT); #endif - glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max); + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &GG.samples_color_texture_max); - const char *vendor = (const char *)glGetString(GL_VENDOR); - const char *renderer = (const char *)glGetString(GL_RENDERER); - const char *version = (const char *)glGetString(GL_VERSION); + const char *vendor = (const char *)glGetString(GL_VENDOR); + const char *renderer = (const char *)glGetString(GL_RENDERER); + const char *version = (const char *)glGetString(GL_VERSION); - if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) { - GG.device = GPU_DEVICE_ATI; - GG.driver = GPU_DRIVER_OFFICIAL; + if (strstr(vendor, "ATI") || strstr(vendor, "AMD")) { + GG.device = GPU_DEVICE_ATI; + GG.driver = GPU_DRIVER_OFFICIAL; #ifdef _WIN32 - if (strstr(version, "4.5.13399") || - strstr(version, "4.5.13417") || - strstr(version, "4.5.13422")) - { - /* The renderers include: - * Mobility Radeon HD 5000; - * Radeon HD 7500M; - * Radeon HD 7570M; - * Radeon HD 7600M; - * And many others... */ - - GG.unused_fb_slot_workaround = true; - } + if (strstr(version, "4.5.13399") || strstr(version, "4.5.13417") || + strstr(version, "4.5.13422")) { + /* The renderers include: + * Mobility Radeon HD 5000; + * Radeon HD 7500M; + * Radeon HD 7570M; + * Radeon HD 7600M; + * And many others... */ + + GG.unused_fb_slot_workaround = true; + } #endif #if defined(__APPLE__) - if (strstr(renderer, "AMD Radeon Pro") || - strstr(renderer, "AMD Radeon R9") || - strstr(renderer, "AMD Radeon RX")) - { - GG.depth_blitting_workaround = true; - } + if (strstr(renderer, "AMD Radeon Pro") || strstr(renderer, "AMD Radeon R9") || + strstr(renderer, "AMD Radeon RX")) { + GG.depth_blitting_workaround = true; + } #endif - } - else if (strstr(vendor, "NVIDIA")) { - GG.device = GPU_DEVICE_NVIDIA; - GG.driver = GPU_DRIVER_OFFICIAL; - } - else if (strstr(vendor, "Intel") || - /* src/mesa/drivers/dri/intel/intel_context.c */ - strstr(renderer, "Mesa DRI Intel") || - strstr(renderer, "Mesa DRI Mobile Intel")) - { - GG.device = GPU_DEVICE_INTEL; - GG.driver = GPU_DRIVER_OFFICIAL; - - if (strstr(renderer, "UHD Graphics") || - /* Not UHD but affected by the same bugs. */ - strstr(renderer, "HD Graphics 530") || - strstr(renderer, "Kaby Lake GT2")) - { - GG.device |= GPU_DEVICE_INTEL_UHD; - } - } - else if ((strstr(renderer, "Mesa DRI R")) || - (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) || - (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || - (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) - { - GG.device = GPU_DEVICE_ATI; - GG.driver = GPU_DRIVER_OPENSOURCE; - } - else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) { - GG.device = GPU_DEVICE_NVIDIA; - GG.driver = GPU_DRIVER_OPENSOURCE; - } - else if (strstr(vendor, "Mesa")) { - GG.device = GPU_DEVICE_SOFTWARE; - GG.driver = GPU_DRIVER_SOFTWARE; - } - else if (strstr(vendor, "Microsoft")) { - GG.device = GPU_DEVICE_SOFTWARE; - GG.driver = GPU_DRIVER_SOFTWARE; - } - else if (strstr(renderer, "Apple Software Renderer")) { - GG.device = GPU_DEVICE_SOFTWARE; - GG.driver = GPU_DRIVER_SOFTWARE; - } - else if (strstr(renderer, "llvmpipe")) { - GG.device = GPU_DEVICE_SOFTWARE; - GG.driver = GPU_DRIVER_SOFTWARE; - } - else { - printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n"); - printf("Detected OpenGL configuration:\n"); - printf("Vendor: %s\n", vendor); - printf("Renderer: %s\n", renderer); - GG.device = GPU_DEVICE_ANY; - GG.driver = GPU_DRIVER_ANY; - } + } + else if (strstr(vendor, "NVIDIA")) { + GG.device = GPU_DEVICE_NVIDIA; + GG.driver = GPU_DRIVER_OFFICIAL; + } + else if (strstr(vendor, "Intel") || + /* src/mesa/drivers/dri/intel/intel_context.c */ + strstr(renderer, "Mesa DRI Intel") || strstr(renderer, "Mesa DRI Mobile Intel")) { + GG.device = GPU_DEVICE_INTEL; + GG.driver = GPU_DRIVER_OFFICIAL; + + if (strstr(renderer, "UHD Graphics") || + /* Not UHD but affected by the same bugs. */ + strstr(renderer, "HD Graphics 530") || strstr(renderer, "Kaby Lake GT2")) { + GG.device |= GPU_DEVICE_INTEL_UHD; + } + } + else if ((strstr(renderer, "Mesa DRI R")) || + (strstr(renderer, "Radeon") && strstr(vendor, "X.Org")) || + (strstr(renderer, "Gallium ") && strstr(renderer, " on ATI ")) || + (strstr(renderer, "Gallium ") && strstr(renderer, " on AMD "))) { + GG.device = GPU_DEVICE_ATI; + GG.driver = GPU_DRIVER_OPENSOURCE; + } + else if (strstr(renderer, "Nouveau") || strstr(vendor, "nouveau")) { + GG.device = GPU_DEVICE_NVIDIA; + GG.driver = GPU_DRIVER_OPENSOURCE; + } + else if (strstr(vendor, "Mesa")) { + GG.device = GPU_DEVICE_SOFTWARE; + GG.driver = GPU_DRIVER_SOFTWARE; + } + else if (strstr(vendor, "Microsoft")) { + GG.device = GPU_DEVICE_SOFTWARE; + GG.driver = GPU_DRIVER_SOFTWARE; + } + else if (strstr(renderer, "Apple Software Renderer")) { + GG.device = GPU_DEVICE_SOFTWARE; + GG.driver = GPU_DRIVER_SOFTWARE; + } + else if (strstr(renderer, "llvmpipe")) { + GG.device = GPU_DEVICE_SOFTWARE; + GG.driver = GPU_DRIVER_SOFTWARE; + } + else { + printf("Warning: Could not find a matching GPU name. Things may not behave as expected.\n"); + printf("Detected OpenGL configuration:\n"); + printf("Vendor: %s\n", vendor); + printf("Renderer: %s\n", renderer); + GG.device = GPU_DEVICE_ANY; + GG.driver = GPU_DRIVER_ANY; + } #ifdef _WIN32 - GG.os = GPU_OS_WIN; + GG.os = GPU_OS_WIN; #elif defined(__APPLE__) - GG.os = GPU_OS_MAC; + GG.os = GPU_OS_MAC; #else - GG.os = GPU_OS_UNIX; + GG.os = GPU_OS_UNIX; #endif - gpu_detect_mip_render_workaround(); - - if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) { - printf("\n"); - printf("GPU: Bypassing workaround detection.\n"); - printf("GPU: OpenGL identification strings\n"); - printf("GPU: vendor: %s\n", vendor); - printf("GPU: renderer: %s\n", renderer); - printf("GPU: version: %s\n\n", version); - GG.mip_render_workaround = true; - GG.depth_blitting_workaround = true; - GG.unused_fb_slot_workaround = true; - } - - /* df/dy calculation factors, those are dependent on driver */ - if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) { - GG.dfdyfactors[0] = 1.0; - GG.dfdyfactors[1] = -1.0; - } - else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) && - (strstr(version, "4.0.0 - Build 10.18.10.3308") || - strstr(version, "4.0.0 - Build 9.18.10.3186") || - strstr(version, "4.0.0 - Build 9.18.10.3165") || - strstr(version, "3.1.0 - Build 9.17.10.3347") || - strstr(version, "3.1.0 - Build 9.17.10.4101") || - strstr(version, "3.3.0 - Build 8.15.10.2618"))) - { - GG.dfdyfactors[0] = -1.0; - GG.dfdyfactors[1] = 1.0; - } - else { - GG.dfdyfactors[0] = 1.0; - GG.dfdyfactors[1] = 1.0; - } - - - GPU_invalid_tex_init(); + gpu_detect_mip_render_workaround(); + + if (G.debug & G_DEBUG_GPU_FORCE_WORKAROUNDS) { + printf("\n"); + printf("GPU: Bypassing workaround detection.\n"); + printf("GPU: OpenGL identification strings\n"); + printf("GPU: vendor: %s\n", vendor); + printf("GPU: renderer: %s\n", renderer); + printf("GPU: version: %s\n\n", version); + GG.mip_render_workaround = true; + GG.depth_blitting_workaround = true; + GG.unused_fb_slot_workaround = true; + } + + /* df/dy calculation factors, those are dependent on driver */ + if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) { + GG.dfdyfactors[0] = 1.0; + GG.dfdyfactors[1] = -1.0; + } + else if ((GG.device == GPU_DEVICE_INTEL) && (GG.os == GPU_OS_WIN) && + (strstr(version, "4.0.0 - Build 10.18.10.3308") || + strstr(version, "4.0.0 - Build 9.18.10.3186") || + strstr(version, "4.0.0 - Build 9.18.10.3165") || + strstr(version, "3.1.0 - Build 9.17.10.3347") || + strstr(version, "3.1.0 - Build 9.17.10.4101") || + strstr(version, "3.3.0 - Build 8.15.10.2618"))) { + GG.dfdyfactors[0] = -1.0; + GG.dfdyfactors[1] = 1.0; + } + else { + GG.dfdyfactors[0] = 1.0; + GG.dfdyfactors[1] = 1.0; + } + + GPU_invalid_tex_init(); } void gpu_extensions_exit(void) { - GPU_invalid_tex_free(); + GPU_invalid_tex_free(); } bool GPU_mem_stats_supported(void) { - return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM); + return (GLEW_NVX_gpu_memory_info || GLEW_ATI_meminfo) && (G.debug & G_DEBUG_GPU_MEM); } - void GPU_mem_stats_get(int *totalmem, int *freemem) { - /* TODO(merwin): use Apple's platform API to get this info */ - - if (GLEW_NVX_gpu_memory_info) { - /* returned value in Kb */ - glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem); - - glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem); - } - else if (GLEW_ATI_meminfo) { - int stats[4]; - - glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats); - *freemem = stats[0]; - *totalmem = 0; - } - else { - *totalmem = 0; - *freemem = 0; - } + /* TODO(merwin): use Apple's platform API to get this info */ + + if (GLEW_NVX_gpu_memory_info) { + /* returned value in Kb */ + glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem); + + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem); + } + else if (GLEW_ATI_meminfo) { + int stats[4]; + + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats); + *freemem = stats[0]; + *totalmem = 0; + } + else { + *totalmem = 0; + *freemem = 0; + } } diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index c5ed3f8e01d..bd4572cc643 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -27,7 +27,6 @@ #include "BLI_utildefines.h" #include "BLI_math_base.h" - #include "GPU_batch.h" #include "GPU_draw.h" #include "GPU_extensions.h" @@ -40,18 +39,18 @@ #include "gpu_context_private.h" typedef enum { - GPU_FB_DEPTH_ATTACHMENT = 0, - GPU_FB_DEPTH_STENCIL_ATTACHMENT, - GPU_FB_COLOR_ATTACHMENT0, - GPU_FB_COLOR_ATTACHMENT1, - GPU_FB_COLOR_ATTACHMENT2, - GPU_FB_COLOR_ATTACHMENT3, - GPU_FB_COLOR_ATTACHMENT4, - /* Number of maximum output slots. - * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */ - /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to - * the maximum number of COLOR attachments specified by glDrawBuffers. */ - GPU_FB_MAX_ATTACHEMENT, + GPU_FB_DEPTH_ATTACHMENT = 0, + GPU_FB_DEPTH_STENCIL_ATTACHMENT, + GPU_FB_COLOR_ATTACHMENT0, + GPU_FB_COLOR_ATTACHMENT1, + GPU_FB_COLOR_ATTACHMENT2, + GPU_FB_COLOR_ATTACHMENT3, + GPU_FB_COLOR_ATTACHMENT4, + /* Number of maximum output slots. + * We support 5 outputs for now (usually we wouldn't need more to preserve fill rate). */ + /* Keep in mind that GL max is GL_MAX_DRAW_BUFFERS and is at least 8, corresponding to + * the maximum number of COLOR attachments specified by glDrawBuffers. */ + GPU_FB_MAX_ATTACHEMENT, } GPUAttachmentType; #define GPU_FB_MAX_COLOR_ATTACHMENT (GPU_FB_MAX_ATTACHEMENT - GPU_FB_COLOR_ATTACHMENT0) @@ -62,102 +61,100 @@ typedef enum { #define GPU_FB_ATTACHEMENT_SET_DIRTY(flag, type) (flag |= (1 << type)) struct GPUFrameBuffer { - GPUContext *ctx; - GLuint object; - GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT]; - uint16_t dirty_flag; - int width, height; - bool multisample; - /* TODO Check that we always use the right context when binding - * (FBOs are not shared across ogl contexts). */ - // void *ctx; + GPUContext *ctx; + GLuint object; + GPUAttachment attachments[GPU_FB_MAX_ATTACHEMENT]; + uint16_t dirty_flag; + int width, height; + bool multisample; + /* TODO Check that we always use the right context when binding + * (FBOs are not shared across ogl contexts). */ + // void *ctx; }; static GLenum convert_attachment_type_to_gl(GPUAttachmentType type) { - static const GLenum table[] = { - [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT, - [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT, - [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0, - [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1, - [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2, - [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3, - [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4, - }; - return table[type]; + static const GLenum table[] = { + [GPU_FB_DEPTH_ATTACHMENT] = GL_DEPTH_ATTACHMENT, + [GPU_FB_DEPTH_STENCIL_ATTACHMENT] = GL_DEPTH_STENCIL_ATTACHMENT, + [GPU_FB_COLOR_ATTACHMENT0] = GL_COLOR_ATTACHMENT0, + [GPU_FB_COLOR_ATTACHMENT1] = GL_COLOR_ATTACHMENT1, + [GPU_FB_COLOR_ATTACHMENT2] = GL_COLOR_ATTACHMENT2, + [GPU_FB_COLOR_ATTACHMENT3] = GL_COLOR_ATTACHMENT3, + [GPU_FB_COLOR_ATTACHMENT4] = GL_COLOR_ATTACHMENT4, + }; + return table[type]; } static GPUAttachmentType attachment_type_from_tex(GPUTexture *tex, int slot) { - switch (GPU_texture_format(tex)) { - case GPU_DEPTH_COMPONENT32F: - case GPU_DEPTH_COMPONENT24: - case GPU_DEPTH_COMPONENT16: - return GPU_FB_DEPTH_ATTACHMENT; - case GPU_DEPTH24_STENCIL8: - case GPU_DEPTH32F_STENCIL8: - return GPU_FB_DEPTH_STENCIL_ATTACHMENT; - default: - return GPU_FB_COLOR_ATTACHMENT0 + slot; - } + switch (GPU_texture_format(tex)) { + case GPU_DEPTH_COMPONENT32F: + case GPU_DEPTH_COMPONENT24: + case GPU_DEPTH_COMPONENT16: + return GPU_FB_DEPTH_ATTACHMENT; + case GPU_DEPTH24_STENCIL8: + case GPU_DEPTH32F_STENCIL8: + return GPU_FB_DEPTH_STENCIL_ATTACHMENT; + default: + return GPU_FB_COLOR_ATTACHMENT0 + slot; + } } static GLenum convert_buffer_bits_to_gl(eGPUFrameBufferBits bits) { - GLbitfield mask = 0; - mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0; - mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0; - mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0; - return mask; + GLbitfield mask = 0; + mask |= (bits & GPU_DEPTH_BIT) ? GL_DEPTH_BUFFER_BIT : 0; + mask |= (bits & GPU_STENCIL_BIT) ? GL_STENCIL_BUFFER_BIT : 0; + mask |= (bits & GPU_COLOR_BIT) ? GL_COLOR_BUFFER_BIT : 0; + return mask; } static GPUTexture *framebuffer_get_depth_tex(GPUFrameBuffer *fb) { - if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex) - return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex; - else - return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex; + if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex) + return fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex; + else + return fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex; } static GPUTexture *framebuffer_get_color_tex(GPUFrameBuffer *fb, int slot) { - return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; + return fb->attachments[GPU_FB_COLOR_ATTACHMENT0 + slot].tex; } static void gpu_print_framebuffer_error(GLenum status, char err_out[256]) { - const char *format = "GPUFrameBuffer: framebuffer status %s\n"; - const char *err = "unknown"; + const char *format = "GPUFrameBuffer: framebuffer status %s\n"; + const char *err = "unknown"; #define format_status(X) \ - case GL_FRAMEBUFFER_##X: err = "GL_FRAMEBUFFER_"#X; \ - break; - - switch (status) { - /* success */ - format_status(COMPLETE) - /* errors shared by OpenGL desktop & ES */ - format_status(INCOMPLETE_ATTACHMENT) - format_status(INCOMPLETE_MISSING_ATTACHMENT) - format_status(UNSUPPORTED) + case GL_FRAMEBUFFER_##X: \ + err = "GL_FRAMEBUFFER_" #X; \ + break; + + switch (status) { + /* success */ + format_status(COMPLETE) + /* errors shared by OpenGL desktop & ES */ + format_status(INCOMPLETE_ATTACHMENT) format_status(INCOMPLETE_MISSING_ATTACHMENT) + format_status(UNSUPPORTED) #if 0 /* for OpenGL ES only */ - format_status(INCOMPLETE_DIMENSIONS) + format_status(INCOMPLETE_DIMENSIONS) #else /* for desktop GL only */ - format_status(INCOMPLETE_DRAW_BUFFER) - format_status(INCOMPLETE_READ_BUFFER) - format_status(INCOMPLETE_MULTISAMPLE) - format_status(UNDEFINED) + format_status(INCOMPLETE_DRAW_BUFFER) format_status(INCOMPLETE_READ_BUFFER) + format_status(INCOMPLETE_MULTISAMPLE) format_status(UNDEFINED) #endif - } + } #undef format_status - if (err_out) { - BLI_snprintf(err_out, 256, format, err); - } - else { - fprintf(stderr, format, err); - } + if (err_out) { + BLI_snprintf(err_out, 256, format, err); + } + else { + fprintf(stderr, format, err); + } } void gpu_framebuffer_module_init(void) @@ -170,133 +167,137 @@ void gpu_framebuffer_module_exit(void) GPUFrameBuffer *GPU_framebuffer_active_get(void) { - GPUContext *ctx = GPU_context_active_get(); - if (ctx) { - return gpu_context_active_framebuffer_get(ctx); - } - else { - return 0; - } + GPUContext *ctx = GPU_context_active_get(); + if (ctx) { + return gpu_context_active_framebuffer_get(ctx); + } + else { + return 0; + } } static void gpu_framebuffer_current_set(GPUFrameBuffer *fb) { - GPUContext *ctx = GPU_context_active_get(); - if (ctx) { - gpu_context_active_framebuffer_set(ctx, fb); - } + GPUContext *ctx = GPU_context_active_get(); + if (ctx) { + gpu_context_active_framebuffer_set(ctx, fb); + } } /* GPUFrameBuffer */ GPUFrameBuffer *GPU_framebuffer_create(void) { - /* We generate the FB object later at first use in order to - * create the framebuffer in the right opengl context. */ - return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); + /* We generate the FB object later at first use in order to + * create the framebuffer in the right opengl context. */ + return MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer"); } static void gpu_framebuffer_init(GPUFrameBuffer *fb) { - fb->object = GPU_fbo_alloc(); - fb->ctx = GPU_context_active_get(); - gpu_context_add_framebuffer(fb->ctx, fb); + fb->object = GPU_fbo_alloc(); + fb->ctx = GPU_context_active_get(); + gpu_context_add_framebuffer(fb->ctx, fb); } void GPU_framebuffer_free(GPUFrameBuffer *fb) { - for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) { - if (fb->attachments[type].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex); - } - } + for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; type++) { + if (fb->attachments[type].tex != NULL) { + GPU_framebuffer_texture_detach(fb, fb->attachments[type].tex); + } + } - if (fb->object != 0) { - /* This restores the framebuffer if it was bound */ - GPU_fbo_free(fb->object, fb->ctx); - gpu_context_remove_framebuffer(fb->ctx, fb); - } + if (fb->object != 0) { + /* This restores the framebuffer if it was bound */ + GPU_fbo_free(fb->object, fb->ctx); + gpu_context_remove_framebuffer(fb->ctx, fb); + } - if (GPU_framebuffer_active_get() == fb) { - gpu_framebuffer_current_set(NULL); - } + if (GPU_framebuffer_active_get() == fb) { + gpu_framebuffer_current_set(NULL); + } - MEM_freeN(fb); + MEM_freeN(fb); } /* ---------- Attach ----------- */ -static void gpu_framebuffer_texture_attach_ex(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) +static void gpu_framebuffer_texture_attach_ex( + GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) { - if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) { - fprintf(stderr, - "Attaching to index %d framebuffer slot unsupported. " - "Use at most %d\n", slot, GPU_FB_MAX_COLOR_ATTACHMENT); - return; - } + if (slot >= GPU_FB_MAX_COLOR_ATTACHMENT) { + fprintf(stderr, + "Attaching to index %d framebuffer slot unsupported. " + "Use at most %d\n", + slot, + GPU_FB_MAX_COLOR_ATTACHMENT); + return; + } - GPUAttachmentType type = attachment_type_from_tex(tex, slot); - GPUAttachment *attachment = &fb->attachments[type]; + GPUAttachmentType type = attachment_type_from_tex(tex, slot); + GPUAttachment *attachment = &fb->attachments[type]; - if ((attachment->tex == tex) && - (attachment->mip == mip) && - (attachment->layer == layer)) - { - return; /* Exact same texture already bound here. */ - } - else if (attachment->tex != NULL) { - GPU_framebuffer_texture_detach(fb, attachment->tex); - } + if ((attachment->tex == tex) && (attachment->mip == mip) && (attachment->layer == layer)) { + return; /* Exact same texture already bound here. */ + } + else if (attachment->tex != NULL) { + GPU_framebuffer_texture_detach(fb, attachment->tex); + } - if (attachment->tex == NULL) { - GPU_texture_attach_framebuffer(tex, fb, type); - } + if (attachment->tex == NULL) { + GPU_texture_attach_framebuffer(tex, fb, type); + } - attachment->tex = tex; - attachment->mip = mip; - attachment->layer = layer; - GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); + attachment->tex = tex; + attachment->mip = mip; + attachment->layer = layer; + GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); } void GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int mip) { - gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip); + gpu_framebuffer_texture_attach_ex(fb, tex, slot, -1, mip); } -void GPU_framebuffer_texture_layer_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) +void GPU_framebuffer_texture_layer_attach( + GPUFrameBuffer *fb, GPUTexture *tex, int slot, int layer, int mip) { - /* NOTE: We could support 1D ARRAY texture. */ - BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY); - gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip); + /* NOTE: We could support 1D ARRAY texture. */ + BLI_assert(GPU_texture_target(tex) == GL_TEXTURE_2D_ARRAY); + gpu_framebuffer_texture_attach_ex(fb, tex, slot, layer, mip); } -void GPU_framebuffer_texture_cubeface_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip) +void GPU_framebuffer_texture_cubeface_attach( + GPUFrameBuffer *fb, GPUTexture *tex, int slot, int face, int mip) { - BLI_assert(GPU_texture_cube(tex)); - gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip); + BLI_assert(GPU_texture_cube(tex)); + gpu_framebuffer_texture_attach_ex(fb, tex, slot, face, mip); } /* ---------- Detach ----------- */ void GPU_framebuffer_texture_detach_slot(GPUFrameBuffer *fb, GPUTexture *tex, int type) { - GPUAttachment *attachment = &fb->attachments[type]; + GPUAttachment *attachment = &fb->attachments[type]; - if (attachment->tex != tex) { - fprintf(stderr, - "Warning, attempting to detach Texture %p from framebuffer %p " - "but texture is not attached.\n", tex, fb); - return; - } + if (attachment->tex != tex) { + fprintf(stderr, + "Warning, attempting to detach Texture %p from framebuffer %p " + "but texture is not attached.\n", + tex, + fb); + return; + } - attachment->tex = NULL; - GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); + attachment->tex = NULL; + GPU_FB_ATTACHEMENT_SET_DIRTY(fb->dirty_flag, type); } void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) { - GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb); - GPU_framebuffer_texture_detach_slot(fb, tex, type); + GPUAttachmentType type = GPU_texture_detach_framebuffer(tex, fb); + GPU_framebuffer_texture_detach_slot(fb, tex, type); } /* ---------- Config (Attach & Detach) ----------- */ @@ -309,105 +310,109 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex) */ void GPU_framebuffer_config_array(GPUFrameBuffer *fb, const GPUAttachment *config, int config_len) { - if (config[0].tex) { - BLI_assert(GPU_texture_depth(config[0].tex)); - gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip); - } - else if (config[0].mip == -1) { - /* Leave texture attached */ - } - else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex); - } - else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) { - GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex); - } - - int slot = 0; - for (int i = 1; i < config_len; ++i, ++slot) { - if (config[i].tex != NULL) { - BLI_assert(GPU_texture_depth(config[i].tex) == false); - gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip); - } - else if (config[i].mip != -1) { - GPUTexture *tex = framebuffer_get_color_tex(fb, slot); - if (tex != NULL) { - GPU_framebuffer_texture_detach(fb, tex); - } - } - } + if (config[0].tex) { + BLI_assert(GPU_texture_depth(config[0].tex)); + gpu_framebuffer_texture_attach_ex(fb, config[0].tex, 0, config[0].layer, config[0].mip); + } + else if (config[0].mip == -1) { + /* Leave texture attached */ + } + else if (fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex != NULL) { + GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_ATTACHMENT].tex); + } + else if (fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex != NULL) { + GPU_framebuffer_texture_detach(fb, fb->attachments[GPU_FB_DEPTH_STENCIL_ATTACHMENT].tex); + } + + int slot = 0; + for (int i = 1; i < config_len; ++i, ++slot) { + if (config[i].tex != NULL) { + BLI_assert(GPU_texture_depth(config[i].tex) == false); + gpu_framebuffer_texture_attach_ex(fb, config[i].tex, slot, config[i].layer, config[i].mip); + } + else if (config[i].mip != -1) { + GPUTexture *tex = framebuffer_get_color_tex(fb, slot); + if (tex != NULL) { + GPU_framebuffer_texture_detach(fb, tex); + } + } + } } /* ---------- Bind / Restore ----------- */ static void gpu_framebuffer_attachment_attach(GPUAttachment *attach, GPUAttachmentType attach_type) { - int tex_bind = GPU_texture_opengl_bindcode(attach->tex); - GLenum gl_attachment = convert_attachment_type_to_gl(attach_type); + int tex_bind = GPU_texture_opengl_bindcode(attach->tex); + GLenum gl_attachment = convert_attachment_type_to_gl(attach_type); - if (attach->layer > -1) { - if (GPU_texture_cube(attach->tex)) { - glFramebufferTexture2D( - GL_FRAMEBUFFER, gl_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer, - tex_bind, attach->mip); - } - else { - glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer); - } - } - else { - glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip); - } + if (attach->layer > -1) { + if (GPU_texture_cube(attach->tex)) { + glFramebufferTexture2D(GL_FRAMEBUFFER, + gl_attachment, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + attach->layer, + tex_bind, + attach->mip); + } + else { + glFramebufferTextureLayer( + GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip, attach->layer); + } + } + else { + glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, tex_bind, attach->mip); + } } -static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), GPUAttachmentType attach_type) +static void gpu_framebuffer_attachment_detach(GPUAttachment *UNUSED(attachment), + GPUAttachmentType attach_type) { - GLenum gl_attachment = convert_attachment_type_to_gl(attach_type); - glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0); + GLenum gl_attachment = convert_attachment_type_to_gl(attach_type); + glFramebufferTexture(GL_FRAMEBUFFER, gl_attachment, 0, 0); } static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) { - GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; - int numslots = 0; - - BLI_assert(GPU_framebuffer_active_get() == fb); - - /* Update attachments */ - for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { - - if (type >= GPU_FB_COLOR_ATTACHMENT0) { - if (fb->attachments[type].tex) { - gl_attachments[numslots] = convert_attachment_type_to_gl(type); - } - else { - gl_attachments[numslots] = GL_NONE; - } - numslots++; - } - - if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) { - continue; - } - else if (fb->attachments[type].tex != NULL) { - gpu_framebuffer_attachment_attach(&fb->attachments[type], type); - - fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0); - fb->width = GPU_texture_width(fb->attachments[type].tex); - fb->height = GPU_texture_height(fb->attachments[type].tex); - } - else { - gpu_framebuffer_attachment_detach(&fb->attachments[type], type); - } - } - fb->dirty_flag = 0; - - /* Update draw buffers (color targets) - * This state is saved in the FBO */ - if (numslots) - glDrawBuffers(numslots, gl_attachments); - else - glDrawBuffer(GL_NONE); + GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; + int numslots = 0; + + BLI_assert(GPU_framebuffer_active_get() == fb); + + /* Update attachments */ + for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { + + if (type >= GPU_FB_COLOR_ATTACHMENT0) { + if (fb->attachments[type].tex) { + gl_attachments[numslots] = convert_attachment_type_to_gl(type); + } + else { + gl_attachments[numslots] = GL_NONE; + } + numslots++; + } + + if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type) == false) { + continue; + } + else if (fb->attachments[type].tex != NULL) { + gpu_framebuffer_attachment_attach(&fb->attachments[type], type); + + fb->multisample = (GPU_texture_samples(fb->attachments[type].tex) > 0); + fb->width = GPU_texture_width(fb->attachments[type].tex); + fb->height = GPU_texture_height(fb->attachments[type].tex); + } + else { + gpu_framebuffer_attachment_detach(&fb->attachments[type], type); + } + } + fb->dirty_flag = 0; + + /* Update draw buffers (color targets) + * This state is saved in the FBO */ + if (numslots) + glDrawBuffers(numslots, gl_attachments); + else + glDrawBuffer(GL_NONE); } /** @@ -417,556 +422,564 @@ static void gpu_framebuffer_update_attachments(GPUFrameBuffer *fb) */ static void gpu_framebuffer_update_attachments_and_fill_empty_slots(GPUFrameBuffer *fb) { - GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; - int dummy_tex = 0; - - BLI_assert(GPU_framebuffer_active_get() == fb); - - /* Update attachments */ - for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) { - GPUTexture *tex = fb->attachments[type].tex; - - if (type >= GPU_FB_COLOR_ATTACHMENT0) { - int slot = type - GPU_FB_COLOR_ATTACHMENT0; - if (tex != NULL || (dummy_tex != 0)) { - gl_attachments[slot] = convert_attachment_type_to_gl(type); - - if (dummy_tex == 0) { - dummy_tex = GPU_texture_opengl_bindcode(tex); - } - } - else { - gl_attachments[slot] = GL_NONE; - } - } - else { - dummy_tex = 0; - } - - if ((dummy_tex != 0) && tex == NULL) { - /* Fill empty slot */ - glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0); - } - else if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) { - if (tex != NULL) { - gpu_framebuffer_attachment_attach(&fb->attachments[type], type); - - fb->multisample = (GPU_texture_samples(tex) > 0); - fb->width = GPU_texture_width(tex); - fb->height = GPU_texture_height(tex); - } - else { - gpu_framebuffer_attachment_detach(&fb->attachments[type], type); - } - } - } - fb->dirty_flag = 0; - - /* Update draw buffers (color targets) - * This state is saved in the FBO */ - glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments); + GLenum gl_attachments[GPU_FB_MAX_COLOR_ATTACHMENT]; + int dummy_tex = 0; + + BLI_assert(GPU_framebuffer_active_get() == fb); + + /* Update attachments */ + for (GPUAttachmentType type = GPU_FB_MAX_ATTACHEMENT; type--;) { + GPUTexture *tex = fb->attachments[type].tex; + + if (type >= GPU_FB_COLOR_ATTACHMENT0) { + int slot = type - GPU_FB_COLOR_ATTACHMENT0; + if (tex != NULL || (dummy_tex != 0)) { + gl_attachments[slot] = convert_attachment_type_to_gl(type); + + if (dummy_tex == 0) { + dummy_tex = GPU_texture_opengl_bindcode(tex); + } + } + else { + gl_attachments[slot] = GL_NONE; + } + } + else { + dummy_tex = 0; + } + + if ((dummy_tex != 0) && tex == NULL) { + /* Fill empty slot */ + glFramebufferTexture(GL_FRAMEBUFFER, convert_attachment_type_to_gl(type), dummy_tex, 0); + } + else if (GPU_FB_ATTACHEMENT_IS_DIRTY(fb->dirty_flag, type)) { + if (tex != NULL) { + gpu_framebuffer_attachment_attach(&fb->attachments[type], type); + + fb->multisample = (GPU_texture_samples(tex) > 0); + fb->width = GPU_texture_width(tex); + fb->height = GPU_texture_height(tex); + } + else { + gpu_framebuffer_attachment_detach(&fb->attachments[type], type); + } + } + } + fb->dirty_flag = 0; + + /* Update draw buffers (color targets) + * This state is saved in the FBO */ + glDrawBuffers(GPU_FB_MAX_COLOR_ATTACHMENT, gl_attachments); } - #define FRAMEBUFFER_STACK_DEPTH 16 static struct { - GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH]; - uint top; + GPUFrameBuffer *framebuffers[FRAMEBUFFER_STACK_DEPTH]; + uint top; } FrameBufferStack = {{0}}; static void gpuPushFrameBuffer(GPUFrameBuffer *fbo) { - BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH); - FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo; - FrameBufferStack.top++; + BLI_assert(FrameBufferStack.top < FRAMEBUFFER_STACK_DEPTH); + FrameBufferStack.framebuffers[FrameBufferStack.top] = fbo; + FrameBufferStack.top++; } static GPUFrameBuffer *gpuPopFrameBuffer(void) { - BLI_assert(FrameBufferStack.top > 0); - FrameBufferStack.top--; - return FrameBufferStack.framebuffers[FrameBufferStack.top]; + BLI_assert(FrameBufferStack.top > 0); + FrameBufferStack.top--; + return FrameBufferStack.framebuffers[FrameBufferStack.top]; } #undef FRAMEBUFFER_STACK_DEPTH - void GPU_framebuffer_bind(GPUFrameBuffer *fb) { - if (fb->object == 0) - gpu_framebuffer_init(fb); + if (fb->object == 0) + gpu_framebuffer_init(fb); - if (GPU_framebuffer_active_get() != fb) - glBindFramebuffer(GL_FRAMEBUFFER, fb->object); + if (GPU_framebuffer_active_get() != fb) + glBindFramebuffer(GL_FRAMEBUFFER, fb->object); - gpu_framebuffer_current_set(fb); + gpu_framebuffer_current_set(fb); - if (fb->dirty_flag != 0) { - if (GPU_unused_fb_slot_workaround()) { - /* XXX: Please AMD, fix this. */ - gpu_framebuffer_update_attachments_and_fill_empty_slots(fb); - } - else { - gpu_framebuffer_update_attachments(fb); - } - } + if (fb->dirty_flag != 0) { + if (GPU_unused_fb_slot_workaround()) { + /* XXX: Please AMD, fix this. */ + gpu_framebuffer_update_attachments_and_fill_empty_slots(fb); + } + else { + gpu_framebuffer_update_attachments(fb); + } + } - /* TODO manually check for errors? */ + /* TODO manually check for errors? */ #if 0 - char err_out[256]; - if (!GPU_framebuffer_check_valid(fb, err_out)) { - printf("Invalid %s\n", err_out); - } + char err_out[256]; + if (!GPU_framebuffer_check_valid(fb, err_out)) { + printf("Invalid %s\n", err_out); + } #endif - if (fb->multisample) - glEnable(GL_MULTISAMPLE); + if (fb->multisample) + glEnable(GL_MULTISAMPLE); - glViewport(0, 0, fb->width, fb->height); + glViewport(0, 0, fb->width, fb->height); } void GPU_framebuffer_restore(void) { - if (GPU_framebuffer_active_get() != NULL) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - gpu_framebuffer_current_set(NULL); - } + if (GPU_framebuffer_active_get() != NULL) { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + gpu_framebuffer_current_set(NULL); + } } bool GPU_framebuffer_bound(GPUFrameBuffer *fb) { - return (fb == GPU_framebuffer_active_get()) && (fb->object != 0); + return (fb == GPU_framebuffer_active_get()) && (fb->object != 0); } bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]) { - if (!GPU_framebuffer_bound(fb)) - GPU_framebuffer_bind(fb); + if (!GPU_framebuffer_bound(fb)) + GPU_framebuffer_bind(fb); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - GPU_framebuffer_restore(); - gpu_print_framebuffer_error(status, err_out); - return false; - } + if (status != GL_FRAMEBUFFER_COMPLETE) { + GPU_framebuffer_restore(); + gpu_print_framebuffer_error(status, err_out); + return false; + } - return true; + return true; } /* ---------- Framebuffer Operations ----------- */ #define CHECK_FRAMEBUFFER_IS_BOUND(_fb) \ - BLI_assert(GPU_framebuffer_bound(_fb)); \ - UNUSED_VARS_NDEBUG(_fb); + BLI_assert(GPU_framebuffer_bound(_fb)); \ + UNUSED_VARS_NDEBUG(_fb); /* Needs to be done after binding. */ void GPU_framebuffer_viewport_set(GPUFrameBuffer *fb, int x, int y, int w, int h) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(fb); - glViewport(x, y, w, h); + glViewport(x, y, w, h); } -void GPU_framebuffer_clear( - GPUFrameBuffer *fb, eGPUFrameBufferBits buffers, - const float clear_col[4], float clear_depth, uint clear_stencil) +void GPU_framebuffer_clear(GPUFrameBuffer *fb, + eGPUFrameBufferBits buffers, + const float clear_col[4], + float clear_depth, + uint clear_stencil) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(fb); - if (buffers & GPU_COLOR_BIT) { - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]); - } - if (buffers & GPU_DEPTH_BIT) { - glDepthMask(GL_TRUE); - glClearDepth(clear_depth); - } - if (buffers & GPU_STENCIL_BIT) { - glStencilMask(0xFF); - glClearStencil(clear_stencil); - } + if (buffers & GPU_COLOR_BIT) { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glClearColor(clear_col[0], clear_col[1], clear_col[2], clear_col[3]); + } + if (buffers & GPU_DEPTH_BIT) { + glDepthMask(GL_TRUE); + glClearDepth(clear_depth); + } + if (buffers & GPU_STENCIL_BIT) { + glStencilMask(0xFF); + glClearStencil(clear_stencil); + } - GLbitfield mask = convert_buffer_bits_to_gl(buffers); - glClear(mask); + GLbitfield mask = convert_buffer_bits_to_gl(buffers); + glClear(mask); } void GPU_framebuffer_read_depth(GPUFrameBuffer *fb, int x, int y, int w, int h, float *data) { - CHECK_FRAMEBUFFER_IS_BOUND(fb); + CHECK_FRAMEBUFFER_IS_BOUND(fb); - GLenum type = GL_DEPTH_COMPONENT; - glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */ - glReadPixels(x, y, w, h, type, GL_FLOAT, data); + GLenum type = GL_DEPTH_COMPONENT; + glReadBuffer(GL_COLOR_ATTACHMENT0); /* This is OK! */ + glReadPixels(x, y, w, h, type, GL_FLOAT, data); } void GPU_framebuffer_read_color( - GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data) -{ - CHECK_FRAMEBUFFER_IS_BOUND(fb); - - GLenum type; - switch (channels) { - case 1: type = GL_RED; break; - case 2: type = GL_RG; break; - case 3: type = GL_RGB; break; - case 4: type = GL_RGBA; break; - default: - BLI_assert(false && "wrong number of read channels"); - return; - } - glReadBuffer(GL_COLOR_ATTACHMENT0 + slot); - glReadPixels(x, y, w, h, type, GL_FLOAT, data); + GPUFrameBuffer *fb, int x, int y, int w, int h, int channels, int slot, float *data) +{ + CHECK_FRAMEBUFFER_IS_BOUND(fb); + + GLenum type; + switch (channels) { + case 1: + type = GL_RED; + break; + case 2: + type = GL_RG; + break; + case 3: + type = GL_RGB; + break; + case 4: + type = GL_RGBA; + break; + default: + BLI_assert(false && "wrong number of read channels"); + return; + } + glReadBuffer(GL_COLOR_ATTACHMENT0 + slot); + glReadPixels(x, y, w, h, type, GL_FLOAT, data); } /* read_slot and write_slot are only used for color buffers. */ -void GPU_framebuffer_blit( - GPUFrameBuffer *fb_read, int read_slot, - GPUFrameBuffer *fb_write, int write_slot, - eGPUFrameBufferBits blit_buffers) -{ - BLI_assert(blit_buffers != 0); - - GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); - - /* Framebuffers must be up to date. This simplify this function. */ - if (fb_read->dirty_flag != 0 || fb_read->object == 0) { - GPU_framebuffer_bind(fb_read); - } - if (fb_write->dirty_flag != 0 || fb_write->object == 0) { - GPU_framebuffer_bind(fb_write); - } - - const bool do_color = (blit_buffers & GPU_COLOR_BIT); - const bool do_depth = (blit_buffers & GPU_DEPTH_BIT); - const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT); - - GPUTexture *read_tex = ( - (do_depth || do_stencil) ? - framebuffer_get_depth_tex(fb_read) : - framebuffer_get_color_tex(fb_read, read_slot)); - GPUTexture *write_tex = ( - (do_depth || do_stencil) ? - framebuffer_get_depth_tex(fb_write) : - framebuffer_get_color_tex(fb_write, read_slot)); - - if (do_depth) { - BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex)); - BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); - } - if (do_stencil) { - BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex)); - BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); - } - if (GPU_texture_samples(write_tex) != 0 || - GPU_texture_samples(read_tex) != 0) - { - /* Can only blit multisample textures to another texture of the same size. */ - BLI_assert((fb_read->width == fb_write->width) && - (fb_read->height == fb_write->height)); - } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object); - - if (do_color) { - glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot); - glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot); - /* XXX we messed with the glDrawBuffer, this will reset the - * glDrawBuffers the next time we bind fb_write. */ - fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER; - } - - GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers); - - glBlitFramebuffer( - 0, 0, fb_read->width, fb_read->height, - 0, 0, fb_write->width, fb_write->height, - mask, GL_NEAREST); - - /* Restore previous framebuffer */ - if (fb_write == prev_fb) { - GPU_framebuffer_bind(fb_write); /* To update drawbuffers */ - } - else if (prev_fb) { - glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object); - gpu_framebuffer_current_set(prev_fb); - } - else { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - gpu_framebuffer_current_set(NULL); - } +void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, + int read_slot, + GPUFrameBuffer *fb_write, + int write_slot, + eGPUFrameBufferBits blit_buffers) +{ + BLI_assert(blit_buffers != 0); + + GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); + + /* Framebuffers must be up to date. This simplify this function. */ + if (fb_read->dirty_flag != 0 || fb_read->object == 0) { + GPU_framebuffer_bind(fb_read); + } + if (fb_write->dirty_flag != 0 || fb_write->object == 0) { + GPU_framebuffer_bind(fb_write); + } + + const bool do_color = (blit_buffers & GPU_COLOR_BIT); + const bool do_depth = (blit_buffers & GPU_DEPTH_BIT); + const bool do_stencil = (blit_buffers & GPU_STENCIL_BIT); + + GPUTexture *read_tex = ((do_depth || do_stencil) ? + framebuffer_get_depth_tex(fb_read) : + framebuffer_get_color_tex(fb_read, read_slot)); + GPUTexture *write_tex = ((do_depth || do_stencil) ? + framebuffer_get_depth_tex(fb_write) : + framebuffer_get_color_tex(fb_write, read_slot)); + + if (do_depth) { + BLI_assert(GPU_texture_depth(read_tex) && GPU_texture_depth(write_tex)); + BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); + } + if (do_stencil) { + BLI_assert(GPU_texture_stencil(read_tex) && GPU_texture_stencil(write_tex)); + BLI_assert(GPU_texture_format(read_tex) == GPU_texture_format(write_tex)); + } + if (GPU_texture_samples(write_tex) != 0 || GPU_texture_samples(read_tex) != 0) { + /* Can only blit multisample textures to another texture of the same size. */ + BLI_assert((fb_read->width == fb_write->width) && (fb_read->height == fb_write->height)); + } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object); + + if (do_color) { + glReadBuffer(GL_COLOR_ATTACHMENT0 + read_slot); + glDrawBuffer(GL_COLOR_ATTACHMENT0 + write_slot); + /* XXX we messed with the glDrawBuffer, this will reset the + * glDrawBuffers the next time we bind fb_write. */ + fb_write->dirty_flag = GPU_FB_DIRTY_DRAWBUFFER; + } + + GLbitfield mask = convert_buffer_bits_to_gl(blit_buffers); + + glBlitFramebuffer(0, + 0, + fb_read->width, + fb_read->height, + 0, + 0, + fb_write->width, + fb_write->height, + mask, + GL_NEAREST); + + /* Restore previous framebuffer */ + if (fb_write == prev_fb) { + GPU_framebuffer_bind(fb_write); /* To update drawbuffers */ + } + else if (prev_fb) { + glBindFramebuffer(GL_FRAMEBUFFER, prev_fb->object); + gpu_framebuffer_current_set(prev_fb); + } + else { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + gpu_framebuffer_current_set(NULL); + } } /** * Use this if you need to custom downsample your texture and use the previous mip level as input. * This function only takes care of the correct texture handling. It execute the callback for each texture level. */ -void GPU_framebuffer_recursive_downsample( - GPUFrameBuffer *fb, int max_lvl, - void (*callback)(void *userData, int level), void *userData) -{ - /* Framebuffer must be up to date and bound. This simplify this function. */ - if (GPU_framebuffer_active_get() != fb || fb->dirty_flag != 0 || fb->object == 0) { - GPU_framebuffer_bind(fb); - } - /* HACK: We make the framebuffer appear not bound in order to - * not trigger any error in GPU_texture_bind(). */ - GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); - gpu_framebuffer_current_set(NULL); - - int levels = floor(log2(max_ii(fb->width, fb->height))); - max_lvl = min_ii(max_lvl, levels); - - int i; - int current_dim[2] = {fb->width, fb->height}; - for (i = 1; i < max_lvl + 1; i++) { - /* calculate next viewport size */ - current_dim[0] = max_ii(current_dim[0] / 2, 1); - current_dim[1] = max_ii(current_dim[1] / 2, 1); - - for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { - if (fb->attachments[type].tex != NULL) { - /* Some Intel HDXXX have issue with rendering to a mipmap that is below - * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case - * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */ - int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1; - /* bind next level for rendering but first restrict fetches only to previous level */ - GPUTexture *tex = fb->attachments[type].tex; - GPU_texture_bind(tex, 0); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl); - GPU_texture_unbind(tex); - /* copy attachment and replace miplevel. */ - GPUAttachment attachment = fb->attachments[type]; - attachment.mip = i; - gpu_framebuffer_attachment_attach(&attachment, type); - } - } - - BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)); - - glViewport(0, 0, current_dim[0], current_dim[1]); - callback(userData, i); - - if (current_dim[0] == 1 && current_dim[1] == 1) - break; - } - - for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { - if (fb->attachments[type].tex != NULL) { - /* reset mipmap level range */ - GPUTexture *tex = fb->attachments[type].tex; - GPU_texture_bind(tex, 0); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0); - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1); - GPU_texture_unbind(tex); - /* Reattach original level */ - /* NOTE: This is not necessary but this makes the FBO config - * remain in sync with the GPUFrameBuffer config. */ - gpu_framebuffer_attachment_attach(&fb->attachments[type], type); - } - } - - gpu_framebuffer_current_set(prev_fb); +void GPU_framebuffer_recursive_downsample(GPUFrameBuffer *fb, + int max_lvl, + void (*callback)(void *userData, int level), + void *userData) +{ + /* Framebuffer must be up to date and bound. This simplify this function. */ + if (GPU_framebuffer_active_get() != fb || fb->dirty_flag != 0 || fb->object == 0) { + GPU_framebuffer_bind(fb); + } + /* HACK: We make the framebuffer appear not bound in order to + * not trigger any error in GPU_texture_bind(). */ + GPUFrameBuffer *prev_fb = GPU_framebuffer_active_get(); + gpu_framebuffer_current_set(NULL); + + int levels = floor(log2(max_ii(fb->width, fb->height))); + max_lvl = min_ii(max_lvl, levels); + + int i; + int current_dim[2] = {fb->width, fb->height}; + for (i = 1; i < max_lvl + 1; i++) { + /* calculate next viewport size */ + current_dim[0] = max_ii(current_dim[0] / 2, 1); + current_dim[1] = max_ii(current_dim[1] / 2, 1); + + for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { + if (fb->attachments[type].tex != NULL) { + /* Some Intel HDXXX have issue with rendering to a mipmap that is below + * the texture GL_TEXTURE_MAX_LEVEL. So even if it not correct, in this case + * we allow GL_TEXTURE_MAX_LEVEL to be one level lower. In practice it does work! */ + int next_lvl = (GPU_mip_render_workaround()) ? i : i - 1; + /* bind next level for rendering but first restrict fetches only to previous level */ + GPUTexture *tex = fb->attachments[type].tex; + GPU_texture_bind(tex, 0); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, i - 1); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, next_lvl); + GPU_texture_unbind(tex); + /* copy attachment and replace miplevel. */ + GPUAttachment attachment = fb->attachments[type]; + attachment.mip = i; + gpu_framebuffer_attachment_attach(&attachment, type); + } + } + + BLI_assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)); + + glViewport(0, 0, current_dim[0], current_dim[1]); + callback(userData, i); + + if (current_dim[0] == 1 && current_dim[1] == 1) + break; + } + + for (GPUAttachmentType type = 0; type < GPU_FB_MAX_ATTACHEMENT; ++type) { + if (fb->attachments[type].tex != NULL) { + /* reset mipmap level range */ + GPUTexture *tex = fb->attachments[type].tex; + GPU_texture_bind(tex, 0); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_BASE_LEVEL, 0); + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, i - 1); + GPU_texture_unbind(tex); + /* Reattach original level */ + /* NOTE: This is not necessary but this makes the FBO config + * remain in sync with the GPUFrameBuffer config. */ + gpu_framebuffer_attachment_attach(&fb->attachments[type], type); + } + } + + gpu_framebuffer_current_set(prev_fb); } /* GPUOffScreen */ struct GPUOffScreen { - GPUFrameBuffer *fb; - GPUTexture *color; - GPUTexture *depth; + GPUFrameBuffer *fb; + GPUTexture *color; + GPUTexture *depth; }; -GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256]) +GPUOffScreen *GPU_offscreen_create( + int width, int height, int samples, bool depth, bool high_bitdepth, char err_out[256]) { - GPUOffScreen *ofs; + GPUOffScreen *ofs; - ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); + ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); - /* Sometimes areas can have 0 height or width and this will - * create a 1D texture which we don't want. */ - height = max_ii(1, height); - width = max_ii(1, width); + /* Sometimes areas can have 0 height or width and this will + * create a 1D texture which we don't want. */ + height = max_ii(1, height); + width = max_ii(1, width); - ofs->color = GPU_texture_create_2d_multisample( - width, height, - (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out); + ofs->color = GPU_texture_create_2d_multisample( + width, height, (high_bitdepth) ? GPU_RGBA16F : GPU_RGBA8, NULL, samples, err_out); - if (depth) { - ofs->depth = GPU_texture_create_2d_multisample(width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out); - } + if (depth) { + ofs->depth = GPU_texture_create_2d_multisample( + width, height, GPU_DEPTH24_STENCIL8, NULL, samples, err_out); + } - if ((depth && !ofs->depth) || !ofs->color) { - GPU_offscreen_free(ofs); - return NULL; - } + if ((depth && !ofs->depth) || !ofs->color) { + GPU_offscreen_free(ofs); + return NULL; + } - gpuPushAttr(GPU_VIEWPORT_BIT); + gpuPushAttr(GPU_VIEWPORT_BIT); - GPU_framebuffer_ensure_config(&ofs->fb, { - GPU_ATTACHMENT_TEXTURE(ofs->depth), - GPU_ATTACHMENT_TEXTURE(ofs->color) - }); + GPU_framebuffer_ensure_config( + &ofs->fb, {GPU_ATTACHMENT_TEXTURE(ofs->depth), GPU_ATTACHMENT_TEXTURE(ofs->color)}); - /* check validity at the very end! */ - if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) { - GPU_offscreen_free(ofs); - gpuPopAttr(); - return NULL; - } + /* check validity at the very end! */ + if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) { + GPU_offscreen_free(ofs); + gpuPopAttr(); + return NULL; + } - GPU_framebuffer_restore(); + GPU_framebuffer_restore(); - gpuPopAttr(); + gpuPopAttr(); - return ofs; + return ofs; } void GPU_offscreen_free(GPUOffScreen *ofs) { - if (ofs->fb) - GPU_framebuffer_free(ofs->fb); - if (ofs->color) - GPU_texture_free(ofs->color); - if (ofs->depth) - GPU_texture_free(ofs->depth); + if (ofs->fb) + GPU_framebuffer_free(ofs->fb); + if (ofs->color) + GPU_texture_free(ofs->color); + if (ofs->depth) + GPU_texture_free(ofs->depth); - MEM_freeN(ofs); + MEM_freeN(ofs); } void GPU_offscreen_bind(GPUOffScreen *ofs, bool save) { - if (save) { - gpuPushAttr(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT); - GPUFrameBuffer *fb = GPU_framebuffer_active_get(); - gpuPushFrameBuffer(fb); - } - glDisable(GL_SCISSOR_TEST); - GPU_framebuffer_bind(ofs->fb); + if (save) { + gpuPushAttr(GPU_SCISSOR_BIT | GPU_VIEWPORT_BIT); + GPUFrameBuffer *fb = GPU_framebuffer_active_get(); + gpuPushFrameBuffer(fb); + } + glDisable(GL_SCISSOR_TEST); + GPU_framebuffer_bind(ofs->fb); } void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore) { - GPUFrameBuffer *fb = NULL; + GPUFrameBuffer *fb = NULL; - if (restore) { - gpuPopAttr(); - fb = gpuPopFrameBuffer(); - } + if (restore) { + gpuPopAttr(); + fb = gpuPopFrameBuffer(); + } - if (fb) { - GPU_framebuffer_bind(fb); - } - else { - GPU_framebuffer_restore(); - } + if (fb) { + GPU_framebuffer_bind(fb); + } + else { + GPU_framebuffer_restore(); + } } void GPU_offscreen_draw_to_screen(GPUOffScreen *ofs, int x, int y) { - const int w = GPU_texture_width(ofs->color); - const int h = GPU_texture_height(ofs->color); + const int w = GPU_texture_width(ofs->color); + const int h = GPU_texture_height(ofs->color); - glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object); - GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); + glBindFramebuffer(GL_READ_FRAMEBUFFER, ofs->fb->object); + GLenum status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); - if (status == GL_FRAMEBUFFER_COMPLETE) { - glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST); - } - else { - gpu_print_framebuffer_error(status, NULL); - } + if (status == GL_FRAMEBUFFER_COMPLETE) { + glBlitFramebuffer(0, 0, w, h, x, y, x + w, y + h, GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + else { + gpu_print_framebuffer_error(status, NULL); + } - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); } void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels) { - const int w = GPU_texture_width(ofs->color); - const int h = GPU_texture_height(ofs->color); - - BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT); - - if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) { - /* For a multi-sample texture, - * we need to create an intermediate buffer to blit to, - * before its copied using 'glReadPixels' */ - GLuint fbo_blit = 0; - GLuint tex_blit = 0; - - /* create texture for new 'fbo_blit' */ - glGenTextures(1, &tex_blit); - glBindTexture(GL_TEXTURE_2D, tex_blit); - glTexImage2D( - GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8, - w, h, 0, GL_RGBA, type, 0); - - /* write into new single-sample buffer */ - glGenFramebuffers(1, &fbo_blit); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit); - glFramebufferTexture2D( - GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, tex_blit, 0); - - GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - if (status != GL_FRAMEBUFFER_COMPLETE) { - goto finally; - } - - /* perform the copy */ - glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); - - /* read the results */ - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit); - glReadPixels(0, 0, w, h, GL_RGBA, type, pixels); - - /* restore the original frame-bufer */ - glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object); - -finally: - /* cleanup */ - glDeleteTextures(1, &tex_blit); - glDeleteFramebuffers(1, &fbo_blit); - } - else { - glReadPixels(0, 0, w, h, GL_RGBA, type, pixels); - } + const int w = GPU_texture_width(ofs->color); + const int h = GPU_texture_height(ofs->color); + + BLI_assert(type == GL_UNSIGNED_BYTE || type == GL_FLOAT); + + if (GPU_texture_target(ofs->color) == GL_TEXTURE_2D_MULTISAMPLE) { + /* For a multi-sample texture, + * we need to create an intermediate buffer to blit to, + * before its copied using 'glReadPixels' */ + GLuint fbo_blit = 0; + GLuint tex_blit = 0; + + /* create texture for new 'fbo_blit' */ + glGenTextures(1, &tex_blit); + glBindTexture(GL_TEXTURE_2D, tex_blit); + glTexImage2D( + GL_TEXTURE_2D, 0, (type == GL_FLOAT) ? GL_RGBA16F : GL_RGBA8, w, h, 0, GL_RGBA, type, 0); + + /* write into new single-sample buffer */ + glGenFramebuffers(1, &fbo_blit); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_blit); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_blit, 0); + + GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + goto finally; + } + + /* perform the copy */ + glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); + + /* read the results */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo_blit); + glReadPixels(0, 0, w, h, GL_RGBA, type, pixels); + + /* restore the original frame-bufer */ + glBindFramebuffer(GL_FRAMEBUFFER, ofs->fb->object); + + finally: + /* cleanup */ + glDeleteTextures(1, &tex_blit); + glDeleteFramebuffers(1, &fbo_blit); + } + else { + glReadPixels(0, 0, w, h, GL_RGBA, type, pixels); + } } int GPU_offscreen_width(const GPUOffScreen *ofs) { - return GPU_texture_width(ofs->color); + return GPU_texture_width(ofs->color); } int GPU_offscreen_height(const GPUOffScreen *ofs) { - return GPU_texture_height(ofs->color); + return GPU_texture_height(ofs->color); } GPUTexture *GPU_offscreen_color_texture(const GPUOffScreen *ofs) { - return ofs->color; + return ofs->color; } /* only to be used by viewport code! */ -void GPU_offscreen_viewport_data_get( - GPUOffScreen *ofs, - GPUFrameBuffer **r_fb, GPUTexture **r_color, GPUTexture **r_depth) +void GPU_offscreen_viewport_data_get(GPUOffScreen *ofs, + GPUFrameBuffer **r_fb, + GPUTexture **r_color, + GPUTexture **r_depth) { - *r_fb = ofs->fb; - *r_color = ofs->color; - *r_depth = ofs->depth; + *r_fb = ofs->fb; + *r_color = ofs->color; + *r_depth = ofs->depth; } void GPU_clear_color(float red, float green, float blue, float alpha) { - glClearColor(red, green, blue, alpha); + glClearColor(red, green, blue, alpha); } void GPU_clear(eGPUFrameBufferBits flags) { - glClear(convert_buffer_bits_to_gl(flags)); + glClear(convert_buffer_bits_to_gl(flags)); } diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index f24aa454560..a1708fffa9c 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -42,33 +42,34 @@ extern void GPU_matrix_bind(const GPUShaderInterface *); extern bool GPU_matrix_dirty_get(void); typedef struct { - /* TODO: organize this struct by frequency of change (run-time) */ - - GPUBatch *batch; - GPUContext *context; - - /* current draw call */ - GLubyte *buffer_data; - uint buffer_offset; - uint buffer_bytes_mapped; - uint vertex_len; - bool strict_vertex_len; - GPUPrimType prim_type; - - GPUVertFormat vertex_format; - - /* current vertex */ - uint vertex_idx; - GLubyte *vertex_data; - uint16_t unassigned_attr_bits; /* which attributes of current vertex have not been given values? */ - - GLuint vbo_id; - GLuint vao_id; - - GLuint bound_program; - const GPUShaderInterface *shader_interface; - GPUAttrBinding attr_binding; - uint16_t prev_enabled_attr_bits; /* <-- only affects this VAO, so we're ok */ + /* TODO: organize this struct by frequency of change (run-time) */ + + GPUBatch *batch; + GPUContext *context; + + /* current draw call */ + GLubyte *buffer_data; + uint buffer_offset; + uint buffer_bytes_mapped; + uint vertex_len; + bool strict_vertex_len; + GPUPrimType prim_type; + + GPUVertFormat vertex_format; + + /* current vertex */ + uint vertex_idx; + GLubyte *vertex_data; + uint16_t + unassigned_attr_bits; /* which attributes of current vertex have not been given values? */ + + GLuint vbo_id; + GLuint vao_id; + + GLuint bound_program; + const GPUShaderInterface *shader_interface; + GPUAttrBinding attr_binding; + uint16_t prev_enabled_attr_bits; /* <-- only affects this VAO, so we're ok */ } Immediate; /* size of internal buffer -- make this adjustable? */ @@ -80,663 +81,674 @@ static Immediate imm; void immInit(void) { #if TRUST_NO_ONE - assert(!initialized); + assert(!initialized); #endif - memset(&imm, 0, sizeof(Immediate)); + memset(&imm, 0, sizeof(Immediate)); - imm.vbo_id = GPU_buf_alloc(); - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); + imm.vbo_id = GPU_buf_alloc(); + glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); + glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); - imm.prim_type = GPU_PRIM_NONE; - imm.strict_vertex_len = true; + imm.prim_type = GPU_PRIM_NONE; + imm.strict_vertex_len = true; - glBindBuffer(GL_ARRAY_BUFFER, 0); - initialized = true; + glBindBuffer(GL_ARRAY_BUFFER, 0); + initialized = true; } void immActivate(void) { #if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */ - assert(imm.vao_id == 0); + assert(initialized); + assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */ + assert(imm.vao_id == 0); #endif - imm.vao_id = GPU_vao_alloc(); - imm.context = GPU_context_active_get(); + imm.vao_id = GPU_vao_alloc(); + imm.context = GPU_context_active_get(); } void immDeactivate(void) { #if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */ - assert(imm.vao_id != 0); + assert(initialized); + assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we're not between a Begin/End pair */ + assert(imm.vao_id != 0); #endif - GPU_vao_free(imm.vao_id, imm.context); - imm.vao_id = 0; - imm.prev_enabled_attr_bits = 0; + GPU_vao_free(imm.vao_id, imm.context); + imm.vao_id = 0; + imm.prev_enabled_attr_bits = 0; } void immDestroy(void) { - GPU_buf_free(imm.vbo_id); - initialized = false; + GPU_buf_free(imm.vbo_id); + initialized = false; } GPUVertFormat *immVertexFormat(void) { - GPU_vertformat_clear(&imm.vertex_format); - return &imm.vertex_format; + GPU_vertformat_clear(&imm.vertex_format); + return &imm.vertex_format; } void immBindProgram(GLuint program, const GPUShaderInterface *shaderface) { #if TRUST_NO_ONE - assert(imm.bound_program == 0); - assert(glIsProgram(program)); + assert(imm.bound_program == 0); + assert(glIsProgram(program)); #endif - imm.bound_program = program; - imm.shader_interface = shaderface; + imm.bound_program = program; + imm.shader_interface = shaderface; - if (!imm.vertex_format.packed) - VertexFormat_pack(&imm.vertex_format); + if (!imm.vertex_format.packed) + VertexFormat_pack(&imm.vertex_format); - glUseProgram(program); - get_attr_locations(&imm.vertex_format, &imm.attr_binding, shaderface); - GPU_matrix_bind(shaderface); + glUseProgram(program); + get_attr_locations(&imm.vertex_format, &imm.attr_binding, shaderface); + GPU_matrix_bind(shaderface); } void immBindBuiltinProgram(eGPUBuiltinShader shader_id) { - GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); - immBindProgram(shader->program, shader->interface); + GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); + immBindProgram(shader->program, shader->interface); } void immUnbindProgram(void) { #if TRUST_NO_ONE - assert(imm.bound_program != 0); + assert(imm.bound_program != 0); #endif #if PROGRAM_NO_OPTI - glUseProgram(0); + glUseProgram(0); #endif - imm.bound_program = 0; + imm.bound_program = 0; } #if TRUST_NO_ONE static bool vertex_count_makes_sense_for_primitive(uint vertex_len, GPUPrimType prim_type) { - /* does vertex_len make sense for this primitive type? */ - if (vertex_len == 0) { - return false; - } - - switch (prim_type) { - case GPU_PRIM_POINTS: - return true; - case GPU_PRIM_LINES: - return vertex_len % 2 == 0; - case GPU_PRIM_LINE_STRIP: - case GPU_PRIM_LINE_LOOP: - return vertex_len >= 2; - case GPU_PRIM_LINE_STRIP_ADJ: - return vertex_len >= 4; - case GPU_PRIM_TRIS: - return vertex_len % 3 == 0; - case GPU_PRIM_TRI_STRIP: - case GPU_PRIM_TRI_FAN: - return vertex_len >= 3; - default: - return false; - } + /* does vertex_len make sense for this primitive type? */ + if (vertex_len == 0) { + return false; + } + + switch (prim_type) { + case GPU_PRIM_POINTS: + return true; + case GPU_PRIM_LINES: + return vertex_len % 2 == 0; + case GPU_PRIM_LINE_STRIP: + case GPU_PRIM_LINE_LOOP: + return vertex_len >= 2; + case GPU_PRIM_LINE_STRIP_ADJ: + return vertex_len >= 4; + case GPU_PRIM_TRIS: + return vertex_len % 3 == 0; + case GPU_PRIM_TRI_STRIP: + case GPU_PRIM_TRI_FAN: + return vertex_len >= 3; + default: + return false; + } } #endif void immBegin(GPUPrimType prim_type, uint vertex_len) { #if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */ - assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); + assert(initialized); + assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */ + assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); #endif - imm.prim_type = prim_type; - imm.vertex_len = vertex_len; - imm.vertex_idx = 0; - imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; + imm.prim_type = prim_type; + imm.vertex_len = vertex_len; + imm.vertex_idx = 0; + imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; - /* how many bytes do we need for this draw call? */ - const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len); + /* how many bytes do we need for this draw call? */ + const uint bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_len); #if TRUST_NO_ONE - assert(bytes_needed <= IMM_BUFFER_SIZE); + assert(bytes_needed <= IMM_BUFFER_SIZE); #endif - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); + glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - /* does the current buffer have enough room? */ - const uint available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset; - /* ensure vertex data is aligned */ - const uint pre_padding = padding(imm.buffer_offset, imm.vertex_format.stride); /* might waste a little space, but it's safe */ - if ((bytes_needed + pre_padding) <= available_bytes) { - imm.buffer_offset += pre_padding; - } - else { - /* orphan this buffer & start with a fresh one */ - /* this method works on all platforms, old & new */ - glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); + /* does the current buffer have enough room? */ + const uint available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset; + /* ensure vertex data is aligned */ + const uint pre_padding = padding( + imm.buffer_offset, imm.vertex_format.stride); /* might waste a little space, but it's safe */ + if ((bytes_needed + pre_padding) <= available_bytes) { + imm.buffer_offset += pre_padding; + } + else { + /* orphan this buffer & start with a fresh one */ + /* this method works on all platforms, old & new */ + glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); - imm.buffer_offset = 0; - } + imm.buffer_offset = 0; + } -/* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ + /* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ - imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed, - GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); + imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, + imm.buffer_offset, + bytes_needed, + GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | + (imm.strict_vertex_len ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); #if TRUST_NO_ONE - assert(imm.buffer_data != NULL); + assert(imm.buffer_data != NULL); #endif - imm.buffer_bytes_mapped = bytes_needed; - imm.vertex_data = imm.buffer_data; + imm.buffer_bytes_mapped = bytes_needed; + imm.vertex_data = imm.buffer_data; } void immBeginAtMost(GPUPrimType prim_type, uint vertex_len) { #if TRUST_NO_ONE - assert(vertex_len > 0); + assert(vertex_len > 0); #endif - imm.strict_vertex_len = false; - immBegin(prim_type, vertex_len); + imm.strict_vertex_len = false; + immBegin(prim_type, vertex_len); } - GPUBatch *immBeginBatch(GPUPrimType prim_type, uint vertex_len) { #if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */ - assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); + assert(initialized); + assert(imm.prim_type == GPU_PRIM_NONE); /* make sure we haven't already begun */ + assert(vertex_count_makes_sense_for_primitive(vertex_len, prim_type)); #endif - imm.prim_type = prim_type; - imm.vertex_len = vertex_len; - imm.vertex_idx = 0; - imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; + imm.prim_type = prim_type; + imm.vertex_len = vertex_len; + imm.vertex_idx = 0; + imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; - GPUVertBuf *verts = GPU_vertbuf_create_with_format(&imm.vertex_format); - GPU_vertbuf_data_alloc(verts, vertex_len); + GPUVertBuf *verts = GPU_vertbuf_create_with_format(&imm.vertex_format); + GPU_vertbuf_data_alloc(verts, vertex_len); - imm.buffer_bytes_mapped = GPU_vertbuf_size_get(verts); - imm.vertex_data = verts->data; + imm.buffer_bytes_mapped = GPU_vertbuf_size_get(verts); + imm.vertex_data = verts->data; - imm.batch = GPU_batch_create_ex(prim_type, verts, NULL, GPU_BATCH_OWNS_VBO); - imm.batch->phase = GPU_BATCH_BUILDING; + imm.batch = GPU_batch_create_ex(prim_type, verts, NULL, GPU_BATCH_OWNS_VBO); + imm.batch->phase = GPU_BATCH_BUILDING; - return imm.batch; + return imm.batch; } GPUBatch *immBeginBatchAtMost(GPUPrimType prim_type, uint vertex_len) { - imm.strict_vertex_len = false; - return immBeginBatch(prim_type, vertex_len); + imm.strict_vertex_len = false; + return immBeginBatch(prim_type, vertex_len); } static void immDrawSetup(void) { - /* set up VAO -- can be done during Begin or End really */ - glBindVertexArray(imm.vao_id); + /* set up VAO -- can be done during Begin or End really */ + glBindVertexArray(imm.vao_id); - /* Enable/Disable vertex attributes as needed. */ - if (imm.attr_binding.enabled_bits != imm.prev_enabled_attr_bits) { - for (uint loc = 0; loc < GPU_VERT_ATTR_MAX_LEN; ++loc) { - bool is_enabled = imm.attr_binding.enabled_bits & (1 << loc); - bool was_enabled = imm.prev_enabled_attr_bits & (1 << loc); + /* Enable/Disable vertex attributes as needed. */ + if (imm.attr_binding.enabled_bits != imm.prev_enabled_attr_bits) { + for (uint loc = 0; loc < GPU_VERT_ATTR_MAX_LEN; ++loc) { + bool is_enabled = imm.attr_binding.enabled_bits & (1 << loc); + bool was_enabled = imm.prev_enabled_attr_bits & (1 << loc); - if (is_enabled && !was_enabled) { - glEnableVertexAttribArray(loc); - } - else if (was_enabled && !is_enabled) { - glDisableVertexAttribArray(loc); - } - } + if (is_enabled && !was_enabled) { + glEnableVertexAttribArray(loc); + } + else if (was_enabled && !is_enabled) { + glDisableVertexAttribArray(loc); + } + } - imm.prev_enabled_attr_bits = imm.attr_binding.enabled_bits; - } + imm.prev_enabled_attr_bits = imm.attr_binding.enabled_bits; + } - const uint stride = imm.vertex_format.stride; + const uint stride = imm.vertex_format.stride; - for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { - const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx]; + for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { + const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx]; - const uint offset = imm.buffer_offset + a->offset; - const GLvoid *pointer = (const GLubyte *)0 + offset; + const uint offset = imm.buffer_offset + a->offset; + const GLvoid *pointer = (const GLubyte *)0 + offset; - const uint loc = read_attr_location(&imm.attr_binding, a_idx); + const uint loc = read_attr_location(&imm.attr_binding, a_idx); - switch (a->fetch_mode) { - case GPU_FETCH_FLOAT: - case GPU_FETCH_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); - break; - case GPU_FETCH_INT_TO_FLOAT_UNIT: - glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer); - break; - case GPU_FETCH_INT: - glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer); - } - } + switch (a->fetch_mode) { + case GPU_FETCH_FLOAT: + case GPU_FETCH_INT_TO_FLOAT: + glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_FALSE, stride, pointer); + break; + case GPU_FETCH_INT_TO_FLOAT_UNIT: + glVertexAttribPointer(loc, a->comp_len, a->gl_comp_type, GL_TRUE, stride, pointer); + break; + case GPU_FETCH_INT: + glVertexAttribIPointer(loc, a->comp_len, a->gl_comp_type, stride, pointer); + } + } - if (GPU_matrix_dirty_get()) { - GPU_matrix_bind(imm.shader_interface); - } + if (GPU_matrix_dirty_get()) { + GPU_matrix_bind(imm.shader_interface); + } } void immEnd(void) { #if TRUST_NO_ONE - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - uint buffer_bytes_used; - if (imm.strict_vertex_len) { + uint buffer_bytes_used; + if (imm.strict_vertex_len) { #if TRUST_NO_ONE - assert(imm.vertex_idx == imm.vertex_len); /* with all vertices defined */ + assert(imm.vertex_idx == imm.vertex_len); /* with all vertices defined */ #endif - buffer_bytes_used = imm.buffer_bytes_mapped; - } - else { + buffer_bytes_used = imm.buffer_bytes_mapped; + } + else { #if TRUST_NO_ONE - assert(imm.vertex_idx <= imm.vertex_len); + assert(imm.vertex_idx <= imm.vertex_len); #endif - if (imm.vertex_idx == imm.vertex_len) { - buffer_bytes_used = imm.buffer_bytes_mapped; - } - else { + if (imm.vertex_idx == imm.vertex_len) { + buffer_bytes_used = imm.buffer_bytes_mapped; + } + else { #if TRUST_NO_ONE - assert(imm.vertex_idx == 0 || vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type)); -#endif - imm.vertex_len = imm.vertex_idx; - buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len); - /* unused buffer bytes are available to the next immBegin */ - } - /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */ - glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); - } - - if (imm.batch) { - if (buffer_bytes_used != imm.buffer_bytes_mapped) { - GPU_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len); - /* TODO: resize only if vertex count is much smaller */ - } - GPU_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface); - imm.batch->phase = GPU_BATCH_READY_TO_DRAW; - imm.batch = NULL; /* don't free, batch belongs to caller */ - } - else { - glUnmapBuffer(GL_ARRAY_BUFFER); - if (imm.vertex_len > 0) { - immDrawSetup(); - glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len); - } - /* These lines are causing crash on startup on some old GPU + drivers. - * They are not required so just comment them. (T55722) */ - // glBindBuffer(GL_ARRAY_BUFFER, 0); - // glBindVertexArray(0); - /* prep for next immBegin */ - imm.buffer_offset += buffer_bytes_used; - } - - /* prep for next immBegin */ - imm.prim_type = GPU_PRIM_NONE; - imm.strict_vertex_len = true; + assert(imm.vertex_idx == 0 || + vertex_count_makes_sense_for_primitive(imm.vertex_idx, imm.prim_type)); +#endif + imm.vertex_len = imm.vertex_idx; + buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_len); + /* unused buffer bytes are available to the next immBegin */ + } + /* tell OpenGL what range was modified so it doesn't copy the whole mapped range */ + glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); + } + + if (imm.batch) { + if (buffer_bytes_used != imm.buffer_bytes_mapped) { + GPU_vertbuf_data_resize(imm.batch->verts[0], imm.vertex_len); + /* TODO: resize only if vertex count is much smaller */ + } + GPU_batch_program_set(imm.batch, imm.bound_program, imm.shader_interface); + imm.batch->phase = GPU_BATCH_READY_TO_DRAW; + imm.batch = NULL; /* don't free, batch belongs to caller */ + } + else { + glUnmapBuffer(GL_ARRAY_BUFFER); + if (imm.vertex_len > 0) { + immDrawSetup(); + glDrawArrays(convert_prim_type_to_gl(imm.prim_type), 0, imm.vertex_len); + } + /* These lines are causing crash on startup on some old GPU + drivers. + * They are not required so just comment them. (T55722) */ + // glBindBuffer(GL_ARRAY_BUFFER, 0); + // glBindVertexArray(0); + /* prep for next immBegin */ + imm.buffer_offset += buffer_bytes_used; + } + + /* prep for next immBegin */ + imm.prim_type = GPU_PRIM_NONE; + imm.strict_vertex_len = true; } static void setAttrValueBit(uint attr_id) { - uint16_t mask = 1 << attr_id; + uint16_t mask = 1 << attr_id; #if TRUST_NO_ONE - assert(imm.unassigned_attr_bits & mask); /* not already set */ + assert(imm.unassigned_attr_bits & mask); /* not already set */ #endif - imm.unassigned_attr_bits &= ~mask; + imm.unassigned_attr_bits &= ~mask; } - /* --- generic attribute functions --- */ void immAttr1f(uint attr_id, float x) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_F32); - assert(attr->comp_len == 1); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_F32); + assert(attr->comp_len == 1); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - float *data = (float *)(imm.vertex_data + attr->offset); -/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ + float *data = (float *)(imm.vertex_data + attr->offset); + /* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ - data[0] = x; + data[0] = x; } void immAttr2f(uint attr_id, float x, float y) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_F32); - assert(attr->comp_len == 2); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_F32); + assert(attr->comp_len == 2); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - float *data = (float *)(imm.vertex_data + attr->offset); -/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ + float *data = (float *)(imm.vertex_data + attr->offset); + /* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ - data[0] = x; - data[1] = y; + data[0] = x; + data[1] = y; } void immAttr3f(uint attr_id, float x, float y, float z) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_F32); - assert(attr->comp_len == 3); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_F32); + assert(attr->comp_len == 3); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - float *data = (float *)(imm.vertex_data + attr->offset); -/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ + float *data = (float *)(imm.vertex_data + attr->offset); + /* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ - data[0] = x; - data[1] = y; - data[2] = z; + data[0] = x; + data[1] = y; + data[2] = z; } void immAttr4f(uint attr_id, float x, float y, float z, float w) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_F32); - assert(attr->comp_len == 4); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_F32); + assert(attr->comp_len == 4); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - float *data = (float *)(imm.vertex_data + attr->offset); -/* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ + float *data = (float *)(imm.vertex_data + attr->offset); + /* printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); */ - data[0] = x; - data[1] = y; - data[2] = z; - data[3] = w; + data[0] = x; + data[1] = y; + data[2] = z; + data[3] = w; } void immAttr1u(uint attr_id, uint x) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_U32); - assert(attr->comp_len == 1); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_U32); + assert(attr->comp_len == 1); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - uint *data = (uint *)(imm.vertex_data + attr->offset); + uint *data = (uint *)(imm.vertex_data + attr->offset); - data[0] = x; + data[0] = x; } void immAttr2i(uint attr_id, int x, int y) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_I32); - assert(attr->comp_len == 2); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_I32); + assert(attr->comp_len == 2); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - int *data = (int *)(imm.vertex_data + attr->offset); + int *data = (int *)(imm.vertex_data + attr->offset); - data[0] = x; - data[1] = y; + data[0] = x; + data[1] = y; } void immAttr2s(uint attr_id, short x, short y) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_I16); - assert(attr->comp_len == 2); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_I16); + assert(attr->comp_len == 2); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - short *data = (short *)(imm.vertex_data + attr->offset); + short *data = (short *)(imm.vertex_data + attr->offset); - data[0] = x; - data[1] = y; + data[0] = x; + data[1] = y; } void immAttr2fv(uint attr_id, const float data[2]) { - immAttr2f(attr_id, data[0], data[1]); + immAttr2f(attr_id, data[0], data[1]); } void immAttr3fv(uint attr_id, const float data[3]) { - immAttr3f(attr_id, data[0], data[1], data[2]); + immAttr3f(attr_id, data[0], data[1], data[2]); } void immAttr4fv(uint attr_id, const float data[4]) { - immAttr4f(attr_id, data[0], data[1], data[2], data[3]); + immAttr4f(attr_id, data[0], data[1], data[2], data[3]); } void immAttr3ub(uint attr_id, uchar r, uchar g, uchar b) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_U8); - assert(attr->comp_len == 3); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_U8); + assert(attr->comp_len == 3); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - GLubyte *data = imm.vertex_data + attr->offset; -/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ + GLubyte *data = imm.vertex_data + attr->offset; + /* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ - data[0] = r; - data[1] = g; - data[2] = b; + data[0] = r; + data[1] = g; + data[2] = b; } void immAttr4ub(uint attr_id, uchar r, uchar g, uchar b, uchar a) { - GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; + GPUVertAttr *attr = &imm.vertex_format.attrs[attr_id]; #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(attr->comp_type == GPU_COMP_U8); - assert(attr->comp_len == 4); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(attr->comp_type == GPU_COMP_U8); + assert(attr->comp_len == 4); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); - GLubyte *data = imm.vertex_data + attr->offset; -/* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ + GLubyte *data = imm.vertex_data + attr->offset; + /* printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); */ - data[0] = r; - data[1] = g; - data[2] = b; - data[3] = a; + data[0] = r; + data[1] = g; + data[2] = b; + data[3] = a; } void immAttr3ubv(uint attr_id, const uchar data[3]) { - immAttr3ub(attr_id, data[0], data[1], data[2]); + immAttr3ub(attr_id, data[0], data[1], data[2]); } void immAttr4ubv(uint attr_id, const uchar data[4]) { - immAttr4ub(attr_id, data[0], data[1], data[2], data[3]); + immAttr4ub(attr_id, data[0], data[1], data[2], data[3]); } void immAttrSkip(uint attr_id) { #if TRUST_NO_ONE - assert(attr_id < imm.vertex_format.attr_len); - assert(imm.vertex_idx < imm.vertex_len); - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(attr_id < imm.vertex_format.attr_len); + assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ #endif - setAttrValueBit(attr_id); + setAttrValueBit(attr_id); } static void immEndVertex(void) /* and move on to the next vertex */ { #if TRUST_NO_ONE - assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ - assert(imm.vertex_idx < imm.vertex_len); + assert(imm.prim_type != GPU_PRIM_NONE); /* make sure we're between a Begin/End pair */ + assert(imm.vertex_idx < imm.vertex_len); #endif - /* Have all attributes been assigned values? - * If not, copy value from previous vertex. */ - if (imm.unassigned_attr_bits) { + /* Have all attributes been assigned values? + * If not, copy value from previous vertex. */ + if (imm.unassigned_attr_bits) { #if TRUST_NO_ONE - assert(imm.vertex_idx > 0); /* first vertex must have all attributes specified */ + assert(imm.vertex_idx > 0); /* first vertex must have all attributes specified */ #endif - for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { - if ((imm.unassigned_attr_bits >> a_idx) & 1) { - const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx]; + for (uint a_idx = 0; a_idx < imm.vertex_format.attr_len; ++a_idx) { + if ((imm.unassigned_attr_bits >> a_idx) & 1) { + const GPUVertAttr *a = &imm.vertex_format.attrs[a_idx]; -/* printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx); */ + /* printf("copying %s from vertex %u to %u\n", a->name, imm.vertex_idx - 1, imm.vertex_idx); */ - GLubyte *data = imm.vertex_data + a->offset; - memcpy(data, data - imm.vertex_format.stride, a->sz); - /* TODO: consolidate copy of adjacent attributes */ - } - } - } + GLubyte *data = imm.vertex_data + a->offset; + memcpy(data, data - imm.vertex_format.stride, a->sz); + /* TODO: consolidate copy of adjacent attributes */ + } + } + } - imm.vertex_idx++; - imm.vertex_data += imm.vertex_format.stride; - imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; + imm.vertex_idx++; + imm.vertex_data += imm.vertex_format.stride; + imm.unassigned_attr_bits = imm.attr_binding.enabled_bits; } void immVertex2f(uint attr_id, float x, float y) { - immAttr2f(attr_id, x, y); - immEndVertex(); + immAttr2f(attr_id, x, y); + immEndVertex(); } void immVertex3f(uint attr_id, float x, float y, float z) { - immAttr3f(attr_id, x, y, z); - immEndVertex(); + immAttr3f(attr_id, x, y, z); + immEndVertex(); } void immVertex4f(uint attr_id, float x, float y, float z, float w) { - immAttr4f(attr_id, x, y, z, w); - immEndVertex(); + immAttr4f(attr_id, x, y, z, w); + immEndVertex(); } void immVertex2i(uint attr_id, int x, int y) { - immAttr2i(attr_id, x, y); - immEndVertex(); + immAttr2i(attr_id, x, y); + immEndVertex(); } void immVertex2s(uint attr_id, short x, short y) { - immAttr2s(attr_id, x, y); - immEndVertex(); + immAttr2s(attr_id, x, y); + immEndVertex(); } void immVertex2fv(uint attr_id, const float data[2]) { - immAttr2f(attr_id, data[0], data[1]); - immEndVertex(); + immAttr2f(attr_id, data[0], data[1]); + immEndVertex(); } void immVertex3fv(uint attr_id, const float data[3]) { - immAttr3f(attr_id, data[0], data[1], data[2]); - immEndVertex(); + immAttr3f(attr_id, data[0], data[1], data[2]); + immEndVertex(); } void immVertex2iv(uint attr_id, const int data[2]) { - immAttr2i(attr_id, data[0], data[1]); - immEndVertex(); + immAttr2i(attr_id, data[0], data[1]); + immEndVertex(); } - /* --- generic uniform functions --- */ #if 0 # if TRUST_NO_ONE -# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, name); assert(uniform); +# define GET_UNIFORM \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ + name); \ + assert(uniform); # else -# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, name); +# define GET_UNIFORM \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ + name); # endif #else - /* NOTE: It is possible to have uniform fully optimized out from the shader. - * In this case we can't assert failure or allow NULL-pointer dereference. - * TODO(sergey): How can we detect existing-but-optimized-out uniform but still - * catch typos in uniform names passed to immUniform*() functions? */ -# define GET_UNIFORM const GPUShaderInput* uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, name); if (uniform == NULL) return; +/* NOTE: It is possible to have uniform fully optimized out from the shader. + * In this case we can't assert failure or allow NULL-pointer dereference. + * TODO(sergey): How can we detect existing-but-optimized-out uniform but still + * catch typos in uniform names passed to immUniform*() functions? */ +# define GET_UNIFORM \ + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \ + name); \ + if (uniform == NULL) \ + return; #endif void immUniform1f(const char *name, float x) { - GET_UNIFORM - glUniform1f(uniform->location, x); + GET_UNIFORM + glUniform1f(uniform->location, x); } void immUniform2f(const char *name, float x, float y) { - GET_UNIFORM - glUniform2f(uniform->location, x, y); + GET_UNIFORM + glUniform2f(uniform->location, x, y); } void immUniform2fv(const char *name, const float data[2]) { - GET_UNIFORM - glUniform2fv(uniform->location, 1, data); + GET_UNIFORM + glUniform2fv(uniform->location, 1, data); } void immUniform3f(const char *name, float x, float y, float z) { - GET_UNIFORM - glUniform3f(uniform->location, x, y, z); + GET_UNIFORM + glUniform3f(uniform->location, x, y, z); } void immUniform3fv(const char *name, const float data[3]) { - GET_UNIFORM - glUniform3fv(uniform->location, 1, data); + GET_UNIFORM + glUniform3fv(uniform->location, 1, data); } /* can increase this limit or move to another file */ @@ -744,175 +756,176 @@ void immUniform3fv(const char *name, const float data[3]) void immUniformArray3fv(const char *bare_name, const float *data, int count) { - /* look up "name[0]" when given "name" */ - const size_t len = strlen(bare_name); + /* look up "name[0]" when given "name" */ + const size_t len = strlen(bare_name); #if TRUST_NO_ONE - assert(len <= MAX_UNIFORM_NAME_LEN); + assert(len <= MAX_UNIFORM_NAME_LEN); #endif - char name[MAX_UNIFORM_NAME_LEN]; - strcpy(name, bare_name); - name[len + 0] = '['; - name[len + 1] = '0'; - name[len + 2] = ']'; - name[len + 3] = '\0'; + char name[MAX_UNIFORM_NAME_LEN]; + strcpy(name, bare_name); + name[len + 0] = '['; + name[len + 1] = '0'; + name[len + 2] = ']'; + name[len + 3] = '\0'; - GET_UNIFORM - glUniform3fv(uniform->location, count, data); + GET_UNIFORM + glUniform3fv(uniform->location, count, data); } void immUniform4f(const char *name, float x, float y, float z, float w) { - GET_UNIFORM - glUniform4f(uniform->location, x, y, z, w); + GET_UNIFORM + glUniform4f(uniform->location, x, y, z, w); } void immUniform4fv(const char *name, const float data[4]) { - GET_UNIFORM - glUniform4fv(uniform->location, 1, data); + GET_UNIFORM + glUniform4fv(uniform->location, 1, data); } void immUniformArray4fv(const char *bare_name, const float *data, int count) { - /* look up "name[0]" when given "name" */ - const size_t len = strlen(bare_name); + /* look up "name[0]" when given "name" */ + const size_t len = strlen(bare_name); #if TRUST_NO_ONE - assert(len <= MAX_UNIFORM_NAME_LEN); + assert(len <= MAX_UNIFORM_NAME_LEN); #endif - char name[MAX_UNIFORM_NAME_LEN]; - strcpy(name, bare_name); - name[len + 0] = '['; - name[len + 1] = '0'; - name[len + 2] = ']'; - name[len + 3] = '\0'; + char name[MAX_UNIFORM_NAME_LEN]; + strcpy(name, bare_name); + name[len + 0] = '['; + name[len + 1] = '0'; + name[len + 2] = ']'; + name[len + 3] = '\0'; - GET_UNIFORM - glUniform4fv(uniform->location, count, data); + GET_UNIFORM + glUniform4fv(uniform->location, count, data); } void immUniformMatrix4fv(const char *name, const float data[4][4]) { - GET_UNIFORM - glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data); + GET_UNIFORM + glUniformMatrix4fv(uniform->location, 1, GL_FALSE, (float *)data); } void immUniform1i(const char *name, int x) { - GET_UNIFORM - glUniform1i(uniform->location, x); + GET_UNIFORM + glUniform1i(uniform->location, x); } void immUniform4iv(const char *name, const int data[4]) { - GET_UNIFORM - glUniform4iv(uniform->location, 1, data); + GET_UNIFORM + glUniform4iv(uniform->location, 1, data); } /* --- convenience functions for setting "uniform vec4 color" --- */ void immUniformColor4f(float r, float g, float b, float a) { - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(imm.shader_interface, GPU_UNIFORM_COLOR); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(imm.shader_interface, + GPU_UNIFORM_COLOR); #if TRUST_NO_ONE - assert(uniform != NULL); + assert(uniform != NULL); #endif - glUniform4f(uniform->location, r, g, b, a); + glUniform4f(uniform->location, r, g, b, a); } void immUniformColor4fv(const float rgba[4]) { - immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]); + immUniformColor4f(rgba[0], rgba[1], rgba[2], rgba[3]); } void immUniformColor3f(float r, float g, float b) { - immUniformColor4f(r, g, b, 1.0f); + immUniformColor4f(r, g, b, 1.0f); } void immUniformColor3fv(const float rgb[3]) { - immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f); + immUniformColor4f(rgb[0], rgb[1], rgb[2], 1.0f); } void immUniformColor3fvAlpha(const float rgb[3], float a) { - immUniformColor4f(rgb[0], rgb[1], rgb[2], a); + immUniformColor4f(rgb[0], rgb[1], rgb[2], a); } /* TODO: v-- treat as sRGB? --v */ void immUniformColor3ub(uchar r, uchar g, uchar b) { - const float scale = 1.0f / 255.0f; - immUniformColor4f(scale * r, scale * g, scale * b, 1.0f); + const float scale = 1.0f / 255.0f; + immUniformColor4f(scale * r, scale * g, scale * b, 1.0f); } void immUniformColor4ub(uchar r, uchar g, uchar b, uchar a) { - const float scale = 1.0f / 255.0f; - immUniformColor4f(scale * r, scale * g, scale * b, scale * a); + const float scale = 1.0f / 255.0f; + immUniformColor4f(scale * r, scale * g, scale * b, scale * a); } void immUniformColor3ubv(const uchar rgb[3]) { - immUniformColor3ub(rgb[0], rgb[1], rgb[2]); + immUniformColor3ub(rgb[0], rgb[1], rgb[2]); } void immUniformColor3ubvAlpha(const uchar rgb[3], uchar alpha) { - immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha); + immUniformColor4ub(rgb[0], rgb[1], rgb[2], alpha); } void immUniformColor4ubv(const uchar rgba[4]) { - immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]); + immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]); } void immUniformThemeColor(int color_id) { - float color[4]; - UI_GetThemeColor4fv(color_id, color); - immUniformColor4fv(color); + float color[4]; + UI_GetThemeColor4fv(color_id, color); + immUniformColor4fv(color); } void immUniformThemeColor3(int color_id) { - float color[3]; - UI_GetThemeColor3fv(color_id, color); - immUniformColor3fv(color); + float color[3]; + UI_GetThemeColor3fv(color_id, color); + immUniformColor3fv(color); } void immUniformThemeColorShade(int color_id, int offset) { - float color[4]; - UI_GetThemeColorShade4fv(color_id, offset, color); - immUniformColor4fv(color); + float color[4]; + UI_GetThemeColorShade4fv(color_id, offset, color); + immUniformColor4fv(color); } void immUniformThemeColorShadeAlpha(int color_id, int color_offset, int alpha_offset) { - float color[4]; - UI_GetThemeColorShadeAlpha4fv(color_id, color_offset, alpha_offset, color); - immUniformColor4fv(color); + float color[4]; + UI_GetThemeColorShadeAlpha4fv(color_id, color_offset, alpha_offset, color); + immUniformColor4fv(color); } void immUniformThemeColorBlendShade(int color_id1, int color_id2, float fac, int offset) { - float color[4]; - UI_GetThemeColorBlendShade4fv(color_id1, color_id2, fac, offset, color); - immUniformColor4fv(color); + float color[4]; + UI_GetThemeColorBlendShade4fv(color_id1, color_id2, fac, offset, color); + immUniformColor4fv(color); } void immUniformThemeColorBlend(int color_id1, int color_id2, float fac) { - uint8_t color[3]; - UI_GetThemeColorBlend3ubv(color_id1, color_id2, fac, color); - immUniformColor3ubv(color); + uint8_t color[3]; + UI_GetThemeColorBlend3ubv(color_id1, color_id2, fac, color); + immUniformColor3ubv(color); } void immThemeColorShadeAlpha(int colorid, int coloffset, int alphaoffset) { - uchar col[4]; - UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col); - immUniformColor4ub(col[0], col[1], col[2], col[3]); + uchar col[4]; + UI_GetThemeColorShadeAlpha4ubv(colorid, coloffset, alphaoffset, col); + immUniformColor4ub(col[0], col[1], col[2], col[3]); } diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index 53a69b0b9d7..ca0c2506750 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -31,112 +31,114 @@ #include "GPU_matrix.h" static const float cube_coords[8][3] = { - {-1, -1, -1}, - {-1, -1, +1}, - {-1, +1, -1}, - {-1, +1, +1}, - {+1, -1, -1}, - {+1, -1, +1}, - {+1, +1, -1}, - {+1, +1, +1}, + {-1, -1, -1}, + {-1, -1, +1}, + {-1, +1, -1}, + {-1, +1, +1}, + {+1, -1, -1}, + {+1, -1, +1}, + {+1, +1, -1}, + {+1, +1, +1}, }; static const int cube_quad_index[6][4] = { - {0, 1, 3, 2}, - {0, 2, 6, 4}, - {0, 4, 5, 1}, - {1, 5, 7, 3}, - {2, 3, 7, 6}, - {4, 6, 7, 5}, + {0, 1, 3, 2}, + {0, 2, 6, 4}, + {0, 4, 5, 1}, + {1, 5, 7, 3}, + {2, 3, 7, 6}, + {4, 6, 7, 5}, }; static const int cube_line_index[12][2] = { - {0, 1}, - {0, 2}, - {0, 4}, - {1, 3}, - {1, 5}, - {2, 3}, - {2, 6}, - {3, 7}, - {4, 5}, - {4, 6}, - {5, 7}, - {6, 7}, + {0, 1}, + {0, 2}, + {0, 4}, + {1, 3}, + {1, 5}, + {2, 3}, + {2, 6}, + {3, 7}, + {4, 5}, + {4, 6}, + {5, 7}, + {6, 7}, }; void immRectf(uint pos, float x1, float y1, float x2, float y2) { - immBegin(GPU_PRIM_TRI_FAN, 4); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x2, y1); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x1, y2); - immEnd(); + immBegin(GPU_PRIM_TRI_FAN, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x1, y2); + immEnd(); } void immRecti(uint pos, int x1, int y1, int x2, int y2) { - immBegin(GPU_PRIM_TRI_FAN, 4); - immVertex2i(pos, x1, y1); - immVertex2i(pos, x2, y1); - immVertex2i(pos, x2, y2); - immVertex2i(pos, x1, y2); - immEnd(); + immBegin(GPU_PRIM_TRI_FAN, 4); + immVertex2i(pos, x1, y1); + immVertex2i(pos, x2, y1); + immVertex2i(pos, x2, y2); + immVertex2i(pos, x1, y2); + immEnd(); } void immRectf_fast(uint pos, float x1, float y1, float x2, float y2) { - immVertex2f(pos, x1, y1); - immVertex2f(pos, x2, y1); - immVertex2f(pos, x2, y2); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y1); + immVertex2f(pos, x2, y2); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x1, y2); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x1, y2); } -void immRectf_fast_with_color(uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]) +void immRectf_fast_with_color( + uint pos, uint col, float x1, float y1, float x2, float y2, const float color[4]) { - immAttr4fv(col, color); - immVertex2f(pos, x1, y1); - immAttr4fv(col, color); - immVertex2f(pos, x2, y1); - immAttr4fv(col, color); - immVertex2f(pos, x2, y2); - - immAttr4fv(col, color); - immVertex2f(pos, x1, y1); - immAttr4fv(col, color); - immVertex2f(pos, x2, y2); - immAttr4fv(col, color); - immVertex2f(pos, x1, y2); + immAttr4fv(col, color); + immVertex2f(pos, x1, y1); + immAttr4fv(col, color); + immVertex2f(pos, x2, y1); + immAttr4fv(col, color); + immVertex2f(pos, x2, y2); + + immAttr4fv(col, color); + immVertex2f(pos, x1, y1); + immAttr4fv(col, color); + immVertex2f(pos, x2, y2); + immAttr4fv(col, color); + immVertex2f(pos, x1, y2); } -void immRecti_fast_with_color(uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]) +void immRecti_fast_with_color( + uint pos, uint col, int x1, int y1, int x2, int y2, const float color[4]) { - immAttr4fv(col, color); - immVertex2i(pos, x1, y1); - immAttr4fv(col, color); - immVertex2i(pos, x2, y1); - immAttr4fv(col, color); - immVertex2i(pos, x2, y2); - - immAttr4fv(col, color); - immVertex2i(pos, x1, y1); - immAttr4fv(col, color); - immVertex2i(pos, x2, y2); - immAttr4fv(col, color); - immVertex2i(pos, x1, y2); + immAttr4fv(col, color); + immVertex2i(pos, x1, y1); + immAttr4fv(col, color); + immVertex2i(pos, x2, y1); + immAttr4fv(col, color); + immVertex2i(pos, x2, y2); + + immAttr4fv(col, color); + immVertex2i(pos, x1, y1); + immAttr4fv(col, color); + immVertex2i(pos, x2, y2); + immAttr4fv(col, color); + immVertex2i(pos, x1, y2); } #if 0 /* more complete version in case we want that */ void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4]) { - GPUVertFormat *format = immVertexFormat(); - uint pos = add_attr(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4fv(color); - immRecti(pos, x1, y1, x2, y2); - immUnbindProgram(); + GPUVertFormat *format = immVertexFormat(); + uint pos = add_attr(format, "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + immUniformColor4fv(color); + immRecti(pos, x1, y1, x2, y2); + immUnbindProgram(); } #endif @@ -153,20 +155,23 @@ void immRecti_complete(int x1, int y1, int x2, int y2, const float color[4]) */ void imm_cpack(uint x) { - immUniformColor3ub(((x) & 0xFF), - (((x) >> 8) & 0xFF), - (((x) >> 16) & 0xFF)); + immUniformColor3ub(((x)&0xFF), (((x) >> 8) & 0xFF), (((x) >> 16) & 0xFF)); } -static void imm_draw_circle( - GPUPrimType prim_type, const uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments) +static void imm_draw_circle(GPUPrimType prim_type, + const uint shdr_pos, + float x, + float y, + float rad_x, + float rad_y, + int nsegments) { - immBegin(prim_type, nsegments); - for (int i = 0; i < nsegments; ++i) { - const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); - immVertex2f(shdr_pos, x + (rad_x * cosf(angle)), y + (rad_y * sinf(angle))); - } - immEnd(); + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; ++i) { + const float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex2f(shdr_pos, x + (rad_x * cosf(angle)), y + (rad_y * sinf(angle))); + } + immEnd(); } /** @@ -181,7 +186,7 @@ static void imm_draw_circle( */ void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nsegments) { - imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments); + imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad, rad, nsegments); } /** @@ -196,64 +201,76 @@ void imm_draw_circle_wire_2d(uint shdr_pos, float x, float y, float rad, int nse */ void imm_draw_circle_fill_2d(uint shdr_pos, float x, float y, float rad, int nsegments) { - imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments); + imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad, rad, nsegments); } -void imm_draw_circle_wire_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments) +void imm_draw_circle_wire_aspect_2d( + uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments) { - imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments); + imm_draw_circle(GPU_PRIM_LINE_LOOP, shdr_pos, x, y, rad_x, rad_y, nsegments); } -void imm_draw_circle_fill_aspect_2d(uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments) +void imm_draw_circle_fill_aspect_2d( + uint shdr_pos, float x, float y, float rad_x, float rad_y, int nsegments) { - imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments); + imm_draw_circle(GPU_PRIM_TRI_FAN, shdr_pos, x, y, rad_x, rad_y, nsegments); } -static void imm_draw_circle_partial( - GPUPrimType prim_type, uint pos, float x, float y, - float rad, int nsegments, float start, float sweep) +static void imm_draw_circle_partial(GPUPrimType prim_type, + uint pos, + float x, + float y, + float rad, + int nsegments, + float start, + float sweep) { - /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); - const float angle_end = -(DEG2RADF(sweep) - angle_start); - nsegments += 1; - immBegin(prim_type, nsegments); - for (int i = 0; i < nsegments; ++i) { - const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); - const float angle_sin = sinf(angle); - const float angle_cos = cosf(angle); - immVertex2f(pos, x + rad * angle_cos, y + rad * angle_sin); - } - immEnd(); + /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ + const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_end = -(DEG2RADF(sweep) - angle_start); + nsegments += 1; + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; ++i) { + const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + immVertex2f(pos, x + rad * angle_cos, y + rad * angle_sin); + } + immEnd(); } void imm_draw_circle_partial_wire_2d( - uint pos, float x, float y, - float rad, int nsegments, float start, float sweep) + uint pos, float x, float y, float rad, int nsegments, float start, float sweep) { - imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, rad, nsegments, start, sweep); + imm_draw_circle_partial(GPU_PRIM_LINE_STRIP, pos, x, y, rad, nsegments, start, sweep); } -static void imm_draw_disk_partial( - GPUPrimType prim_type, uint pos, float x, float y, - float rad_inner, float rad_outer, int nsegments, float start, float sweep) +static void imm_draw_disk_partial(GPUPrimType prim_type, + uint pos, + float x, + float y, + float rad_inner, + float rad_outer, + int nsegments, + float start, + float sweep) { - /* to avoid artifacts */ - const float max_angle = 3 * 360; - CLAMP(sweep, -max_angle, max_angle); - - /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ - const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); - const float angle_end = -(DEG2RADF(sweep) - angle_start); - nsegments += 1; - immBegin(prim_type, nsegments * 2); - for (int i = 0; i < nsegments; ++i) { - const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); - const float angle_sin = sinf(angle); - const float angle_cos = cosf(angle); - immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin); - immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin); - } - immEnd(); + /* to avoid artifacts */ + const float max_angle = 3 * 360; + CLAMP(sweep, -max_angle, max_angle); + + /* shift & reverse angle, increase 'nsegments' to match gluPartialDisk */ + const float angle_start = -(DEG2RADF(start)) + (float)(M_PI / 2); + const float angle_end = -(DEG2RADF(sweep) - angle_start); + nsegments += 1; + immBegin(prim_type, nsegments * 2); + for (int i = 0; i < nsegments; ++i) { + const float angle = interpf(angle_start, angle_end, ((float)i / (float)(nsegments - 1))); + const float angle_sin = sinf(angle); + const float angle_cos = cosf(angle); + immVertex2f(pos, x + rad_inner * angle_cos, y + rad_inner * angle_sin); + immVertex2f(pos, x + rad_outer * angle_cos, y + rad_outer * angle_sin); + } + immEnd(); } /** @@ -271,33 +288,38 @@ static void imm_draw_disk_partial( * \param start: Specifies the starting angle, in degrees, of the disk portion. * \param sweep: Specifies the sweep angle, in degrees, of the disk portion. */ -void imm_draw_disk_partial_fill_2d( - uint pos, float x, float y, - float rad_inner, float rad_outer, int nsegments, float start, float sweep) +void imm_draw_disk_partial_fill_2d(uint pos, + float x, + float y, + float rad_inner, + float rad_outer, + int nsegments, + float start, + float sweep) { - imm_draw_disk_partial(GPU_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep); + imm_draw_disk_partial( + GPU_PRIM_TRI_STRIP, pos, x, y, rad_inner, rad_outer, nsegments, start, sweep); } static void imm_draw_circle_3D( - GPUPrimType prim_type, uint pos, float x, float y, - float rad, int nsegments) + GPUPrimType prim_type, uint pos, float x, float y, float rad, int nsegments) { - immBegin(prim_type, nsegments); - for (int i = 0; i < nsegments; ++i) { - float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); - immVertex3f(pos, x + rad * cosf(angle), y + rad * sinf(angle), 0.0f); - } - immEnd(); + immBegin(prim_type, nsegments); + for (int i = 0; i < nsegments; ++i) { + float angle = (float)(2 * M_PI) * ((float)i / (float)nsegments); + immVertex3f(pos, x + rad * cosf(angle), y + rad * sinf(angle), 0.0f); + } + immEnd(); } void imm_draw_circle_wire_3d(uint pos, float x, float y, float rad, int nsegments) { - imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, rad, nsegments); + imm_draw_circle_3D(GPU_PRIM_LINE_LOOP, pos, x, y, rad, nsegments); } void imm_draw_circle_fill_3d(uint pos, float x, float y, float rad, int nsegments) { - imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, rad, nsegments); + imm_draw_circle_3D(GPU_PRIM_TRI_FAN, pos, x, y, rad, nsegments); } /** @@ -311,23 +333,23 @@ void imm_draw_circle_fill_3d(uint pos, float x, float y, float rad, int nsegment */ void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2) { - immBegin(GPU_PRIM_LINE_LOOP, 4); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x1, y2); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x2, y1); - immEnd(); + immBegin(GPU_PRIM_LINE_LOOP, 4); + immVertex2f(pos, x1, y1); + immVertex2f(pos, x1, y2); + immVertex2f(pos, x2, y2); + immVertex2f(pos, x2, y1); + immEnd(); } void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2) { - /* use this version when GPUVertFormat has a vec3 position */ - immBegin(GPU_PRIM_LINE_LOOP, 4); - immVertex3f(pos, x1, y1, 0.0f); - immVertex3f(pos, x1, y2, 0.0f); - immVertex3f(pos, x2, y2, 0.0f); - immVertex3f(pos, x2, y1, 0.0f); - immEnd(); + /* use this version when GPUVertFormat has a vec3 position */ + immBegin(GPU_PRIM_LINE_LOOP, 4); + immVertex3f(pos, x1, y1, 0.0f); + immVertex3f(pos, x1, y2, 0.0f); + immVertex3f(pos, x2, y2, 0.0f); + immVertex3f(pos, x2, y1, 0.0f); + immEnd(); } /** @@ -335,53 +357,53 @@ void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2) */ void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2) { - uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); + uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); - immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f); - immUniform4f("color2", 0.2f, 0.2f, 0.2f, 1.0f); - immUniform1i("size", 8); + immUniform4f("color1", 0.15f, 0.15f, 0.15f, 1.0f); + immUniform4f("color2", 0.2f, 0.2f, 0.2f, 1.0f); + immUniform1i("size", 8); - immRectf(pos, x1, y1, x2, y2); + immRectf(pos, x1, y1, x2, y2); - immUnbindProgram(); + immUnbindProgram(); } void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]) { - float coords[ARRAY_SIZE(cube_coords)][3]; - - for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) { - madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect); - } - - immBegin(GPU_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2); - for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) { - immVertex3fv(pos, coords[cube_quad_index[i][0]]); - immVertex3fv(pos, coords[cube_quad_index[i][1]]); - immVertex3fv(pos, coords[cube_quad_index[i][2]]); - - immVertex3fv(pos, coords[cube_quad_index[i][0]]); - immVertex3fv(pos, coords[cube_quad_index[i][2]]); - immVertex3fv(pos, coords[cube_quad_index[i][3]]); - } - immEnd(); + float coords[ARRAY_SIZE(cube_coords)][3]; + + for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) { + madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect); + } + + immBegin(GPU_PRIM_TRIS, ARRAY_SIZE(cube_quad_index) * 3 * 2); + for (int i = 0; i < ARRAY_SIZE(cube_quad_index); i++) { + immVertex3fv(pos, coords[cube_quad_index[i][0]]); + immVertex3fv(pos, coords[cube_quad_index[i][1]]); + immVertex3fv(pos, coords[cube_quad_index[i][2]]); + + immVertex3fv(pos, coords[cube_quad_index[i][0]]); + immVertex3fv(pos, coords[cube_quad_index[i][2]]); + immVertex3fv(pos, coords[cube_quad_index[i][3]]); + } + immEnd(); } void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3]) { - float coords[ARRAY_SIZE(cube_coords)][3]; - - for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) { - madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect); - } - - immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2); - for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) { - immVertex3fv(pos, coords[cube_line_index[i][0]]); - immVertex3fv(pos, coords[cube_line_index[i][1]]); - } - immEnd(); + float coords[ARRAY_SIZE(cube_coords)][3]; + + for (int i = 0; i < ARRAY_SIZE(cube_coords); i++) { + madd_v3_v3v3v3(coords[i], co, cube_coords[i], aspect); + } + + immBegin(GPU_PRIM_LINES, ARRAY_SIZE(cube_line_index) * 2); + for (int i = 0; i < ARRAY_SIZE(cube_line_index); i++) { + immVertex3fv(pos, coords[cube_line_index[i][0]]); + immVertex3fv(pos, coords[cube_line_index[i][1]]); + } + immEnd(); } /** @@ -397,128 +419,134 @@ void imm_draw_cube_wire_3d(uint pos, const float co[3], const float aspect[3]) * \param stacks: Specifies the number of subdivisions along the z axis. */ void imm_draw_cylinder_fill_normal_3d( - uint pos, uint nor, float base, float top, float height, int slices, int stacks) + uint pos, uint nor, float base, float top, float height, int slices, int stacks) { - immBegin(GPU_PRIM_TRIS, 6 * slices * stacks); - for (int i = 0; i < slices; ++i) { - const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); - const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); - const float cos1 = cosf(angle1); - const float sin1 = sinf(angle1); - const float cos2 = cosf(angle2); - const float sin2 = sinf(angle2); - - for (int j = 0; j < stacks; ++j) { - float fac1 = (float)j / (float)stacks; - float fac2 = (float)(j + 1) / (float)stacks; - float r1 = base * (1.f - fac1) + top * fac1; - float r2 = base * (1.f - fac2) + top * fac2; - float h1 = height * ((float)j / (float)stacks); - float h2 = height * ((float)(j + 1) / (float)stacks); - - float v1[3] = {r1 * cos2, r1 * sin2, h1}; - float v2[3] = {r2 * cos2, r2 * sin2, h2}; - float v3[3] = {r2 * cos1, r2 * sin1, h2}; - float v4[3] = {r1 * cos1, r1 * sin1, h1}; - float n1[3], n2[3]; - - /* calc normals */ - sub_v3_v3v3(n1, v2, v1); - normalize_v3(n1); - n1[0] = cos1; n1[1] = sin1; n1[2] = 1 - n1[2]; - - sub_v3_v3v3(n2, v3, v4); - normalize_v3(n2); - n2[0] = cos2; n2[1] = sin2; n2[2] = 1 - n2[2]; - - /* first tri */ - immAttr3fv(nor, n2); - immVertex3fv(pos, v1); - immVertex3fv(pos, v2); - immAttr3fv(nor, n1); - immVertex3fv(pos, v3); - - /* second tri */ - immVertex3fv(pos, v3); - immVertex3fv(pos, v4); - immAttr3fv(nor, n2); - immVertex3fv(pos, v1); - } - } - immEnd(); + immBegin(GPU_PRIM_TRIS, 6 * slices * stacks); + for (int i = 0; i < slices; ++i) { + const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); + const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); + const float cos1 = cosf(angle1); + const float sin1 = sinf(angle1); + const float cos2 = cosf(angle2); + const float sin2 = sinf(angle2); + + for (int j = 0; j < stacks; ++j) { + float fac1 = (float)j / (float)stacks; + float fac2 = (float)(j + 1) / (float)stacks; + float r1 = base * (1.f - fac1) + top * fac1; + float r2 = base * (1.f - fac2) + top * fac2; + float h1 = height * ((float)j / (float)stacks); + float h2 = height * ((float)(j + 1) / (float)stacks); + + float v1[3] = {r1 * cos2, r1 * sin2, h1}; + float v2[3] = {r2 * cos2, r2 * sin2, h2}; + float v3[3] = {r2 * cos1, r2 * sin1, h2}; + float v4[3] = {r1 * cos1, r1 * sin1, h1}; + float n1[3], n2[3]; + + /* calc normals */ + sub_v3_v3v3(n1, v2, v1); + normalize_v3(n1); + n1[0] = cos1; + n1[1] = sin1; + n1[2] = 1 - n1[2]; + + sub_v3_v3v3(n2, v3, v4); + normalize_v3(n2); + n2[0] = cos2; + n2[1] = sin2; + n2[2] = 1 - n2[2]; + + /* first tri */ + immAttr3fv(nor, n2); + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immAttr3fv(nor, n1); + immVertex3fv(pos, v3); + + /* second tri */ + immVertex3fv(pos, v3); + immVertex3fv(pos, v4); + immAttr3fv(nor, n2); + immVertex3fv(pos, v1); + } + } + immEnd(); } -void imm_draw_cylinder_wire_3d(uint pos, float base, float top, float height, int slices, int stacks) +void imm_draw_cylinder_wire_3d( + uint pos, float base, float top, float height, int slices, int stacks) { - immBegin(GPU_PRIM_LINES, 6 * slices * stacks); - for (int i = 0; i < slices; ++i) { - const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); - const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); - const float cos1 = cosf(angle1); - const float sin1 = sinf(angle1); - const float cos2 = cosf(angle2); - const float sin2 = sinf(angle2); - - for (int j = 0; j < stacks; ++j) { - float fac1 = (float)j / (float)stacks; - float fac2 = (float)(j + 1) / (float)stacks; - float r1 = base * (1.f - fac1) + top * fac1; - float r2 = base * (1.f - fac2) + top * fac2; - float h1 = height * ((float)j / (float)stacks); - float h2 = height * ((float)(j + 1) / (float)stacks); - - float v1[3] = {r1 * cos2, r1 * sin2, h1}; - float v2[3] = {r2 * cos2, r2 * sin2, h2}; - float v3[3] = {r2 * cos1, r2 * sin1, h2}; - float v4[3] = {r1 * cos1, r1 * sin1, h1}; - - immVertex3fv(pos, v1); - immVertex3fv(pos, v2); - - immVertex3fv(pos, v2); - immVertex3fv(pos, v3); - - immVertex3fv(pos, v1); - immVertex3fv(pos, v4); - } - } - immEnd(); + immBegin(GPU_PRIM_LINES, 6 * slices * stacks); + for (int i = 0; i < slices; ++i) { + const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); + const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); + const float cos1 = cosf(angle1); + const float sin1 = sinf(angle1); + const float cos2 = cosf(angle2); + const float sin2 = sinf(angle2); + + for (int j = 0; j < stacks; ++j) { + float fac1 = (float)j / (float)stacks; + float fac2 = (float)(j + 1) / (float)stacks; + float r1 = base * (1.f - fac1) + top * fac1; + float r2 = base * (1.f - fac2) + top * fac2; + float h1 = height * ((float)j / (float)stacks); + float h2 = height * ((float)(j + 1) / (float)stacks); + + float v1[3] = {r1 * cos2, r1 * sin2, h1}; + float v2[3] = {r2 * cos2, r2 * sin2, h2}; + float v3[3] = {r2 * cos1, r2 * sin1, h2}; + float v4[3] = {r1 * cos1, r1 * sin1, h1}; + + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + + immVertex3fv(pos, v2); + immVertex3fv(pos, v3); + + immVertex3fv(pos, v1); + immVertex3fv(pos, v4); + } + } + immEnd(); } -void imm_draw_cylinder_fill_3d(uint pos, float base, float top, float height, int slices, int stacks) +void imm_draw_cylinder_fill_3d( + uint pos, float base, float top, float height, int slices, int stacks) { - immBegin(GPU_PRIM_TRIS, 6 * slices * stacks); - for (int i = 0; i < slices; ++i) { - const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); - const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); - const float cos1 = cosf(angle1); - const float sin1 = sinf(angle1); - const float cos2 = cosf(angle2); - const float sin2 = sinf(angle2); - - for (int j = 0; j < stacks; ++j) { - float fac1 = (float)j / (float)stacks; - float fac2 = (float)(j + 1) / (float)stacks; - float r1 = base * (1.f - fac1) + top * fac1; - float r2 = base * (1.f - fac2) + top * fac2; - float h1 = height * ((float)j / (float)stacks); - float h2 = height * ((float)(j + 1) / (float)stacks); - - float v1[3] = {r1 * cos2, r1 * sin2, h1}; - float v2[3] = {r2 * cos2, r2 * sin2, h2}; - float v3[3] = {r2 * cos1, r2 * sin1, h2}; - float v4[3] = {r1 * cos1, r1 * sin1, h1}; - - /* first tri */ - immVertex3fv(pos, v1); - immVertex3fv(pos, v2); - immVertex3fv(pos, v3); - - /* second tri */ - immVertex3fv(pos, v3); - immVertex3fv(pos, v4); - immVertex3fv(pos, v1); - } - } - immEnd(); + immBegin(GPU_PRIM_TRIS, 6 * slices * stacks); + for (int i = 0; i < slices; ++i) { + const float angle1 = (float)(2 * M_PI) * ((float)i / (float)slices); + const float angle2 = (float)(2 * M_PI) * ((float)(i + 1) / (float)slices); + const float cos1 = cosf(angle1); + const float sin1 = sinf(angle1); + const float cos2 = cosf(angle2); + const float sin2 = sinf(angle2); + + for (int j = 0; j < stacks; ++j) { + float fac1 = (float)j / (float)stacks; + float fac2 = (float)(j + 1) / (float)stacks; + float r1 = base * (1.f - fac1) + top * fac1; + float r2 = base * (1.f - fac2) + top * fac2; + float h1 = height * ((float)j / (float)stacks); + float h2 = height * ((float)(j + 1) / (float)stacks); + + float v1[3] = {r1 * cos2, r1 * sin2, h1}; + float v2[3] = {r2 * cos2, r2 * sin2, h2}; + float v3[3] = {r2 * cos1, r2 * sin1, h2}; + float v4[3] = {r1 * cos1, r1 * sin1, h1}; + + /* first tri */ + immVertex3fv(pos, v1); + immVertex3fv(pos, v2); + immVertex3fv(pos, v3); + + /* second tri */ + immVertex3fv(pos, v3); + immVertex3fv(pos, v4); + immVertex3fv(pos, v1); + } + } + immEnd(); } diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c index b1bdfccacff..310320673d0 100644 --- a/source/blender/gpu/intern/gpu_init_exit.c +++ b/source/blender/gpu/intern/gpu_init_exit.c @@ -23,7 +23,7 @@ #include "BLI_sys_types.h" #include "GPU_buffers.h" -#include "GPU_init_exit.h" /* interface */ +#include "GPU_init_exit.h" /* interface */ #include "GPU_immediate.h" #include "GPU_batch.h" #include "GPU_texture.h" @@ -41,51 +41,49 @@ static bool initialized = false; void GPU_init(void) { - /* can't avoid calling this multiple times, see wm_window_ghostwindow_add */ - if (initialized) - return; + /* can't avoid calling this multiple times, see wm_window_ghostwindow_add */ + if (initialized) + return; - initialized = true; + initialized = true; - gpu_extensions_init(); /* must come first */ + gpu_extensions_init(); /* must come first */ - gpu_codegen_init(); - gpu_framebuffer_module_init(); + gpu_codegen_init(); + gpu_framebuffer_module_init(); - if (G.debug & G_DEBUG_GPU) - gpu_debug_init(); + if (G.debug & G_DEBUG_GPU) + gpu_debug_init(); - gpu_batch_init(); + gpu_batch_init(); - if (!G.background) { - immInit(); - } + if (!G.background) { + immInit(); + } - GPU_pbvh_fix_linking(); + GPU_pbvh_fix_linking(); } - void GPU_exit(void) { - if (!G.background) { - immDestroy(); - } + if (!G.background) { + immDestroy(); + } - gpu_batch_exit(); + gpu_batch_exit(); - if (G.debug & G_DEBUG_GPU) - gpu_debug_exit(); + if (G.debug & G_DEBUG_GPU) + gpu_debug_exit(); - gpu_framebuffer_module_exit(); - gpu_codegen_exit(); + gpu_framebuffer_module_exit(); + gpu_codegen_exit(); - gpu_extensions_exit(); /* must come last */ + gpu_extensions_exit(); /* must come last */ - initialized = false; + initialized = false; } - bool GPU_is_initialized(void) { - return initialized; + return initialized; } diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index af8fcf6164e..cae60351bd5 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -54,182 +54,185 @@ #define MAX_COLOR_BAND 128 typedef struct GPUColorBandBuilder { - float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4]; - int current_layer; + float pixels[MAX_COLOR_BAND][CM_TABLE + 1][4]; + int current_layer; } GPUColorBandBuilder; struct GPUMaterial { - Scene *scene; /* DEPRECATED was only useful for lights. */ - Material *ma; - - eGPUMaterialStatus status; - - const void *engine_type; /* attached engine type */ - int options; /* to identify shader variations (shadow, probe, world background...) */ - - /* for creating the material */ - ListBase nodes; - GPUNodeLink *outlink; - - /* for binding the material */ - GPUPass *pass; - ListBase inputs; /* GPUInput */ - GPUVertAttrLayers attrs; - int builtins; - int alpha, obcolalpha; - int dynproperty; - - /* for passing uniforms */ - int viewmatloc, invviewmatloc; - int obmatloc, invobmatloc; - int localtoviewmatloc, invlocaltoviewmatloc; - int obcolloc, obautobumpscaleloc; - int cameratexcofacloc; - - int partscalarpropsloc; - int partcoloc; - int partvel; - int partangvel; - - int objectinfoloc; - - /* XXX: Should be in Material. But it depends on the output node - * used and since the output selection is difference for GPUMaterial... - */ - int domain; - - /* Only used by Eevee to know which bsdf are used. */ - int flag; - - /* Used by 2.8 pipeline */ - GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */ - - /* Eevee SSS */ - GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */ - GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */ - float sss_enabled; - float sss_radii[3]; - int sss_samples; - short int sss_falloff; - float sss_sharpness; - bool sss_dirty; - - GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */ - GPUColorBandBuilder *coba_builder; + Scene *scene; /* DEPRECATED was only useful for lights. */ + Material *ma; + + eGPUMaterialStatus status; + + const void *engine_type; /* attached engine type */ + int options; /* to identify shader variations (shadow, probe, world background...) */ + + /* for creating the material */ + ListBase nodes; + GPUNodeLink *outlink; + + /* for binding the material */ + GPUPass *pass; + ListBase inputs; /* GPUInput */ + GPUVertAttrLayers attrs; + int builtins; + int alpha, obcolalpha; + int dynproperty; + + /* for passing uniforms */ + int viewmatloc, invviewmatloc; + int obmatloc, invobmatloc; + int localtoviewmatloc, invlocaltoviewmatloc; + int obcolloc, obautobumpscaleloc; + int cameratexcofacloc; + + int partscalarpropsloc; + int partcoloc; + int partvel; + int partangvel; + + int objectinfoloc; + + /* XXX: Should be in Material. But it depends on the output node + * used and since the output selection is difference for GPUMaterial... + */ + int domain; + + /* Only used by Eevee to know which bsdf are used. */ + int flag; + + /* Used by 2.8 pipeline */ + GPUUniformBuffer *ubo; /* UBOs for shader uniforms. */ + + /* Eevee SSS */ + GPUUniformBuffer *sss_profile; /* UBO containing SSS profile. */ + GPUTexture *sss_tex_profile; /* Texture containing SSS profile. */ + float sss_enabled; + float sss_radii[3]; + int sss_samples; + short int sss_falloff; + float sss_sharpness; + bool sss_dirty; + + GPUTexture *coba_tex; /* 1D Texture array containing all color bands. */ + GPUColorBandBuilder *coba_builder; #ifndef NDEBUG - char name[64]; + char name[64]; #endif }; enum { - GPU_DOMAIN_SURFACE = (1 << 0), - GPU_DOMAIN_VOLUME = (1 << 1), - GPU_DOMAIN_SSS = (1 << 2), + GPU_DOMAIN_SURFACE = (1 << 0), + GPU_DOMAIN_VOLUME = (1 << 1), + GPU_DOMAIN_SSS = (1 << 2), }; /* Functions */ /* Returns the address of the future pointer to coba_tex */ -GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, int size, float *pixels, float *row) +GPUTexture **gpu_material_ramp_texture_row_set(GPUMaterial *mat, + int size, + float *pixels, + float *row) { - /* In order to put all the colorbands into one 1D array texture, - * we need them to be the same size. */ - BLI_assert(size == CM_TABLE + 1); - UNUSED_VARS_NDEBUG(size); + /* In order to put all the colorbands into one 1D array texture, + * we need them to be the same size. */ + BLI_assert(size == CM_TABLE + 1); + UNUSED_VARS_NDEBUG(size); - if (mat->coba_builder == NULL) { - mat->coba_builder = MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder"); - mat->coba_builder->current_layer = 0; - } + if (mat->coba_builder == NULL) { + mat->coba_builder = MEM_mallocN(sizeof(GPUColorBandBuilder), "GPUColorBandBuilder"); + mat->coba_builder->current_layer = 0; + } - int layer = mat->coba_builder->current_layer; - *row = (float)layer; + int layer = mat->coba_builder->current_layer; + *row = (float)layer; - if (*row == MAX_COLOR_BAND) { - printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n"); - } - else { - float *dst = (float *)mat->coba_builder->pixels[layer]; - memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4); - mat->coba_builder->current_layer += 1; - } + if (*row == MAX_COLOR_BAND) { + printf("Too many color band in shader! Remove some Curve, Black Body or Color Ramp Node.\n"); + } + else { + float *dst = (float *)mat->coba_builder->pixels[layer]; + memcpy(dst, pixels, sizeof(float) * (CM_TABLE + 1) * 4); + mat->coba_builder->current_layer += 1; + } - return &mat->coba_tex; + return &mat->coba_tex; } static void gpu_material_ramp_texture_build(GPUMaterial *mat) { - if (mat->coba_builder == NULL) - return; + if (mat->coba_builder == NULL) + return; - GPUColorBandBuilder *builder = mat->coba_builder; + GPUColorBandBuilder *builder = mat->coba_builder; - mat->coba_tex = GPU_texture_create_1d_array(CM_TABLE + 1, builder->current_layer, GPU_RGBA16F, - (float *)builder->pixels, NULL); + mat->coba_tex = GPU_texture_create_1d_array( + CM_TABLE + 1, builder->current_layer, GPU_RGBA16F, (float *)builder->pixels, NULL); - MEM_freeN(builder); - mat->coba_builder = NULL; + MEM_freeN(builder); + mat->coba_builder = NULL; } static void gpu_material_free_single(GPUMaterial *material) { - /* Cancel / wait any pending lazy compilation. */ - DRW_deferred_shader_remove(material); - - GPU_pass_free_nodes(&material->nodes); - GPU_inputs_free(&material->inputs); - - if (material->pass != NULL) { - GPU_pass_release(material->pass); - } - if (material->ubo != NULL) { - GPU_uniformbuffer_free(material->ubo); - } - if (material->sss_tex_profile != NULL) { - GPU_texture_free(material->sss_tex_profile); - } - if (material->sss_profile != NULL) { - GPU_uniformbuffer_free(material->sss_profile); - } - if (material->coba_tex != NULL) { - GPU_texture_free(material->coba_tex); - } + /* Cancel / wait any pending lazy compilation. */ + DRW_deferred_shader_remove(material); + + GPU_pass_free_nodes(&material->nodes); + GPU_inputs_free(&material->inputs); + + if (material->pass != NULL) { + GPU_pass_release(material->pass); + } + if (material->ubo != NULL) { + GPU_uniformbuffer_free(material->ubo); + } + if (material->sss_tex_profile != NULL) { + GPU_texture_free(material->sss_tex_profile); + } + if (material->sss_profile != NULL) { + GPU_uniformbuffer_free(material->sss_profile); + } + if (material->coba_tex != NULL) { + GPU_texture_free(material->coba_tex); + } } void GPU_material_free(ListBase *gpumaterial) { - for (LinkData *link = gpumaterial->first; link; link = link->next) { - GPUMaterial *material = link->data; - gpu_material_free_single(material); - MEM_freeN(material); - } - BLI_freelistN(gpumaterial); + for (LinkData *link = gpumaterial->first; link; link = link->next) { + GPUMaterial *material = link->data; + gpu_material_free_single(material); + MEM_freeN(material); + } + BLI_freelistN(gpumaterial); } eGPUBuiltin GPU_get_material_builtins(GPUMaterial *material) { - return material->builtins; + return material->builtins; } Scene *GPU_material_scene(GPUMaterial *material) { - return material->scene; + return material->scene; } GPUPass *GPU_material_get_pass(GPUMaterial *material) { - return material->pass; + return material->pass; } ListBase *GPU_material_get_inputs(GPUMaterial *material) { - return &material->inputs; + return &material->inputs; } GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material) { - return material->ubo; + return material->ubo; } /** @@ -239,7 +242,7 @@ GPUUniformBuffer *GPU_material_uniform_buffer_get(GPUMaterial *material) */ void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs) { - material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL); + material->ubo = GPU_uniformbuffer_dynamic_create(inputs, NULL); } /* Eevee Subsurface scattering. */ @@ -249,313 +252,319 @@ void GPU_material_uniform_buffer_create(GPUMaterial *material, ListBase *inputs) #define SSS_EXPONENT 2.0f /* Importance sampling exponent */ typedef struct GPUSssKernelData { - float kernel[SSS_SAMPLES][4]; - float param[3], max_radius; - int samples; + float kernel[SSS_SAMPLES][4]; + float param[3], max_radius; + int samples; } GPUSssKernelData; static void sss_calculate_offsets(GPUSssKernelData *kd, int count, float exponent) { - float step = 2.0f / (float)(count - 1); - for (int i = 0; i < count; i++) { - float o = ((float)i) * step - 1.0f; - float sign = (o < 0.0f) ? -1.0f : 1.0f; - float ofs = sign * fabsf(powf(o, exponent)); - kd->kernel[i][3] = ofs; - } + float step = 2.0f / (float)(count - 1); + for (int i = 0; i < count; i++) { + float o = ((float)i) * step - 1.0f; + float sign = (o < 0.0f) ? -1.0f : 1.0f; + float ofs = sign * fabsf(powf(o, exponent)); + kd->kernel[i][3] = ofs; + } } #define GAUSS_TRUNCATE 12.46f static float gaussian_profile(float r, float radius) { - const float v = radius * radius * (0.25f * 0.25f); - const float Rm = sqrtf(v * GAUSS_TRUNCATE); + const float v = radius * radius * (0.25f * 0.25f); + const float Rm = sqrtf(v * GAUSS_TRUNCATE); - if (r >= Rm) { - return 0.0f; - } - return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v); + if (r >= Rm) { + return 0.0f; + } + return expf(-r * r / (2.0f * v)) / (2.0f * M_PI * v); } -#define BURLEY_TRUNCATE 16.0f -#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE) +#define BURLEY_TRUNCATE 16.0f +#define BURLEY_TRUNCATE_CDF 0.9963790093708328f // cdf(BURLEY_TRUNCATE) static float burley_profile(float r, float d) { - float exp_r_3_d = expf(-r / (3.0f * d)); - float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d; - return (exp_r_d + exp_r_3_d) / (4.0f * d); + float exp_r_3_d = expf(-r / (3.0f * d)); + float exp_r_d = exp_r_3_d * exp_r_3_d * exp_r_3_d; + return (exp_r_d + exp_r_3_d) / (4.0f * d); } static float cubic_profile(float r, float radius, float sharpness) { - float Rm = radius * (1.0f + sharpness); + float Rm = radius * (1.0f + sharpness); - if (r >= Rm) { - return 0.0f; - } - /* custom variation with extra sharpness, to match the previous code */ - const float y = 1.0f / (1.0f + sharpness); - float Rmy, ry, ryinv; + if (r >= Rm) { + return 0.0f; + } + /* custom variation with extra sharpness, to match the previous code */ + const float y = 1.0f / (1.0f + sharpness); + float Rmy, ry, ryinv; - Rmy = powf(Rm, y); - ry = powf(r, y); - ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f; + Rmy = powf(Rm, y); + ry = powf(r, y); + ryinv = (r > 0.0f) ? powf(r, y - 1.0f) : 0.0f; - const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy; - const float f = Rmy - ry; - const float num = f * (f * f) * (y * ryinv); + const float Rmy5 = (Rmy * Rmy) * (Rmy * Rmy) * Rmy; + const float f = Rmy - ry; + const float num = f * (f * f) * (y * ryinv); - return (10.0f * num) / (Rmy5 * M_PI); + return (10.0f * num) / (Rmy5 * M_PI); } static float eval_profile(float r, short falloff_type, float sharpness, float param) { - r = fabsf(r); + r = fabsf(r); - if (falloff_type == SHD_SUBSURFACE_BURLEY || - falloff_type == SHD_SUBSURFACE_RANDOM_WALK) - { - return burley_profile(r, param) / BURLEY_TRUNCATE_CDF; - } - else if (falloff_type == SHD_SUBSURFACE_CUBIC) { - return cubic_profile(r, param, sharpness); - } - else { - return gaussian_profile(r, param); - } + if (falloff_type == SHD_SUBSURFACE_BURLEY || falloff_type == SHD_SUBSURFACE_RANDOM_WALK) { + return burley_profile(r, param) / BURLEY_TRUNCATE_CDF; + } + else if (falloff_type == SHD_SUBSURFACE_CUBIC) { + return cubic_profile(r, param, sharpness); + } + else { + return gaussian_profile(r, param); + } } /* Resolution for each sample of the precomputed kernel profile */ #define INTEGRAL_RESOLUTION 32 static float eval_integral(float x0, float x1, short falloff_type, float sharpness, float param) { - const float range = x1 - x0; - const float step = range / INTEGRAL_RESOLUTION; - float integral = 0.0f; + const float range = x1 - x0; + const float step = range / INTEGRAL_RESOLUTION; + float integral = 0.0f; - for (int i = 0; i < INTEGRAL_RESOLUTION; ++i) { - float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION; - float y = eval_profile(x, falloff_type, sharpness, param); - integral += y * step; - } + for (int i = 0; i < INTEGRAL_RESOLUTION; ++i) { + float x = x0 + range * ((float)i + 0.5f) / (float)INTEGRAL_RESOLUTION; + float y = eval_profile(x, falloff_type, sharpness, param); + integral += y * step; + } - return integral; + return integral; } #undef INTEGRAL_RESOLUTION static void compute_sss_kernel( - GPUSssKernelData *kd, float radii[3], int sample_len, int falloff_type, float sharpness) -{ - float rad[3]; - /* Minimum radius */ - rad[0] = MAX2(radii[0], 1e-15f); - rad[1] = MAX2(radii[1], 1e-15f); - rad[2] = MAX2(radii[2], 1e-15f); - - /* Christensen-Burley fitting */ - float l[3], d[3]; - - if (falloff_type == SHD_SUBSURFACE_BURLEY || - falloff_type == SHD_SUBSURFACE_RANDOM_WALK) - { - mul_v3_v3fl(l, rad, 0.25f * M_1_PI); - const float A = 1.0f; - const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f); - /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */ - mul_v3_v3fl(d, l, 0.6f / s); - mul_v3_v3fl(rad, d, BURLEY_TRUNCATE); - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - - copy_v3_v3(kd->param, d); - } - else if (falloff_type == SHD_SUBSURFACE_CUBIC) { - copy_v3_v3(kd->param, rad); - mul_v3_fl(rad, 1.0f + sharpness); - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - } - else { - kd->max_radius = MAX3(rad[0], rad[1], rad[2]); - - copy_v3_v3(kd->param, rad); - } - - /* Compute samples locations on the 1d kernel [-1..1] */ - sss_calculate_offsets(kd, sample_len, SSS_EXPONENT); - - /* Weights sum for normalization */ - float sum[3] = {0.0f, 0.0f, 0.0f}; - - /* Compute integral of each sample footprint */ - for (int i = 0; i < sample_len; i++) { - float x0, x1; - - if (i == 0) { - x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f; - } - else { - x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f; - } - - if (i == sample_len - 1) { - x1 = kd->kernel[sample_len - 1][3] + fabsf(kd->kernel[sample_len - 2][3] - kd->kernel[sample_len - 1][3]) / 2.0f; - } - else { - x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f; - } - - x0 *= kd->max_radius; - x1 *= kd->max_radius; - - kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]); - kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]); - kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]); - - sum[0] += kd->kernel[i][0]; - sum[1] += kd->kernel[i][1]; - sum[2] += kd->kernel[i][2]; - } - - for (int i = 0; i < 3; ++i) { - if (sum[i] > 0.0f) { - /* Normalize */ - for (int j = 0; j < sample_len; j++) { - kd->kernel[j][i] /= sum[i]; - } - } - else { - /* Avoid 0 kernel sum. */ - kd->kernel[sample_len / 2][i] = 1.0f; - } - } - - /* Put center sample at the start of the array (to sample first) */ - float tmpv[4]; - copy_v4_v4(tmpv, kd->kernel[sample_len / 2]); - for (int i = sample_len / 2; i > 0; i--) { - copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]); - } - copy_v4_v4(kd->kernel[0], tmpv); - - kd->samples = sample_len; + GPUSssKernelData *kd, float radii[3], int sample_len, int falloff_type, float sharpness) +{ + float rad[3]; + /* Minimum radius */ + rad[0] = MAX2(radii[0], 1e-15f); + rad[1] = MAX2(radii[1], 1e-15f); + rad[2] = MAX2(radii[2], 1e-15f); + + /* Christensen-Burley fitting */ + float l[3], d[3]; + + if (falloff_type == SHD_SUBSURFACE_BURLEY || falloff_type == SHD_SUBSURFACE_RANDOM_WALK) { + mul_v3_v3fl(l, rad, 0.25f * M_1_PI); + const float A = 1.0f; + const float s = 1.9f - A + 3.5f * (A - 0.8f) * (A - 0.8f); + /* XXX 0.6f Out of nowhere to match cycles! Empirical! Can be tweak better. */ + mul_v3_v3fl(d, l, 0.6f / s); + mul_v3_v3fl(rad, d, BURLEY_TRUNCATE); + kd->max_radius = MAX3(rad[0], rad[1], rad[2]); + + copy_v3_v3(kd->param, d); + } + else if (falloff_type == SHD_SUBSURFACE_CUBIC) { + copy_v3_v3(kd->param, rad); + mul_v3_fl(rad, 1.0f + sharpness); + kd->max_radius = MAX3(rad[0], rad[1], rad[2]); + } + else { + kd->max_radius = MAX3(rad[0], rad[1], rad[2]); + + copy_v3_v3(kd->param, rad); + } + + /* Compute samples locations on the 1d kernel [-1..1] */ + sss_calculate_offsets(kd, sample_len, SSS_EXPONENT); + + /* Weights sum for normalization */ + float sum[3] = {0.0f, 0.0f, 0.0f}; + + /* Compute integral of each sample footprint */ + for (int i = 0; i < sample_len; i++) { + float x0, x1; + + if (i == 0) { + x0 = kd->kernel[0][3] - fabsf(kd->kernel[0][3] - kd->kernel[1][3]) / 2.0f; + } + else { + x0 = (kd->kernel[i - 1][3] + kd->kernel[i][3]) / 2.0f; + } + + if (i == sample_len - 1) { + x1 = kd->kernel[sample_len - 1][3] + + fabsf(kd->kernel[sample_len - 2][3] - kd->kernel[sample_len - 1][3]) / 2.0f; + } + else { + x1 = (kd->kernel[i][3] + kd->kernel[i + 1][3]) / 2.0f; + } + + x0 *= kd->max_radius; + x1 *= kd->max_radius; + + kd->kernel[i][0] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[0]); + kd->kernel[i][1] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[1]); + kd->kernel[i][2] = eval_integral(x0, x1, falloff_type, sharpness, kd->param[2]); + + sum[0] += kd->kernel[i][0]; + sum[1] += kd->kernel[i][1]; + sum[2] += kd->kernel[i][2]; + } + + for (int i = 0; i < 3; ++i) { + if (sum[i] > 0.0f) { + /* Normalize */ + for (int j = 0; j < sample_len; j++) { + kd->kernel[j][i] /= sum[i]; + } + } + else { + /* Avoid 0 kernel sum. */ + kd->kernel[sample_len / 2][i] = 1.0f; + } + } + + /* Put center sample at the start of the array (to sample first) */ + float tmpv[4]; + copy_v4_v4(tmpv, kd->kernel[sample_len / 2]); + for (int i = sample_len / 2; i > 0; i--) { + copy_v4_v4(kd->kernel[i], kd->kernel[i - 1]); + } + copy_v4_v4(kd->kernel[0], tmpv); + + kd->samples = sample_len; } #define INTEGRAL_RESOLUTION 512 -static void compute_sss_translucence_kernel( - const GPUSssKernelData *kd, int resolution, short falloff_type, float sharpness, float **output) -{ - float (*texels)[4]; - texels = MEM_callocN(sizeof(float) * 4 * resolution, "compute_sss_translucence_kernel"); - *output = (float *)texels; - - /* Last texel should be black, hence the - 1. */ - for (int i = 0; i < resolution - 1; ++i) { - /* Distance from surface. */ - float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution); - - /* For each distance d we compute the radiance incoming from an hypothetic parallel plane. */ - /* Compute radius of the footprint on the hypothetic plane */ - float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d); - float r_step = r_fp / INTEGRAL_RESOLUTION; - float area_accum = 0.0f; - for (float r = 0.0f; r < r_fp; r += r_step) { - /* Compute distance to the "shading" point through the medium. */ - /* r_step * 0.5f to put sample between the area borders */ - float dist = hypotf(r + r_step * 0.5f, d); - - float profile[3]; - profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]); - profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]); - profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]); - - /* Since the profile and configuration are radially symmetrical we - * can just evaluate it once and weight it accordingly */ - float r_next = r + r_step; - float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r); - - mul_v3_fl(profile, disk_area); - add_v3_v3(texels[i], profile); - area_accum += disk_area; - } - /* Normalize over the disk. */ - mul_v3_fl(texels[i], 1.0f / (area_accum)); - } - - /* Normalize */ - for (int j = resolution - 2; j > 0; j--) { - texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f; - texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f; - texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f; - } - - /* First texel should be white */ - texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f; - texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f; - texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f; - - /* dim the last few texels for smoother transition */ - mul_v3_fl(texels[resolution - 2], 0.25f); - mul_v3_fl(texels[resolution - 3], 0.5f); - mul_v3_fl(texels[resolution - 4], 0.75f); +static void compute_sss_translucence_kernel(const GPUSssKernelData *kd, + int resolution, + short falloff_type, + float sharpness, + float **output) +{ + float(*texels)[4]; + texels = MEM_callocN(sizeof(float) * 4 * resolution, "compute_sss_translucence_kernel"); + *output = (float *)texels; + + /* Last texel should be black, hence the - 1. */ + for (int i = 0; i < resolution - 1; ++i) { + /* Distance from surface. */ + float d = kd->max_radius * ((float)i + 0.00001f) / ((float)resolution); + + /* For each distance d we compute the radiance incoming from an hypothetic parallel plane. */ + /* Compute radius of the footprint on the hypothetic plane */ + float r_fp = sqrtf(kd->max_radius * kd->max_radius - d * d); + float r_step = r_fp / INTEGRAL_RESOLUTION; + float area_accum = 0.0f; + for (float r = 0.0f; r < r_fp; r += r_step) { + /* Compute distance to the "shading" point through the medium. */ + /* r_step * 0.5f to put sample between the area borders */ + float dist = hypotf(r + r_step * 0.5f, d); + + float profile[3]; + profile[0] = eval_profile(dist, falloff_type, sharpness, kd->param[0]); + profile[1] = eval_profile(dist, falloff_type, sharpness, kd->param[1]); + profile[2] = eval_profile(dist, falloff_type, sharpness, kd->param[2]); + + /* Since the profile and configuration are radially symmetrical we + * can just evaluate it once and weight it accordingly */ + float r_next = r + r_step; + float disk_area = (M_PI * r_next * r_next) - (M_PI * r * r); + + mul_v3_fl(profile, disk_area); + add_v3_v3(texels[i], profile); + area_accum += disk_area; + } + /* Normalize over the disk. */ + mul_v3_fl(texels[i], 1.0f / (area_accum)); + } + + /* Normalize */ + for (int j = resolution - 2; j > 0; j--) { + texels[j][0] /= (texels[0][0] > 0.0f) ? texels[0][0] : 1.0f; + texels[j][1] /= (texels[0][1] > 0.0f) ? texels[0][1] : 1.0f; + texels[j][2] /= (texels[0][2] > 0.0f) ? texels[0][2] : 1.0f; + } + + /* First texel should be white */ + texels[0][0] = (texels[0][0] > 0.0f) ? 1.0f : 0.0f; + texels[0][1] = (texels[0][1] > 0.0f) ? 1.0f : 0.0f; + texels[0][2] = (texels[0][2] > 0.0f) ? 1.0f : 0.0f; + + /* dim the last few texels for smoother transition */ + mul_v3_fl(texels[resolution - 2], 0.25f); + mul_v3_fl(texels[resolution - 3], 0.5f); + mul_v3_fl(texels[resolution - 4], 0.75f); } #undef INTEGRAL_RESOLUTION -void GPU_material_sss_profile_create(GPUMaterial *material, float radii[3], short *falloff_type, float *sharpness) +void GPU_material_sss_profile_create(GPUMaterial *material, + float radii[3], + short *falloff_type, + float *sharpness) { - copy_v3_v3(material->sss_radii, radii); - material->sss_falloff = (falloff_type) ? *falloff_type : 0.0; - material->sss_sharpness = (sharpness) ? *sharpness : 0.0; - material->sss_dirty = true; - material->sss_enabled = true; + copy_v3_v3(material->sss_radii, radii); + material->sss_falloff = (falloff_type) ? *falloff_type : 0.0; + material->sss_sharpness = (sharpness) ? *sharpness : 0.0; + material->sss_dirty = true; + material->sss_enabled = true; - /* Update / Create UBO */ - if (material->sss_profile == NULL) { - material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL); - } + /* Update / Create UBO */ + if (material->sss_profile == NULL) { + material->sss_profile = GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL); + } } -struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, int sample_len, GPUTexture **tex_profile) +struct GPUUniformBuffer *GPU_material_sss_profile_get(GPUMaterial *material, + int sample_len, + GPUTexture **tex_profile) { - if (!material->sss_enabled) - return NULL; + if (!material->sss_enabled) + return NULL; - if (material->sss_dirty || (material->sss_samples != sample_len)) { - GPUSssKernelData kd; + if (material->sss_dirty || (material->sss_samples != sample_len)) { + GPUSssKernelData kd; - float sharpness = material->sss_sharpness; + float sharpness = material->sss_sharpness; - /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */ - sharpness *= 0.5f; + /* XXX Black magic but it seems to fit. Maybe because we integrate -1..1 */ + sharpness *= 0.5f; - compute_sss_kernel(&kd, material->sss_radii, sample_len, material->sss_falloff, sharpness); + compute_sss_kernel(&kd, material->sss_radii, sample_len, material->sss_falloff, sharpness); - /* Update / Create UBO */ - GPU_uniformbuffer_update(material->sss_profile, &kd); + /* Update / Create UBO */ + GPU_uniformbuffer_update(material->sss_profile, &kd); - /* Update / Create Tex */ - float *translucence_profile; - compute_sss_translucence_kernel(&kd, 64, material->sss_falloff, sharpness, &translucence_profile); + /* Update / Create Tex */ + float *translucence_profile; + compute_sss_translucence_kernel( + &kd, 64, material->sss_falloff, sharpness, &translucence_profile); - if (material->sss_tex_profile != NULL) { - GPU_texture_free(material->sss_tex_profile); - } + if (material->sss_tex_profile != NULL) { + GPU_texture_free(material->sss_tex_profile); + } - material->sss_tex_profile = GPU_texture_create_1d(64, GPU_RGBA16F, translucence_profile, NULL); + material->sss_tex_profile = GPU_texture_create_1d(64, GPU_RGBA16F, translucence_profile, NULL); - MEM_freeN(translucence_profile); + MEM_freeN(translucence_profile); - material->sss_samples = sample_len; - material->sss_dirty = false; - } + material->sss_samples = sample_len; + material->sss_dirty = false; + } - if (tex_profile != NULL) { - *tex_profile = material->sss_tex_profile; - } - return material->sss_profile; + if (tex_profile != NULL) { + *tex_profile = material->sss_tex_profile; + } + return material->sss_profile; } struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void) { - return GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL); + return GPU_uniformbuffer_create(sizeof(GPUSssKernelData), NULL, NULL); } #undef SSS_EXPONENT @@ -563,69 +572,68 @@ struct GPUUniformBuffer *GPU_material_create_sss_profile_ubo(void) void GPU_material_vertex_attrs(GPUMaterial *material, GPUVertAttrLayers *r_attrs) { - *r_attrs = material->attrs; + *r_attrs = material->attrs; } void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link) { - if (!material->outlink) - material->outlink = link; + if (!material->outlink) + material->outlink = link; } void gpu_material_add_node(GPUMaterial *material, GPUNode *node) { - BLI_addtail(&material->nodes, node); + BLI_addtail(&material->nodes, node); } /* Return true if the material compilation has not yet begin or begin. */ eGPUMaterialStatus GPU_material_status(GPUMaterial *mat) { - return mat->status; + return mat->status; } /* Code generation */ bool GPU_material_do_color_management(GPUMaterial *mat) { - if (!BKE_scene_check_color_management_enabled(mat->scene)) - return false; + if (!BKE_scene_check_color_management_enabled(mat->scene)) + return false; - return true; + return true; } bool GPU_material_use_domain_surface(GPUMaterial *mat) { - return (mat->domain & GPU_DOMAIN_SURFACE); + return (mat->domain & GPU_DOMAIN_SURFACE); } bool GPU_material_use_domain_volume(GPUMaterial *mat) { - return (mat->domain & GPU_DOMAIN_VOLUME); + return (mat->domain & GPU_DOMAIN_VOLUME); } void GPU_material_flag_set(GPUMaterial *mat, eGPUMatFlag flag) { - mat->flag |= flag; + mat->flag |= flag; } bool GPU_material_flag_get(GPUMaterial *mat, eGPUMatFlag flag) { - return (mat->flag & flag); + return (mat->flag & flag); } -GPUMaterial *GPU_material_from_nodetree_find( - ListBase *gpumaterials, const void *engine_type, int options) +GPUMaterial *GPU_material_from_nodetree_find(ListBase *gpumaterials, + const void *engine_type, + int options) { - for (LinkData *link = gpumaterials->first; link; link = link->next) { - GPUMaterial *current_material = (GPUMaterial *)link->data; - if (current_material->engine_type == engine_type && - current_material->options == options) - { - return current_material; - } - } + for (LinkData *link = gpumaterials->first; link; link = link->next) { + GPUMaterial *current_material = (GPUMaterial *)link->data; + if (current_material->engine_type == engine_type && current_material->options == options) { + return current_material; + } + } - return NULL; + return NULL; } /** @@ -633,132 +641,138 @@ GPUMaterial *GPU_material_from_nodetree_find( * This is enforced since constructing other arguments to this function may be expensive * so only do this when they are needed. */ -GPUMaterial *GPU_material_from_nodetree( - Scene *scene, struct bNodeTree *ntree, ListBase *gpumaterials, const void *engine_type, int options, - const char *vert_code, const char *geom_code, const char *frag_lib, const char *defines, const char *name) -{ - LinkData *link; - bool has_volume_output, has_surface_output; - - /* Caller must re-use materials. */ - BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL); - - /* allocate material */ - GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); - mat->scene = scene; - mat->engine_type = engine_type; - mat->options = options; +GPUMaterial *GPU_material_from_nodetree(Scene *scene, + struct bNodeTree *ntree, + ListBase *gpumaterials, + const void *engine_type, + int options, + const char *vert_code, + const char *geom_code, + const char *frag_lib, + const char *defines, + const char *name) +{ + LinkData *link; + bool has_volume_output, has_surface_output; + + /* Caller must re-use materials. */ + BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL); + + /* allocate material */ + GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial"); + mat->scene = scene; + mat->engine_type = engine_type; + mat->options = options; #ifndef NDEBUG - BLI_snprintf(mat->name, sizeof(mat->name), "%s", name); + BLI_snprintf(mat->name, sizeof(mat->name), "%s", name); #else - UNUSED_VARS(name); + UNUSED_VARS(name); #endif - /* localize tree to create links for reroute and mute */ - bNodeTree *localtree = ntreeLocalize(ntree); - ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output); - - gpu_material_ramp_texture_build(mat); - - if (has_surface_output) { - mat->domain |= GPU_DOMAIN_SURFACE; - } - if (has_volume_output) { - mat->domain |= GPU_DOMAIN_VOLUME; - } - - if (mat->outlink) { - /* Prune the unused nodes and extract attributes before compiling so the - * generated VBOs are ready to accept the future shader. */ - GPU_nodes_prune(&mat->nodes, mat->outlink); - GPU_nodes_get_vertex_attrs(&mat->nodes, &mat->attrs); - /* Create source code and search pass cache for an already compiled version. */ - mat->pass = GPU_generate_pass( - mat, - mat->outlink, - &mat->attrs, - &mat->nodes, - &mat->builtins, - vert_code, - geom_code, - frag_lib, - defines); - - if (mat->pass == NULL) { - /* We had a cache hit and the shader has already failed to compile. */ - mat->status = GPU_MAT_FAILED; - } - else { - GPUShader *sh = GPU_pass_shader_get(mat->pass); - if (sh != NULL) { - /* We had a cache hit and the shader is already compiled. */ - mat->status = GPU_MAT_SUCCESS; - GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes); - } - else { - mat->status = GPU_MAT_QUEUED; - } - } - } - else { - mat->status = GPU_MAT_FAILED; - } - - /* Only free after GPU_pass_shader_get where GPUUniformBuffer - * read data from the local tree. */ - ntreeFreeLocalTree(localtree); - MEM_freeN(localtree); - - /* note that even if building the shader fails in some way, we still keep - * it to avoid trying to compile again and again, and simply do not use - * the actual shader on drawing */ - - link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); - link->data = mat; - BLI_addtail(gpumaterials, link); - - return mat; + /* localize tree to create links for reroute and mute */ + bNodeTree *localtree = ntreeLocalize(ntree); + ntreeGPUMaterialNodes(localtree, mat, &has_surface_output, &has_volume_output); + + gpu_material_ramp_texture_build(mat); + + if (has_surface_output) { + mat->domain |= GPU_DOMAIN_SURFACE; + } + if (has_volume_output) { + mat->domain |= GPU_DOMAIN_VOLUME; + } + + if (mat->outlink) { + /* Prune the unused nodes and extract attributes before compiling so the + * generated VBOs are ready to accept the future shader. */ + GPU_nodes_prune(&mat->nodes, mat->outlink); + GPU_nodes_get_vertex_attrs(&mat->nodes, &mat->attrs); + /* Create source code and search pass cache for an already compiled version. */ + mat->pass = GPU_generate_pass(mat, + mat->outlink, + &mat->attrs, + &mat->nodes, + &mat->builtins, + vert_code, + geom_code, + frag_lib, + defines); + + if (mat->pass == NULL) { + /* We had a cache hit and the shader has already failed to compile. */ + mat->status = GPU_MAT_FAILED; + } + else { + GPUShader *sh = GPU_pass_shader_get(mat->pass); + if (sh != NULL) { + /* We had a cache hit and the shader is already compiled. */ + mat->status = GPU_MAT_SUCCESS; + GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes); + } + else { + mat->status = GPU_MAT_QUEUED; + } + } + } + else { + mat->status = GPU_MAT_FAILED; + } + + /* Only free after GPU_pass_shader_get where GPUUniformBuffer + * read data from the local tree. */ + ntreeFreeLocalTree(localtree); + MEM_freeN(localtree); + + /* note that even if building the shader fails in some way, we still keep + * it to avoid trying to compile again and again, and simply do not use + * the actual shader on drawing */ + + link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink"); + link->data = mat; + BLI_addtail(gpumaterials, link); + + return mat; } void GPU_material_compile(GPUMaterial *mat) { - /* Only run once! */ - BLI_assert(mat->status == GPU_MAT_QUEUED); - BLI_assert(mat->pass); + /* Only run once! */ + BLI_assert(mat->status == GPU_MAT_QUEUED); + BLI_assert(mat->pass); - /* NOTE: The shader may have already been compiled here since we are - * sharing GPUShader across GPUMaterials. In this case it's a no-op. */ + /* NOTE: The shader may have already been compiled here since we are + * sharing GPUShader across GPUMaterials. In this case it's a no-op. */ #ifndef NDEBUG - GPU_pass_compile(mat->pass, mat->name); + GPU_pass_compile(mat->pass, mat->name); #else - GPU_pass_compile(mat->pass, __func__); + GPU_pass_compile(mat->pass, __func__); #endif - GPUShader *sh = GPU_pass_shader_get(mat->pass); + GPUShader *sh = GPU_pass_shader_get(mat->pass); - if (sh != NULL) { - mat->status = GPU_MAT_SUCCESS; - GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes); - } - else { - mat->status = GPU_MAT_FAILED; - GPU_pass_free_nodes(&mat->nodes); - GPU_pass_release(mat->pass); - mat->pass = NULL; - } + if (sh != NULL) { + mat->status = GPU_MAT_SUCCESS; + GPU_nodes_extract_dynamic_inputs(sh, &mat->inputs, &mat->nodes); + } + else { + mat->status = GPU_MAT_FAILED; + GPU_pass_free_nodes(&mat->nodes); + GPU_pass_release(mat->pass); + mat->pass = NULL; + } } void GPU_materials_free(Main *bmain) { - Material *ma; - World *wo; - extern Material defmaterial; + Material *ma; + World *wo; + extern Material defmaterial; - for (ma = bmain->materials.first; ma; ma = ma->id.next) - GPU_material_free(&ma->gpumaterial); + for (ma = bmain->materials.first; ma; ma = ma->id.next) + GPU_material_free(&ma->gpumaterial); - for (wo = bmain->worlds.first; wo; wo = wo->id.next) - GPU_material_free(&wo->gpumaterial); + for (wo = bmain->worlds.first; wo; wo = wo->id.next) + GPU_material_free(&wo->gpumaterial); - GPU_material_free(&defmaterial.gpumaterial); + GPU_material_free(&defmaterial.gpumaterial); } diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c index 9f0a5851390..667ee7f6e47 100644 --- a/source/blender/gpu/intern/gpu_matrix.c +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -24,7 +24,7 @@ #include "GPU_shader_interface.h" #define SUPPRESS_GENERIC_MATRIX_API -#define USE_GPU_PY_MATRIX_API /* only so values are declared */ +#define USE_GPU_PY_MATRIX_API /* only so values are declared */ #include "GPU_matrix.h" #undef USE_GPU_PY_MATRIX_API @@ -32,7 +32,6 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.h" - #define DEBUG_MATRIX_BIND 0 #define MATRIX_STACK_DEPTH 32 @@ -41,33 +40,36 @@ typedef float Mat4[4][4]; typedef float Mat3[3][3]; typedef struct MatrixStack { - Mat4 stack[MATRIX_STACK_DEPTH]; - uint top; + Mat4 stack[MATRIX_STACK_DEPTH]; + uint top; } MatrixStack; typedef struct { - MatrixStack model_view_stack; - MatrixStack projection_stack; + MatrixStack model_view_stack; + MatrixStack projection_stack; - bool dirty; + bool dirty; - /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc) - * generate as needed for shaders, invalidate when original matrices change - * - * TODO: separate Model from View transform? Batches/objects have model, - * camera/eye has view & projection - */ + /* TODO: cache of derived matrices (Normal, MVP, inverse MVP, etc) + * generate as needed for shaders, invalidate when original matrices change + * + * TODO: separate Model from View transform? Batches/objects have model, + * camera/eye has view & projection + */ } MatrixState; -#define MATRIX_4X4_IDENTITY {{1.0f, 0.0f, 0.0f, 0.0f}, \ - {0.0f, 1.0f, 0.0f, 0.0f}, \ - {0.0f, 0.0f, 1.0f, 0.0f}, \ - {0.0f, 0.0f, 0.0f, 1.0f}} +#define MATRIX_4X4_IDENTITY \ + { \ + {1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 1.0f, 0.0f}, \ + { \ + 0.0f, 0.0f, 0.0f, 1.0f \ + } \ + } static MatrixState state = { - .model_view_stack = {{MATRIX_4X4_IDENTITY}, 0}, - .projection_stack = {{MATRIX_4X4_IDENTITY}, 0}, - .dirty = true, + .model_view_stack = {{MATRIX_4X4_IDENTITY}, 0}, + .projection_stack = {{MATRIX_4X4_IDENTITY}, 0}, + .dirty = true, }; #undef MATRIX_4X4_IDENTITY @@ -80,11 +82,11 @@ static MatrixState state = { void GPU_matrix_reset(void) { - state.model_view_stack.top = 0; - state.projection_stack.top = 0; - unit_m4(ModelView); - unit_m4(Projection); - state.dirty = true; + state.model_view_stack.top = 0; + state.projection_stack.top = 0; + unit_m4(ModelView); + unit_m4(Projection); + state.dirty = true; } #ifdef WITH_GPU_SAFETY @@ -92,241 +94,242 @@ void GPU_matrix_reset(void) /* Check if matrix is numerically good */ static void checkmat(cosnt float *m) { - const int n = 16; - for (int i = 0; i < n; i++) { -#if _MSC_VER - BLI_assert(_finite(m[i])); -#else - BLI_assert(!isinf(m[i])); -#endif - } + const int n = 16; + for (int i = 0; i < n; i++) { +# if _MSC_VER + BLI_assert(_finite(m[i])); +# else + BLI_assert(!isinf(m[i])); +# endif + } } -#define CHECKMAT(m) checkmat((const float *)m) +# define CHECKMAT(m) checkmat((const float *)m) #else -#define CHECKMAT(m) +# define CHECKMAT(m) #endif - void GPU_matrix_push(void) { - BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH); - ModelViewStack.top++; - copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]); + BLI_assert(ModelViewStack.top + 1 < MATRIX_STACK_DEPTH); + ModelViewStack.top++; + copy_m4_m4(ModelView, ModelViewStack.stack[ModelViewStack.top - 1]); } void GPU_matrix_pop(void) { - BLI_assert(ModelViewStack.top > 0); - ModelViewStack.top--; - state.dirty = true; + BLI_assert(ModelViewStack.top > 0); + ModelViewStack.top--; + state.dirty = true; } void GPU_matrix_push_projection(void) { - BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH); - ProjectionStack.top++; - copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]); + BLI_assert(ProjectionStack.top + 1 < MATRIX_STACK_DEPTH); + ProjectionStack.top++; + copy_m4_m4(Projection, ProjectionStack.stack[ProjectionStack.top - 1]); } void GPU_matrix_pop_projection(void) { - BLI_assert(ProjectionStack.top > 0); - ProjectionStack.top--; - state.dirty = true; + BLI_assert(ProjectionStack.top > 0); + ProjectionStack.top--; + state.dirty = true; } void GPU_matrix_set(const float m[4][4]) { - copy_m4_m4(ModelView, m); - CHECKMAT(ModelView3D); - state.dirty = true; + copy_m4_m4(ModelView, m); + CHECKMAT(ModelView3D); + state.dirty = true; } void GPU_matrix_identity_projection_set(void) { - unit_m4(Projection); - CHECKMAT(Projection3D); - state.dirty = true; + unit_m4(Projection); + CHECKMAT(Projection3D); + state.dirty = true; } void GPU_matrix_projection_set(const float m[4][4]) { - copy_m4_m4(Projection, m); - CHECKMAT(Projection3D); - state.dirty = true; + copy_m4_m4(Projection, m); + CHECKMAT(Projection3D); + state.dirty = true; } void GPU_matrix_identity_set(void) { - unit_m4(ModelView); - state.dirty = true; + unit_m4(ModelView); + state.dirty = true; } void GPU_matrix_translate_2f(float x, float y) { - Mat4 m; - unit_m4(m); - m[3][0] = x; - m[3][1] = y; - GPU_matrix_mul(m); + Mat4 m; + unit_m4(m); + m[3][0] = x; + m[3][1] = y; + GPU_matrix_mul(m); } void GPU_matrix_translate_2fv(const float vec[2]) { - GPU_matrix_translate_2f(vec[0], vec[1]); + GPU_matrix_translate_2f(vec[0], vec[1]); } void GPU_matrix_translate_3f(float x, float y, float z) { #if 1 - translate_m4(ModelView, x, y, z); - CHECKMAT(ModelView); + translate_m4(ModelView, x, y, z); + CHECKMAT(ModelView); #else /* above works well in early testing, below is generic version */ - Mat4 m; - unit_m4(m); - m[3][0] = x; - m[3][1] = y; - m[3][2] = z; - GPU_matrix_mul(m); + Mat4 m; + unit_m4(m); + m[3][0] = x; + m[3][1] = y; + m[3][2] = z; + GPU_matrix_mul(m); #endif - state.dirty = true; + state.dirty = true; } void GPU_matrix_translate_3fv(const float vec[3]) { - GPU_matrix_translate_3f(vec[0], vec[1], vec[2]); + GPU_matrix_translate_3f(vec[0], vec[1], vec[2]); } void GPU_matrix_scale_1f(float factor) { - Mat4 m; - scale_m4_fl(m, factor); - GPU_matrix_mul(m); + Mat4 m; + scale_m4_fl(m, factor); + GPU_matrix_mul(m); } void GPU_matrix_scale_2f(float x, float y) { - Mat4 m = {{0.0f}}; - m[0][0] = x; - m[1][1] = y; - m[2][2] = 1.0f; - m[3][3] = 1.0f; - GPU_matrix_mul(m); + Mat4 m = {{0.0f}}; + m[0][0] = x; + m[1][1] = y; + m[2][2] = 1.0f; + m[3][3] = 1.0f; + GPU_matrix_mul(m); } void GPU_matrix_scale_2fv(const float vec[2]) { - GPU_matrix_scale_2f(vec[0], vec[1]); + GPU_matrix_scale_2f(vec[0], vec[1]); } void GPU_matrix_scale_3f(float x, float y, float z) { - Mat4 m = {{0.0f}}; - m[0][0] = x; - m[1][1] = y; - m[2][2] = z; - m[3][3] = 1.0f; - GPU_matrix_mul(m); + Mat4 m = {{0.0f}}; + m[0][0] = x; + m[1][1] = y; + m[2][2] = z; + m[3][3] = 1.0f; + GPU_matrix_mul(m); } void GPU_matrix_scale_3fv(const float vec[3]) { - GPU_matrix_scale_3f(vec[0], vec[1], vec[2]); + GPU_matrix_scale_3f(vec[0], vec[1], vec[2]); } void GPU_matrix_mul(const float m[4][4]) { - mul_m4_m4_post(ModelView, m); - CHECKMAT(ModelView); - state.dirty = true; + mul_m4_m4_post(ModelView, m); + CHECKMAT(ModelView); + state.dirty = true; } void GPU_matrix_rotate_2d(float deg) { - /* essentially RotateAxis('Z') - * TODO: simpler math for 2D case - */ - rotate_m4(ModelView, 'Z', DEG2RADF(deg)); + /* essentially RotateAxis('Z') + * TODO: simpler math for 2D case + */ + rotate_m4(ModelView, 'Z', DEG2RADF(deg)); } void GPU_matrix_rotate_3f(float deg, float x, float y, float z) { - const float axis[3] = {x, y, z}; - GPU_matrix_rotate_3fv(deg, axis); + const float axis[3] = {x, y, z}; + GPU_matrix_rotate_3fv(deg, axis); } void GPU_matrix_rotate_3fv(float deg, const float axis[3]) { - Mat4 m; - axis_angle_to_mat4(m, axis, DEG2RADF(deg)); - GPU_matrix_mul(m); + Mat4 m; + axis_angle_to_mat4(m, axis, DEG2RADF(deg)); + GPU_matrix_mul(m); } void GPU_matrix_rotate_axis(float deg, char axis) { - /* rotate_m4 works in place */ - rotate_m4(ModelView, axis, DEG2RADF(deg)); - CHECKMAT(ModelView); - state.dirty = true; + /* rotate_m4 works in place */ + rotate_m4(ModelView, axis, DEG2RADF(deg)); + CHECKMAT(ModelView); + state.dirty = true; } -static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, float top, float near, float far) +static void mat4_ortho_set( + float m[4][4], float left, float right, float bottom, float top, float near, float far) { - m[0][0] = 2.0f / (right - left); - m[1][0] = 0.0f; - m[2][0] = 0.0f; - m[3][0] = -(right + left) / (right - left); + m[0][0] = 2.0f / (right - left); + m[1][0] = 0.0f; + m[2][0] = 0.0f; + m[3][0] = -(right + left) / (right - left); - m[0][1] = 0.0f; - m[1][1] = 2.0f / (top - bottom); - m[2][1] = 0.0f; - m[3][1] = -(top + bottom) / (top - bottom); + m[0][1] = 0.0f; + m[1][1] = 2.0f / (top - bottom); + m[2][1] = 0.0f; + m[3][1] = -(top + bottom) / (top - bottom); - m[0][2] = 0.0f; - m[1][2] = 0.0f; - m[2][2] = -2.0f / (far - near); - m[3][2] = -(far + near) / (far - near); + m[0][2] = 0.0f; + m[1][2] = 0.0f; + m[2][2] = -2.0f / (far - near); + m[3][2] = -(far + near) / (far - near); - m[0][3] = 0.0f; - m[1][3] = 0.0f; - m[2][3] = 0.0f; - m[3][3] = 1.0f; + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; - state.dirty = true; + state.dirty = true; } -static void mat4_frustum_set(float m[4][4], float left, float right, float bottom, float top, float near, float far) +static void mat4_frustum_set( + float m[4][4], float left, float right, float bottom, float top, float near, float far) { - m[0][0] = 2.0f * near / (right - left); - m[1][0] = 0.0f; - m[2][0] = (right + left) / (right - left); - m[3][0] = 0.0f; + m[0][0] = 2.0f * near / (right - left); + m[1][0] = 0.0f; + m[2][0] = (right + left) / (right - left); + m[3][0] = 0.0f; - m[0][1] = 0.0f; - m[1][1] = 2.0f * near / (top - bottom); - m[2][1] = (top + bottom) / (top - bottom); - m[3][1] = 0.0f; + m[0][1] = 0.0f; + m[1][1] = 2.0f * near / (top - bottom); + m[2][1] = (top + bottom) / (top - bottom); + m[3][1] = 0.0f; - m[0][2] = 0.0f; - m[1][2] = 0.0f; - m[2][2] = -(far + near) / (far - near); - m[3][2] = -2.0f * far * near / (far - near); + m[0][2] = 0.0f; + m[1][2] = 0.0f; + m[2][2] = -(far + near) / (far - near); + m[3][2] = -2.0f * far * near / (far - near); - m[0][3] = 0.0f; - m[1][3] = 0.0f; - m[2][3] = -1.0f; - m[3][3] = 0.0f; + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = -1.0f; + m[3][3] = 0.0f; - state.dirty = true; + state.dirty = true; } static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3]) { -/* This function is loosely based on Mesa implementation. + /* This function is loosely based on Mesa implementation. * * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. @@ -357,98 +360,111 @@ static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3 * Silicon Graphics, Inc. */ - float side[3]; + float side[3]; - normalize_v3(lookdir); + normalize_v3(lookdir); - cross_v3_v3v3(side, lookdir, camup); + cross_v3_v3v3(side, lookdir, camup); - normalize_v3(side); + normalize_v3(side); - cross_v3_v3v3(camup, side, lookdir); + cross_v3_v3v3(camup, side, lookdir); - m[0][0] = side[0]; - m[1][0] = side[1]; - m[2][0] = side[2]; - m[3][0] = 0.0f; + m[0][0] = side[0]; + m[1][0] = side[1]; + m[2][0] = side[2]; + m[3][0] = 0.0f; - m[0][1] = camup[0]; - m[1][1] = camup[1]; - m[2][1] = camup[2]; - m[3][1] = 0.0f; + m[0][1] = camup[0]; + m[1][1] = camup[1]; + m[2][1] = camup[2]; + m[3][1] = 0.0f; - m[0][2] = -lookdir[0]; - m[1][2] = -lookdir[1]; - m[2][2] = -lookdir[2]; - m[3][2] = 0.0f; + m[0][2] = -lookdir[0]; + m[1][2] = -lookdir[1]; + m[2][2] = -lookdir[2]; + m[3][2] = 0.0f; - m[0][3] = 0.0f; - m[1][3] = 0.0f; - m[2][3] = 0.0f; - m[3][3] = 1.0f; + m[0][3] = 0.0f; + m[1][3] = 0.0f; + m[2][3] = 0.0f; + m[3][3] = 1.0f; - state.dirty = true; + state.dirty = true; } void GPU_matrix_ortho_set(float left, float right, float bottom, float top, float near, float far) { - mat4_ortho_set(Projection, left, right, bottom, top, near, far); - CHECKMAT(Projection); - state.dirty = true; + mat4_ortho_set(Projection, left, right, bottom, top, near, far); + CHECKMAT(Projection); + state.dirty = true; } void GPU_matrix_ortho_2d_set(float left, float right, float bottom, float top) { - Mat4 m; - mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f); - CHECKMAT(Projection2D); - state.dirty = true; + Mat4 m; + mat4_ortho_set(m, left, right, bottom, top, -1.0f, 1.0f); + CHECKMAT(Projection2D); + state.dirty = true; } -void GPU_matrix_frustum_set(float left, float right, float bottom, float top, float near, float far) +void GPU_matrix_frustum_set( + float left, float right, float bottom, float top, float near, float far) { - mat4_frustum_set(Projection, left, right, bottom, top, near, far); - CHECKMAT(Projection); - state.dirty = true; + mat4_frustum_set(Projection, left, right, bottom, top, near, far); + CHECKMAT(Projection); + state.dirty = true; } void GPU_matrix_perspective_set(float fovy, float aspect, float near, float far) { - float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near; - float half_width = half_height * aspect; - GPU_matrix_frustum_set(-half_width, +half_width, -half_height, +half_height, near, far); + float half_height = tanf(fovy * (float)(M_PI / 360.0)) * near; + float half_width = half_height * aspect; + GPU_matrix_frustum_set(-half_width, +half_width, -half_height, +half_height, near, far); } -void GPU_matrix_look_at(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) +void GPU_matrix_look_at(float eyeX, + float eyeY, + float eyeZ, + float centerX, + float centerY, + float centerZ, + float upX, + float upY, + float upZ) { - Mat4 cm; - float lookdir[3]; - float camup[3] = {upX, upY, upZ}; + Mat4 cm; + float lookdir[3]; + float camup[3] = {upX, upY, upZ}; - lookdir[0] = centerX - eyeX; - lookdir[1] = centerY - eyeY; - lookdir[2] = centerZ - eyeZ; + lookdir[0] = centerX - eyeX; + lookdir[1] = centerY - eyeY; + lookdir[2] = centerZ - eyeZ; - mat4_look_from_origin(cm, lookdir, camup); + mat4_look_from_origin(cm, lookdir, camup); - GPU_matrix_mul(cm); - GPU_matrix_translate_3f(-eyeX, -eyeY, -eyeZ); + GPU_matrix_mul(cm); + GPU_matrix_translate_3f(-eyeX, -eyeY, -eyeZ); } -void GPU_matrix_project(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]) +void GPU_matrix_project(const float world[3], + const float model[4][4], + const float proj[4][4], + const int view[4], + float win[3]) { - float v[4]; + float v[4]; - mul_v4_m4v3(v, model, world); - mul_m4_v4(proj, v); + mul_v4_m4v3(v, model, world); + mul_m4_v4(proj, v); - if (v[3] != 0.0f) { - mul_v3_fl(v, 1.0f / v[3]); - } + if (v[3] != 0.0f) { + mul_v3_fl(v, 1.0f / v[3]); + } - win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f; - win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f; - win[2] = (v[2] + 1) * 0.5f; + win[0] = view[0] + (view[2] * (v[0] + 1)) * 0.5f; + win[1] = view[1] + (view[3] * (v[1] + 1)) * 0.5f; + win[2] = (v[2] + 1) * 0.5f; } /** @@ -468,179 +484,186 @@ void GPU_matrix_project(const float world[3], const float model[4][4], const flo */ static void gpu_mul_invert_projmat_m4_unmapped_v3(const float projmat[4][4], float co[3]) { - float left, right, bottom, top, near, far; - bool is_persp = projmat[3][3] == 0.0f; + float left, right, bottom, top, near, far; + bool is_persp = projmat[3][3] == 0.0f; - projmat_dimensions( - projmat, &left, &right, &bottom, &top, &near, &far); + projmat_dimensions(projmat, &left, &right, &bottom, &top, &near, &far); - co[0] = left + co[0] * (right - left); - co[1] = bottom + co[1] * (top - bottom); + co[0] = left + co[0] * (right - left); + co[1] = bottom + co[1] * (top - bottom); - if (is_persp) { - co[2] = far * near / (far + co[2] * (near - far)); - co[0] *= co[2]; - co[1] *= co[2]; - } - else { - co[2] = near + co[2] * (far - near); - } - co[2] *= -1; + if (is_persp) { + co[2] = far * near / (far + co[2] * (near - far)); + co[0] *= co[2]; + co[1] *= co[2]; + } + else { + co[2] = near + co[2] * (far - near); + } + co[2] *= -1; } -bool GPU_matrix_unproject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]) +bool GPU_matrix_unproject(const float win[3], + const float model[4][4], + const float proj[4][4], + const int view[4], + float world[3]) { - float in[3]; - float viewinv[4][4]; + float in[3]; + float viewinv[4][4]; - if (!invert_m4_m4(viewinv, model)) { - zero_v3(world); - return false; - } + if (!invert_m4_m4(viewinv, model)) { + zero_v3(world); + return false; + } - copy_v3_v3(in, win); + copy_v3_v3(in, win); - /* Map x and y from window coordinates */ - in[0] = (in[0] - view[0]) / view[2]; - in[1] = (in[1] - view[1]) / view[3]; + /* Map x and y from window coordinates */ + in[0] = (in[0] - view[0]) / view[2]; + in[1] = (in[1] - view[1]) / view[3]; - gpu_mul_invert_projmat_m4_unmapped_v3(proj, in); - mul_v3_m4v3(world, viewinv, in); + gpu_mul_invert_projmat_m4_unmapped_v3(proj, in); + mul_v3_m4v3(world, viewinv, in); - return true; + return true; } const float (*GPU_matrix_model_view_get(float m[4][4]))[4] { - if (m) { - copy_m4_m4(m, ModelView); - return m; - } - else { - return ModelView; - } + if (m) { + copy_m4_m4(m, ModelView); + return m; + } + else { + return ModelView; + } } const float (*GPU_matrix_projection_get(float m[4][4]))[4] { - if (m) { - copy_m4_m4(m, Projection); - return m; - } - else { - return Projection; - } + if (m) { + copy_m4_m4(m, Projection); + return m; + } + else { + return Projection; + } } const float (*GPU_matrix_model_view_projection_get(float m[4][4]))[4] { - if (m == NULL) { - static Mat4 temp; - m = temp; - } + if (m == NULL) { + static Mat4 temp; + m = temp; + } - mul_m4_m4m4(m, Projection, ModelView); - return m; + mul_m4_m4m4(m, Projection, ModelView); + return m; } const float (*GPU_matrix_normal_get(float m[3][3]))[3] { - if (m == NULL) { - static Mat3 temp3; - m = temp3; - } + if (m == NULL) { + static Mat3 temp3; + m = temp3; + } - copy_m3_m4(m, (const float (*)[4])GPU_matrix_model_view_get(NULL)); + copy_m3_m4(m, (const float(*)[4])GPU_matrix_model_view_get(NULL)); - invert_m3(m); - transpose_m3(m); + invert_m3(m); + transpose_m3(m); - return m; + return m; } const float (*GPU_matrix_normal_inverse_get(float m[3][3]))[3] { - if (m == NULL) { - static Mat3 temp3; - m = temp3; - } + if (m == NULL) { + static Mat3 temp3; + m = temp3; + } - GPU_matrix_normal_get(m); - invert_m3(m); + GPU_matrix_normal_get(m); + invert_m3(m); - return m; + return m; } void GPU_matrix_bind(const GPUShaderInterface *shaderface) { - /* set uniform values to matrix stack values - * call this before a draw call if desired matrices are dirty - * call glUseProgram before this, as glUniform expects program to be bound - */ + /* set uniform values to matrix stack values + * call this before a draw call if desired matrices are dirty + * call glUseProgram before this, as glUniform expects program to be bound + */ - const GPUShaderInput *MV = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW); - const GPUShaderInput *P = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION); - const GPUShaderInput *MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP); + const GPUShaderInput *MV = GPU_shaderinterface_uniform_builtin(shaderface, + GPU_UNIFORM_MODELVIEW); + const GPUShaderInput *P = GPU_shaderinterface_uniform_builtin(shaderface, + GPU_UNIFORM_PROJECTION); + const GPUShaderInput *MVP = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MVP); - const GPUShaderInput *N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL); - const GPUShaderInput *MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_MODELVIEW_INV); - const GPUShaderInput *P_inv = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_PROJECTION_INV); + const GPUShaderInput *N = GPU_shaderinterface_uniform_builtin(shaderface, GPU_UNIFORM_NORMAL); + const GPUShaderInput *MV_inv = GPU_shaderinterface_uniform_builtin(shaderface, + GPU_UNIFORM_MODELVIEW_INV); + const GPUShaderInput *P_inv = GPU_shaderinterface_uniform_builtin(shaderface, + GPU_UNIFORM_PROJECTION_INV); - if (MV) { + if (MV) { #if DEBUG_MATRIX_BIND - puts("setting MV matrix"); + puts("setting MV matrix"); #endif - glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL)); - } + glUniformMatrix4fv(MV->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_get(NULL)); + } - if (P) { + if (P) { #if DEBUG_MATRIX_BIND - puts("setting P matrix"); + puts("setting P matrix"); #endif - glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL)); - } + glUniformMatrix4fv(P->location, 1, GL_FALSE, (const float *)GPU_matrix_projection_get(NULL)); + } - if (MVP) { + if (MVP) { #if DEBUG_MATRIX_BIND - puts("setting MVP matrix"); + puts("setting MVP matrix"); #endif - glUniformMatrix4fv(MVP->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL)); - } + glUniformMatrix4fv( + MVP->location, 1, GL_FALSE, (const float *)GPU_matrix_model_view_projection_get(NULL)); + } - if (N) { + if (N) { #if DEBUG_MATRIX_BIND - puts("setting normal matrix"); + puts("setting normal matrix"); #endif - glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL)); - } + glUniformMatrix3fv(N->location, 1, GL_FALSE, (const float *)GPU_matrix_normal_get(NULL)); + } - if (MV_inv) { - Mat4 m; - GPU_matrix_model_view_get(m); - invert_m4(m); - glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m); - } + if (MV_inv) { + Mat4 m; + GPU_matrix_model_view_get(m); + invert_m4(m); + glUniformMatrix4fv(MV_inv->location, 1, GL_FALSE, (const float *)m); + } - if (P_inv) { - Mat4 m; - GPU_matrix_projection_get(m); - invert_m4(m); - glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m); - } + if (P_inv) { + Mat4 m; + GPU_matrix_projection_get(m); + invert_m4(m); + glUniformMatrix4fv(P_inv->location, 1, GL_FALSE, (const float *)m); + } - state.dirty = false; + state.dirty = false; } bool GPU_matrix_dirty_get(void) { - return state.dirty; + return state.dirty; } - /* -------------------------------------------------------------------- */ /** \name Python API Helpers * \{ */ @@ -650,12 +673,12 @@ BLI_STATIC_ASSERT(GPU_PY_MATRIX_STACK_LEN + 1 == MATRIX_STACK_DEPTH, "define mis int GPU_matrix_stack_level_get_model_view(void) { - return (int)state.model_view_stack.top; + return (int)state.model_view_stack.top; } int GPU_matrix_stack_level_get_projection(void) { - return (int)state.projection_stack.top; + return (int)state.projection_stack.top; } /** \} */ diff --git a/source/blender/gpu/intern/gpu_primitive.c b/source/blender/gpu/intern/gpu_primitive.c index e59e4a953d7..2285c1ab95b 100644 --- a/source/blender/gpu/intern/gpu_primitive.c +++ b/source/blender/gpu/intern/gpu_primitive.c @@ -28,51 +28,51 @@ GPUPrimClass GPU_primtype_class(GPUPrimType prim_type) { - static const GPUPrimClass classes[] = { - [GPU_PRIM_POINTS] = GPU_PRIM_CLASS_POINT, - [GPU_PRIM_LINES] = GPU_PRIM_CLASS_LINE, - [GPU_PRIM_LINE_STRIP] = GPU_PRIM_CLASS_LINE, - [GPU_PRIM_LINE_LOOP] = GPU_PRIM_CLASS_LINE, - [GPU_PRIM_TRIS] = GPU_PRIM_CLASS_SURFACE, - [GPU_PRIM_TRI_STRIP] = GPU_PRIM_CLASS_SURFACE, - [GPU_PRIM_TRI_FAN] = GPU_PRIM_CLASS_SURFACE, + static const GPUPrimClass classes[] = { + [GPU_PRIM_POINTS] = GPU_PRIM_CLASS_POINT, + [GPU_PRIM_LINES] = GPU_PRIM_CLASS_LINE, + [GPU_PRIM_LINE_STRIP] = GPU_PRIM_CLASS_LINE, + [GPU_PRIM_LINE_LOOP] = GPU_PRIM_CLASS_LINE, + [GPU_PRIM_TRIS] = GPU_PRIM_CLASS_SURFACE, + [GPU_PRIM_TRI_STRIP] = GPU_PRIM_CLASS_SURFACE, + [GPU_PRIM_TRI_FAN] = GPU_PRIM_CLASS_SURFACE, - [GPU_PRIM_LINES_ADJ] = GPU_PRIM_CLASS_LINE, - [GPU_PRIM_LINE_STRIP_ADJ] = GPU_PRIM_CLASS_LINE, - [GPU_PRIM_TRIS_ADJ] = GPU_PRIM_CLASS_SURFACE, + [GPU_PRIM_LINES_ADJ] = GPU_PRIM_CLASS_LINE, + [GPU_PRIM_LINE_STRIP_ADJ] = GPU_PRIM_CLASS_LINE, + [GPU_PRIM_TRIS_ADJ] = GPU_PRIM_CLASS_SURFACE, - [GPU_PRIM_NONE] = GPU_PRIM_CLASS_NONE, - }; + [GPU_PRIM_NONE] = GPU_PRIM_CLASS_NONE, + }; - return classes[prim_type]; + return classes[prim_type]; } bool GPU_primtype_belongs_to_class(GPUPrimType prim_type, GPUPrimClass prim_class) { - if (prim_class == GPU_PRIM_CLASS_NONE && prim_type == GPU_PRIM_NONE) { - return true; - } - return prim_class & GPU_primtype_class(prim_type); + if (prim_class == GPU_PRIM_CLASS_NONE && prim_type == GPU_PRIM_NONE) { + return true; + } + return prim_class & GPU_primtype_class(prim_type); } GLenum convert_prim_type_to_gl(GPUPrimType prim_type) { #if TRUST_NO_ONE - assert(prim_type != GPU_PRIM_NONE); + assert(prim_type != GPU_PRIM_NONE); #endif - static const GLenum table[] = { - [GPU_PRIM_POINTS] = GL_POINTS, - [GPU_PRIM_LINES] = GL_LINES, - [GPU_PRIM_LINE_STRIP] = GL_LINE_STRIP, - [GPU_PRIM_LINE_LOOP] = GL_LINE_LOOP, - [GPU_PRIM_TRIS] = GL_TRIANGLES, - [GPU_PRIM_TRI_STRIP] = GL_TRIANGLE_STRIP, - [GPU_PRIM_TRI_FAN] = GL_TRIANGLE_FAN, + static const GLenum table[] = { + [GPU_PRIM_POINTS] = GL_POINTS, + [GPU_PRIM_LINES] = GL_LINES, + [GPU_PRIM_LINE_STRIP] = GL_LINE_STRIP, + [GPU_PRIM_LINE_LOOP] = GL_LINE_LOOP, + [GPU_PRIM_TRIS] = GL_TRIANGLES, + [GPU_PRIM_TRI_STRIP] = GL_TRIANGLE_STRIP, + [GPU_PRIM_TRI_FAN] = GL_TRIANGLE_FAN, - [GPU_PRIM_LINES_ADJ] = GL_LINES_ADJACENCY, - [GPU_PRIM_LINE_STRIP_ADJ] = GL_LINE_STRIP_ADJACENCY, - [GPU_PRIM_TRIS_ADJ] = GL_TRIANGLES_ADJACENCY, - }; + [GPU_PRIM_LINES_ADJ] = GL_LINES_ADJACENCY, + [GPU_PRIM_LINE_STRIP_ADJ] = GL_LINE_STRIP_ADJACENCY, + [GPU_PRIM_TRIS_ADJ] = GL_TRIANGLES_ADJACENCY, + }; - return table[prim_type]; + return table[prim_type]; } diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h index a92ff7287f6..4b90f8daa8c 100644 --- a/source/blender/gpu/intern/gpu_private.h +++ b/source/blender/gpu/intern/gpu_private.h @@ -36,4 +36,4 @@ void gpu_debug_exit(void); void gpu_framebuffer_module_init(void); void gpu_framebuffer_module_exit(void); -#endif /* __GPU_PRIVATE_H__ */ +#endif /* __GPU_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 875bcdcc674..4cfedc0708b 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -42,23 +42,23 @@ /* Internal algorithm used */ enum { - /** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c` - * Only sets 4th component (ID) correctly. */ - ALGO_GL_QUERY = 1, - /** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c` - * Only sets 4th component (ID) correctly. */ - ALGO_GL_PICK = 2, + /** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c` + * Only sets 4th component (ID) correctly. */ + ALGO_GL_QUERY = 1, + /** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c` + * Only sets 4th component (ID) correctly. */ + ALGO_GL_PICK = 2, }; typedef struct GPUSelectState { - /* To ignore selection id calls when not initialized */ - bool select_is_active; - /* mode of operation */ - char mode; - /* internal algorithm for selection */ - char algorithm; - /* allow GPU_select_begin/end without drawing */ - bool use_cache; + /* To ignore selection id calls when not initialized */ + bool select_is_active; + /* mode of operation */ + char mode; + /* internal algorithm for selection */ + char algorithm; + /* allow GPU_select_begin/end without drawing */ + bool use_cache; } GPUSelectState; static GPUSelectState g_select_state = {0}; @@ -68,35 +68,34 @@ static GPUSelectState g_select_state = {0}; */ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, int oldhits) { - if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { - /* In the case hits was '-1', don't start the second pass since it's not going to give useful results. - * As well as buffer overflow in 'gpu_select_query_load_id'. */ - BLI_assert(oldhits != -1); - } - - g_select_state.select_is_active = true; - g_select_state.mode = mode; - - if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) { - g_select_state.algorithm = ALGO_GL_PICK; - } - else { - g_select_state.algorithm = ALGO_GL_QUERY; - } - - switch (g_select_state.algorithm) { - case ALGO_GL_QUERY: - { - g_select_state.use_cache = false; - gpu_select_query_begin((uint (*)[4])buffer, bufsize / 4, input, mode, oldhits); - break; - } - default: /* ALGO_GL_PICK */ - { - gpu_select_pick_begin((uint (*)[4])buffer, bufsize / 4, input, mode); - break; - } - } + if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { + /* In the case hits was '-1', don't start the second pass since it's not going to give useful results. + * As well as buffer overflow in 'gpu_select_query_load_id'. */ + BLI_assert(oldhits != -1); + } + + g_select_state.select_is_active = true; + g_select_state.mode = mode; + + if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) { + g_select_state.algorithm = ALGO_GL_PICK; + } + else { + g_select_state.algorithm = ALGO_GL_QUERY; + } + + switch (g_select_state.algorithm) { + case ALGO_GL_QUERY: { + g_select_state.use_cache = false; + gpu_select_query_begin((uint(*)[4])buffer, bufsize / 4, input, mode, oldhits); + break; + } + default: /* ALGO_GL_PICK */ + { + gpu_select_pick_begin((uint(*)[4])buffer, bufsize / 4, input, mode); + break; + } + } } /** @@ -108,20 +107,19 @@ void GPU_select_begin(uint *buffer, uint bufsize, const rcti *input, char mode, */ bool GPU_select_load_id(uint id) { - /* if no selection mode active, ignore */ - if (!g_select_state.select_is_active) - return true; - - switch (g_select_state.algorithm) { - case ALGO_GL_QUERY: - { - return gpu_select_query_load_id(id); - } - default: /* ALGO_GL_PICK */ - { - return gpu_select_pick_load_id(id); - } - } + /* if no selection mode active, ignore */ + if (!g_select_state.select_is_active) + return true; + + switch (g_select_state.algorithm) { + case ALGO_GL_QUERY: { + return gpu_select_query_load_id(id); + } + default: /* ALGO_GL_PICK */ + { + return gpu_select_pick_load_id(id); + } + } } /** @@ -131,24 +129,23 @@ bool GPU_select_load_id(uint id) */ uint GPU_select_end(void) { - uint hits = 0; - - switch (g_select_state.algorithm) { - case ALGO_GL_QUERY: - { - hits = gpu_select_query_end(); - break; - } - default: /* ALGO_GL_PICK */ - { - hits = gpu_select_pick_end(); - break; - } - } - - g_select_state.select_is_active = false; - - return hits; + uint hits = 0; + + switch (g_select_state.algorithm) { + case ALGO_GL_QUERY: { + hits = gpu_select_query_end(); + break; + } + default: /* ALGO_GL_PICK */ + { + hits = gpu_select_pick_end(); + break; + } + } + + g_select_state.select_is_active = false; + + return hits; } /* ---------------------------------------------------------------------------- @@ -160,36 +157,35 @@ uint GPU_select_end(void) void GPU_select_cache_begin(void) { - /* validate on GPU_select_begin, clear if not supported */ - BLI_assert(g_select_state.use_cache == false); - g_select_state.use_cache = true; - if (g_select_state.algorithm == ALGO_GL_PICK) { - gpu_select_pick_cache_begin(); - } + /* validate on GPU_select_begin, clear if not supported */ + BLI_assert(g_select_state.use_cache == false); + g_select_state.use_cache = true; + if (g_select_state.algorithm == ALGO_GL_PICK) { + gpu_select_pick_cache_begin(); + } } void GPU_select_cache_load_id(void) { - BLI_assert(g_select_state.use_cache == true); - if (g_select_state.algorithm == ALGO_GL_PICK) { - gpu_select_pick_cache_load_id(); - } + BLI_assert(g_select_state.use_cache == true); + if (g_select_state.algorithm == ALGO_GL_PICK) { + gpu_select_pick_cache_load_id(); + } } void GPU_select_cache_end(void) { - if (g_select_state.algorithm == ALGO_GL_PICK) { - gpu_select_pick_cache_end(); - } - g_select_state.use_cache = false; + if (g_select_state.algorithm == ALGO_GL_PICK) { + gpu_select_pick_cache_end(); + } + g_select_state.use_cache = false; } bool GPU_select_is_cached(void) { - return g_select_state.use_cache && gpu_select_pick_is_cached(); + return g_select_state.use_cache && gpu_select_pick_is_cached(); } - /* ---------------------------------------------------------------------------- * Utilities */ @@ -202,50 +198,49 @@ bool GPU_select_is_cached(void) */ const uint *GPU_select_buffer_near(const uint *buffer, int hits) { - const uint *buffer_near = NULL; - uint depth_min = (uint) - 1; - for (int i = 0; i < hits; i++) { - if (buffer[1] < depth_min) { - BLI_assert(buffer[3] != -1); - depth_min = buffer[1]; - buffer_near = buffer; - } - buffer += 4; - } - return buffer_near; + const uint *buffer_near = NULL; + uint depth_min = (uint)-1; + for (int i = 0; i < hits; i++) { + if (buffer[1] < depth_min) { + BLI_assert(buffer[3] != -1); + depth_min = buffer[1]; + buffer_near = buffer; + } + buffer += 4; + } + return buffer_near; } /* Part of the solution copied from `rect_subregion_stride_calc`. */ -void GPU_select_buffer_stride_realign( - const rcti *src, const rcti *dst, uint *r_buf) +void GPU_select_buffer_stride_realign(const rcti *src, const rcti *dst, uint *r_buf) { - const int x = dst->xmin - src->xmin; - const int y = dst->ymin - src->ymin; - - BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && - src->xmax >= dst->xmax && src->ymax >= dst->ymax); - BLI_assert(x >= 0 && y >= 0); - - const int src_x = BLI_rcti_size_x(src); - const int src_y = BLI_rcti_size_y(src); - const int dst_x = BLI_rcti_size_x(dst); - const int dst_y = BLI_rcti_size_y(dst); - - int last_px_written = dst_x * dst_y - 1; - int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1); - const int skip = src_x - dst_x; - - memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf)); - - while (true) { - for (int i = dst_x; i--;) { - r_buf[last_px_id--] = r_buf[last_px_written--]; - } - if (last_px_written < 0) { - break; - } - last_px_id -= skip; - memset(&r_buf[last_px_id + 1], 0, skip * sizeof(*r_buf)); - } - memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf)); + const int x = dst->xmin - src->xmin; + const int y = dst->ymin - src->ymin; + + BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax && + src->ymax >= dst->ymax); + BLI_assert(x >= 0 && y >= 0); + + const int src_x = BLI_rcti_size_x(src); + const int src_y = BLI_rcti_size_y(src); + const int dst_x = BLI_rcti_size_x(dst); + const int dst_y = BLI_rcti_size_y(dst); + + int last_px_written = dst_x * dst_y - 1; + int last_px_id = src_x * (y + dst_y - 1) + (x + dst_x - 1); + const int skip = src_x - dst_x; + + memset(&r_buf[last_px_id + 1], 0, (src_x * src_y - (last_px_id + 1)) * sizeof(*r_buf)); + + while (true) { + for (int i = dst_x; i--;) { + r_buf[last_px_id--] = r_buf[last_px_written--]; + } + if (last_px_written < 0) { + break; + } + last_px_id -= skip; + memset(&r_buf[last_px_id + 1], 0, skip * sizeof(*r_buf)); + } + memset(r_buf, 0, (last_px_id + 1) * sizeof(*r_buf)); } diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c index 22388deccdb..46e450d455e 100644 --- a/source/blender/gpu/intern/gpu_select_pick.c +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -57,10 +57,10 @@ /* For looping over a sub-region of a rect, could be moved into 'rct.c'*/ typedef struct SubRectStride { - uint start; /* start here */ - uint span; /* read these */ - uint span_len; /* len times (read span 'len' times). */ - uint skip; /* skip those */ + uint start; /* start here */ + uint span; /* read these */ + uint span_len; /* len times (read span 'len' times). */ + uint skip; /* skip those */ } SubRectStride; /* we may want to change back to float if uint isn't well supported */ @@ -73,21 +73,21 @@ typedef uint depth_t; */ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRectStride *r_sub) { - const int src_x = BLI_rcti_size_x(src); - // const int src_y = BLI_rcti_size_y(src); - const int dst_x = BLI_rcti_size_x(dst); - const int dst_y = BLI_rcti_size_y(dst); - const int x = dst->xmin - src->xmin; - const int y = dst->ymin - src->ymin; - - BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && - src->xmax >= dst->xmax && src->ymax >= dst->ymax); - BLI_assert(x >= 0 && y >= 0); - - r_sub->start = (uint)((src_x * y) + x); - r_sub->span = (uint)dst_x; - r_sub->span_len = (uint)dst_y; - r_sub->skip = (uint)(src_x - dst_x); + const int src_x = BLI_rcti_size_x(src); + // const int src_y = BLI_rcti_size_y(src); + const int dst_x = BLI_rcti_size_x(dst); + const int dst_y = BLI_rcti_size_y(dst); + const int x = dst->xmin - src->xmin; + const int y = dst->ymin - src->ymin; + + BLI_assert(src->xmin <= dst->xmin && src->ymin <= dst->ymin && src->xmax >= dst->xmax && + src->ymax >= dst->ymax); + BLI_assert(x >= 0 && y >= 0); + + r_sub->start = (uint)((src_x * y) + x); + r_sub->span = (uint)dst_x; + r_sub->span_len = (uint)dst_y; + r_sub->skip = (uint)(src_x - dst_x); } /** @@ -96,7 +96,7 @@ static void rect_subregion_stride_calc(const rcti *src, const rcti *dst, SubRect */ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr) { - return (*prev != *curr) && (*curr != DEPTH_MAX); + return (*prev != *curr) && (*curr != DEPTH_MAX); } /* ---------------------------------------------------------------------------- @@ -108,87 +108,84 @@ BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr) /* store result of glReadPixels */ typedef struct DepthBufCache { - struct DepthBufCache *next, *prev; - uint id; - depth_t buf[0]; + struct DepthBufCache *next, *prev; + uint id; + depth_t buf[0]; } DepthBufCache; static DepthBufCache *depth_buf_malloc(uint rect_len) { - DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__); - rect->id = SELECT_ID_NONE; - return rect; + DepthBufCache *rect = MEM_mallocN(sizeof(DepthBufCache) + sizeof(depth_t) * rect_len, __func__); + rect->id = SELECT_ID_NONE; + return rect; } -static bool depth_buf_rect_depth_any( - const DepthBufCache *rect_depth, - uint rect_len) +static bool depth_buf_rect_depth_any(const DepthBufCache *rect_depth, uint rect_len) { - const depth_t *curr = rect_depth->buf; - for (uint i = 0; i < rect_len; i++, curr++) { - if (*curr != DEPTH_MAX) { - return true; - } - } - return false; + const depth_t *curr = rect_depth->buf; + for (uint i = 0; i < rect_len; i++, curr++) { + if (*curr != DEPTH_MAX) { + return true; + } + } + return false; } -static bool depth_buf_subrect_depth_any( - const DepthBufCache *rect_depth, - const SubRectStride *sub_rect) +static bool depth_buf_subrect_depth_any(const DepthBufCache *rect_depth, + const SubRectStride *sub_rect) { - const depth_t *curr = rect_depth->buf + sub_rect->start; - for (uint i = 0; i < sub_rect->span_len; i++) { - const depth_t *curr_end = curr + sub_rect->span; - for (; curr < curr_end; curr++, curr++) { - if (*curr != DEPTH_MAX) { - return true; - } - } - curr += sub_rect->skip; - } - return false; + const depth_t *curr = rect_depth->buf + sub_rect->start; + for (uint i = 0; i < sub_rect->span_len; i++) { + const depth_t *curr_end = curr + sub_rect->span; + for (; curr < curr_end; curr++, curr++) { + if (*curr != DEPTH_MAX) { + return true; + } + } + curr += sub_rect->skip; + } + return false; } -static bool depth_buf_rect_depth_any_filled( - const DepthBufCache *rect_prev, const DepthBufCache *rect_curr, - uint rect_len) +static bool depth_buf_rect_depth_any_filled(const DepthBufCache *rect_prev, + const DepthBufCache *rect_curr, + uint rect_len) { #if 0 - return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0; + return memcmp(rect_depth_a->buf, rect_depth_b->buf, rect_len * sizeof(depth_t)) != 0; #else - const depth_t *prev = rect_prev->buf; - const depth_t *curr = rect_curr->buf; - for (uint i = 0; i < rect_len; i++, curr++, prev++) { - if (depth_is_filled(prev, curr)) { - return true; - } - } - return false; + const depth_t *prev = rect_prev->buf; + const depth_t *curr = rect_curr->buf; + for (uint i = 0; i < rect_len; i++, curr++, prev++) { + if (depth_is_filled(prev, curr)) { + return true; + } + } + return false; #endif } /** * Both buffers are the same size, just check if the sub-rect contains any differences. */ -static bool depth_buf_subrect_depth_any_filled( - const DepthBufCache *rect_src, const DepthBufCache *rect_dst, - const SubRectStride *sub_rect) +static bool depth_buf_subrect_depth_any_filled(const DepthBufCache *rect_src, + const DepthBufCache *rect_dst, + const SubRectStride *sub_rect) { - /* same as above but different rect sizes */ - const depth_t *prev = rect_src->buf + sub_rect->start; - const depth_t *curr = rect_dst->buf + sub_rect->start; - for (uint i = 0; i < sub_rect->span_len; i++) { - const depth_t *curr_end = curr + sub_rect->span; - for (; curr < curr_end; prev++, curr++) { - if (depth_is_filled(prev, curr)) { - return true; - } - } - prev += sub_rect->skip; - curr += sub_rect->skip; - } - return false; + /* same as above but different rect sizes */ + const depth_t *prev = rect_src->buf + sub_rect->start; + const depth_t *curr = rect_dst->buf + sub_rect->start; + for (uint i = 0; i < sub_rect->span_len; i++) { + const depth_t *curr_end = curr + sub_rect->span; + for (; curr < curr_end; prev++, curr++) { + if (depth_is_filled(prev, curr)) { + return true; + } + } + prev += sub_rect->skip; + curr += sub_rect->skip; + } + return false; } /* ---------------------------------------------------------------------------- @@ -198,190 +195,187 @@ static bool depth_buf_subrect_depth_any_filled( */ typedef struct DepthID { - uint id; - depth_t depth; + uint id; + depth_t depth; } DepthID; static int depth_id_cmp(const void *v1, const void *v2) { - const DepthID *d1 = v1, *d2 = v2; - if (d1->id < d2->id) { - return -1; - } - else if (d1->id > d2->id) { - return 1; - } - else { - return 0; - } + const DepthID *d1 = v1, *d2 = v2; + if (d1->id < d2->id) { + return -1; + } + else if (d1->id > d2->id) { + return 1; + } + else { + return 0; + } } static int depth_cmp(const void *v1, const void *v2) { - const DepthID *d1 = v1, *d2 = v2; - if (d1->depth < d2->depth) { - return -1; - } - else if (d1->depth > d2->depth) { - return 1; - } - else { - return 0; - } + const DepthID *d1 = v1, *d2 = v2; + if (d1->depth < d2->depth) { + return -1; + } + else if (d1->depth > d2->depth) { + return 1; + } + else { + return 0; + } } /* depth sorting */ typedef struct GPUPickState { - /* cache on initialization */ - uint (*buffer)[4]; - - /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ - uint bufsize; - /* mode of operation */ - char mode; - - /* OpenGL drawing, never use when (is_cached == true). */ - struct { - /* The current depth, accumulated as we draw */ - DepthBufCache *rect_depth; - /* Scratch buffer, avoid allocs every time (when not caching) */ - DepthBufCache *rect_depth_test; - - /* Pass to glReadPixels (x, y, w, h) */ - int clip_readpixels[4]; - - /* Set after first draw */ - bool is_init; - uint prev_id; - } gl; - - /* src: data stored in 'cache' and 'gl', - * dst: use when cached region is smaller (where src -> dst isn't 1:1) */ - struct { - rcti clip_rect; - uint rect_len; - } src, dst; - - /* Store cache between `GPU_select_cache_begin/end` */ - bool use_cache; - bool is_cached; - struct { - /* Cleanup used for iterating over both source and destination buffers: - * src.clip_rect -> dst.clip_rect */ - SubRectStride sub_rect; - - /* List of DepthBufCache, sized of 'src.clip_rect' */ - ListBase bufs; - } cache; - - /* Pickign methods */ - union { - /* GPU_SELECT_PICK_ALL */ - struct { - DepthID *hits; - uint hits_len; - uint hits_len_alloc; - } all; - - /* GPU_SELECT_PICK_NEAREST */ - struct { - uint *rect_id; - } nearest; - }; + /* cache on initialization */ + uint (*buffer)[4]; + + /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ + uint bufsize; + /* mode of operation */ + char mode; + + /* OpenGL drawing, never use when (is_cached == true). */ + struct { + /* The current depth, accumulated as we draw */ + DepthBufCache *rect_depth; + /* Scratch buffer, avoid allocs every time (when not caching) */ + DepthBufCache *rect_depth_test; + + /* Pass to glReadPixels (x, y, w, h) */ + int clip_readpixels[4]; + + /* Set after first draw */ + bool is_init; + uint prev_id; + } gl; + + /* src: data stored in 'cache' and 'gl', + * dst: use when cached region is smaller (where src -> dst isn't 1:1) */ + struct { + rcti clip_rect; + uint rect_len; + } src, dst; + + /* Store cache between `GPU_select_cache_begin/end` */ + bool use_cache; + bool is_cached; + struct { + /* Cleanup used for iterating over both source and destination buffers: + * src.clip_rect -> dst.clip_rect */ + SubRectStride sub_rect; + + /* List of DepthBufCache, sized of 'src.clip_rect' */ + ListBase bufs; + } cache; + + /* Pickign methods */ + union { + /* GPU_SELECT_PICK_ALL */ + struct { + DepthID *hits; + uint hits_len; + uint hits_len_alloc; + } all; + + /* GPU_SELECT_PICK_NEAREST */ + struct { + uint *rect_id; + } nearest; + }; } GPUPickState; - static GPUPickState g_pick_state = {0}; -void gpu_select_pick_begin( - uint (*buffer)[4], uint bufsize, - const rcti *input, char mode) +void gpu_select_pick_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode) { - GPUPickState *ps = &g_pick_state; + GPUPickState *ps = &g_pick_state; #ifdef DEBUG_PRINT - printf("%s: mode=%d, use_cache=%d, is_cache=%d\n", __func__, mode, ps->use_cache, ps->is_cached); + printf("%s: mode=%d, use_cache=%d, is_cache=%d\n", __func__, mode, ps->use_cache, ps->is_cached); #endif - ps->bufsize = bufsize; - ps->buffer = buffer; - ps->mode = mode; + ps->bufsize = bufsize; + ps->buffer = buffer; + ps->mode = mode; - const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input)); - ps->dst.clip_rect = *input; - ps->dst.rect_len = rect_len; + const uint rect_len = (uint)(BLI_rcti_size_x(input) * BLI_rcti_size_y(input)); + ps->dst.clip_rect = *input; + ps->dst.rect_len = rect_len; - /* Restrict OpenGL operations for when we don't have cache */ - if (ps->is_cached == false) { - gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT); + /* Restrict OpenGL operations for when we don't have cache */ + if (ps->is_cached == false) { + gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT); - /* disable writing to the framebuffer */ - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + /* disable writing to the framebuffer */ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); - if (mode == GPU_SELECT_PICK_ALL) { - /* Note that other depth settings (such as #GL_LEQUAL) work too, - * since the depth is always cleared. - * Noting this for cases when depth picking is used where drawing calls change depth settings. */ - glDepthFunc(GL_ALWAYS); - } - else { - glDepthFunc(GL_LEQUAL); - } + if (mode == GPU_SELECT_PICK_ALL) { + /* Note that other depth settings (such as #GL_LEQUAL) work too, + * since the depth is always cleared. + * Noting this for cases when depth picking is used where drawing calls change depth settings. */ + glDepthFunc(GL_ALWAYS); + } + else { + glDepthFunc(GL_LEQUAL); + } - float viewport[4]; - glGetFloatv(GL_VIEWPORT, viewport); + float viewport[4]; + glGetFloatv(GL_VIEWPORT, viewport); - ps->src.clip_rect = *input; - ps->src.rect_len = rect_len; + ps->src.clip_rect = *input; + ps->src.rect_len = rect_len; - ps->gl.clip_readpixels[0] = (int)viewport[0]; - ps->gl.clip_readpixels[1] = (int)viewport[1]; - ps->gl.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect); - ps->gl.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect); + ps->gl.clip_readpixels[0] = (int)viewport[0]; + ps->gl.clip_readpixels[1] = (int)viewport[1]; + ps->gl.clip_readpixels[2] = BLI_rcti_size_x(&ps->src.clip_rect); + ps->gl.clip_readpixels[3] = BLI_rcti_size_y(&ps->src.clip_rect); - glViewport(UNPACK4(ps->gl.clip_readpixels)); + glViewport(UNPACK4(ps->gl.clip_readpixels)); - /* It's possible we don't want to clear depth buffer, - * so existing elements are masked by current z-buffer. */ - glClear(GL_DEPTH_BUFFER_BIT); + /* It's possible we don't want to clear depth buffer, + * so existing elements are masked by current z-buffer. */ + glClear(GL_DEPTH_BUFFER_BIT); - /* scratch buffer (read new values here) */ - ps->gl.rect_depth_test = depth_buf_malloc(rect_len); - ps->gl.rect_depth = depth_buf_malloc(rect_len); + /* scratch buffer (read new values here) */ + ps->gl.rect_depth_test = depth_buf_malloc(rect_len); + ps->gl.rect_depth = depth_buf_malloc(rect_len); - /* set initial 'far' value */ + /* set initial 'far' value */ #if 0 - glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf); + glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf); #else - for (uint i = 0; i < rect_len; i++) { - ps->gl.rect_depth->buf[i] = DEPTH_MAX; - } + for (uint i = 0; i < rect_len; i++) { + ps->gl.rect_depth->buf[i] = DEPTH_MAX; + } #endif - ps->gl.is_init = false; - ps->gl.prev_id = 0; - } - else { - /* Using cache (ps->is_cached == true) */ - /* src.clip_rect -> dst.clip_rect */ - rect_subregion_stride_calc(&ps->src.clip_rect, &ps->dst.clip_rect, &ps->cache.sub_rect); - BLI_assert(ps->gl.rect_depth == NULL); - BLI_assert(ps->gl.rect_depth_test == NULL); - } - - if (mode == GPU_SELECT_PICK_ALL) { - ps->all.hits = MEM_mallocN(sizeof(*ps->all.hits) * ALLOC_DEPTHS, __func__); - ps->all.hits_len = 0; - ps->all.hits_len_alloc = ALLOC_DEPTHS; - } - else { - /* Set to 0xff for SELECT_ID_NONE */ - ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__); - memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len); - } + ps->gl.is_init = false; + ps->gl.prev_id = 0; + } + else { + /* Using cache (ps->is_cached == true) */ + /* src.clip_rect -> dst.clip_rect */ + rect_subregion_stride_calc(&ps->src.clip_rect, &ps->dst.clip_rect, &ps->cache.sub_rect); + BLI_assert(ps->gl.rect_depth == NULL); + BLI_assert(ps->gl.rect_depth_test == NULL); + } + + if (mode == GPU_SELECT_PICK_ALL) { + ps->all.hits = MEM_mallocN(sizeof(*ps->all.hits) * ALLOC_DEPTHS, __func__); + ps->all.hits_len = 0; + ps->all.hits_len_alloc = ALLOC_DEPTHS; + } + else { + /* Set to 0xff for SELECT_ID_NONE */ + ps->nearest.rect_id = MEM_mallocN(sizeof(uint) * ps->dst.rect_len, __func__); + memset(ps->nearest.rect_id, 0xff, sizeof(uint) * ps->dst.rect_len); + } } /** @@ -390,294 +384,300 @@ void gpu_select_pick_begin( */ static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr) { - GPUPickState *ps = &g_pick_state; - const uint id = rect_curr->id; - /* find the best depth for this pass and store in 'all.hits' */ - depth_t depth_best = DEPTH_MAX; + GPUPickState *ps = &g_pick_state; + const uint id = rect_curr->id; + /* find the best depth for this pass and store in 'all.hits' */ + depth_t depth_best = DEPTH_MAX; #define EVAL_TEST() \ - if (depth_best > *curr) { \ - depth_best = *curr; \ - } ((void)0) - - if (ps->is_cached == false) { - const depth_t *curr = rect_curr->buf; - BLI_assert(ps->src.rect_len == ps->dst.rect_len); - const uint rect_len = ps->src.rect_len; - for (uint i = 0; i < rect_len; i++, curr++) { - EVAL_TEST(); - } - } - else { - /* same as above but different rect sizes */ - const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start; - for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) { - const depth_t *curr_end = curr + ps->cache.sub_rect.span; - for (; curr < curr_end; curr++) { - EVAL_TEST(); - } - curr += ps->cache.sub_rect.skip; - } - } + if (depth_best > *curr) { \ + depth_best = *curr; \ + } \ + ((void)0) + + if (ps->is_cached == false) { + const depth_t *curr = rect_curr->buf; + BLI_assert(ps->src.rect_len == ps->dst.rect_len); + const uint rect_len = ps->src.rect_len; + for (uint i = 0; i < rect_len; i++, curr++) { + EVAL_TEST(); + } + } + else { + /* same as above but different rect sizes */ + const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start; + for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) { + const depth_t *curr_end = curr + ps->cache.sub_rect.span; + for (; curr < curr_end; curr++) { + EVAL_TEST(); + } + curr += ps->cache.sub_rect.skip; + } + } #undef EVAL_TEST - /* ensure enough space */ - if (UNLIKELY(ps->all.hits_len == ps->all.hits_len_alloc)) { - ps->all.hits_len_alloc += ALLOC_DEPTHS; - ps->all.hits = MEM_reallocN(ps->all.hits, ps->all.hits_len_alloc * sizeof(*ps->all.hits)); - } - DepthID *d = &ps->all.hits[ps->all.hits_len++]; - d->id = id; - d->depth = depth_best; + /* ensure enough space */ + if (UNLIKELY(ps->all.hits_len == ps->all.hits_len_alloc)) { + ps->all.hits_len_alloc += ALLOC_DEPTHS; + ps->all.hits = MEM_reallocN(ps->all.hits, ps->all.hits_len_alloc * sizeof(*ps->all.hits)); + } + DepthID *d = &ps->all.hits[ps->all.hits_len++]; + d->id = id; + d->depth = depth_best; } -static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr) +static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, + const DepthBufCache *rect_curr) { - GPUPickState *ps = &g_pick_state; - const uint id = rect_curr->id; - /* keep track each pixels ID in 'nearest.rect_id' */ - if (id != SELECT_ID_NONE) { - uint *id_ptr = ps->nearest.rect_id; - - /* Check against DEPTH_MAX because XRAY will clear the buffer, - * so previously set values will become unset. - * In this case just leave those id's left as-is. */ + GPUPickState *ps = &g_pick_state; + const uint id = rect_curr->id; + /* keep track each pixels ID in 'nearest.rect_id' */ + if (id != SELECT_ID_NONE) { + uint *id_ptr = ps->nearest.rect_id; + + /* Check against DEPTH_MAX because XRAY will clear the buffer, + * so previously set values will become unset. + * In this case just leave those id's left as-is. */ #define EVAL_TEST() \ - if (depth_is_filled(prev, curr)) { \ - *id_ptr = id; \ - } ((void)0) - - if (ps->is_cached == false) { - const depth_t *prev = rect_prev->buf; - const depth_t *curr = rect_curr->buf; - BLI_assert(ps->src.rect_len == ps->dst.rect_len); - const uint rect_len = ps->src.rect_len; - for (uint i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) { - EVAL_TEST(); - } - } - else { - /* same as above but different rect sizes */ - const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start; - const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start; - for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) { - const depth_t *curr_end = curr + ps->cache.sub_rect.span; - for (; curr < curr_end; prev++, curr++, id_ptr++) { - EVAL_TEST(); - } - prev += ps->cache.sub_rect.skip; - curr += ps->cache.sub_rect.skip; - } - } + if (depth_is_filled(prev, curr)) { \ + *id_ptr = id; \ + } \ + ((void)0) + + if (ps->is_cached == false) { + const depth_t *prev = rect_prev->buf; + const depth_t *curr = rect_curr->buf; + BLI_assert(ps->src.rect_len == ps->dst.rect_len); + const uint rect_len = ps->src.rect_len; + for (uint i = 0; i < rect_len; i++, curr++, prev++, id_ptr++) { + EVAL_TEST(); + } + } + else { + /* same as above but different rect sizes */ + const depth_t *prev = rect_prev->buf + ps->cache.sub_rect.start; + const depth_t *curr = rect_curr->buf + ps->cache.sub_rect.start; + for (uint i = 0; i < ps->cache.sub_rect.span_len; i++) { + const depth_t *curr_end = curr + ps->cache.sub_rect.span; + for (; curr < curr_end; prev++, curr++, id_ptr++) { + EVAL_TEST(); + } + prev += ps->cache.sub_rect.skip; + curr += ps->cache.sub_rect.skip; + } + } #undef EVAL_TEST - } + } } - bool gpu_select_pick_load_id(uint id) { - GPUPickState *ps = &g_pick_state; - if (ps->gl.is_init) { - const uint rect_len = ps->src.rect_len; - glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth_test->buf); - /* perform initial check since most cases the array remains unchanged */ - - bool do_pass = false; - if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { - if (depth_buf_rect_depth_any(ps->gl.rect_depth_test, rect_len)) { - ps->gl.rect_depth_test->id = ps->gl.prev_id; - gpu_select_load_id_pass_all(ps->gl.rect_depth_test); - do_pass = true; - } - } - else { - if (depth_buf_rect_depth_any_filled(ps->gl.rect_depth, ps->gl.rect_depth_test, rect_len)) { - ps->gl.rect_depth_test->id = ps->gl.prev_id; - gpu_select_load_id_pass_nearest(ps->gl.rect_depth, ps->gl.rect_depth_test); - do_pass = true; - } - } - - if (do_pass) { - /* Store depth in cache */ - if (ps->use_cache) { - BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth); - ps->gl.rect_depth = depth_buf_malloc(ps->src.rect_len); - } - - SWAP(DepthBufCache *, ps->gl.rect_depth, ps->gl.rect_depth_test); - - if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { - /* we want new depths every time */ - glClear(GL_DEPTH_BUFFER_BIT); - } - } - } - - ps->gl.is_init = true; - ps->gl.prev_id = id; - - return true; + GPUPickState *ps = &g_pick_state; + if (ps->gl.is_init) { + const uint rect_len = ps->src.rect_len; + glReadPixels(UNPACK4(ps->gl.clip_readpixels), + GL_DEPTH_COMPONENT, + GL_UNSIGNED_INT, + ps->gl.rect_depth_test->buf); + /* perform initial check since most cases the array remains unchanged */ + + bool do_pass = false; + if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { + if (depth_buf_rect_depth_any(ps->gl.rect_depth_test, rect_len)) { + ps->gl.rect_depth_test->id = ps->gl.prev_id; + gpu_select_load_id_pass_all(ps->gl.rect_depth_test); + do_pass = true; + } + } + else { + if (depth_buf_rect_depth_any_filled(ps->gl.rect_depth, ps->gl.rect_depth_test, rect_len)) { + ps->gl.rect_depth_test->id = ps->gl.prev_id; + gpu_select_load_id_pass_nearest(ps->gl.rect_depth, ps->gl.rect_depth_test); + do_pass = true; + } + } + + if (do_pass) { + /* Store depth in cache */ + if (ps->use_cache) { + BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth); + ps->gl.rect_depth = depth_buf_malloc(ps->src.rect_len); + } + + SWAP(DepthBufCache *, ps->gl.rect_depth, ps->gl.rect_depth_test); + + if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { + /* we want new depths every time */ + glClear(GL_DEPTH_BUFFER_BIT); + } + } + } + + ps->gl.is_init = true; + ps->gl.prev_id = id; + + return true; } uint gpu_select_pick_end(void) { - GPUPickState *ps = &g_pick_state; + GPUPickState *ps = &g_pick_state; #ifdef DEBUG_PRINT - printf("%s\n", __func__); + printf("%s\n", __func__); #endif - if (ps->is_cached == false) { - if (ps->gl.is_init) { - /* force finishing last pass */ - gpu_select_pick_load_id(ps->gl.prev_id); - } - gpuPopAttr(); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - - /* assign but never free directly since it may be in cache */ - DepthBufCache *rect_depth_final; - - /* Store depth in cache */ - if (ps->use_cache && !ps->is_cached) { - BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth); - ps->gl.rect_depth = NULL; - rect_depth_final = ps->cache.bufs.last; - } - else if (ps->is_cached) { - rect_depth_final = ps->cache.bufs.last; - } - else { - /* common case, no cache */ - rect_depth_final = ps->gl.rect_depth; - } - - uint maxhits = g_pick_state.bufsize; - DepthID *depth_data; - uint depth_data_len = 0; - - if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { - depth_data = ps->all.hits; - depth_data_len = ps->all.hits_len; - /* move ownership */ - ps->all.hits = NULL; - ps->all.hits_len = 0; - ps->all.hits_len_alloc = 0; - } - else { - /* GPU_SELECT_PICK_NEAREST */ - - /* Over alloc (unlikely we have as many depths as pixels) */ - uint depth_data_len_first_pass = 0; - depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__); - - /* Partially de-duplicating copy, - * when contiguous ID's are found - update their closest depth. - * This isn't essential but means there is less data to sort. */ + if (ps->is_cached == false) { + if (ps->gl.is_init) { + /* force finishing last pass */ + gpu_select_pick_load_id(ps->gl.prev_id); + } + gpuPopAttr(); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + /* assign but never free directly since it may be in cache */ + DepthBufCache *rect_depth_final; + + /* Store depth in cache */ + if (ps->use_cache && !ps->is_cached) { + BLI_addtail(&ps->cache.bufs, ps->gl.rect_depth); + ps->gl.rect_depth = NULL; + rect_depth_final = ps->cache.bufs.last; + } + else if (ps->is_cached) { + rect_depth_final = ps->cache.bufs.last; + } + else { + /* common case, no cache */ + rect_depth_final = ps->gl.rect_depth; + } + + uint maxhits = g_pick_state.bufsize; + DepthID *depth_data; + uint depth_data_len = 0; + + if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { + depth_data = ps->all.hits; + depth_data_len = ps->all.hits_len; + /* move ownership */ + ps->all.hits = NULL; + ps->all.hits_len = 0; + ps->all.hits_len_alloc = 0; + } + else { + /* GPU_SELECT_PICK_NEAREST */ + + /* Over alloc (unlikely we have as many depths as pixels) */ + uint depth_data_len_first_pass = 0; + depth_data = MEM_mallocN(ps->dst.rect_len * sizeof(*depth_data), __func__); + + /* Partially de-duplicating copy, + * when contiguous ID's are found - update their closest depth. + * This isn't essential but means there is less data to sort. */ #define EVAL_TEST(i_src, i_dst) \ - { \ - const uint id = ps->nearest.rect_id[i_dst]; \ - if (id != SELECT_ID_NONE) { \ - const depth_t depth = rect_depth_final->buf[i_src]; \ - if (depth_last == NULL || depth_last->id != id) { \ - DepthID *d = &depth_data[depth_data_len_first_pass++]; \ - d->id = id; \ - d->depth = depth; \ - } \ - else if (depth_last->depth > depth) { \ - depth_last->depth = depth; \ - } \ - } \ - } ((void)0) - - { - DepthID *depth_last = NULL; - if (ps->is_cached == false) { - for (uint i = 0; i < ps->src.rect_len; i++) { - EVAL_TEST(i, i); - } - } - else { - /* same as above but different rect sizes */ - uint i_src = ps->cache.sub_rect.start, i_dst = 0; - for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) { - const uint i_src_end = i_src + ps->cache.sub_rect.span; - for (; i_src < i_src_end; i_src++, i_dst++) { - EVAL_TEST(i_src, i_dst); - } - i_src += ps->cache.sub_rect.skip; - } - } - } + { \ + const uint id = ps->nearest.rect_id[i_dst]; \ + if (id != SELECT_ID_NONE) { \ + const depth_t depth = rect_depth_final->buf[i_src]; \ + if (depth_last == NULL || depth_last->id != id) { \ + DepthID *d = &depth_data[depth_data_len_first_pass++]; \ + d->id = id; \ + d->depth = depth; \ + } \ + else if (depth_last->depth > depth) { \ + depth_last->depth = depth; \ + } \ + } \ + } \ + ((void)0) + + { + DepthID *depth_last = NULL; + if (ps->is_cached == false) { + for (uint i = 0; i < ps->src.rect_len; i++) { + EVAL_TEST(i, i); + } + } + else { + /* same as above but different rect sizes */ + uint i_src = ps->cache.sub_rect.start, i_dst = 0; + for (uint j = 0; j < ps->cache.sub_rect.span_len; j++) { + const uint i_src_end = i_src + ps->cache.sub_rect.span; + for (; i_src < i_src_end; i_src++, i_dst++) { + EVAL_TEST(i_src, i_dst); + } + i_src += ps->cache.sub_rect.skip; + } + } + } #undef EVAL_TEST - qsort(depth_data, depth_data_len_first_pass, sizeof(DepthID), depth_id_cmp); - - /* Sort by ID's then keep the best depth for each ID */ - depth_data_len = 0; - { - DepthID *depth_last = NULL; - for (uint i = 0; i < depth_data_len_first_pass; i++) { - if (depth_last == NULL || depth_last->id != depth_data[i].id) { - depth_last = &depth_data[depth_data_len++]; - *depth_last = depth_data[i]; - } - else if (depth_last->depth > depth_data[i].depth) { - depth_last->depth = depth_data[i].depth; - } - } - } - } - - /* Finally sort each unique (id, depth) pair by depth - * so the final hit-list is sorted by depth (nearest first) */ - uint hits = 0; - - if (depth_data_len > maxhits) { - hits = (uint)-1; - } - else { - /* leave sorting up to the caller */ - qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp); - - for (uint i = 0; i < depth_data_len; i++) { + qsort(depth_data, depth_data_len_first_pass, sizeof(DepthID), depth_id_cmp); + + /* Sort by ID's then keep the best depth for each ID */ + depth_data_len = 0; + { + DepthID *depth_last = NULL; + for (uint i = 0; i < depth_data_len_first_pass; i++) { + if (depth_last == NULL || depth_last->id != depth_data[i].id) { + depth_last = &depth_data[depth_data_len++]; + *depth_last = depth_data[i]; + } + else if (depth_last->depth > depth_data[i].depth) { + depth_last->depth = depth_data[i].depth; + } + } + } + } + + /* Finally sort each unique (id, depth) pair by depth + * so the final hit-list is sorted by depth (nearest first) */ + uint hits = 0; + + if (depth_data_len > maxhits) { + hits = (uint)-1; + } + else { + /* leave sorting up to the caller */ + qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp); + + for (uint i = 0; i < depth_data_len; i++) { #ifdef DEBUG_PRINT - printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth); + printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth); #endif - /* first 3 are dummy values */ - g_pick_state.buffer[hits][0] = 1; - g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */ - g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */ - g_pick_state.buffer[hits][3] = depth_data[i].id; - hits++; - } - BLI_assert(hits < maxhits); - } - - MEM_freeN(depth_data); - - MEM_SAFE_FREE(ps->gl.rect_depth); - MEM_SAFE_FREE(ps->gl.rect_depth_test); - - if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { - /* 'hits' already freed as 'depth_data' */ - } - else { - MEM_freeN(ps->nearest.rect_id); - ps->nearest.rect_id = NULL; - } - - if (ps->use_cache) { - ps->is_cached = true; - } - - return hits; + /* first 3 are dummy values */ + g_pick_state.buffer[hits][0] = 1; + g_pick_state.buffer[hits][1] = 0x0; /* depth_data[i].depth; */ /* unused */ + g_pick_state.buffer[hits][2] = 0x0; /* z-far is currently never used. */ + g_pick_state.buffer[hits][3] = depth_data[i].id; + hits++; + } + BLI_assert(hits < maxhits); + } + + MEM_freeN(depth_data); + + MEM_SAFE_FREE(ps->gl.rect_depth); + MEM_SAFE_FREE(ps->gl.rect_depth_test); + + if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { + /* 'hits' already freed as 'depth_data' */ + } + else { + MEM_freeN(ps->nearest.rect_id); + ps->nearest.rect_id = NULL; + } + + if (ps->use_cache) { + ps->is_cached = true; + } + + return hits; } /* ---------------------------------------------------------------------------- @@ -688,52 +688,54 @@ uint gpu_select_pick_end(void) void gpu_select_pick_cache_begin(void) { - BLI_assert(g_pick_state.use_cache == false); + BLI_assert(g_pick_state.use_cache == false); #ifdef DEBUG_PRINT - printf("%s\n", __func__); + printf("%s\n", __func__); #endif - g_pick_state.use_cache = true; - g_pick_state.is_cached = false; + g_pick_state.use_cache = true; + g_pick_state.is_cached = false; } void gpu_select_pick_cache_end(void) { #ifdef DEBUG_PRINT - printf("%s: with %d buffers\n", __func__, BLI_listbase_count(&g_pick_state.cache.bufs)); + printf("%s: with %d buffers\n", __func__, BLI_listbase_count(&g_pick_state.cache.bufs)); #endif - g_pick_state.use_cache = false; - g_pick_state.is_cached = false; + g_pick_state.use_cache = false; + g_pick_state.is_cached = false; - BLI_freelistN(&g_pick_state.cache.bufs); + BLI_freelistN(&g_pick_state.cache.bufs); } /* is drawing needed? */ bool gpu_select_pick_is_cached(void) { - return g_pick_state.is_cached; + return g_pick_state.is_cached; } void gpu_select_pick_cache_load_id(void) { - BLI_assert(g_pick_state.is_cached == true); - GPUPickState *ps = &g_pick_state; + BLI_assert(g_pick_state.is_cached == true); + GPUPickState *ps = &g_pick_state; #ifdef DEBUG_PRINT - printf("%s (building depth from cache)\n", __func__); + printf("%s (building depth from cache)\n", __func__); #endif - for (DepthBufCache *rect_depth = ps->cache.bufs.first; rect_depth; rect_depth = rect_depth->next) { - if (rect_depth->next != NULL) { - /* we know the buffers differ, but this sub-region may not. - * double check before adding an id-pass */ - if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { - if (depth_buf_subrect_depth_any(rect_depth->next, &ps->cache.sub_rect)) { - gpu_select_load_id_pass_all(rect_depth->next); - } - } - else { - if (depth_buf_subrect_depth_any_filled(rect_depth, rect_depth->next, &ps->cache.sub_rect)) { - gpu_select_load_id_pass_nearest(rect_depth, rect_depth->next); - } - } - } - } + for (DepthBufCache *rect_depth = ps->cache.bufs.first; rect_depth; + rect_depth = rect_depth->next) { + if (rect_depth->next != NULL) { + /* we know the buffers differ, but this sub-region may not. + * double check before adding an id-pass */ + if (g_pick_state.mode == GPU_SELECT_PICK_ALL) { + if (depth_buf_subrect_depth_any(rect_depth->next, &ps->cache.sub_rect)) { + gpu_select_load_id_pass_all(rect_depth->next); + } + } + else { + if (depth_buf_subrect_depth_any_filled( + rect_depth, rect_depth->next, &ps->cache.sub_rect)) { + gpu_select_load_id_pass_nearest(rect_depth, rect_depth->next); + } + } + } + } } diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h index b89d6fd244a..bc40e58ba96 100644 --- a/source/blender/gpu/intern/gpu_select_private.h +++ b/source/blender/gpu/intern/gpu_select_private.h @@ -37,11 +37,11 @@ bool gpu_select_pick_is_cached(void); void gpu_select_pick_cache_load_id(void); /* gpu_select_sample_query */ -void gpu_select_query_begin(uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits); +void gpu_select_query_begin( + uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits); bool gpu_select_query_load_id(uint id); uint gpu_select_query_end(void); - #define SELECT_ID_NONE ((uint)0xffffffff) -#endif /* __GPU_SELECT_PRIVATE_H__ */ +#endif /* __GPU_SELECT_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_select_sample_query.c b/source/blender/gpu/intern/gpu_select_sample_query.c index 60f42b31725..3fbc24d6089 100644 --- a/source/blender/gpu/intern/gpu_select_sample_query.c +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -42,179 +42,179 @@ #include "gpu_select_private.h" - /* Ad hoc number of queries to allocate to skip doing many glGenQueries */ #define ALLOC_QUERIES 200 typedef struct GPUQueryState { - /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */ - bool query_issued; - /* array holding the OpenGL query identifiers */ - uint *queries; - /* array holding the id corresponding to each query */ - uint *id; - /* number of queries in *queries and *id */ - uint num_of_queries; - /* index to the next query to start */ - uint active_query; - /* cache on initialization */ - uint (*buffer)[4]; - /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ - uint bufsize; - /* mode of operation */ - char mode; - uint index; - int oldhits; + /* Tracks whether a query has been issued so that gpu_load_id can end the previous one */ + bool query_issued; + /* array holding the OpenGL query identifiers */ + uint *queries; + /* array holding the id corresponding to each query */ + uint *id; + /* number of queries in *queries and *id */ + uint num_of_queries; + /* index to the next query to start */ + uint active_query; + /* cache on initialization */ + uint (*buffer)[4]; + /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ + uint bufsize; + /* mode of operation */ + char mode; + uint index; + int oldhits; } GPUQueryState; static GPUQueryState g_query_state = {0}; - void gpu_select_query_begin( - uint (*buffer)[4], uint bufsize, - const rcti *input, char mode, - int oldhits) + uint (*buffer)[4], uint bufsize, const rcti *input, char mode, int oldhits) { - float viewport[4]; - - g_query_state.query_issued = false; - g_query_state.active_query = 0; - g_query_state.num_of_queries = 0; - g_query_state.bufsize = bufsize; - g_query_state.buffer = buffer; - g_query_state.mode = mode; - g_query_state.index = 0; - g_query_state.oldhits = oldhits; - - g_query_state.num_of_queries = ALLOC_QUERIES; - - g_query_state.queries = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries"); - g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), "gpu selection ids"); - glGenQueries(g_query_state.num_of_queries, g_query_state.queries); - - gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT | GPU_SCISSOR_BIT); - /* disable writing to the framebuffer */ - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - - /* In order to save some fill rate we minimize the viewport using rect. - * We need to get the region of the viewport so that our geometry doesn't - * get rejected before the depth test. Should probably cull rect against - * the viewport but this is a rare case I think */ - glGetFloatv(GL_VIEWPORT, viewport); - glViewport(viewport[0], viewport[1], BLI_rcti_size_x(input), BLI_rcti_size_y(input)); - - /* occlusion queries operates on fragments that pass tests and since we are interested on all - * objects in the view frustum independently of their order, we need to disable the depth test */ - if (mode == GPU_SELECT_ALL) { - glDisable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - } - else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) { - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LEQUAL); - } - else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDepthFunc(GL_EQUAL); - } + float viewport[4]; + + g_query_state.query_issued = false; + g_query_state.active_query = 0; + g_query_state.num_of_queries = 0; + g_query_state.bufsize = bufsize; + g_query_state.buffer = buffer; + g_query_state.mode = mode; + g_query_state.index = 0; + g_query_state.oldhits = oldhits; + + g_query_state.num_of_queries = ALLOC_QUERIES; + + g_query_state.queries = MEM_mallocN( + g_query_state.num_of_queries * sizeof(*g_query_state.queries), "gpu selection queries"); + g_query_state.id = MEM_mallocN(g_query_state.num_of_queries * sizeof(*g_query_state.id), + "gpu selection ids"); + glGenQueries(g_query_state.num_of_queries, g_query_state.queries); + + gpuPushAttr(GPU_DEPTH_BUFFER_BIT | GPU_VIEWPORT_BIT | GPU_SCISSOR_BIT); + /* disable writing to the framebuffer */ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + /* In order to save some fill rate we minimize the viewport using rect. + * We need to get the region of the viewport so that our geometry doesn't + * get rejected before the depth test. Should probably cull rect against + * the viewport but this is a rare case I think */ + glGetFloatv(GL_VIEWPORT, viewport); + glViewport(viewport[0], viewport[1], BLI_rcti_size_x(input), BLI_rcti_size_y(input)); + + /* occlusion queries operates on fragments that pass tests and since we are interested on all + * objects in the view frustum independently of their order, we need to disable the depth test */ + if (mode == GPU_SELECT_ALL) { + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + } + else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) { + glClear(GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + glDepthFunc(GL_LEQUAL); + } + else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + glDepthFunc(GL_EQUAL); + } } bool gpu_select_query_load_id(uint id) { - if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); - } - /* if required, allocate extra queries */ - if (g_query_state.active_query == g_query_state.num_of_queries) { - g_query_state.num_of_queries += ALLOC_QUERIES; - g_query_state.queries = MEM_reallocN(g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries)); - g_query_state.id = MEM_reallocN(g_query_state.id, g_query_state.num_of_queries * sizeof(*g_query_state.id)); - glGenQueries(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]); - } - - glBeginQuery(GL_SAMPLES_PASSED, g_query_state.queries[g_query_state.active_query]); - g_query_state.id[g_query_state.active_query] = id; - g_query_state.active_query++; - g_query_state.query_issued = true; - - if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) { - /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */ - BLI_assert(g_query_state.oldhits != -1); - if (g_query_state.index < g_query_state.oldhits) { - if (g_query_state.buffer[g_query_state.index][3] == id) { - g_query_state.index++; - return true; - } - else { - return false; - } - } - } - - return true; + if (g_query_state.query_issued) { + glEndQuery(GL_SAMPLES_PASSED); + } + /* if required, allocate extra queries */ + if (g_query_state.active_query == g_query_state.num_of_queries) { + g_query_state.num_of_queries += ALLOC_QUERIES; + g_query_state.queries = MEM_reallocN( + g_query_state.queries, g_query_state.num_of_queries * sizeof(*g_query_state.queries)); + g_query_state.id = MEM_reallocN(g_query_state.id, + g_query_state.num_of_queries * sizeof(*g_query_state.id)); + glGenQueries(ALLOC_QUERIES, &g_query_state.queries[g_query_state.active_query]); + } + + glBeginQuery(GL_SAMPLES_PASSED, g_query_state.queries[g_query_state.active_query]); + g_query_state.id[g_query_state.active_query] = id; + g_query_state.active_query++; + g_query_state.query_issued = true; + + if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) { + /* Second pass should never run if first pass fails, can read past 'bufsize' in this case. */ + BLI_assert(g_query_state.oldhits != -1); + if (g_query_state.index < g_query_state.oldhits) { + if (g_query_state.buffer[g_query_state.index][3] == id) { + g_query_state.index++; + return true; + } + else { + return false; + } + } + } + + return true; } uint gpu_select_query_end(void) { - int i; - - uint hits = 0; - const uint maxhits = g_query_state.bufsize; - - if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); - } - - for (i = 0; i < g_query_state.active_query; i++) { - uint result = 0; - /* Wait until the result is available. */ - while (result == 0) { - glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result); - if (result == 0) { - /* (fclem) Not sure if this is better than calling - * glGetQueryObjectuiv() indefinitely. */ - PIL_sleep_ms(1); - } - } - glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result); - if (result > 0) { - if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) { - - if (hits < maxhits) { - g_query_state.buffer[hits][0] = 1; - g_query_state.buffer[hits][1] = 0xFFFF; - g_query_state.buffer[hits][2] = 0xFFFF; - g_query_state.buffer[hits][3] = g_query_state.id[i]; - - hits++; - } - else { - hits = -1; - break; - } - } - else { - int j; - /* search in buffer and make selected object first */ - for (j = 0; j < g_query_state.oldhits; j++) { - if (g_query_state.buffer[j][3] == g_query_state.id[i]) { - g_query_state.buffer[j][1] = 0; - g_query_state.buffer[j][2] = 0; - } - } - break; - } - } - } - - glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries); - MEM_freeN(g_query_state.queries); - MEM_freeN(g_query_state.id); - gpuPopAttr(); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - - return hits; + int i; + + uint hits = 0; + const uint maxhits = g_query_state.bufsize; + + if (g_query_state.query_issued) { + glEndQuery(GL_SAMPLES_PASSED); + } + + for (i = 0; i < g_query_state.active_query; i++) { + uint result = 0; + /* Wait until the result is available. */ + while (result == 0) { + glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT_AVAILABLE, &result); + if (result == 0) { + /* (fclem) Not sure if this is better than calling + * glGetQueryObjectuiv() indefinitely. */ + PIL_sleep_ms(1); + } + } + glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result); + if (result > 0) { + if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) { + + if (hits < maxhits) { + g_query_state.buffer[hits][0] = 1; + g_query_state.buffer[hits][1] = 0xFFFF; + g_query_state.buffer[hits][2] = 0xFFFF; + g_query_state.buffer[hits][3] = g_query_state.id[i]; + + hits++; + } + else { + hits = -1; + break; + } + } + else { + int j; + /* search in buffer and make selected object first */ + for (j = 0; j < g_query_state.oldhits; j++) { + if (g_query_state.buffer[j][3] == g_query_state.id[i]) { + g_query_state.buffer[j][1] = 0; + g_query_state.buffer[j][2] = 0; + } + } + break; + } + } + } + + glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries); + MEM_freeN(g_query_state.queries); + MEM_freeN(g_query_state.id); + gpuPopAttr(); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + return hits; } diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 21807e07643..dd8035e2618 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -173,14 +173,16 @@ extern char datatoc_gpu_shader_gpencil_fill_frag_glsl[]; extern char datatoc_gpu_shader_cfg_world_clip_lib_glsl[]; const struct GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN] = { - [GPU_SHADER_CFG_DEFAULT] = { - .lib = "", - .def = "", - }, - [GPU_SHADER_CFG_CLIPPED] = { - .lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl, - .def = "#define USE_WORLD_CLIP_PLANES\n", - }, + [GPU_SHADER_CFG_DEFAULT] = + { + .lib = "", + .def = "", + }, + [GPU_SHADER_CFG_CLIPPED] = + { + .lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl, + .def = "#define USE_WORLD_CLIP_PLANES\n", + }, }; /* cache of built-in shaders (each is created on first use) */ @@ -191,115 +193,106 @@ static uint g_shaderid = 0; #endif typedef struct { - const char *vert; - /** Optional. */ - const char *geom; - const char *frag; - /** Optional. */ - const char *defs; + const char *vert; + /** Optional. */ + const char *geom; + const char *frag; + /** Optional. */ + const char *defs; } GPUShaderStages; static void shader_print_errors(const char *task, const char *log, const char **code, int totcode) { - int line = 1; + int line = 1; - fprintf(stderr, "GPUShader: %s error:\n", task); + fprintf(stderr, "GPUShader: %s error:\n", task); - for (int i = 0; i < totcode; i++) { - const char *c, *pos, *end = code[i] + strlen(code[i]); + for (int i = 0; i < totcode; i++) { + const char *c, *pos, *end = code[i] + strlen(code[i]); - if (G.debug & G_DEBUG) { - fprintf(stderr, "===== shader string %d ====\n", i + 1); + if (G.debug & G_DEBUG) { + fprintf(stderr, "===== shader string %d ====\n", i + 1); - c = code[i]; - while ((c < end) && (pos = strchr(c, '\n'))) { - fprintf(stderr, "%2d ", line); - fwrite(c, (pos + 1) - c, 1, stderr); - c = pos + 1; - line++; - } + c = code[i]; + while ((c < end) && (pos = strchr(c, '\n'))) { + fprintf(stderr, "%2d ", line); + fwrite(c, (pos + 1) - c, 1, stderr); + c = pos + 1; + line++; + } - fprintf(stderr, "%s", c); - } - } + fprintf(stderr, "%s", c); + } + } - fprintf(stderr, "%s\n", log); + fprintf(stderr, "%s\n", log); } static const char *gpu_shader_version(void) { - return "#version 330\n"; + return "#version 330\n"; } static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH]) { - /* enable extensions for features that are not part of our base GLSL version - * don't use an extension for something already available! - */ - - if (GLEW_ARB_texture_gather) { - /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather - * is reported to be supported but yield a compile error (see T55802). */ - if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) || GLEW_VERSION_4_0) { - strcat(defines, "#extension GL_ARB_texture_gather: enable\n"); - - /* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the - * shader so double check the preprocessor define (see T56544). */ - if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) { - strcat(defines, "#ifdef GL_ARB_texture_gather\n"); - strcat(defines, "# define GPU_ARB_texture_gather\n"); - strcat(defines, "#endif\n"); - } - else { - strcat(defines, "#define GPU_ARB_texture_gather\n"); - } - } - } - if (GLEW_ARB_texture_query_lod) { - /* a #version 400 feature, but we use #version 330 maximum so use extension */ - strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); - } + /* enable extensions for features that are not part of our base GLSL version + * don't use an extension for something already available! + */ + + if (GLEW_ARB_texture_gather) { + /* There is a bug on older Nvidia GPU where GL_ARB_texture_gather + * is reported to be supported but yield a compile error (see T55802). */ + if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) || GLEW_VERSION_4_0) { + strcat(defines, "#extension GL_ARB_texture_gather: enable\n"); + + /* Some drivers don't agree on GLEW_ARB_texture_gather and the actual support in the + * shader so double check the preprocessor define (see T56544). */ + if (!GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY) && !GLEW_VERSION_4_0) { + strcat(defines, "#ifdef GL_ARB_texture_gather\n"); + strcat(defines, "# define GPU_ARB_texture_gather\n"); + strcat(defines, "#endif\n"); + } + else { + strcat(defines, "#define GPU_ARB_texture_gather\n"); + } + } + } + if (GLEW_ARB_texture_query_lod) { + /* a #version 400 feature, but we use #version 330 maximum so use extension */ + strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"); + } } static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH]) { - /* some useful defines to detect GPU type */ - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) - strcat(defines, "#define GPU_ATI\n"); - else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) - strcat(defines, "#define GPU_NVIDIA\n"); - else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) - strcat(defines, "#define GPU_INTEL\n"); - - /* some useful defines to detect OS type */ - if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_WIN, GPU_DRIVER_ANY)) - strcat(defines, "#define OS_WIN\n"); - else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) - strcat(defines, "#define OS_MAC\n"); - else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_ANY)) - strcat(defines, "#define OS_UNIX\n"); - - return; + /* some useful defines to detect GPU type */ + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) + strcat(defines, "#define GPU_ATI\n"); + else if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) + strcat(defines, "#define GPU_NVIDIA\n"); + else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) + strcat(defines, "#define GPU_INTEL\n"); + + /* some useful defines to detect OS type */ + if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_WIN, GPU_DRIVER_ANY)) + strcat(defines, "#define OS_WIN\n"); + else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_MAC, GPU_DRIVER_ANY)) + strcat(defines, "#define OS_MAC\n"); + else if (GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_ANY)) + strcat(defines, "#define OS_UNIX\n"); + + return; } -GPUShader *GPU_shader_create( - const char *vertexcode, - const char *fragcode, - const char *geocode, - const char *libcode, - const char *defines, - const char *shname) +GPUShader *GPU_shader_create(const char *vertexcode, + const char *fragcode, + const char *geocode, + const char *libcode, + const char *defines, + const char *shname) { - return GPU_shader_create_ex( - vertexcode, - fragcode, - geocode, - libcode, - defines, - GPU_SHADER_TFB_NONE, - NULL, - 0, - shname); + return GPU_shader_create_ex( + vertexcode, fragcode, geocode, libcode, defines, GPU_SHADER_TFB_NONE, NULL, 0, shname); } #define DEBUG_SHADER_NONE "" @@ -316,204 +309,208 @@ GPUShader *GPU_shader_create( */ static void gpu_dump_shaders(const char **code, const int num_shaders, const char *extension) { - if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) { - return; - } - - /* We use the same shader index for shaders in the same program. - * So we call this function once before calling for the individual shaders. */ - static int shader_index = 0; - if (code == NULL) { - shader_index++; - BLI_assert(STREQ(DEBUG_SHADER_NONE, extension)); - return; - } - - /* Determine the full path of the new shader. */ - char shader_path[FILE_MAX]; - - char file_name[512] = {'\0'}; - sprintf(file_name, "%04d.%s", shader_index, extension); - - BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name); - - /* Write shader to disk. */ - FILE *f = fopen(shader_path, "w"); - if (f == NULL) { - printf("Error writing to file: %s\n", shader_path); - } - for (int j = 0; j < num_shaders; j++) { - fprintf(f, "%s", code[j]); - } - fclose(f); - printf("Shader file written to disk: %s\n", shader_path); + if ((G.debug & G_DEBUG_GPU_SHADERS) == 0) { + return; + } + + /* We use the same shader index for shaders in the same program. + * So we call this function once before calling for the individual shaders. */ + static int shader_index = 0; + if (code == NULL) { + shader_index++; + BLI_assert(STREQ(DEBUG_SHADER_NONE, extension)); + return; + } + + /* Determine the full path of the new shader. */ + char shader_path[FILE_MAX]; + + char file_name[512] = {'\0'}; + sprintf(file_name, "%04d.%s", shader_index, extension); + + BLI_join_dirfile(shader_path, sizeof(shader_path), BKE_tempdir_session(), file_name); + + /* Write shader to disk. */ + FILE *f = fopen(shader_path, "w"); + if (f == NULL) { + printf("Error writing to file: %s\n", shader_path); + } + for (int j = 0; j < num_shaders; j++) { + fprintf(f, "%s", code[j]); + } + fclose(f); + printf("Shader file written to disk: %s\n", shader_path); } -GPUShader *GPU_shader_create_ex( - const char *vertexcode, - const char *fragcode, - const char *geocode, - const char *libcode, - const char *defines, - const eGPUShaderTFBType tf_type, - const char **tf_names, - const int tf_count, - const char *shname) +GPUShader *GPU_shader_create_ex(const char *vertexcode, + const char *fragcode, + const char *geocode, + const char *libcode, + const char *defines, + const eGPUShaderTFBType tf_type, + const char **tf_names, + const int tf_count, + const char *shname) { - GLint status; - GLchar log[5000]; - GLsizei length = 0; - GPUShader *shader; - char standard_defines[MAX_DEFINE_LENGTH] = ""; - char standard_extensions[MAX_EXT_DEFINE_LENGTH] = ""; + GLint status; + GLchar log[5000]; + GLsizei length = 0; + GPUShader *shader; + char standard_defines[MAX_DEFINE_LENGTH] = ""; + char standard_extensions[MAX_EXT_DEFINE_LENGTH] = ""; - shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); - gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE); + shader = MEM_callocN(sizeof(GPUShader), "GPUShader"); + gpu_dump_shaders(NULL, 0, DEBUG_SHADER_NONE); #ifndef NDEBUG - BLI_snprintf(shader->name, sizeof(shader->name), "%s_%u", shname, g_shaderid++); + BLI_snprintf(shader->name, sizeof(shader->name), "%s_%u", shname, g_shaderid++); #else - UNUSED_VARS(shname); + UNUSED_VARS(shname); #endif - /* At least a vertex shader and a fragment shader are required. */ - BLI_assert((fragcode != NULL) && (vertexcode != NULL)); + /* At least a vertex shader and a fragment shader are required. */ + BLI_assert((fragcode != NULL) && (vertexcode != NULL)); - if (vertexcode) - shader->vertex = glCreateShader(GL_VERTEX_SHADER); - if (fragcode) - shader->fragment = glCreateShader(GL_FRAGMENT_SHADER); - if (geocode) - shader->geometry = glCreateShader(GL_GEOMETRY_SHADER); + if (vertexcode) + shader->vertex = glCreateShader(GL_VERTEX_SHADER); + if (fragcode) + shader->fragment = glCreateShader(GL_FRAGMENT_SHADER); + if (geocode) + shader->geometry = glCreateShader(GL_GEOMETRY_SHADER); - shader->program = glCreateProgram(); + shader->program = glCreateProgram(); - if (!shader->program || - (vertexcode && !shader->vertex) || - (fragcode && !shader->fragment) || - (geocode && !shader->geometry)) - { - fprintf(stderr, "GPUShader, object creation failed.\n"); - GPU_shader_free(shader); - return NULL; - } + if (!shader->program || (vertexcode && !shader->vertex) || (fragcode && !shader->fragment) || + (geocode && !shader->geometry)) { + fprintf(stderr, "GPUShader, object creation failed.\n"); + GPU_shader_free(shader); + return NULL; + } - gpu_shader_standard_defines(standard_defines); - gpu_shader_standard_extensions(standard_extensions); + gpu_shader_standard_defines(standard_defines); + gpu_shader_standard_extensions(standard_extensions); - if (vertexcode) { - const char *source[6]; - /* custom limit, may be too small, beware */ - int num_source = 0; - - source[num_source++] = gpu_shader_version(); - source[num_source++] = "#define GPU_VERTEX_SHADER\n"; - source[num_source++] = standard_extensions; - source[num_source++] = standard_defines; - - if (defines) source[num_source++] = defines; - source[num_source++] = vertexcode; - - gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX); - - glAttachShader(shader->program, shader->vertex); - glShaderSource(shader->vertex, num_source, source, NULL); - - glCompileShader(shader->vertex); - glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status); - - if (!status) { - glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log); - shader_print_errors("compile", log, source, num_source); - - GPU_shader_free(shader); - return NULL; - } - } - - if (fragcode) { - const char *source[7]; - int num_source = 0; - - source[num_source++] = gpu_shader_version(); - source[num_source++] = "#define GPU_FRAGMENT_SHADER\n"; - source[num_source++] = standard_extensions; - source[num_source++] = standard_defines; - - if (defines) source[num_source++] = defines; - if (libcode) source[num_source++] = libcode; - source[num_source++] = fragcode; - - gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT); - - glAttachShader(shader->program, shader->fragment); - glShaderSource(shader->fragment, num_source, source, NULL); - - glCompileShader(shader->fragment); - glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status); - - if (!status) { - glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log); - shader_print_errors("compile", log, source, num_source); - - GPU_shader_free(shader); - return NULL; - } - } - - if (geocode) { - const char *source[6]; - int num_source = 0; - - source[num_source++] = gpu_shader_version(); - source[num_source++] = "#define GPU_GEOMETRY_SHADER\n"; - source[num_source++] = standard_extensions; - source[num_source++] = standard_defines; - - if (defines) source[num_source++] = defines; - source[num_source++] = geocode; - - gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY); - - glAttachShader(shader->program, shader->geometry); - glShaderSource(shader->geometry, num_source, source, NULL); - - glCompileShader(shader->geometry); - glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status); - - if (!status) { - glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log); - shader_print_errors("compile", log, source, num_source); - - GPU_shader_free(shader); - return NULL; - } - } - - if (tf_names != NULL) { - glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS); - /* Primitive type must be setup */ - BLI_assert(tf_type != GPU_SHADER_TFB_NONE); - shader->feedback_transform_type = tf_type; - } - - glLinkProgram(shader->program); - glGetProgramiv(shader->program, GL_LINK_STATUS, &status); - if (!status) { - glGetProgramInfoLog(shader->program, sizeof(log), &length, log); - /* print attached shaders in pipeline order */ - if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1); - if (geocode) shader_print_errors("linking", log, &geocode, 1); - if (libcode) shader_print_errors("linking", log, &libcode, 1); - if (fragcode) shader_print_errors("linking", log, &fragcode, 1); - - GPU_shader_free(shader); - return NULL; - } - - shader->interface = GPU_shaderinterface_create(shader->program); - - return shader; + if (vertexcode) { + const char *source[6]; + /* custom limit, may be too small, beware */ + int num_source = 0; + + source[num_source++] = gpu_shader_version(); + source[num_source++] = "#define GPU_VERTEX_SHADER\n"; + source[num_source++] = standard_extensions; + source[num_source++] = standard_defines; + + if (defines) + source[num_source++] = defines; + source[num_source++] = vertexcode; + + gpu_dump_shaders(source, num_source, DEBUG_SHADER_VERTEX); + + glAttachShader(shader->program, shader->vertex); + glShaderSource(shader->vertex, num_source, source, NULL); + + glCompileShader(shader->vertex); + glGetShaderiv(shader->vertex, GL_COMPILE_STATUS, &status); + + if (!status) { + glGetShaderInfoLog(shader->vertex, sizeof(log), &length, log); + shader_print_errors("compile", log, source, num_source); + + GPU_shader_free(shader); + return NULL; + } + } + + if (fragcode) { + const char *source[7]; + int num_source = 0; + + source[num_source++] = gpu_shader_version(); + source[num_source++] = "#define GPU_FRAGMENT_SHADER\n"; + source[num_source++] = standard_extensions; + source[num_source++] = standard_defines; + + if (defines) + source[num_source++] = defines; + if (libcode) + source[num_source++] = libcode; + source[num_source++] = fragcode; + + gpu_dump_shaders(source, num_source, DEBUG_SHADER_FRAGMENT); + + glAttachShader(shader->program, shader->fragment); + glShaderSource(shader->fragment, num_source, source, NULL); + + glCompileShader(shader->fragment); + glGetShaderiv(shader->fragment, GL_COMPILE_STATUS, &status); + + if (!status) { + glGetShaderInfoLog(shader->fragment, sizeof(log), &length, log); + shader_print_errors("compile", log, source, num_source); + + GPU_shader_free(shader); + return NULL; + } + } + + if (geocode) { + const char *source[6]; + int num_source = 0; + + source[num_source++] = gpu_shader_version(); + source[num_source++] = "#define GPU_GEOMETRY_SHADER\n"; + source[num_source++] = standard_extensions; + source[num_source++] = standard_defines; + + if (defines) + source[num_source++] = defines; + source[num_source++] = geocode; + + gpu_dump_shaders(source, num_source, DEBUG_SHADER_GEOMETRY); + + glAttachShader(shader->program, shader->geometry); + glShaderSource(shader->geometry, num_source, source, NULL); + + glCompileShader(shader->geometry); + glGetShaderiv(shader->geometry, GL_COMPILE_STATUS, &status); + + if (!status) { + glGetShaderInfoLog(shader->geometry, sizeof(log), &length, log); + shader_print_errors("compile", log, source, num_source); + + GPU_shader_free(shader); + return NULL; + } + } + + if (tf_names != NULL) { + glTransformFeedbackVaryings(shader->program, tf_count, tf_names, GL_INTERLEAVED_ATTRIBS); + /* Primitive type must be setup */ + BLI_assert(tf_type != GPU_SHADER_TFB_NONE); + shader->feedback_transform_type = tf_type; + } + + glLinkProgram(shader->program); + glGetProgramiv(shader->program, GL_LINK_STATUS, &status); + if (!status) { + glGetProgramInfoLog(shader->program, sizeof(log), &length, log); + /* print attached shaders in pipeline order */ + if (vertexcode) + shader_print_errors("linking", log, &vertexcode, 1); + if (geocode) + shader_print_errors("linking", log, &geocode, 1); + if (libcode) + shader_print_errors("linking", log, &libcode, 1); + if (fragcode) + shader_print_errors("linking", log, &fragcode, 1); + + GPU_shader_free(shader); + return NULL; + } + + shader->interface = GPU_shaderinterface_create(shader->program); + + return shader; } #undef DEBUG_SHADER_GEOMETRY @@ -523,28 +520,28 @@ GPUShader *GPU_shader_create_ex( static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_is_alloc) { - bool is_alloc = false; - if (str_arr == NULL) { - *r_is_alloc = false; - return NULL; - } - /* Skip empty strings (avoid alloc if we can). */ - while (str_arr[0] && str_arr[0][0] == '\0') { - str_arr++; - } - int i; - for (i = 0; str_arr[i]; i++) { - if (i != 0 && str_arr[i][0] != '\0') { - is_alloc = true; - } - } - *r_is_alloc = is_alloc; - if (is_alloc) { - return BLI_string_join_arrayN(str_arr, i); - } - else { - return str_arr[0]; - } + bool is_alloc = false; + if (str_arr == NULL) { + *r_is_alloc = false; + return NULL; + } + /* Skip empty strings (avoid alloc if we can). */ + while (str_arr[0] && str_arr[0][0] == '\0') { + str_arr++; + } + int i; + for (i = 0; str_arr[i]; i++) { + if (i != 0 && str_arr[i][0] != '\0') { + is_alloc = true; + } + } + *r_is_alloc = is_alloc; + if (is_alloc) { + return BLI_string_join_arrayN(str_arr, i); + } + else { + return str_arr[0]; + } } /** @@ -568,724 +565,815 @@ static const char *string_join_array_maybe_alloc(const char **str_arr, bool *r_i * \endcode */ struct GPUShader *GPU_shader_create_from_arrays_impl( - const struct GPU_ShaderCreateFromArray_Params *params) + const struct GPU_ShaderCreateFromArray_Params *params) { - struct { const char *str; bool is_alloc;} str_dst[4] = {{0}}; - const char **str_src[4] = {params->vert, params->frag, params->geom, params->defs}; - - for (int i = 0; i < ARRAY_SIZE(str_src); i++) { - str_dst[i].str = string_join_array_maybe_alloc(str_src[i], &str_dst[i].is_alloc); - } - - GPUShader *sh = GPU_shader_create( - str_dst[0].str, str_dst[1].str, str_dst[2].str, NULL, str_dst[3].str, __func__); - - for (int i = 0; i < ARRAY_SIZE(str_dst); i++) { - if (str_dst[i].is_alloc) { - MEM_freeN((void *)str_dst[i].str); - } - } - return sh; + struct { + const char *str; + bool is_alloc; + } str_dst[4] = {{0}}; + const char **str_src[4] = {params->vert, params->frag, params->geom, params->defs}; + + for (int i = 0; i < ARRAY_SIZE(str_src); i++) { + str_dst[i].str = string_join_array_maybe_alloc(str_src[i], &str_dst[i].is_alloc); + } + + GPUShader *sh = GPU_shader_create( + str_dst[0].str, str_dst[1].str, str_dst[2].str, NULL, str_dst[3].str, __func__); + + for (int i = 0; i < ARRAY_SIZE(str_dst); i++) { + if (str_dst[i].is_alloc) { + MEM_freeN((void *)str_dst[i].str); + } + } + return sh; } void GPU_shader_bind(GPUShader *shader) { - BLI_assert(shader && shader->program); + BLI_assert(shader && shader->program); - glUseProgram(shader->program); - GPU_matrix_bind(shader->interface); + glUseProgram(shader->program); + GPU_matrix_bind(shader->interface); } void GPU_shader_unbind(void) { - glUseProgram(0); + glUseProgram(0); } bool GPU_shader_transform_feedback_enable(GPUShader *shader, uint vbo_id) { - if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) { - return false; - } - - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id); - - switch (shader->feedback_transform_type) { - case GPU_SHADER_TFB_POINTS: glBeginTransformFeedback(GL_POINTS); return true; - case GPU_SHADER_TFB_LINES: glBeginTransformFeedback(GL_LINES); return true; - case GPU_SHADER_TFB_TRIANGLES: glBeginTransformFeedback(GL_TRIANGLES); return true; - default: return false; - } + if (shader->feedback_transform_type == GPU_SHADER_TFB_NONE) { + return false; + } + + glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo_id); + + switch (shader->feedback_transform_type) { + case GPU_SHADER_TFB_POINTS: + glBeginTransformFeedback(GL_POINTS); + return true; + case GPU_SHADER_TFB_LINES: + glBeginTransformFeedback(GL_LINES); + return true; + case GPU_SHADER_TFB_TRIANGLES: + glBeginTransformFeedback(GL_TRIANGLES); + return true; + default: + return false; + } } void GPU_shader_transform_feedback_disable(GPUShader *UNUSED(shader)) { - glEndTransformFeedback(); + glEndTransformFeedback(); } void GPU_shader_free(GPUShader *shader) { #if 0 /* Would be nice to have, but for now the Deferred compilation * does not have a GPUContext. */ - BLI_assert(GPU_context_active_get() != NULL); + BLI_assert(GPU_context_active_get() != NULL); #endif - BLI_assert(shader); + BLI_assert(shader); - if (shader->vertex) - glDeleteShader(shader->vertex); - if (shader->geometry) - glDeleteShader(shader->geometry); - if (shader->fragment) - glDeleteShader(shader->fragment); - if (shader->program) - glDeleteProgram(shader->program); + if (shader->vertex) + glDeleteShader(shader->vertex); + if (shader->geometry) + glDeleteShader(shader->geometry); + if (shader->fragment) + glDeleteShader(shader->fragment); + if (shader->program) + glDeleteProgram(shader->program); - if (shader->interface) - GPU_shaderinterface_discard(shader->interface); + if (shader->interface) + GPU_shaderinterface_discard(shader->interface); - MEM_freeN(shader); + MEM_freeN(shader); } int GPU_shader_get_uniform(GPUShader *shader, const char *name) { - BLI_assert(shader && shader->program); - const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name); - return uniform ? uniform->location : -2; + BLI_assert(shader && shader->program); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name); + return uniform ? uniform->location : -2; } int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name) { - BLI_assert(shader && shader->program); - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name); - return uniform ? uniform->location : -1; + BLI_assert(shader && shader->program); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name); + return uniform ? uniform->location : -1; } int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin) { - BLI_assert(shader && shader->program); - const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin); - return uniform ? uniform->location : -1; + BLI_assert(shader && shader->program); + const GPUShaderInput *uniform = GPU_shaderinterface_uniform_builtin(shader->interface, builtin); + return uniform ? uniform->location : -1; } int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) { - BLI_assert(shader && shader->program); - const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); - return ubo ? ubo->location : -1; + BLI_assert(shader && shader->program); + const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name); + return ubo ? ubo->location : -1; } void *GPU_shader_get_interface(GPUShader *shader) { - return shader->interface; + return shader->interface; } /* Clement : Temp */ int GPU_shader_get_program(GPUShader *shader) { - return (int)shader->program; + return (int)shader->program; } void GPU_shader_uniform_float(GPUShader *UNUSED(shader), int location, float value) { - if (location == -1) - return; + if (location == -1) + return; - glUniform1f(location, value); + glUniform1f(location, value); } -void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value) +void GPU_shader_uniform_vector( + GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value) { - if (location == -1 || value == NULL) - return; - - if (length == 1) glUniform1fv(location, arraysize, value); - else if (length == 2) glUniform2fv(location, arraysize, value); - else if (length == 3) glUniform3fv(location, arraysize, value); - else if (length == 4) glUniform4fv(location, arraysize, value); - else if (length == 9) glUniformMatrix3fv(location, arraysize, 0, value); - else if (length == 16) glUniformMatrix4fv(location, arraysize, 0, value); + if (location == -1 || value == NULL) + return; + + if (length == 1) + glUniform1fv(location, arraysize, value); + else if (length == 2) + glUniform2fv(location, arraysize, value); + else if (length == 3) + glUniform3fv(location, arraysize, value); + else if (length == 4) + glUniform4fv(location, arraysize, value); + else if (length == 9) + glUniformMatrix3fv(location, arraysize, 0, value); + else if (length == 16) + glUniformMatrix4fv(location, arraysize, 0, value); } -void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value) +void GPU_shader_uniform_vector_int( + GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value) { - if (location == -1) - return; - - if (length == 1) glUniform1iv(location, arraysize, value); - else if (length == 2) glUniform2iv(location, arraysize, value); - else if (length == 3) glUniform3iv(location, arraysize, value); - else if (length == 4) glUniform4iv(location, arraysize, value); + if (location == -1) + return; + + if (length == 1) + glUniform1iv(location, arraysize, value); + else if (length == 2) + glUniform2iv(location, arraysize, value); + else if (length == 3) + glUniform3iv(location, arraysize, value); + else if (length == 4) + glUniform4iv(location, arraysize, value); } void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value) { - if (location == -1) - return; + if (location == -1) + return; - glUniform1i(location, value); + glUniform1i(location, value); } void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo) { - int bindpoint = GPU_uniformbuffer_bindpoint(ubo); + int bindpoint = GPU_uniformbuffer_bindpoint(ubo); - if (location == -1) { - return; - } + if (location == -1) { + return; + } - glUniformBlockBinding(shader->program, location, bindpoint); + glUniformBlockBinding(shader->program, location, bindpoint); } void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex) { - int number = GPU_texture_bound_number(tex); + int number = GPU_texture_bound_number(tex); - if (number == -1) { - fprintf(stderr, "Texture is not bound.\n"); - BLI_assert(0); - return; - } + if (number == -1) { + fprintf(stderr, "Texture is not bound.\n"); + BLI_assert(0); + return; + } - if (location == -1) - return; + if (location == -1) + return; - glUniform1i(location, number); + glUniform1i(location, number); } int GPU_shader_get_attribute(GPUShader *shader, const char *name) { - BLI_assert(shader && shader->program); - const GPUShaderInput *attr = GPU_shaderinterface_attr(shader->interface, name); - return attr ? attr->location : -1; + BLI_assert(shader && shader->program); + const GPUShaderInput *attr = GPU_shaderinterface_attr(shader->interface, name); + return attr ? attr->location : -1; } static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = { - [GPU_SHADER_TEXT] = { - .vert = datatoc_gpu_shader_text_vert_glsl, - .geom = datatoc_gpu_shader_text_geom_glsl, - .frag = datatoc_gpu_shader_text_frag_glsl, - }, - [GPU_SHADER_TEXT_SIMPLE] = { - .vert = datatoc_gpu_shader_text_simple_vert_glsl, - .geom = datatoc_gpu_shader_text_simple_geom_glsl, - .frag = datatoc_gpu_shader_text_frag_glsl, - }, - [GPU_SHADER_KEYFRAME_DIAMOND] = { - .vert = datatoc_gpu_shader_keyframe_diamond_vert_glsl, - .frag = datatoc_gpu_shader_keyframe_diamond_frag_glsl, - }, - /* This version is magical but slow! */ - [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = { - .vert = datatoc_gpu_shader_edges_front_back_persp_vert_glsl, - .geom = datatoc_gpu_shader_edges_front_back_persp_geom_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = { - .vert = datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .geom = datatoc_gpu_shader_edges_overlay_simple_geom_glsl, - .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, - }, - [GPU_SHADER_EDGES_OVERLAY] = { - .vert = datatoc_gpu_shader_edges_overlay_vert_glsl, - .geom = datatoc_gpu_shader_edges_overlay_geom_glsl, - .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, - }, - [GPU_SHADER_SIMPLE_LIGHTING] = { - .vert = datatoc_gpu_shader_3D_normal_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_frag_glsl, - }, - /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ - [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, - .defs = - "#define USE_FLAT_NORMAL\n", - }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, - }, - [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = { - .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl, - }, - - [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_mask_uniform_color_frag_glsl, - }, - [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_modulate_alpha_frag_glsl, - }, - [GPU_SHADER_3D_IMAGE_DEPTH] = { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_depth_linear_frag_glsl, - }, - [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = { - .vert = datatoc_gpu_shader_3D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_depth_copy_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 2\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 4\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 8\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 16\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 2\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 4\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 8\n" - "#define USE_DEPTH\n", - }, - [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, - .defs = - "#define SAMPLES 16\n" - "#define USE_DEPTH\n", - }, - - [GPU_SHADER_2D_IMAGE_INTERLACE] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_interlace_frag_glsl, - }, - [GPU_SHADER_2D_CHECKER] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_checker_frag_glsl, - }, - - [GPU_SHADER_2D_DIAG_STRIPES] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_diag_stripes_frag_glsl, - }, - - [GPU_SHADER_2D_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - }, - [GPU_SHADER_2D_FLAT_COLOR] = { - .vert = datatoc_gpu_shader_2D_flat_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_2D_SMOOTH_COLOR] = { - .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, - }, - [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = { - .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_linear_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_color_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_desaturate_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_alpha_color_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_vert_glsl, - .frag = datatoc_gpu_shader_image_shuffle_color_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_RECT_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_rect_vert_glsl, - .frag = datatoc_gpu_shader_image_color_frag_glsl, - }, - [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = { - .vert = datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, - .frag = datatoc_gpu_shader_image_varying_color_frag_glsl, - }, - - [GPU_SHADER_3D_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - }, - [GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND] = { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - .defs = - "#define USE_BACKGROUND\n", - }, - [GPU_SHADER_3D_FLAT_COLOR] = { - .vert = datatoc_gpu_shader_3D_flat_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_3D_SMOOTH_COLOR] = { - .vert = datatoc_gpu_shader_3D_smooth_color_vert_glsl, - .frag = datatoc_gpu_shader_3D_smooth_color_frag_glsl, - }, - [GPU_SHADER_3D_DEPTH_ONLY] = { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .frag = datatoc_gpu_shader_depth_only_frag_glsl, - }, - [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - }, - - [GPU_SHADER_3D_GROUNDPOINT] = { - .vert = datatoc_gpu_shader_3D_groundpoint_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, - }, - [GPU_SHADER_3D_GROUNDLINE] = { - .vert = datatoc_gpu_shader_3D_passthrough_vert_glsl, - .geom = datatoc_gpu_shader_3D_groundline_geom_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - }, - - [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl, - .geom = datatoc_gpu_shader_2D_line_dashed_geom_glsl, - .frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl, - }, - [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl, - .geom = datatoc_gpu_shader_2D_line_dashed_geom_glsl, - .frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl, - }, - - [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = { - .vert = datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, - .frag = datatoc_gpu_shader_simple_lighting_frag_glsl, - .defs = - "#define USE_INSTANCE_COLOR\n", - }, - [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { - .vert = datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { - .vert = datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { - .vert = datatoc_gpu_shader_instance_screen_aligned_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - .defs = - "#define AXIS_NAME\n", - }, - [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = { - .vert = datatoc_gpu_shader_instance_screen_aligned_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - - [GPU_SHADER_CAMERA] = { - .vert = datatoc_gpu_shader_instance_camera_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_DISTANCE_LINES] = { - .vert = datatoc_gpu_shader_instance_distance_line_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - - [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, - }, - [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = { - .vert = datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, - }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = { - .vert = datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl, - }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = { - .vert = datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl, - }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = { - .vert = datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl, - }, - [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, - }, - [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { - .vert = datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, - }, - [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_3D_point_varying_size_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, - }, - [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = { - .vert = datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, - }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = { - .vert = datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl, - }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = { - .vert = datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, - .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl, - }, - - [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_instance_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - }, - [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] = { - .vert = datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl, - .frag = datatoc_gpu_shader_flat_id_frag_glsl, - .defs = - "#define UNIFORM_SCALE\n", - }, - [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = { - .vert = datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - .defs = - "#define UNIFORM_SCALE\n", - }, - [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] = { - .vert = datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { - .vert = datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, - .geom = datatoc_gpu_shader_instance_edges_variying_color_geom_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - - [GPU_SHADER_2D_AREA_EDGES] = { - .vert = datatoc_gpu_shader_2D_area_borders_vert_glsl, - .frag = datatoc_gpu_shader_2D_area_borders_frag_glsl, - }, - [GPU_SHADER_2D_WIDGET_BASE] = { - .vert = datatoc_gpu_shader_2D_widget_base_vert_glsl, - .frag = datatoc_gpu_shader_2D_widget_base_frag_glsl, - }, - [GPU_SHADER_2D_WIDGET_BASE_INST] = { - .vert = datatoc_gpu_shader_2D_widget_base_vert_glsl, - .frag = datatoc_gpu_shader_2D_widget_base_frag_glsl, - .defs = - "#define USE_INSTANCE\n", - }, - [GPU_SHADER_2D_WIDGET_SHADOW] = { - .vert = datatoc_gpu_shader_2D_widget_shadow_vert_glsl, - .frag = datatoc_gpu_shader_2D_widget_shadow_frag_glsl, - }, - [GPU_SHADER_2D_NODELINK] = { - .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl, - .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl, - }, - [GPU_SHADER_2D_NODELINK_INST] = { - .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl, - .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl, - .defs = - "#define USE_INSTANCE\n", - }, - - [GPU_SHADER_2D_UV_UNIFORM_COLOR] = { - .vert = datatoc_gpu_shader_2D_vert_glsl, - .frag = datatoc_gpu_shader_uniform_color_frag_glsl, - .defs = - "#define UV_POS\n", - }, - [GPU_SHADER_2D_UV_VERTS] = { - .vert = datatoc_gpu_shader_2D_edituvs_points_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl, - }, - [GPU_SHADER_2D_UV_FACEDOTS] = { - .vert = datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl, - .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, - }, - [GPU_SHADER_2D_UV_EDGES] = { - .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_2D_UV_EDGES_SMOOTH] = { - .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, - .defs = - "#define SMOOTH_COLOR\n", - }, - [GPU_SHADER_2D_UV_FACES] = { - .vert = datatoc_gpu_shader_2D_edituvs_faces_vert_glsl, - .frag = datatoc_gpu_shader_flat_color_frag_glsl, - }, - [GPU_SHADER_2D_UV_FACES_STRETCH_AREA] = { - .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, - }, - [GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE] = { - .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl, - .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, - .defs = - "#define STRETCH_ANGLE\n", - }, - - [GPU_SHADER_3D_FLAT_SELECT_ID] = { - .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, - .frag = datatoc_gpu_shader_selection_id_frag_glsl, - }, - [GPU_SHADER_3D_UNIFORM_SELECT_ID] = { - .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, - .frag = datatoc_gpu_shader_selection_id_frag_glsl, - .defs = - "#define UNIFORM_ID\n", - }, - - [GPU_SHADER_GPENCIL_STROKE] = { - .vert = datatoc_gpu_shader_gpencil_stroke_vert_glsl, - .geom = datatoc_gpu_shader_gpencil_stroke_geom_glsl, - .frag = datatoc_gpu_shader_gpencil_stroke_frag_glsl, - }, - - [GPU_SHADER_GPENCIL_FILL] = { - .vert = datatoc_gpu_shader_gpencil_fill_vert_glsl, - .frag = datatoc_gpu_shader_gpencil_fill_frag_glsl, - }, + [GPU_SHADER_TEXT] = + { + .vert = datatoc_gpu_shader_text_vert_glsl, + .geom = datatoc_gpu_shader_text_geom_glsl, + .frag = datatoc_gpu_shader_text_frag_glsl, + }, + [GPU_SHADER_TEXT_SIMPLE] = + { + .vert = datatoc_gpu_shader_text_simple_vert_glsl, + .geom = datatoc_gpu_shader_text_simple_geom_glsl, + .frag = datatoc_gpu_shader_text_frag_glsl, + }, + [GPU_SHADER_KEYFRAME_DIAMOND] = + { + .vert = datatoc_gpu_shader_keyframe_diamond_vert_glsl, + .frag = datatoc_gpu_shader_keyframe_diamond_frag_glsl, + }, + /* This version is magical but slow! */ + [GPU_SHADER_EDGES_FRONT_BACK_PERSP] = + { + .vert = datatoc_gpu_shader_edges_front_back_persp_vert_glsl, + .geom = datatoc_gpu_shader_edges_front_back_persp_geom_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_EDGES_FRONT_BACK_ORTHO] = + { + .vert = datatoc_gpu_shader_edges_front_back_ortho_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_EDGES_OVERLAY_SIMPLE] = + { + .vert = datatoc_gpu_shader_3D_vert_glsl, + .geom = datatoc_gpu_shader_edges_overlay_simple_geom_glsl, + .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, + }, + [GPU_SHADER_EDGES_OVERLAY] = + { + .vert = datatoc_gpu_shader_edges_overlay_vert_glsl, + .geom = datatoc_gpu_shader_edges_overlay_geom_glsl, + .frag = datatoc_gpu_shader_edges_overlay_frag_glsl, + }, + [GPU_SHADER_SIMPLE_LIGHTING] = + { + .vert = datatoc_gpu_shader_3D_normal_vert_glsl, + .frag = datatoc_gpu_shader_simple_lighting_frag_glsl, + }, + /* Use 'USE_FLAT_NORMAL' to make flat shader from smooth */ + [GPU_SHADER_SIMPLE_LIGHTING_FLAT_COLOR] = + { + .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, + .defs = "#define USE_FLAT_NORMAL\n", + }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = + { + .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl, + }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR_ALPHA] = + { + .vert = datatoc_gpu_shader_3D_normal_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_simple_lighting_smooth_color_alpha_frag_glsl, + }, + + [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_mask_uniform_color_frag_glsl, + }, + [GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] = + { + .vert = datatoc_gpu_shader_3D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_modulate_alpha_frag_glsl, + }, + [GPU_SHADER_3D_IMAGE_DEPTH] = + { + .vert = datatoc_gpu_shader_3D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_depth_linear_frag_glsl, + }, + [GPU_SHADER_3D_IMAGE_DEPTH_COPY] = + { + .vert = datatoc_gpu_shader_3D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_depth_copy_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 2\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 4\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 8\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 16\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 2\n" + "#define USE_DEPTH\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_4_DEPTH_TEST] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 4\n" + "#define USE_DEPTH\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_8_DEPTH_TEST] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 8\n" + "#define USE_DEPTH\n", + }, + [GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_image_multisample_resolve_frag_glsl, + .defs = "#define SAMPLES 16\n" + "#define USE_DEPTH\n", + }, + + [GPU_SHADER_2D_IMAGE_INTERLACE] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_interlace_frag_glsl, + }, + [GPU_SHADER_2D_CHECKER] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_checker_frag_glsl, + }, + + [GPU_SHADER_2D_DIAG_STRIPES] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_diag_stripes_frag_glsl, + }, + + [GPU_SHADER_2D_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + }, + [GPU_SHADER_2D_FLAT_COLOR] = + { + .vert = datatoc_gpu_shader_2D_flat_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_2D_SMOOTH_COLOR] = + { + .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, + }, + [GPU_SHADER_2D_SMOOTH_COLOR_DITHER] = + { + .vert = datatoc_gpu_shader_2D_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_2D_smooth_color_dithered_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_LINEAR_TO_SRGB] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_linear_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_color_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_DESATURATE_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_desaturate_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_ALPHA_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_alpha_color_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_vert_glsl, + .frag = datatoc_gpu_shader_image_shuffle_color_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_RECT_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_rect_vert_glsl, + .frag = datatoc_gpu_shader_image_color_frag_glsl, + }, + [GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR] = + { + .vert = datatoc_gpu_shader_2D_image_multi_rect_vert_glsl, + .frag = datatoc_gpu_shader_image_varying_color_frag_glsl, + }, + + [GPU_SHADER_3D_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + }, + [GPU_SHADER_3D_UNIFORM_COLOR_BACKGROUND] = + { + .vert = datatoc_gpu_shader_3D_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + .defs = "#define USE_BACKGROUND\n", + }, + [GPU_SHADER_3D_FLAT_COLOR] = + { + .vert = datatoc_gpu_shader_3D_flat_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_3D_SMOOTH_COLOR] = + { + .vert = datatoc_gpu_shader_3D_smooth_color_vert_glsl, + .frag = datatoc_gpu_shader_3D_smooth_color_frag_glsl, + }, + [GPU_SHADER_3D_DEPTH_ONLY] = + { + .vert = datatoc_gpu_shader_3D_vert_glsl, + .frag = datatoc_gpu_shader_depth_only_frag_glsl, + }, + [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + }, + + [GPU_SHADER_3D_GROUNDPOINT] = + { + .vert = datatoc_gpu_shader_3D_groundpoint_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, + }, + [GPU_SHADER_3D_GROUNDLINE] = + { + .vert = datatoc_gpu_shader_3D_passthrough_vert_glsl, + .geom = datatoc_gpu_shader_3D_groundline_geom_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + }, + + [GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl, + .geom = datatoc_gpu_shader_2D_line_dashed_geom_glsl, + .frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl, + }, + [GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_vert_glsl, + .geom = datatoc_gpu_shader_2D_line_dashed_geom_glsl, + .frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl, + }, + + [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = + { + .vert = datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + .frag = datatoc_gpu_shader_simple_lighting_frag_glsl, + .defs = "#define USE_INSTANCE_COLOR\n", + }, + [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = + { + .vert = datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = + { + .vert = datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = + { + .vert = datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + .defs = "#define AXIS_NAME\n", + }, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED] = + { + .vert = datatoc_gpu_shader_instance_screen_aligned_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + + [GPU_SHADER_CAMERA] = + { + .vert = datatoc_gpu_shader_instance_camera_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_DISTANCE_LINES] = + { + .vert = datatoc_gpu_shader_instance_distance_line_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + + [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, + }, + [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = + { + .vert = datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, + }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { + .vert = datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl, + }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { + .vert = datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl, + }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = + { + .vert = datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl, + }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, + }, + [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = + { + .vert = datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, + }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_3D_point_varying_size_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_frag_glsl, + }, + [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = + { + .vert = datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, + }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { + .vert = datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_aa_frag_glsl, + }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { + .vert = datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, + .frag = datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl, + }, + + [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_instance_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + }, + [GPU_SHADER_INSTANCE_VARIYING_ID_VARIYING_SIZE] = + { + .vert = datatoc_gpu_shader_instance_variying_size_variying_id_vert_glsl, + .frag = datatoc_gpu_shader_flat_id_frag_glsl, + .defs = "#define UNIFORM_SCALE\n", + }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = + { + .vert = datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + .defs = "#define UNIFORM_SCALE\n", + }, + [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE] = + { + .vert = datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = + { + .vert = datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, + .geom = datatoc_gpu_shader_instance_edges_variying_color_geom_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + + [GPU_SHADER_2D_AREA_EDGES] = + { + .vert = datatoc_gpu_shader_2D_area_borders_vert_glsl, + .frag = datatoc_gpu_shader_2D_area_borders_frag_glsl, + }, + [GPU_SHADER_2D_WIDGET_BASE] = + { + .vert = datatoc_gpu_shader_2D_widget_base_vert_glsl, + .frag = datatoc_gpu_shader_2D_widget_base_frag_glsl, + }, + [GPU_SHADER_2D_WIDGET_BASE_INST] = + { + .vert = datatoc_gpu_shader_2D_widget_base_vert_glsl, + .frag = datatoc_gpu_shader_2D_widget_base_frag_glsl, + .defs = "#define USE_INSTANCE\n", + }, + [GPU_SHADER_2D_WIDGET_SHADOW] = + { + .vert = datatoc_gpu_shader_2D_widget_shadow_vert_glsl, + .frag = datatoc_gpu_shader_2D_widget_shadow_frag_glsl, + }, + [GPU_SHADER_2D_NODELINK] = + { + .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl, + .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl, + }, + [GPU_SHADER_2D_NODELINK_INST] = + { + .vert = datatoc_gpu_shader_2D_nodelink_vert_glsl, + .frag = datatoc_gpu_shader_2D_nodelink_frag_glsl, + .defs = "#define USE_INSTANCE\n", + }, + + [GPU_SHADER_2D_UV_UNIFORM_COLOR] = + { + .vert = datatoc_gpu_shader_2D_vert_glsl, + .frag = datatoc_gpu_shader_uniform_color_frag_glsl, + .defs = "#define UV_POS\n", + }, + [GPU_SHADER_2D_UV_VERTS] = + { + .vert = datatoc_gpu_shader_2D_edituvs_points_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_varying_outline_aa_frag_glsl, + }, + [GPU_SHADER_2D_UV_FACEDOTS] = + { + .vert = datatoc_gpu_shader_2D_edituvs_facedots_vert_glsl, + .frag = datatoc_gpu_shader_point_varying_color_frag_glsl, + }, + [GPU_SHADER_2D_UV_EDGES] = + { + .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_2D_UV_EDGES_SMOOTH] = + { + .vert = datatoc_gpu_shader_2D_edituvs_edges_vert_glsl, + .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, + .defs = "#define SMOOTH_COLOR\n", + }, + [GPU_SHADER_2D_UV_FACES] = + { + .vert = datatoc_gpu_shader_2D_edituvs_faces_vert_glsl, + .frag = datatoc_gpu_shader_flat_color_frag_glsl, + }, + [GPU_SHADER_2D_UV_FACES_STRETCH_AREA] = + { + .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl, + .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, + }, + [GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE] = + { + .vert = datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl, + .frag = datatoc_gpu_shader_2D_smooth_color_frag_glsl, + .defs = "#define STRETCH_ANGLE\n", + }, + + [GPU_SHADER_3D_FLAT_SELECT_ID] = + { + .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, + .frag = datatoc_gpu_shader_selection_id_frag_glsl, + }, + [GPU_SHADER_3D_UNIFORM_SELECT_ID] = + { + .vert = datatoc_gpu_shader_3D_selection_id_vert_glsl, + .frag = datatoc_gpu_shader_selection_id_frag_glsl, + .defs = "#define UNIFORM_ID\n", + }, + + [GPU_SHADER_GPENCIL_STROKE] = + { + .vert = datatoc_gpu_shader_gpencil_stroke_vert_glsl, + .geom = datatoc_gpu_shader_gpencil_stroke_geom_glsl, + .frag = datatoc_gpu_shader_gpencil_stroke_frag_glsl, + }, + + [GPU_SHADER_GPENCIL_FILL] = + { + .vert = datatoc_gpu_shader_gpencil_fill_vert_glsl, + .frag = datatoc_gpu_shader_gpencil_fill_frag_glsl, + }, }; -GPUShader *GPU_shader_get_builtin_shader_with_config( - eGPUBuiltinShader shader, eGPUShaderConfig sh_cfg) +GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader, + eGPUShaderConfig sh_cfg) { - BLI_assert(shader < GPU_SHADER_BUILTIN_LEN); - BLI_assert(sh_cfg < GPU_SHADER_CFG_LEN); - GPUShader **sh_p = &builtin_shaders[sh_cfg][shader]; - - if (*sh_p == NULL) { - GPUShaderStages stages_legacy = {NULL}; - const GPUShaderStages *stages = &builtin_shader_stages[shader]; - - if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP) { - /* TODO: remove after switch to core profile (maybe) */ - if (!GLEW_VERSION_3_2) { - stages_legacy.vert = datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl; - stages_legacy.frag = datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl; - stages = &stages_legacy; - } - } - else if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR) { - /* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */ - /* TODO: remove after switch to core profile (maybe) */ - if (!GLEW_VERSION_3_2) { - stages_legacy.vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl; - stages_legacy.frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl; - stages = &stages_legacy; - } - } - - /* common case */ - if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { - *sh_p = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, stages->defs, __func__); - } - else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { - /* Remove eventually, for now ensure support for each shader has been added. */ - BLI_assert(ELEM(shader, - GPU_SHADER_3D_UNIFORM_COLOR, - GPU_SHADER_3D_SMOOTH_COLOR, - GPU_SHADER_3D_DEPTH_ONLY, - GPU_SHADER_CAMERA, - GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, - GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, - GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, - GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, - GPU_SHADER_3D_GROUNDLINE, - GPU_SHADER_3D_GROUNDPOINT, - GPU_SHADER_DISTANCE_LINES, - GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, - GPU_SHADER_3D_FLAT_SELECT_ID, - GPU_SHADER_3D_UNIFORM_SELECT_ID) || - ELEM(shader, - GPU_SHADER_3D_FLAT_COLOR, - GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR)); - const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl; - const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n"; - /* In rare cases geometry shaders calculate clipping themselves. */ - *sh_p = GPU_shader_create_from_arrays({ - .vert = (const char *[]){world_clip_lib, stages->vert, NULL}, - .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL}, - .frag = (const char *[]){stages->frag, NULL}, - .defs = (const char *[]){world_clip_def, stages->defs, NULL}, - }); - } - else { - BLI_assert(0); - } - } - - return *sh_p; + BLI_assert(shader < GPU_SHADER_BUILTIN_LEN); + BLI_assert(sh_cfg < GPU_SHADER_CFG_LEN); + GPUShader **sh_p = &builtin_shaders[sh_cfg][shader]; + + if (*sh_p == NULL) { + GPUShaderStages stages_legacy = {NULL}; + const GPUShaderStages *stages = &builtin_shader_stages[shader]; + + if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP) { + /* TODO: remove after switch to core profile (maybe) */ + if (!GLEW_VERSION_3_2) { + stages_legacy.vert = datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl; + stages_legacy.frag = datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl; + stages = &stages_legacy; + } + } + else if (shader == GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR) { + /* Dashed need geometry shader, which are not supported by legacy OpenGL, fallback to solid lines. */ + /* TODO: remove after switch to core profile (maybe) */ + if (!GLEW_VERSION_3_2) { + stages_legacy.vert = datatoc_gpu_shader_3D_line_dashed_uniform_color_legacy_vert_glsl; + stages_legacy.frag = datatoc_gpu_shader_2D_line_dashed_frag_glsl; + stages = &stages_legacy; + } + } + + /* common case */ + if (sh_cfg == GPU_SHADER_CFG_DEFAULT) { + *sh_p = GPU_shader_create( + stages->vert, stages->frag, stages->geom, NULL, stages->defs, __func__); + } + else if (sh_cfg == GPU_SHADER_CFG_CLIPPED) { + /* Remove eventually, for now ensure support for each shader has been added. */ + BLI_assert(ELEM(shader, + GPU_SHADER_3D_UNIFORM_COLOR, + GPU_SHADER_3D_SMOOTH_COLOR, + GPU_SHADER_3D_DEPTH_ONLY, + GPU_SHADER_CAMERA, + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, + GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SCALE, + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR, + GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED, + GPU_SHADER_3D_GROUNDLINE, + GPU_SHADER_3D_GROUNDPOINT, + GPU_SHADER_DISTANCE_LINES, + GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, + GPU_SHADER_3D_FLAT_SELECT_ID, + GPU_SHADER_3D_UNIFORM_SELECT_ID) || + ELEM(shader, GPU_SHADER_3D_FLAT_COLOR, GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR)); + const char *world_clip_lib = datatoc_gpu_shader_cfg_world_clip_lib_glsl; + const char *world_clip_def = "#define USE_WORLD_CLIP_PLANES\n"; + /* In rare cases geometry shaders calculate clipping themselves. */ + *sh_p = GPU_shader_create_from_arrays({ + .vert = (const char *[]){world_clip_lib, stages->vert, NULL}, + .geom = (const char *[]){stages->geom ? world_clip_lib : NULL, stages->geom, NULL}, + .frag = (const char *[]){stages->frag, NULL}, + .defs = (const char *[]){world_clip_def, stages->defs, NULL}, + }); + } + else { + BLI_assert(0); + } + } + + return *sh_p; } GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader) { - return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT); + return GPU_shader_get_builtin_shader_with_config(shader, GPU_SHADER_CFG_DEFAULT); } -void GPU_shader_get_builtin_shader_code( - eGPUBuiltinShader shader, - const char **r_vert, const char **r_frag, - const char **r_geom, const char **r_defines) +void GPU_shader_get_builtin_shader_code(eGPUBuiltinShader shader, + const char **r_vert, + const char **r_frag, + const char **r_geom, + const char **r_defines) { - const GPUShaderStages *stages = &builtin_shader_stages[shader]; - *r_vert = stages->vert; - *r_frag = stages->frag; - *r_geom = stages->geom; - *r_defines = stages->defs; + const GPUShaderStages *stages = &builtin_shader_stages[shader]; + *r_vert = stages->vert; + *r_frag = stages->frag; + *r_geom = stages->geom; + *r_defines = stages->defs; } void GPU_shader_free_builtin_shaders(void) { - for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) { - for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) { - if (builtin_shaders[i][j]) { - GPU_shader_free(builtin_shaders[i][j]); - builtin_shaders[i][j] = NULL; - } - } - } + for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) { + for (int j = 0; j < GPU_SHADER_BUILTIN_LEN; j++) { + if (builtin_shaders[i][j]) { + GPU_shader_free(builtin_shaders[i][j]); + builtin_shaders[i][j] = NULL; + } + } + } } diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index c5dce2f0da6..698499af1ab 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -44,350 +44,359 @@ static const char *BuiltinUniform_name(GPUUniformBuiltin u) { - static const char *names[] = { - [GPU_UNIFORM_NONE] = NULL, - - [GPU_UNIFORM_MODEL] = "ModelMatrix", - [GPU_UNIFORM_VIEW] = "ViewMatrix", - [GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix", - [GPU_UNIFORM_PROJECTION] = "ProjectionMatrix", - [GPU_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix", - [GPU_UNIFORM_MVP] = "ModelViewProjectionMatrix", - - [GPU_UNIFORM_MODEL_INV] = "ModelMatrixInverse", - [GPU_UNIFORM_VIEW_INV] = "ViewMatrixInverse", - [GPU_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse", - [GPU_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse", - [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse", - - [GPU_UNIFORM_NORMAL] = "NormalMatrix", - [GPU_UNIFORM_NORMAL_INV] = "NormalMatrixInverse", - [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix", - [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors", - [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors", - - [GPU_UNIFORM_COLOR] = "color", - [GPU_UNIFORM_EYE] = "eye", - [GPU_UNIFORM_CALLID] = "callId", - [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo", - - [GPU_UNIFORM_CUSTOM] = NULL, - [GPU_NUM_UNIFORMS] = NULL, - }; - - return names[u]; + static const char *names[] = { + [GPU_UNIFORM_NONE] = NULL, + + [GPU_UNIFORM_MODEL] = "ModelMatrix", + [GPU_UNIFORM_VIEW] = "ViewMatrix", + [GPU_UNIFORM_MODELVIEW] = "ModelViewMatrix", + [GPU_UNIFORM_PROJECTION] = "ProjectionMatrix", + [GPU_UNIFORM_VIEWPROJECTION] = "ViewProjectionMatrix", + [GPU_UNIFORM_MVP] = "ModelViewProjectionMatrix", + + [GPU_UNIFORM_MODEL_INV] = "ModelMatrixInverse", + [GPU_UNIFORM_VIEW_INV] = "ViewMatrixInverse", + [GPU_UNIFORM_MODELVIEW_INV] = "ModelViewMatrixInverse", + [GPU_UNIFORM_PROJECTION_INV] = "ProjectionMatrixInverse", + [GPU_UNIFORM_VIEWPROJECTION_INV] = "ViewProjectionMatrixInverse", + + [GPU_UNIFORM_NORMAL] = "NormalMatrix", + [GPU_UNIFORM_NORMAL_INV] = "NormalMatrixInverse", + [GPU_UNIFORM_WORLDNORMAL] = "WorldNormalMatrix", + [GPU_UNIFORM_CAMERATEXCO] = "CameraTexCoFactors", + [GPU_UNIFORM_ORCO] = "OrcoTexCoFactors", + + [GPU_UNIFORM_COLOR] = "color", + [GPU_UNIFORM_EYE] = "eye", + [GPU_UNIFORM_CALLID] = "callId", + [GPU_UNIFORM_OBJECT_INFO] = "unfobjectinfo", + + [GPU_UNIFORM_CUSTOM] = NULL, + [GPU_NUM_UNIFORMS] = NULL, + }; + + return names[u]; } GPU_INLINE bool match(const char *a, const char *b) { - return strcmp(a, b) == 0; + return strcmp(a, b) == 0; } GPU_INLINE uint hash_string(const char *str) { - uint i = 0, c; - while ((c = *str++)) { - i = i * 37 + c; - } - return i; + uint i = 0, c; + while ((c = *str++)) { + i = i * 37 + c; + } + return i; } -GPU_INLINE void set_input_name( - GPUShaderInterface *shaderface, GPUShaderInput *input, - const char *name, uint32_t name_len) +GPU_INLINE void set_input_name(GPUShaderInterface *shaderface, + GPUShaderInput *input, + const char *name, + uint32_t name_len) { - input->name_offset = shaderface->name_buffer_offset; - input->name_hash = hash_string(name); - shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */ + input->name_offset = shaderface->name_buffer_offset; + input->name_hash = hash_string(name); + shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */ } -GPU_INLINE void shader_input_to_bucket( - GPUShaderInput *input, - GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]) +GPU_INLINE void shader_input_to_bucket(GPUShaderInput *input, + GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]) { - const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; - input->next = buckets[bucket_index]; - buckets[bucket_index] = input; + const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; + input->next = buckets[bucket_index]; + buckets[bucket_index] = input; } GPU_INLINE const GPUShaderInput *buckets_lookup( - GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS], - const char *name_buffer, const char *name) + GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS], + const char *name_buffer, + const char *name) { - const uint name_hash = hash_string(name); - const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; - const GPUShaderInput *input = buckets[bucket_index]; - if (input == NULL) { - /* Requested uniform is not found at all. */ - return NULL; - } - /* Optimization bit: if there is no hash collision detected when constructing shader interface - * it means we can only request the single possible uniform. Surely, it's possible we request - * uniform which causes hash collision, but that will be detected in debug builds. */ - if (input->next == NULL) { - if (name_hash == input->name_hash) { + const uint name_hash = hash_string(name); + const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS; + const GPUShaderInput *input = buckets[bucket_index]; + if (input == NULL) { + /* Requested uniform is not found at all. */ + return NULL; + } + /* Optimization bit: if there is no hash collision detected when constructing shader interface + * it means we can only request the single possible uniform. Surely, it's possible we request + * uniform which causes hash collision, but that will be detected in debug builds. */ + if (input->next == NULL) { + if (name_hash == input->name_hash) { #if TRUST_NO_ONE - assert(match(name_buffer + input->name_offset, name)); + assert(match(name_buffer + input->name_offset, name)); #endif - return input; - } - return NULL; - } - /* Work through possible collisions. */ - const GPUShaderInput *next = input; - while (next != NULL) { - input = next; - next = input->next; - if (input->name_hash != name_hash) { - continue; - } - if (match(name_buffer + input->name_offset, name)) { - return input; - } - } - return NULL; /* not found */ + return input; + } + return NULL; + } + /* Work through possible collisions. */ + const GPUShaderInput *next = input; + while (next != NULL) { + input = next; + next = input->next; + if (input->name_hash != name_hash) { + continue; + } + if (match(name_buffer + input->name_offset, name)) { + return input; + } + } + return NULL; /* not found */ } GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS]) { - for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) { - GPUShaderInput *input = buckets[bucket_index]; - while (input != NULL) { - GPUShaderInput *input_next = input->next; - MEM_freeN(input); - input = input_next; - } - } + for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; ++bucket_index) { + GPUShaderInput *input = buckets[bucket_index]; + while (input != NULL) { + GPUShaderInput *input_next = input->next; + MEM_freeN(input); + input = input_next; + } + } } static bool setup_builtin_uniform(GPUShaderInput *input, const char *name) { - /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */ - - /* detect built-in uniforms (name must match) */ - for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) { - const char *builtin_name = BuiltinUniform_name(u); - if (match(name, builtin_name)) { - input->builtin_type = u; - return true; - } - } - input->builtin_type = GPU_UNIFORM_CUSTOM; - return false; + /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */ + + /* detect built-in uniforms (name must match) */ + for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) { + const char *builtin_name = BuiltinUniform_name(u); + if (match(name, builtin_name)) { + input->builtin_type = u; + return true; + } + } + input->builtin_type = GPU_UNIFORM_CUSTOM; + return false; } static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif"); + GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif"); - input->location = glGetUniformLocation(shaderface->program, name); + input->location = glGetUniformLocation(shaderface->program, name); - uint name_len = strlen(name); - shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, shaderface->name_buffer_offset + name_len + 1); /* include NULL terminator */ - char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset; - strcpy(name_buffer, name); + uint name_len = strlen(name); + shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, + shaderface->name_buffer_offset + name_len + + 1); /* include NULL terminator */ + char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset; + strcpy(name_buffer, name); - set_input_name(shaderface, input, name, name_len); - setup_builtin_uniform(input, name); + set_input_name(shaderface, input, name, name_len); + setup_builtin_uniform(input, name); - shader_input_to_bucket(input, shaderface->uniform_buckets); - if (input->builtin_type != GPU_UNIFORM_NONE && - input->builtin_type != GPU_UNIFORM_CUSTOM) - { - shaderface->builtin_uniforms[input->builtin_type] = input; - } + shader_input_to_bucket(input, shaderface->uniform_buckets); + if (input->builtin_type != GPU_UNIFORM_NONE && input->builtin_type != GPU_UNIFORM_CUSTOM) { + shaderface->builtin_uniforms[input->builtin_type] = input; + } #if DEBUG_SHADER_INTERFACE - printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n", - shaderface, - shaderface->program, - name, - input->location); + printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n", + shaderface, + shaderface->program, + name, + input->location); #endif - return input; + return input; } GPUShaderInterface *GPU_shaderinterface_create(int32_t program) { - GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface"); - shaderface->program = program; + GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface"); + shaderface->program = program; #if DEBUG_SHADER_INTERFACE - printf("%s {\n", __func__); /* enter function */ - printf("GPUShaderInterface %p, program %d\n", shaderface, program); + printf("%s {\n", __func__); /* enter function */ + printf("GPUShaderInterface %p, program %d\n", shaderface, program); #endif - GLint max_attr_name_len = 0, attr_len = 0; - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len); - glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len); + GLint max_attr_name_len = 0, attr_len = 0; + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_attr_name_len); + glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &attr_len); - GLint max_ubo_name_len = 0, ubo_len = 0; - glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); - glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len); + GLint max_ubo_name_len = 0, ubo_len = 0; + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len); + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len); - /* Work around driver bug with Intel HD 4600 on Windows 7/8, where - * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */ - if (attr_len > 0 && max_attr_name_len == 0) { - max_attr_name_len = 256; - } - if (ubo_len > 0 && max_ubo_name_len == 0) { - max_ubo_name_len = 256; - } + /* Work around driver bug with Intel HD 4600 on Windows 7/8, where + * GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */ + if (attr_len > 0 && max_attr_name_len == 0) { + max_attr_name_len = 256; + } + if (ubo_len > 0 && max_ubo_name_len == 0) { + max_ubo_name_len = 256; + } - const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len; - shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer"); + const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len; + shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer"); - /* Attributes */ - for (uint32_t i = 0; i < attr_len; ++i) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr"); - GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; - char *name = shaderface->name_buffer + shaderface->name_buffer_offset; - GLsizei name_len = 0; + /* Attributes */ + for (uint32_t i = 0; i < attr_len; ++i) { + GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr"); + GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; + char *name = shaderface->name_buffer + shaderface->name_buffer_offset; + GLsizei name_len = 0; - glGetActiveAttrib(program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); + glGetActiveAttrib( + program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name); - /* remove "[0]" from array name */ - if (name[name_len - 1] == ']') { - name[name_len - 3] = '\0'; - name_len -= 3; - } + /* remove "[0]" from array name */ + if (name[name_len - 1] == ']') { + name[name_len - 3] = '\0'; + name_len -= 3; + } - /* TODO: reject DOUBLE gl_types */ + /* TODO: reject DOUBLE gl_types */ - input->location = glGetAttribLocation(program, name); + input->location = glGetAttribLocation(program, name); - set_input_name(shaderface, input, name, name_len); + set_input_name(shaderface, input, name, name_len); - shader_input_to_bucket(input, shaderface->attr_buckets); + shader_input_to_bucket(input, shaderface->attr_buckets); #if DEBUG_SHADER_INTERFACE - printf("attr[%u] '%s' at location %d\n", i, name, input->location); + printf("attr[%u] '%s' at location %d\n", i, name, input->location); #endif - } - /* Uniform Blocks */ - for (uint32_t i = 0; i < ubo_len; ++i) { - GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO"); - GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; - char *name = shaderface->name_buffer + shaderface->name_buffer_offset; - GLsizei name_len = 0; + } + /* Uniform Blocks */ + for (uint32_t i = 0; i < ubo_len; ++i) { + GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO"); + GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset; + char *name = shaderface->name_buffer + shaderface->name_buffer_offset; + GLsizei name_len = 0; - glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); + glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name); - input->location = i; + input->location = i; - set_input_name(shaderface, input, name, name_len); + set_input_name(shaderface, input, name, name_len); - shader_input_to_bucket(input, shaderface->ubo_buckets); + shader_input_to_bucket(input, shaderface->ubo_buckets); #if DEBUG_SHADER_INTERFACE - printf("ubo '%s' at location %d\n", name, input->location); + printf("ubo '%s' at location %d\n", name, input->location); #endif - } - /* Builtin Uniforms */ - for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) { - const char *builtin_name = BuiltinUniform_name(u); - if (glGetUniformLocation(program, builtin_name) != -1) { - add_uniform((GPUShaderInterface *)shaderface, builtin_name); - } - } - /* Batches ref buffer */ - shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT; - shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), "GPUShaderInterface batches"); - - return shaderface; + } + /* Builtin Uniforms */ + for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; ++u) { + const char *builtin_name = BuiltinUniform_name(u); + if (glGetUniformLocation(program, builtin_name) != -1) { + add_uniform((GPUShaderInterface *)shaderface, builtin_name); + } + } + /* Batches ref buffer */ + shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT; + shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *), + "GPUShaderInterface batches"); + + return shaderface; } void GPU_shaderinterface_discard(GPUShaderInterface *shaderface) { - /* Free memory used by buckets and has entries. */ - buckets_free(shaderface->uniform_buckets); - buckets_free(shaderface->attr_buckets); - buckets_free(shaderface->ubo_buckets); - /* Free memory used by name_buffer. */ - MEM_freeN(shaderface->name_buffer); - /* Remove this interface from all linked Batches vao cache. */ - for (int i = 0; i < shaderface->batches_len; ++i) { - if (shaderface->batches[i] != NULL) { - gpu_batch_remove_interface_ref(shaderface->batches[i], shaderface); - } - } - MEM_freeN(shaderface->batches); - /* Free memory used by shader interface by its self. */ - MEM_freeN(shaderface); + /* Free memory used by buckets and has entries. */ + buckets_free(shaderface->uniform_buckets); + buckets_free(shaderface->attr_buckets); + buckets_free(shaderface->ubo_buckets); + /* Free memory used by name_buffer. */ + MEM_freeN(shaderface->name_buffer); + /* Remove this interface from all linked Batches vao cache. */ + for (int i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] != NULL) { + gpu_batch_remove_interface_ref(shaderface->batches[i], shaderface); + } + } + MEM_freeN(shaderface->batches); + /* Free memory used by shader interface by its self. */ + MEM_freeN(shaderface); } -const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, const char *name) +const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface, + const char *name) { - return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name); + return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name); } -const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface, const char *name) +const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface, + const char *name) { - const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name); - /* If input is not found add it so it's found next time. */ - if (input == NULL) { - input = add_uniform((GPUShaderInterface *)shaderface, name); + const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name); + /* If input is not found add it so it's found next time. */ + if (input == NULL) { + input = add_uniform((GPUShaderInterface *)shaderface, name); - if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) { - fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name); - } - } + if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) { + fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name); + } + } #if DEBUG_SHADER_UNIFORMS - if ((G.debug & G_DEBUG_GPU) && - input->builtin_type != GPU_UNIFORM_NONE && - input->builtin_type != GPU_UNIFORM_CUSTOM) - { - /* Warn if we find a matching builtin, since these can be looked up much quicker. */ - fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as such!\n", name); - } + if ((G.debug & G_DEBUG_GPU) && input->builtin_type != GPU_UNIFORM_NONE && + input->builtin_type != GPU_UNIFORM_CUSTOM) { + /* Warn if we find a matching builtin, since these can be looked up much quicker. */ + fprintf(stderr, + "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as " + "such!\n", + name); + } #endif - return (input->location != -1) ? input : NULL; + return (input->location != -1) ? input : NULL; } -const GPUShaderInput *GPU_shaderinterface_uniform_builtin( - const GPUShaderInterface *shaderface, GPUUniformBuiltin builtin) +const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface, + GPUUniformBuiltin builtin) { #if TRUST_NO_ONE - assert(builtin != GPU_UNIFORM_NONE); - assert(builtin != GPU_UNIFORM_CUSTOM); - assert(builtin != GPU_NUM_UNIFORMS); + assert(builtin != GPU_UNIFORM_NONE); + assert(builtin != GPU_UNIFORM_CUSTOM); + assert(builtin != GPU_NUM_UNIFORMS); #endif - return shaderface->builtin_uniforms[builtin]; + return shaderface->builtin_uniforms[builtin]; } -const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, const char *name) +const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface, + const char *name) { - return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name); + return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name); } -const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, const char *name) +const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface, + const char *name) { - return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name); + return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name); } void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch) { - int i; /* find first unused slot */ - for (i = 0; i < shaderface->batches_len; ++i) { - if (shaderface->batches[i] == NULL) { - break; - } - } - if (i == shaderface->batches_len) { - /* Not enough place, realloc the array. */ - i = shaderface->batches_len; - shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT; - shaderface->batches = MEM_recallocN(shaderface->batches, sizeof(GPUBatch *) * shaderface->batches_len); - } - shaderface->batches[i] = batch; + int i; /* find first unused slot */ + for (i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] == NULL) { + break; + } + } + if (i == shaderface->batches_len) { + /* Not enough place, realloc the array. */ + i = shaderface->batches_len; + shaderface->batches_len += GPU_SHADERINTERFACE_REF_ALLOC_COUNT; + shaderface->batches = MEM_recallocN(shaderface->batches, + sizeof(GPUBatch *) * shaderface->batches_len); + } + shaderface->batches[i] = batch; } void GPU_shaderinterface_remove_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch) { - for (int i = 0; i < shaderface->batches_len; ++i) { - if (shaderface->batches[i] == batch) { - shaderface->batches[i] = NULL; - break; /* cannot have duplicates */ - } - } + for (int i = 0; i < shaderface->batches_len; ++i) { + if (shaderface->batches[i] == batch) { + shaderface->batches[i] = NULL; + break; /* cannot have duplicates */ + } + } } diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h index da41e3472fd..856a14c6868 100644 --- a/source/blender/gpu/intern/gpu_shader_private.h +++ b/source/blender/gpu/intern/gpu_shader_private.h @@ -25,23 +25,23 @@ #include "GPU_shader_interface.h" struct GPUShader { - /** Handle for full program (links shader stages below). */ - GLuint program; + /** Handle for full program (links shader stages below). */ + GLuint program; - /** Handle for vertex shader. */ - GLuint vertex; - /** Handle for geometry shader. */ - GLuint geometry; - /** Handle for fragment shader. */ - GLuint fragment; + /** Handle for vertex shader. */ + GLuint vertex; + /** Handle for geometry shader. */ + GLuint geometry; + /** Handle for fragment shader. */ + GLuint fragment; - /** Cached uniform & attribute interface for shader. */ - GPUShaderInterface *interface; + /** Cached uniform & attribute interface for shader. */ + GPUShaderInterface *interface; - int feedback_transform_type; + int feedback_transform_type; #ifndef NDEBUG - char name[64]; + char name[64]; #endif }; -#endif /* __GPU_SHADER_PRIVATE_H__ */ +#endif /* __GPU_SHADER_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_state.c b/source/blender/gpu/intern/gpu_state.c index 765bbd5e751..176965bb80f 100644 --- a/source/blender/gpu/intern/gpu_state.c +++ b/source/blender/gpu/intern/gpu_state.c @@ -28,135 +28,135 @@ static GLenum gpu_get_gl_blendfunction(eGPUBlendFunction blend) { - switch (blend) { - case GPU_ONE: - return GL_ONE; - case GPU_SRC_ALPHA: - return GL_SRC_ALPHA; - case GPU_ONE_MINUS_SRC_ALPHA: - return GL_ONE_MINUS_SRC_ALPHA; - case GPU_DST_COLOR: - return GL_DST_COLOR; - case GPU_ZERO: - return GL_ZERO; - default: - BLI_assert(!"Unhandled blend mode"); - return GL_ZERO; - } + switch (blend) { + case GPU_ONE: + return GL_ONE; + case GPU_SRC_ALPHA: + return GL_SRC_ALPHA; + case GPU_ONE_MINUS_SRC_ALPHA: + return GL_ONE_MINUS_SRC_ALPHA; + case GPU_DST_COLOR: + return GL_DST_COLOR; + case GPU_ZERO: + return GL_ZERO; + default: + BLI_assert(!"Unhandled blend mode"); + return GL_ZERO; + } } void GPU_blend(bool enable) { - if (enable) { - glEnable(GL_BLEND); - } - else { - glDisable(GL_BLEND); - } + if (enable) { + glEnable(GL_BLEND); + } + else { + glDisable(GL_BLEND); + } } void GPU_blend_set_func(eGPUBlendFunction sfactor, eGPUBlendFunction dfactor) { - glBlendFunc(gpu_get_gl_blendfunction(sfactor), gpu_get_gl_blendfunction(dfactor)); + glBlendFunc(gpu_get_gl_blendfunction(sfactor), gpu_get_gl_blendfunction(dfactor)); } -void GPU_blend_set_func_separate( - eGPUBlendFunction src_rgb, eGPUBlendFunction dst_rgb, - eGPUBlendFunction src_alpha, eGPUBlendFunction dst_alpha) +void GPU_blend_set_func_separate(eGPUBlendFunction src_rgb, + eGPUBlendFunction dst_rgb, + eGPUBlendFunction src_alpha, + eGPUBlendFunction dst_alpha) { - glBlendFuncSeparate( - gpu_get_gl_blendfunction(src_rgb), - gpu_get_gl_blendfunction(dst_rgb), - gpu_get_gl_blendfunction(src_alpha), - gpu_get_gl_blendfunction(dst_alpha)); + glBlendFuncSeparate(gpu_get_gl_blendfunction(src_rgb), + gpu_get_gl_blendfunction(dst_rgb), + gpu_get_gl_blendfunction(src_alpha), + gpu_get_gl_blendfunction(dst_alpha)); } void GPU_depth_range(float near, float far) { - /* glDepthRangef is only for OpenGL 4.1 or higher */ - glDepthRange(near, far); + /* glDepthRangef is only for OpenGL 4.1 or higher */ + glDepthRange(near, far); } void GPU_depth_test(bool enable) { - if (enable) { - glEnable(GL_DEPTH_TEST); - } - else { - glDisable(GL_DEPTH_TEST); - } + if (enable) { + glEnable(GL_DEPTH_TEST); + } + else { + glDisable(GL_DEPTH_TEST); + } } bool GPU_depth_test_enabled() { - return glIsEnabled(GL_DEPTH_TEST); + return glIsEnabled(GL_DEPTH_TEST); } void GPU_line_smooth(bool enable) { - if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { - glEnable(GL_LINE_SMOOTH); - } - else { - glDisable(GL_LINE_SMOOTH); - } + if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { + glEnable(GL_LINE_SMOOTH); + } + else { + glDisable(GL_LINE_SMOOTH); + } } void GPU_line_width(float width) { - float max_size = GPU_max_line_width(); - float final_size = width * U.pixelsize; - /* Fix opengl errors on certain platform / drivers. */ - CLAMP(final_size, 1.0f, max_size); - glLineWidth(final_size); + float max_size = GPU_max_line_width(); + float final_size = width * U.pixelsize; + /* Fix opengl errors on certain platform / drivers. */ + CLAMP(final_size, 1.0f, max_size); + glLineWidth(final_size); } void GPU_point_size(float size) { - glPointSize(size * U.pixelsize); + glPointSize(size * U.pixelsize); } void GPU_polygon_smooth(bool enable) { - if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { - glEnable(GL_POLYGON_SMOOTH); - } - else { - glDisable(GL_POLYGON_SMOOTH); - } + if (enable && ((G.debug & G_DEBUG_GPU) == 0)) { + glEnable(GL_POLYGON_SMOOTH); + } + else { + glDisable(GL_POLYGON_SMOOTH); + } } void GPU_scissor(int x, int y, int width, int height) { - glScissor(x, y, width, height); + glScissor(x, y, width, height); } void GPU_scissor_get_f(float coords[4]) { - glGetFloatv(GL_SCISSOR_BOX, coords); + glGetFloatv(GL_SCISSOR_BOX, coords); } void GPU_scissor_get_i(int coords[4]) { - glGetIntegerv(GL_SCISSOR_BOX, coords); + glGetIntegerv(GL_SCISSOR_BOX, coords); } void GPU_viewport_size_get_f(float coords[4]) { - glGetFloatv(GL_VIEWPORT, coords); + glGetFloatv(GL_VIEWPORT, coords); } void GPU_viewport_size_get_i(int coords[4]) { - glGetIntegerv(GL_VIEWPORT, coords); + glGetIntegerv(GL_VIEWPORT, coords); } void GPU_flush(void) { - glFlush(); + glFlush(); } void GPU_finish(void) { - glFinish(); + glFinish(); } diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 3ce42ce1d31..afe5e381334 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -43,46 +43,47 @@ #include "gpu_context_private.h" static struct GPUTextureGlobal { - GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ - GPUTexture *invalid_tex_2D; - GPUTexture *invalid_tex_3D; + GPUTexture * + invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */ + GPUTexture *invalid_tex_2D; + GPUTexture *invalid_tex_3D; } GG = {NULL, NULL, NULL}; /* Maximum number of FBOs a texture can be attached to. */ #define GPU_TEX_MAX_FBO_ATTACHED 10 typedef enum eGPUTextureFormatFlag { - GPU_FORMAT_DEPTH = (1 << 0), - GPU_FORMAT_STENCIL = (1 << 1), - GPU_FORMAT_INTEGER = (1 << 2), - GPU_FORMAT_FLOAT = (1 << 3), - - GPU_FORMAT_1D = (1 << 10), - GPU_FORMAT_2D = (1 << 11), - GPU_FORMAT_3D = (1 << 12), - GPU_FORMAT_CUBE = (1 << 13), - GPU_FORMAT_ARRAY = (1 << 14), + GPU_FORMAT_DEPTH = (1 << 0), + GPU_FORMAT_STENCIL = (1 << 1), + GPU_FORMAT_INTEGER = (1 << 2), + GPU_FORMAT_FLOAT = (1 << 3), + + GPU_FORMAT_1D = (1 << 10), + GPU_FORMAT_2D = (1 << 11), + GPU_FORMAT_3D = (1 << 12), + GPU_FORMAT_CUBE = (1 << 13), + GPU_FORMAT_ARRAY = (1 << 14), } eGPUTextureFormatFlag; /* GPUTexture */ struct GPUTexture { - int w, h, d; /* width/height/depth */ - int number; /* number for multitexture binding */ - int refcount; /* reference count */ - GLenum target; /* GL_TEXTURE_* */ - GLenum target_base; /* same as target, (but no multisample) - * use it for unbinding */ - GLuint bindcode; /* opengl identifier for texture */ - - eGPUTextureFormat format; - eGPUTextureFormatFlag format_flag; - - uint bytesize; /* number of byte for one pixel */ - int components; /* number of color/alpha channels */ - int samples; /* number of samples for multisamples textures. 0 if not multisample target */ - - int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED]; - GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; + int w, h, d; /* width/height/depth */ + int number; /* number for multitexture binding */ + int refcount; /* reference count */ + GLenum target; /* GL_TEXTURE_* */ + GLenum target_base; /* same as target, (but no multisample) + * use it for unbinding */ + GLuint bindcode; /* opengl identifier for texture */ + + eGPUTextureFormat format; + eGPUTextureFormatFlag format_flag; + + uint bytesize; /* number of byte for one pixel */ + int components; /* number of color/alpha channels */ + int samples; /* number of samples for multisamples textures. 0 if not multisample target */ + + int fb_attachment[GPU_TEX_MAX_FBO_ATTACHED]; + GPUFrameBuffer *fb[GPU_TEX_MAX_FBO_ATTACHED]; }; /* ------ Memory Management ------- */ @@ -92,38 +93,38 @@ static uint memory_usage; static uint gpu_texture_memory_footprint_compute(GPUTexture *tex) { - int samp = max_ii(tex->samples, 1); - switch (tex->target_base) { - case GL_TEXTURE_1D: - return tex->bytesize * tex->w * samp; - case GL_TEXTURE_1D_ARRAY: - case GL_TEXTURE_2D: - return tex->bytesize * tex->w * tex->h * samp; - case GL_TEXTURE_2D_ARRAY: - case GL_TEXTURE_3D: - return tex->bytesize * tex->w * tex->h * tex->d * samp; - case GL_TEXTURE_CUBE_MAP: - return tex->bytesize * 6 * tex->w * tex->h * samp; - case GL_TEXTURE_CUBE_MAP_ARRAY: - return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp; - default: - return 0; - } + int samp = max_ii(tex->samples, 1); + switch (tex->target_base) { + case GL_TEXTURE_1D: + return tex->bytesize * tex->w * samp; + case GL_TEXTURE_1D_ARRAY: + case GL_TEXTURE_2D: + return tex->bytesize * tex->w * tex->h * samp; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_3D: + return tex->bytesize * tex->w * tex->h * tex->d * samp; + case GL_TEXTURE_CUBE_MAP: + return tex->bytesize * 6 * tex->w * tex->h * samp; + case GL_TEXTURE_CUBE_MAP_ARRAY: + return tex->bytesize * 6 * tex->w * tex->h * tex->d * samp; + default: + return 0; + } } static void gpu_texture_memory_footprint_add(GPUTexture *tex) { - memory_usage += gpu_texture_memory_footprint_compute(tex); + memory_usage += gpu_texture_memory_footprint_compute(tex); } static void gpu_texture_memory_footprint_remove(GPUTexture *tex) { - memory_usage -= gpu_texture_memory_footprint_compute(tex); + memory_usage -= gpu_texture_memory_footprint_compute(tex); } uint GPU_texture_memory_usage_get(void) { - return memory_usage; + return memory_usage; } /* -------------------------------- */ @@ -131,1503 +132,1699 @@ uint GPU_texture_memory_usage_get(void) static const char *gl_enum_to_str(GLenum e) { #define ENUM_TO_STRING(e) [GL_##e] = STRINGIFY_ARG(e) - static const char *enum_strings[] = { - ENUM_TO_STRING(TEXTURE_CUBE_MAP), - ENUM_TO_STRING(TEXTURE_2D), - ENUM_TO_STRING(TEXTURE_2D_ARRAY), - ENUM_TO_STRING(TEXTURE_1D), - ENUM_TO_STRING(TEXTURE_1D_ARRAY), - ENUM_TO_STRING(TEXTURE_3D), - ENUM_TO_STRING(TEXTURE_2D_MULTISAMPLE), - ENUM_TO_STRING(RGBA32F), - ENUM_TO_STRING(RGBA16F), - ENUM_TO_STRING(RGBA16), - ENUM_TO_STRING(RG32F), - ENUM_TO_STRING(RGB16F), - ENUM_TO_STRING(RG16F), - ENUM_TO_STRING(RG16I), - ENUM_TO_STRING(RG16), - ENUM_TO_STRING(RGBA8), - ENUM_TO_STRING(RGBA8UI), - ENUM_TO_STRING(R32F), - ENUM_TO_STRING(R32UI), - ENUM_TO_STRING(R32I), - ENUM_TO_STRING(R16F), - ENUM_TO_STRING(R16I), - ENUM_TO_STRING(R16UI), - ENUM_TO_STRING(RG8), - ENUM_TO_STRING(RG16UI), - ENUM_TO_STRING(R16), - ENUM_TO_STRING(R8), - ENUM_TO_STRING(R8UI), - ENUM_TO_STRING(R11F_G11F_B10F), - ENUM_TO_STRING(DEPTH24_STENCIL8), - ENUM_TO_STRING(DEPTH32F_STENCIL8), - ENUM_TO_STRING(DEPTH_COMPONENT32F), - ENUM_TO_STRING(DEPTH_COMPONENT24), - ENUM_TO_STRING(DEPTH_COMPONENT16), - }; + static const char *enum_strings[] = { + ENUM_TO_STRING(TEXTURE_CUBE_MAP), + ENUM_TO_STRING(TEXTURE_2D), + ENUM_TO_STRING(TEXTURE_2D_ARRAY), + ENUM_TO_STRING(TEXTURE_1D), + ENUM_TO_STRING(TEXTURE_1D_ARRAY), + ENUM_TO_STRING(TEXTURE_3D), + ENUM_TO_STRING(TEXTURE_2D_MULTISAMPLE), + ENUM_TO_STRING(RGBA32F), + ENUM_TO_STRING(RGBA16F), + ENUM_TO_STRING(RGBA16), + ENUM_TO_STRING(RG32F), + ENUM_TO_STRING(RGB16F), + ENUM_TO_STRING(RG16F), + ENUM_TO_STRING(RG16I), + ENUM_TO_STRING(RG16), + ENUM_TO_STRING(RGBA8), + ENUM_TO_STRING(RGBA8UI), + ENUM_TO_STRING(R32F), + ENUM_TO_STRING(R32UI), + ENUM_TO_STRING(R32I), + ENUM_TO_STRING(R16F), + ENUM_TO_STRING(R16I), + ENUM_TO_STRING(R16UI), + ENUM_TO_STRING(RG8), + ENUM_TO_STRING(RG16UI), + ENUM_TO_STRING(R16), + ENUM_TO_STRING(R8), + ENUM_TO_STRING(R8UI), + ENUM_TO_STRING(R11F_G11F_B10F), + ENUM_TO_STRING(DEPTH24_STENCIL8), + ENUM_TO_STRING(DEPTH32F_STENCIL8), + ENUM_TO_STRING(DEPTH_COMPONENT32F), + ENUM_TO_STRING(DEPTH_COMPONENT24), + ENUM_TO_STRING(DEPTH_COMPONENT16), + }; #undef ENUM_TO_STRING - return enum_strings[e]; + return enum_strings[e]; } static int gpu_get_component_count(eGPUTextureFormat format) { - switch (format) { - case GPU_RGBA8: - case GPU_RGBA8UI: - case GPU_RGBA16F: - case GPU_RGBA16: - case GPU_RGBA32F: - return 4; - case GPU_RGB16F: - case GPU_R11F_G11F_B10F: - return 3; - case GPU_RG8: - case GPU_RG16: - case GPU_RG16F: - case GPU_RG16I: - case GPU_RG16UI: - case GPU_RG32F: - return 2; - default: - return 1; - } + switch (format) { + case GPU_RGBA8: + case GPU_RGBA8UI: + case GPU_RGBA16F: + case GPU_RGBA16: + case GPU_RGBA32F: + return 4; + case GPU_RGB16F: + case GPU_R11F_G11F_B10F: + return 3; + case GPU_RG8: + case GPU_RG16: + case GPU_RG16F: + case GPU_RG16I: + case GPU_RG16UI: + case GPU_RG32F: + return 2; + default: + return 1; + } } /* Definitely not complete, edit according to the gl specification. */ static void gpu_validate_data_format(eGPUTextureFormat tex_format, eGPUDataFormat data_format) { - (void)data_format; - - if (ELEM(tex_format, - GPU_DEPTH_COMPONENT24, - GPU_DEPTH_COMPONENT16, - GPU_DEPTH_COMPONENT32F)) - { - BLI_assert(data_format == GPU_DATA_FLOAT); - } - else if (ELEM(tex_format, - GPU_DEPTH24_STENCIL8, - GPU_DEPTH32F_STENCIL8)) - { - BLI_assert(data_format == GPU_DATA_UNSIGNED_INT_24_8); - } - else { - /* Integer formats */ - if (ELEM(tex_format, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R16UI, GPU_R8UI, GPU_R32UI)) { - if (ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_RG16UI, GPU_R32UI)) { - BLI_assert(data_format == GPU_DATA_UNSIGNED_INT); - } - else { - BLI_assert(data_format == GPU_DATA_INT); - } - } - /* Byte formats */ - else if (ELEM(tex_format, GPU_R8, GPU_RG8, GPU_RGBA8, GPU_RGBA8UI)) { - BLI_assert(ELEM(data_format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT)); - } - /* Special case */ - else if (ELEM(tex_format, GPU_R11F_G11F_B10F)) { - BLI_assert(ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT)); - } - /* Float formats */ - else { - BLI_assert(ELEM(data_format, GPU_DATA_FLOAT)); - } - } + (void)data_format; + + if (ELEM(tex_format, GPU_DEPTH_COMPONENT24, GPU_DEPTH_COMPONENT16, GPU_DEPTH_COMPONENT32F)) { + BLI_assert(data_format == GPU_DATA_FLOAT); + } + else if (ELEM(tex_format, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8)) { + BLI_assert(data_format == GPU_DATA_UNSIGNED_INT_24_8); + } + else { + /* Integer formats */ + if (ELEM(tex_format, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R16UI, GPU_R8UI, GPU_R32UI)) { + if (ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_RG16UI, GPU_R32UI)) { + BLI_assert(data_format == GPU_DATA_UNSIGNED_INT); + } + else { + BLI_assert(data_format == GPU_DATA_INT); + } + } + /* Byte formats */ + else if (ELEM(tex_format, GPU_R8, GPU_RG8, GPU_RGBA8, GPU_RGBA8UI)) { + BLI_assert(ELEM(data_format, GPU_DATA_UNSIGNED_BYTE, GPU_DATA_FLOAT)); + } + /* Special case */ + else if (ELEM(tex_format, GPU_R11F_G11F_B10F)) { + BLI_assert(ELEM(data_format, GPU_DATA_10_11_11_REV, GPU_DATA_FLOAT)); + } + /* Float formats */ + else { + BLI_assert(ELEM(data_format, GPU_DATA_FLOAT)); + } + } } static eGPUDataFormat gpu_get_data_format_from_tex_format(eGPUTextureFormat tex_format) { - if (ELEM(tex_format, - GPU_DEPTH_COMPONENT24, - GPU_DEPTH_COMPONENT16, - GPU_DEPTH_COMPONENT32F)) - { - return GPU_DATA_FLOAT; - } - else if (ELEM(tex_format, - GPU_DEPTH24_STENCIL8, - GPU_DEPTH32F_STENCIL8)) - { - return GPU_DATA_UNSIGNED_INT_24_8; - } - else { - /* Integer formats */ - if (ELEM(tex_format, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R8UI, GPU_R16UI, GPU_R32UI)) { - if (ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_RG16UI, GPU_R32UI)) { - return GPU_DATA_UNSIGNED_INT; - } - else { - return GPU_DATA_INT; - } - } - /* Byte formats */ - else if (ELEM(tex_format, GPU_R8)) { - return GPU_DATA_UNSIGNED_BYTE; - } - /* Special case */ - else if (ELEM(tex_format, GPU_R11F_G11F_B10F)) { - return GPU_DATA_10_11_11_REV; - } - else { - return GPU_DATA_FLOAT; - } - } + if (ELEM(tex_format, GPU_DEPTH_COMPONENT24, GPU_DEPTH_COMPONENT16, GPU_DEPTH_COMPONENT32F)) { + return GPU_DATA_FLOAT; + } + else if (ELEM(tex_format, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8)) { + return GPU_DATA_UNSIGNED_INT_24_8; + } + else { + /* Integer formats */ + if (ELEM(tex_format, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R8UI, GPU_R16UI, GPU_R32UI)) { + if (ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_RG16UI, GPU_R32UI)) { + return GPU_DATA_UNSIGNED_INT; + } + else { + return GPU_DATA_INT; + } + } + /* Byte formats */ + else if (ELEM(tex_format, GPU_R8)) { + return GPU_DATA_UNSIGNED_BYTE; + } + /* Special case */ + else if (ELEM(tex_format, GPU_R11F_G11F_B10F)) { + return GPU_DATA_10_11_11_REV; + } + else { + return GPU_DATA_FLOAT; + } + } } /* Definitely not complete, edit according to the gl specification. */ -static GLenum gpu_get_gl_dataformat(eGPUTextureFormat data_type, eGPUTextureFormatFlag *format_flag) +static GLenum gpu_get_gl_dataformat(eGPUTextureFormat data_type, + eGPUTextureFormatFlag *format_flag) { - if (ELEM(data_type, - GPU_DEPTH_COMPONENT24, - GPU_DEPTH_COMPONENT16, - GPU_DEPTH_COMPONENT32F)) - { - *format_flag |= GPU_FORMAT_DEPTH; - return GL_DEPTH_COMPONENT; - } - else if (ELEM(data_type, - GPU_DEPTH24_STENCIL8, - GPU_DEPTH32F_STENCIL8)) - { - *format_flag |= GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL; - return GL_DEPTH_STENCIL; - } - else { - /* Integer formats */ - if (ELEM(data_type, GPU_R8UI, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R16UI, GPU_R32UI)) { - *format_flag |= GPU_FORMAT_INTEGER; - - switch (gpu_get_component_count(data_type)) { - case 1: return GL_RED_INTEGER; break; - case 2: return GL_RG_INTEGER; break; - case 3: return GL_RGB_INTEGER; break; - case 4: return GL_RGBA_INTEGER; break; - } - } - else if (ELEM(data_type, GPU_R8)) { - *format_flag |= GPU_FORMAT_FLOAT; - return GL_RED; - } - else { - *format_flag |= GPU_FORMAT_FLOAT; - - switch (gpu_get_component_count(data_type)) { - case 1: return GL_RED; break; - case 2: return GL_RG; break; - case 3: return GL_RGB; break; - case 4: return GL_RGBA; break; - } - } - } - - BLI_assert(0); - *format_flag |= GPU_FORMAT_FLOAT; - return GL_RGBA; + if (ELEM(data_type, GPU_DEPTH_COMPONENT24, GPU_DEPTH_COMPONENT16, GPU_DEPTH_COMPONENT32F)) { + *format_flag |= GPU_FORMAT_DEPTH; + return GL_DEPTH_COMPONENT; + } + else if (ELEM(data_type, GPU_DEPTH24_STENCIL8, GPU_DEPTH32F_STENCIL8)) { + *format_flag |= GPU_FORMAT_DEPTH | GPU_FORMAT_STENCIL; + return GL_DEPTH_STENCIL; + } + else { + /* Integer formats */ + if (ELEM(data_type, GPU_R8UI, GPU_RG16I, GPU_R16I, GPU_RG16UI, GPU_R16UI, GPU_R32UI)) { + *format_flag |= GPU_FORMAT_INTEGER; + + switch (gpu_get_component_count(data_type)) { + case 1: + return GL_RED_INTEGER; + break; + case 2: + return GL_RG_INTEGER; + break; + case 3: + return GL_RGB_INTEGER; + break; + case 4: + return GL_RGBA_INTEGER; + break; + } + } + else if (ELEM(data_type, GPU_R8)) { + *format_flag |= GPU_FORMAT_FLOAT; + return GL_RED; + } + else { + *format_flag |= GPU_FORMAT_FLOAT; + + switch (gpu_get_component_count(data_type)) { + case 1: + return GL_RED; + break; + case 2: + return GL_RG; + break; + case 3: + return GL_RGB; + break; + case 4: + return GL_RGBA; + break; + } + } + } + + BLI_assert(0); + *format_flag |= GPU_FORMAT_FLOAT; + return GL_RGBA; } static uint gpu_get_bytesize(eGPUTextureFormat data_type) { - switch (data_type) { - case GPU_RGBA32F: - return 32; - case GPU_RG32F: - case GPU_RGBA16F: - case GPU_RGBA16: - return 16; - case GPU_RGB16F: - return 12; - case GPU_DEPTH32F_STENCIL8: - return 8; - case GPU_RG16F: - case GPU_RG16I: - case GPU_RG16UI: - case GPU_RG16: - case GPU_DEPTH24_STENCIL8: - case GPU_DEPTH_COMPONENT32F: - case GPU_RGBA8UI: - case GPU_RGBA8: - case GPU_R11F_G11F_B10F: - case GPU_R32F: - case GPU_R32UI: - case GPU_R32I: - return 4; - case GPU_DEPTH_COMPONENT24: - return 3; - case GPU_DEPTH_COMPONENT16: - case GPU_R16F: - case GPU_R16UI: - case GPU_R16I: - case GPU_RG8: - case GPU_R16: - return 2; - case GPU_R8: - case GPU_R8UI: - return 1; - default: - BLI_assert(!"Texture format incorrect or unsupported\n"); - return 0; - } + switch (data_type) { + case GPU_RGBA32F: + return 32; + case GPU_RG32F: + case GPU_RGBA16F: + case GPU_RGBA16: + return 16; + case GPU_RGB16F: + return 12; + case GPU_DEPTH32F_STENCIL8: + return 8; + case GPU_RG16F: + case GPU_RG16I: + case GPU_RG16UI: + case GPU_RG16: + case GPU_DEPTH24_STENCIL8: + case GPU_DEPTH_COMPONENT32F: + case GPU_RGBA8UI: + case GPU_RGBA8: + case GPU_R11F_G11F_B10F: + case GPU_R32F: + case GPU_R32UI: + case GPU_R32I: + return 4; + case GPU_DEPTH_COMPONENT24: + return 3; + case GPU_DEPTH_COMPONENT16: + case GPU_R16F: + case GPU_R16UI: + case GPU_R16I: + case GPU_RG8: + case GPU_R16: + return 2; + case GPU_R8: + case GPU_R8UI: + return 1; + default: + BLI_assert(!"Texture format incorrect or unsupported\n"); + return 0; + } } static GLenum gpu_get_gl_internalformat(eGPUTextureFormat format) { - /* You can add any of the available type to this list - * For available types see GPU_texture.h */ - switch (format) { - /* Formats texture & renderbuffer */ - case GPU_RGBA32F: return GL_RGBA32F; - case GPU_RGBA16F: return GL_RGBA16F; - case GPU_RGBA16: return GL_RGBA16; - case GPU_RG32F: return GL_RG32F; - case GPU_RGB16F: return GL_RGB16F; - case GPU_RG16F: return GL_RG16F; - case GPU_RG16I: return GL_RG16I; - case GPU_RG16: return GL_RG16; - case GPU_RGBA8: return GL_RGBA8; - case GPU_RGBA8UI: return GL_RGBA8UI; - case GPU_R32F: return GL_R32F; - case GPU_R32UI: return GL_R32UI; - case GPU_R32I: return GL_R32I; - case GPU_R16F: return GL_R16F; - case GPU_R16I: return GL_R16I; - case GPU_R16UI: return GL_R16UI; - case GPU_RG8: return GL_RG8; - case GPU_RG16UI: return GL_RG16UI; - case GPU_R16: return GL_R16; - case GPU_R8: return GL_R8; - case GPU_R8UI: return GL_R8UI; - /* Special formats texture & renderbuffer */ - case GPU_R11F_G11F_B10F: return GL_R11F_G11F_B10F; - case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8; - case GPU_DEPTH32F_STENCIL8: return GL_DEPTH32F_STENCIL8; - /* Texture only format */ - /* ** Add Format here */ - /* Special formats texture only */ - /* ** Add Format here */ - /* Depth Formats */ - case GPU_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT32F; - case GPU_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT24; - case GPU_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT16; - default: - BLI_assert(!"Texture format incorrect or unsupported\n"); - return 0; - } + /* You can add any of the available type to this list + * For available types see GPU_texture.h */ + switch (format) { + /* Formats texture & renderbuffer */ + case GPU_RGBA32F: + return GL_RGBA32F; + case GPU_RGBA16F: + return GL_RGBA16F; + case GPU_RGBA16: + return GL_RGBA16; + case GPU_RG32F: + return GL_RG32F; + case GPU_RGB16F: + return GL_RGB16F; + case GPU_RG16F: + return GL_RG16F; + case GPU_RG16I: + return GL_RG16I; + case GPU_RG16: + return GL_RG16; + case GPU_RGBA8: + return GL_RGBA8; + case GPU_RGBA8UI: + return GL_RGBA8UI; + case GPU_R32F: + return GL_R32F; + case GPU_R32UI: + return GL_R32UI; + case GPU_R32I: + return GL_R32I; + case GPU_R16F: + return GL_R16F; + case GPU_R16I: + return GL_R16I; + case GPU_R16UI: + return GL_R16UI; + case GPU_RG8: + return GL_RG8; + case GPU_RG16UI: + return GL_RG16UI; + case GPU_R16: + return GL_R16; + case GPU_R8: + return GL_R8; + case GPU_R8UI: + return GL_R8UI; + /* Special formats texture & renderbuffer */ + case GPU_R11F_G11F_B10F: + return GL_R11F_G11F_B10F; + case GPU_DEPTH24_STENCIL8: + return GL_DEPTH24_STENCIL8; + case GPU_DEPTH32F_STENCIL8: + return GL_DEPTH32F_STENCIL8; + /* Texture only format */ + /* ** Add Format here */ + /* Special formats texture only */ + /* ** Add Format here */ + /* Depth Formats */ + case GPU_DEPTH_COMPONENT32F: + return GL_DEPTH_COMPONENT32F; + case GPU_DEPTH_COMPONENT24: + return GL_DEPTH_COMPONENT24; + case GPU_DEPTH_COMPONENT16: + return GL_DEPTH_COMPONENT16; + default: + BLI_assert(!"Texture format incorrect or unsupported\n"); + return 0; + } } static GLenum gpu_get_gl_datatype(eGPUDataFormat format) { - switch (format) { - case GPU_DATA_FLOAT: - return GL_FLOAT; - case GPU_DATA_INT: - return GL_INT; - case GPU_DATA_UNSIGNED_INT: - return GL_UNSIGNED_INT; - case GPU_DATA_UNSIGNED_BYTE: - return GL_UNSIGNED_BYTE; - case GPU_DATA_UNSIGNED_INT_24_8: - return GL_UNSIGNED_INT_24_8; - case GPU_DATA_10_11_11_REV: - return GL_UNSIGNED_INT_10F_11F_11F_REV; - default: - BLI_assert(!"Unhandled data format"); - return GL_FLOAT; - } + switch (format) { + case GPU_DATA_FLOAT: + return GL_FLOAT; + case GPU_DATA_INT: + return GL_INT; + case GPU_DATA_UNSIGNED_INT: + return GL_UNSIGNED_INT; + case GPU_DATA_UNSIGNED_BYTE: + return GL_UNSIGNED_BYTE; + case GPU_DATA_UNSIGNED_INT_24_8: + return GL_UNSIGNED_INT_24_8; + case GPU_DATA_10_11_11_REV: + return GL_UNSIGNED_INT_10F_11F_11F_REV; + default: + BLI_assert(!"Unhandled data format"); + return GL_FLOAT; + } } -static float *GPU_texture_rescale_3d(GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels) +static float *GPU_texture_rescale_3d( + GPUTexture *tex, int w, int h, int d, int channels, const float *fpixels) { - const uint xf = w / tex->w, yf = h / tex->h, zf = d / tex->d; - float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, "GPUTexture Rescaled 3Dtex"); - - if (nfpixels) { - GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); - - for (uint k = 0; k < tex->d; k++) { - for (uint j = 0; j < tex->h; j++) { - for (uint i = 0; i < tex->w; i++) { - /* obviously doing nearest filtering here, - * it's going to be slow in any case, let's not make it worse */ - float xb = i * xf; - float yb = j * yf; - float zb = k * zf; - uint offset = k * (tex->w * tex->h) + i * tex->h + j; - uint offset_orig = (zb) * (w * h) + (xb) * h + (yb); - - if (channels == 4) { - nfpixels[offset * 4] = fpixels[offset_orig * 4]; - nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; - nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; - nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; - } - else - nfpixels[offset] = fpixels[offset_orig]; - } - } - } - } - - return nfpixels; + const uint xf = w / tex->w, yf = h / tex->h, zf = d / tex->d; + float *nfpixels = MEM_mallocN(channels * sizeof(float) * tex->w * tex->h * tex->d, + "GPUTexture Rescaled 3Dtex"); + + if (nfpixels) { + GPU_print_error_debug("You need to scale a 3D texture, feel the pain!"); + + for (uint k = 0; k < tex->d; k++) { + for (uint j = 0; j < tex->h; j++) { + for (uint i = 0; i < tex->w; i++) { + /* obviously doing nearest filtering here, + * it's going to be slow in any case, let's not make it worse */ + float xb = i * xf; + float yb = j * yf; + float zb = k * zf; + uint offset = k * (tex->w * tex->h) + i * tex->h + j; + uint offset_orig = (zb) * (w * h) + (xb)*h + (yb); + + if (channels == 4) { + nfpixels[offset * 4] = fpixels[offset_orig * 4]; + nfpixels[offset * 4 + 1] = fpixels[offset_orig * 4 + 1]; + nfpixels[offset * 4 + 2] = fpixels[offset_orig * 4 + 2]; + nfpixels[offset * 4 + 3] = fpixels[offset_orig * 4 + 3]; + } + else + nfpixels[offset] = fpixels[offset_orig]; + } + } + } + } + + return nfpixels; } static bool gpu_texture_check_capacity( - GPUTexture *tex, GLenum proxy, GLenum internalformat, - GLenum data_format, GLenum data_type) + GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum data_format, GLenum data_type) { - if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) { - /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check. - * (see T55888, T56185, T59351). - * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue, - * it just states that the OGL implementation can support the texture. - * So manually check the maximum size and maximum number of layers. */ - switch (proxy) { - case GL_PROXY_TEXTURE_2D_ARRAY: - if ((tex->d < 0) || (tex->d > GPU_max_texture_layers())) - return false; - break; - - case GL_PROXY_TEXTURE_1D_ARRAY: - if ((tex->h < 0) || (tex->h > GPU_max_texture_layers())) - return false; - break; - } - - switch (proxy) { - case GL_PROXY_TEXTURE_3D: - if ((tex->d < 0) || (tex->d > GPU_max_texture_size())) - return false; - ATTR_FALLTHROUGH; - - case GL_PROXY_TEXTURE_2D: - case GL_PROXY_TEXTURE_2D_ARRAY: - if ((tex->h < 0) || (tex->h > GPU_max_texture_size())) - return false; - ATTR_FALLTHROUGH; - - case GL_PROXY_TEXTURE_1D: - case GL_PROXY_TEXTURE_1D_ARRAY: - if ((tex->w < 0) || (tex->w > GPU_max_texture_size())) - return false; - ATTR_FALLTHROUGH; - } - - return true; - } - else { - switch (proxy) { - case GL_PROXY_TEXTURE_1D: - glTexImage1D(proxy, 0, internalformat, tex->w, 0, data_format, data_type, NULL); - break; - case GL_PROXY_TEXTURE_1D_ARRAY: - case GL_PROXY_TEXTURE_2D: - glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, NULL); - break; - case GL_PROXY_TEXTURE_2D_ARRAY: - case GL_PROXY_TEXTURE_3D: - glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, NULL); - break; - } - int width = 0; - glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &width); - - return (width > 0); - } + if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_WIN, GPU_DRIVER_ANY)) { + /* Some AMD drivers have a faulty `GL_PROXY_TEXTURE_..` check. + * (see T55888, T56185, T59351). + * Checking with `GL_PROXY_TEXTURE_..` doesn't prevent `Out Of Memory` issue, + * it just states that the OGL implementation can support the texture. + * So manually check the maximum size and maximum number of layers. */ + switch (proxy) { + case GL_PROXY_TEXTURE_2D_ARRAY: + if ((tex->d < 0) || (tex->d > GPU_max_texture_layers())) + return false; + break; + + case GL_PROXY_TEXTURE_1D_ARRAY: + if ((tex->h < 0) || (tex->h > GPU_max_texture_layers())) + return false; + break; + } + + switch (proxy) { + case GL_PROXY_TEXTURE_3D: + if ((tex->d < 0) || (tex->d > GPU_max_texture_size())) + return false; + ATTR_FALLTHROUGH; + + case GL_PROXY_TEXTURE_2D: + case GL_PROXY_TEXTURE_2D_ARRAY: + if ((tex->h < 0) || (tex->h > GPU_max_texture_size())) + return false; + ATTR_FALLTHROUGH; + + case GL_PROXY_TEXTURE_1D: + case GL_PROXY_TEXTURE_1D_ARRAY: + if ((tex->w < 0) || (tex->w > GPU_max_texture_size())) + return false; + ATTR_FALLTHROUGH; + } + + return true; + } + else { + switch (proxy) { + case GL_PROXY_TEXTURE_1D: + glTexImage1D(proxy, 0, internalformat, tex->w, 0, data_format, data_type, NULL); + break; + case GL_PROXY_TEXTURE_1D_ARRAY: + case GL_PROXY_TEXTURE_2D: + glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, NULL); + break; + case GL_PROXY_TEXTURE_2D_ARRAY: + case GL_PROXY_TEXTURE_3D: + glTexImage3D( + proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, NULL); + break; + } + int width = 0; + glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &width); + + return (width > 0); + } } /* This tries to allocate video memory for a given texture * If alloc fails, lower the resolution until it fits. */ -static bool gpu_texture_try_alloc( - GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum data_format, GLenum data_type, - int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels) +static bool gpu_texture_try_alloc(GPUTexture *tex, + GLenum proxy, + GLenum internalformat, + GLenum data_format, + GLenum data_type, + int channels, + bool try_rescale, + const float *fpixels, + float **rescaled_fpixels) { - bool ret; - ret = gpu_texture_check_capacity(tex, proxy, internalformat, data_format, data_type); - - if (!ret && try_rescale) { - BLI_assert(!ELEM(proxy, GL_PROXY_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_2D_ARRAY)); // not implemented - - const int w = tex->w, h = tex->h, d = tex->d; - - /* Find largest texture possible */ - do { - tex->w /= 2; - tex->h /= 2; - tex->d /= 2; - - /* really unlikely to happen but keep this just in case */ - if (tex->w == 0) break; - if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) break; - if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break; - - ret = gpu_texture_check_capacity(tex, proxy, internalformat, data_format, data_type); - } while (ret == false); - - /* Rescale */ - if (ret) { - switch (proxy) { - case GL_PROXY_TEXTURE_1D: - case GL_PROXY_TEXTURE_2D: - /* Do nothing for now */ - return false; - case GL_PROXY_TEXTURE_3D: - BLI_assert(data_type == GL_FLOAT); - *rescaled_fpixels = GPU_texture_rescale_3d(tex, w, h, d, channels, fpixels); - return (bool)*rescaled_fpixels; - } - } - } - - return ret; + bool ret; + ret = gpu_texture_check_capacity(tex, proxy, internalformat, data_format, data_type); + + if (!ret && try_rescale) { + BLI_assert( + !ELEM(proxy, GL_PROXY_TEXTURE_1D_ARRAY, GL_PROXY_TEXTURE_2D_ARRAY)); // not implemented + + const int w = tex->w, h = tex->h, d = tex->d; + + /* Find largest texture possible */ + do { + tex->w /= 2; + tex->h /= 2; + tex->d /= 2; + + /* really unlikely to happen but keep this just in case */ + if (tex->w == 0) + break; + if (tex->h == 0 && proxy != GL_PROXY_TEXTURE_1D) + break; + if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) + break; + + ret = gpu_texture_check_capacity(tex, proxy, internalformat, data_format, data_type); + } while (ret == false); + + /* Rescale */ + if (ret) { + switch (proxy) { + case GL_PROXY_TEXTURE_1D: + case GL_PROXY_TEXTURE_2D: + /* Do nothing for now */ + return false; + case GL_PROXY_TEXTURE_3D: + BLI_assert(data_type == GL_FLOAT); + *rescaled_fpixels = GPU_texture_rescale_3d(tex, w, h, d, channels, fpixels); + return (bool)*rescaled_fpixels; + } + } + } + + return ret; } -GPUTexture *GPU_texture_create_nD( - int w, int h, int d, int n, const void *pixels, - eGPUTextureFormat tex_format, eGPUDataFormat gpu_data_format, int samples, - const bool can_rescale, char err_out[256]) +GPUTexture *GPU_texture_create_nD(int w, + int h, + int d, + int n, + const void *pixels, + eGPUTextureFormat tex_format, + eGPUDataFormat gpu_data_format, + int samples, + const bool can_rescale, + char err_out[256]) { - if (samples) { - CLAMP_MAX(samples, GPU_max_color_texture_samples()); - } - - if ((tex_format == GPU_DEPTH24_STENCIL8) && GPU_depth_blitting_workaround()) { - /* MacOS + Radeon Pro fails to blit depth on GPU_DEPTH24_STENCIL8 - * but works on GPU_DEPTH32F_STENCIL8. */ - tex_format = GPU_DEPTH32F_STENCIL8; - } - - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->w = w; - tex->h = h; - tex->d = d; - tex->samples = samples; - tex->number = -1; - tex->refcount = 1; - tex->format = tex_format; - tex->components = gpu_get_component_count(tex_format); - tex->bytesize = gpu_get_bytesize(tex_format); - tex->format_flag = 0; - - if (n == 2) { - if (d == 0) - tex->target_base = tex->target = GL_TEXTURE_2D; - else - tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY; - } - else if (n == 1) { - if (h == 0) - tex->target_base = tex->target = GL_TEXTURE_1D; - else - tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY; - } - else if (n == 3) { - tex->target_base = tex->target = GL_TEXTURE_3D; - } - else { - /* should never happen */ - MEM_freeN(tex); - return NULL; - } - - gpu_validate_data_format(tex_format, gpu_data_format); - - if (samples && n == 2 && d == 0) - tex->target = GL_TEXTURE_2D_MULTISAMPLE; - - GLenum internalformat = gpu_get_gl_internalformat(tex_format); - GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - - /* Generate Texture object */ - tex->bindcode = GPU_tex_alloc(); - - if (!tex->bindcode) { - if (err_out) { - BLI_strncpy(err_out, "GPUTexture: texture create failed\n", 256); - } - else { - fprintf(stderr, "GPUTexture: texture create failed\n"); - } - GPU_texture_free(tex); - return NULL; - } - - glBindTexture(tex->target, tex->bindcode); - - /* Check if texture fit in VRAM */ - GLenum proxy = GL_PROXY_TEXTURE_2D; - - if (n == 2) { - if (d > 1) - proxy = GL_PROXY_TEXTURE_2D_ARRAY; - } - else if (n == 1) { - if (h == 0) - proxy = GL_PROXY_TEXTURE_1D; - else - proxy = GL_PROXY_TEXTURE_1D_ARRAY; - } - else if (n == 3) { - proxy = GL_PROXY_TEXTURE_3D; - } - - float *rescaled_pixels = NULL; - bool valid = gpu_texture_try_alloc(tex, proxy, internalformat, data_format, data_type, tex->components, can_rescale, - pixels, &rescaled_pixels); - - if (G.debug & G_DEBUG_GPU || !valid) { - printf("GPUTexture: create : %s, %s, w : %d, h : %d, d : %d, comp : %d, size : %.2f MiB\n", - gl_enum_to_str(tex->target), gl_enum_to_str(internalformat), - w, h, d, tex->components, - gpu_texture_memory_footprint_compute(tex) / 1048576.0f); - } - - if (!valid) { - if (err_out) { - BLI_strncpy(err_out, "GPUTexture: texture alloc failed\n", 256); - } - else { - fprintf(stderr, "GPUTexture: texture alloc failed. Likely not enough Video Memory.\n"); - fprintf(stderr, "Current texture memory usage : %.2f MiB.\n", - gpu_texture_memory_footprint_compute(tex) / 1048576.0f); - } - GPU_texture_free(tex); - return NULL; - } - - gpu_texture_memory_footprint_add(tex); - - /* Upload Texture */ - const float *pix = (rescaled_pixels) ? rescaled_pixels : pixels; - - if (tex->target == GL_TEXTURE_2D || - tex->target == GL_TEXTURE_2D_MULTISAMPLE || - tex->target == GL_TEXTURE_1D_ARRAY) - { - if (samples) { - glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); - if (pix) - glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, data_format, data_type, pix); - } - else { - glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pix); - } - } - else if (tex->target == GL_TEXTURE_1D) { - glTexImage1D(tex->target, 0, internalformat, tex->w, 0, data_format, data_type, pix); - } - else { - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, pix); - } - - if (rescaled_pixels) - MEM_freeN(rescaled_pixels); - - /* Texture Parameters */ - if (GPU_texture_stencil(tex) || /* Does not support filtering */ - GPU_texture_integer(tex) || /* Does not support filtering */ - GPU_texture_depth(tex)) - { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - if (n > 1) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } - if (n > 2) { - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - } - - glBindTexture(tex->target, 0); - - return tex; + if (samples) { + CLAMP_MAX(samples, GPU_max_color_texture_samples()); + } + + if ((tex_format == GPU_DEPTH24_STENCIL8) && GPU_depth_blitting_workaround()) { + /* MacOS + Radeon Pro fails to blit depth on GPU_DEPTH24_STENCIL8 + * but works on GPU_DEPTH32F_STENCIL8. */ + tex_format = GPU_DEPTH32F_STENCIL8; + } + + GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->w = w; + tex->h = h; + tex->d = d; + tex->samples = samples; + tex->number = -1; + tex->refcount = 1; + tex->format = tex_format; + tex->components = gpu_get_component_count(tex_format); + tex->bytesize = gpu_get_bytesize(tex_format); + tex->format_flag = 0; + + if (n == 2) { + if (d == 0) + tex->target_base = tex->target = GL_TEXTURE_2D; + else + tex->target_base = tex->target = GL_TEXTURE_2D_ARRAY; + } + else if (n == 1) { + if (h == 0) + tex->target_base = tex->target = GL_TEXTURE_1D; + else + tex->target_base = tex->target = GL_TEXTURE_1D_ARRAY; + } + else if (n == 3) { + tex->target_base = tex->target = GL_TEXTURE_3D; + } + else { + /* should never happen */ + MEM_freeN(tex); + return NULL; + } + + gpu_validate_data_format(tex_format, gpu_data_format); + + if (samples && n == 2 && d == 0) + tex->target = GL_TEXTURE_2D_MULTISAMPLE; + + GLenum internalformat = gpu_get_gl_internalformat(tex_format); + GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + + /* Generate Texture object */ + tex->bindcode = GPU_tex_alloc(); + + if (!tex->bindcode) { + if (err_out) { + BLI_strncpy(err_out, "GPUTexture: texture create failed\n", 256); + } + else { + fprintf(stderr, "GPUTexture: texture create failed\n"); + } + GPU_texture_free(tex); + return NULL; + } + + glBindTexture(tex->target, tex->bindcode); + + /* Check if texture fit in VRAM */ + GLenum proxy = GL_PROXY_TEXTURE_2D; + + if (n == 2) { + if (d > 1) + proxy = GL_PROXY_TEXTURE_2D_ARRAY; + } + else if (n == 1) { + if (h == 0) + proxy = GL_PROXY_TEXTURE_1D; + else + proxy = GL_PROXY_TEXTURE_1D_ARRAY; + } + else if (n == 3) { + proxy = GL_PROXY_TEXTURE_3D; + } + + float *rescaled_pixels = NULL; + bool valid = gpu_texture_try_alloc(tex, + proxy, + internalformat, + data_format, + data_type, + tex->components, + can_rescale, + pixels, + &rescaled_pixels); + + if (G.debug & G_DEBUG_GPU || !valid) { + printf("GPUTexture: create : %s, %s, w : %d, h : %d, d : %d, comp : %d, size : %.2f MiB\n", + gl_enum_to_str(tex->target), + gl_enum_to_str(internalformat), + w, + h, + d, + tex->components, + gpu_texture_memory_footprint_compute(tex) / 1048576.0f); + } + + if (!valid) { + if (err_out) { + BLI_strncpy(err_out, "GPUTexture: texture alloc failed\n", 256); + } + else { + fprintf(stderr, "GPUTexture: texture alloc failed. Likely not enough Video Memory.\n"); + fprintf(stderr, + "Current texture memory usage : %.2f MiB.\n", + gpu_texture_memory_footprint_compute(tex) / 1048576.0f); + } + GPU_texture_free(tex); + return NULL; + } + + gpu_texture_memory_footprint_add(tex); + + /* Upload Texture */ + const float *pix = (rescaled_pixels) ? rescaled_pixels : pixels; + + if (tex->target == GL_TEXTURE_2D || tex->target == GL_TEXTURE_2D_MULTISAMPLE || + tex->target == GL_TEXTURE_1D_ARRAY) { + if (samples) { + glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); + if (pix) + glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, data_format, data_type, pix); + } + else { + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, pix); + } + } + else if (tex->target == GL_TEXTURE_1D) { + glTexImage1D(tex->target, 0, internalformat, tex->w, 0, data_format, data_type, pix); + } + else { + glTexImage3D( + tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, data_format, data_type, pix); + } + + if (rescaled_pixels) + MEM_freeN(rescaled_pixels); + + /* Texture Parameters */ + if (GPU_texture_stencil(tex) || /* Does not support filtering */ + GPU_texture_integer(tex) || /* Does not support filtering */ + GPU_texture_depth(tex)) { + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else { + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (GPU_texture_depth(tex)) { + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + } + + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + if (n > 1) { + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (n > 2) { + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + } + + glBindTexture(tex->target, 0); + + return tex; } -static GPUTexture *GPU_texture_cube_create( - int w, int d, - const float *fpixels_px, const float *fpixels_py, const float *fpixels_pz, - const float *fpixels_nx, const float *fpixels_ny, const float *fpixels_nz, - eGPUTextureFormat tex_format, eGPUDataFormat gpu_data_format, - char err_out[256]) +static GPUTexture *GPU_texture_cube_create(int w, + int d, + const float *fpixels_px, + const float *fpixels_py, + const float *fpixels_pz, + const float *fpixels_nx, + const float *fpixels_ny, + const float *fpixels_nz, + eGPUTextureFormat tex_format, + eGPUDataFormat gpu_data_format, + char err_out[256]) { - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->w = w; - tex->h = w; - tex->d = d; - tex->samples = 0; - tex->number = -1; - tex->refcount = 1; - tex->format = tex_format; - tex->components = gpu_get_component_count(tex_format); - tex->bytesize = gpu_get_bytesize(tex_format); - tex->format_flag = GPU_FORMAT_CUBE; - - if (d == 0) { - tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP; - } - else { - BLI_assert(false && "Cubemap array Not implemented yet"); - // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY; - } - - GLenum internalformat = gpu_get_gl_internalformat(tex_format); - GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - - /* Generate Texture object */ - tex->bindcode = GPU_tex_alloc(); - - if (!tex->bindcode) { - if (err_out) { - BLI_strncpy(err_out, "GPUTexture: texture create failed\n", 256); - } - else { - fprintf(stderr, "GPUTexture: texture create failed\n"); - } - GPU_texture_free(tex); - return NULL; - } - - if (G.debug & G_DEBUG_GPU) { - printf("GPUTexture: create : %s, %s, w : %d, h : %d, d : %d, comp : %d, size : %.2f MiB\n", - gl_enum_to_str(tex->target), gl_enum_to_str(internalformat), - w, w, d, tex->components, - gpu_texture_memory_footprint_compute(tex) / 1048576.0f); - } - - gpu_texture_memory_footprint_add(tex); - - glBindTexture(tex->target, tex->bindcode); - - /* Upload Texture */ - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_px); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_py); - glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_pz); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_nx); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_ny); - glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, internalformat, tex->w, tex->h, 0, data_format, data_type, fpixels_nz); - - /* Texture Parameters */ - if (GPU_texture_stencil(tex) || /* Does not support filtering */ - GPU_texture_integer(tex) || /* Does not support filtering */ - GPU_texture_depth(tex)) - { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } - else { - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if (GPU_texture_depth(tex)) { - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - - glBindTexture(tex->target, 0); - - return tex; + GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->w = w; + tex->h = w; + tex->d = d; + tex->samples = 0; + tex->number = -1; + tex->refcount = 1; + tex->format = tex_format; + tex->components = gpu_get_component_count(tex_format); + tex->bytesize = gpu_get_bytesize(tex_format); + tex->format_flag = GPU_FORMAT_CUBE; + + if (d == 0) { + tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP; + } + else { + BLI_assert(false && "Cubemap array Not implemented yet"); + // tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP_ARRAY; + } + + GLenum internalformat = gpu_get_gl_internalformat(tex_format); + GLenum data_format = gpu_get_gl_dataformat(tex_format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + + /* Generate Texture object */ + tex->bindcode = GPU_tex_alloc(); + + if (!tex->bindcode) { + if (err_out) { + BLI_strncpy(err_out, "GPUTexture: texture create failed\n", 256); + } + else { + fprintf(stderr, "GPUTexture: texture create failed\n"); + } + GPU_texture_free(tex); + return NULL; + } + + if (G.debug & G_DEBUG_GPU) { + printf("GPUTexture: create : %s, %s, w : %d, h : %d, d : %d, comp : %d, size : %.2f MiB\n", + gl_enum_to_str(tex->target), + gl_enum_to_str(internalformat), + w, + w, + d, + tex->components, + gpu_texture_memory_footprint_compute(tex) / 1048576.0f); + } + + gpu_texture_memory_footprint_add(tex); + + glBindTexture(tex->target, tex->bindcode); + + /* Upload Texture */ + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_px); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_py); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_pz); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_nx); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_ny); + glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + 0, + internalformat, + tex->w, + tex->h, + 0, + data_format, + data_type, + fpixels_nz); + + /* Texture Parameters */ + if (GPU_texture_stencil(tex) || /* Does not support filtering */ + GPU_texture_integer(tex) || /* Does not support filtering */ + GPU_texture_depth(tex)) { + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + else { + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + + if (GPU_texture_depth(tex)) { + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE); + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); + } + + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + + glBindTexture(tex->target, 0); + + return tex; } /* Special buffer textures. tex_format must be compatible with the buffer content. */ GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer) { - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->number = -1; - tex->refcount = 1; - tex->format = tex_format; - tex->components = gpu_get_component_count(tex_format); - tex->format_flag = 0; - tex->target_base = tex->target = GL_TEXTURE_BUFFER; - tex->bytesize = gpu_get_bytesize(tex_format); - - GLenum internalformat = gpu_get_gl_internalformat(tex_format); - - gpu_get_gl_dataformat(tex_format, &tex->format_flag); - - if (!(ELEM(tex_format, GPU_R8, GPU_R16) || - ELEM(tex_format, GPU_R16F, GPU_R32F) || - ELEM(tex_format, GPU_R8I, GPU_R16I, GPU_R32I) || - ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_R32UI) || - ELEM(tex_format, GPU_RG8, GPU_RG16) || - ELEM(tex_format, GPU_RG16F, GPU_RG32F) || - ELEM(tex_format, GPU_RG8I, GPU_RG16I, GPU_RG32I) || - ELEM(tex_format, GPU_RG8UI, GPU_RG16UI, GPU_RG32UI) || - //ELEM(tex_format, GPU_RGB32F, GPU_RGB32I, GPU_RGB32UI) || /* Not available until gl 4.0 */ - ELEM(tex_format, GPU_RGBA8, GPU_RGBA16) || - ELEM(tex_format, GPU_RGBA16F, GPU_RGBA32F) || - ELEM(tex_format, GPU_RGBA8I, GPU_RGBA16I, GPU_RGBA32I) || - ELEM(tex_format, GPU_RGBA8UI, GPU_RGBA16UI, GPU_RGBA32UI))) - { - fprintf(stderr, "GPUTexture: invalid format for texture buffer\n"); - GPU_texture_free(tex); - return NULL; - } - - /* Generate Texture object */ - tex->bindcode = GPU_tex_alloc(); - - if (!tex->bindcode) { - fprintf(stderr, "GPUTexture: texture create failed\n"); - GPU_texture_free(tex); - BLI_assert(0 && "glGenTextures failed: Are you sure a valid OGL context is active on this thread?\n"); - return NULL; - } - - glBindTexture(tex->target, tex->bindcode); - glTexBuffer(tex->target, internalformat, buffer); - glBindTexture(tex->target, 0); - - return tex; + GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->number = -1; + tex->refcount = 1; + tex->format = tex_format; + tex->components = gpu_get_component_count(tex_format); + tex->format_flag = 0; + tex->target_base = tex->target = GL_TEXTURE_BUFFER; + tex->bytesize = gpu_get_bytesize(tex_format); + + GLenum internalformat = gpu_get_gl_internalformat(tex_format); + + gpu_get_gl_dataformat(tex_format, &tex->format_flag); + + if (!(ELEM(tex_format, GPU_R8, GPU_R16) || ELEM(tex_format, GPU_R16F, GPU_R32F) || + ELEM(tex_format, GPU_R8I, GPU_R16I, GPU_R32I) || + ELEM(tex_format, GPU_R8UI, GPU_R16UI, GPU_R32UI) || ELEM(tex_format, GPU_RG8, GPU_RG16) || + ELEM(tex_format, GPU_RG16F, GPU_RG32F) || + ELEM(tex_format, GPU_RG8I, GPU_RG16I, GPU_RG32I) || + ELEM(tex_format, GPU_RG8UI, GPU_RG16UI, GPU_RG32UI) || + //ELEM(tex_format, GPU_RGB32F, GPU_RGB32I, GPU_RGB32UI) || /* Not available until gl 4.0 */ + ELEM(tex_format, GPU_RGBA8, GPU_RGBA16) || ELEM(tex_format, GPU_RGBA16F, GPU_RGBA32F) || + ELEM(tex_format, GPU_RGBA8I, GPU_RGBA16I, GPU_RGBA32I) || + ELEM(tex_format, GPU_RGBA8UI, GPU_RGBA16UI, GPU_RGBA32UI))) { + fprintf(stderr, "GPUTexture: invalid format for texture buffer\n"); + GPU_texture_free(tex); + return NULL; + } + + /* Generate Texture object */ + tex->bindcode = GPU_tex_alloc(); + + if (!tex->bindcode) { + fprintf(stderr, "GPUTexture: texture create failed\n"); + GPU_texture_free(tex); + BLI_assert( + 0 && "glGenTextures failed: Are you sure a valid OGL context is active on this thread?\n"); + return NULL; + } + + glBindTexture(tex->target, tex->bindcode); + glTexBuffer(tex->target, internalformat, buffer); + glBindTexture(tex->target, 0); + + return tex; } GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode) { - /* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP - * these values are correct for glDisable, so textarget can be safely used in - * GPU_texture_bind/GPU_texture_unbind through tex->target_base */ - /* (is any of this obsolete now that we don't glEnable/Disable textures?) */ - GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->bindcode = bindcode; - tex->number = -1; - tex->refcount = 1; - tex->target = textarget; - tex->target_base = textarget; - tex->format = -1; - tex->components = -1; - tex->samples = 0; - - if (!glIsTexture(tex->bindcode)) { - GPU_print_error_debug("Blender Texture Not Loaded"); - } - else { - GLint w, h; - - GLenum gettarget; - - if (textarget == GL_TEXTURE_2D) - gettarget = GL_TEXTURE_2D; - else - gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; - - glBindTexture(textarget, tex->bindcode); - glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); - glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); - tex->w = w; - tex->h = h; - glBindTexture(textarget, 0); - } - - return tex; + /* see GPUInput::textarget: it can take two values - GL_TEXTURE_2D and GL_TEXTURE_CUBE_MAP + * these values are correct for glDisable, so textarget can be safely used in + * GPU_texture_bind/GPU_texture_unbind through tex->target_base */ + /* (is any of this obsolete now that we don't glEnable/Disable textures?) */ + GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = textarget; + tex->target_base = textarget; + tex->format = -1; + tex->components = -1; + tex->samples = 0; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error_debug("Blender Texture Not Loaded"); + } + else { + GLint w, h; + + GLenum gettarget; + + if (textarget == GL_TEXTURE_2D) + gettarget = GL_TEXTURE_2D; + else + gettarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X; + + glBindTexture(textarget, tex->bindcode); + glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(gettarget, 0, GL_TEXTURE_HEIGHT, &h); + tex->w = w; + tex->h = h; + glBindTexture(textarget, 0); + } + + return tex; } GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap) { - GPUTexture *tex = prv->gputexture[0]; - GLuint bindcode = 0; - - if (tex) - bindcode = tex->bindcode; - - /* this binds a texture, so that's why we restore it to 0 */ - if (bindcode == 0) { - GPU_create_gl_tex(&bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL); - } - if (tex) { - tex->bindcode = bindcode; - glBindTexture(GL_TEXTURE_2D, 0); - return tex; - } - - tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); - tex->bindcode = bindcode; - tex->number = -1; - tex->refcount = 1; - tex->target = GL_TEXTURE_2D; - tex->target_base = GL_TEXTURE_2D; - tex->format = -1; - tex->components = -1; - - prv->gputexture[0] = tex; - - if (!glIsTexture(tex->bindcode)) { - GPU_print_error_debug("Blender Texture Not Loaded"); - } - else { - GLint w, h; - - glBindTexture(GL_TEXTURE_2D, tex->bindcode); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); - - tex->w = w; - tex->h = h; - } - - glBindTexture(GL_TEXTURE_2D, 0); - - return tex; - + GPUTexture *tex = prv->gputexture[0]; + GLuint bindcode = 0; + + if (tex) + bindcode = tex->bindcode; + + /* this binds a texture, so that's why we restore it to 0 */ + if (bindcode == 0) { + GPU_create_gl_tex( + &bindcode, prv->rect[0], NULL, prv->w[0], prv->h[0], GL_TEXTURE_2D, mipmap, 0, NULL); + } + if (tex) { + tex->bindcode = bindcode; + glBindTexture(GL_TEXTURE_2D, 0); + return tex; + } + + tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); + tex->bindcode = bindcode; + tex->number = -1; + tex->refcount = 1; + tex->target = GL_TEXTURE_2D; + tex->target_base = GL_TEXTURE_2D; + tex->format = -1; + tex->components = -1; + + prv->gputexture[0] = tex; + + if (!glIsTexture(tex->bindcode)) { + GPU_print_error_debug("Blender Texture Not Loaded"); + } + else { + GLint w, h; + + glBindTexture(GL_TEXTURE_2D, tex->bindcode); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); + + tex->w = w; + tex->h = h; + } + + glBindTexture(GL_TEXTURE_2D, 0); + + return tex; } -GPUTexture *GPU_texture_create_1d( - int w, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) +GPUTexture *GPU_texture_create_1d(int w, + eGPUTextureFormat tex_format, + const float *pixels, + char err_out[256]) { - BLI_assert(w > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, 0, 0, 1, pixels, tex_format, data_format, 0, false, err_out); + BLI_assert(w > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD(w, 0, 0, 1, pixels, tex_format, data_format, 0, false, err_out); } GPUTexture *GPU_texture_create_1d_array( - int w, int h, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) + int w, int h, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) { - BLI_assert(w > 0 && h > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, h, 0, 1, pixels, tex_format, data_format, 0, false, err_out); + BLI_assert(w > 0 && h > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD(w, h, 0, 1, pixels, tex_format, data_format, 0, false, err_out); } GPUTexture *GPU_texture_create_2d( - int w, int h, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) + int w, int h, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) { - BLI_assert(w > 0 && h > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, h, 0, 2, pixels, tex_format, data_format, 0, false, err_out); + BLI_assert(w > 0 && h > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD(w, h, 0, 2, pixels, tex_format, data_format, 0, false, err_out); } -GPUTexture *GPU_texture_create_2d_multisample( - int w, int h, eGPUTextureFormat tex_format, const float *pixels, int samples, char err_out[256]) +GPUTexture *GPU_texture_create_2d_multisample(int w, + int h, + eGPUTextureFormat tex_format, + const float *pixels, + int samples, + char err_out[256]) { - BLI_assert(w > 0 && h > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, h, 0, 2, pixels, tex_format, data_format, samples, false, err_out); + BLI_assert(w > 0 && h > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD( + w, h, 0, 2, pixels, tex_format, data_format, samples, false, err_out); } GPUTexture *GPU_texture_create_2d_array( - int w, int h, int d, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) + int w, int h, int d, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) { - BLI_assert(w > 0 && h > 0 && d > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, h, d, 2, pixels, tex_format, data_format, 0, false, err_out); + BLI_assert(w > 0 && h > 0 && d > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD(w, h, d, 2, pixels, tex_format, data_format, 0, false, err_out); } GPUTexture *GPU_texture_create_3d( - int w, int h, int d, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) + int w, int h, int d, eGPUTextureFormat tex_format, const float *pixels, char err_out[256]) { - BLI_assert(w > 0 && h > 0 && d > 0); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); - return GPU_texture_create_nD(w, h, d, 3, pixels, tex_format, data_format, 0, true, err_out); + BLI_assert(w > 0 && h > 0 && d > 0); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex_format); + return GPU_texture_create_nD(w, h, d, 3, pixels, tex_format, data_format, 0, true, err_out); } -GPUTexture *GPU_texture_create_cube( - int w, eGPUTextureFormat tex_format, const float *fpixels, char err_out[256]) +GPUTexture *GPU_texture_create_cube(int w, + eGPUTextureFormat tex_format, + const float *fpixels, + char err_out[256]) { - BLI_assert(w > 0); - const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz; - const int channels = gpu_get_component_count(tex_format); - - if (fpixels) { - int face_ofs = w * w * channels; - fpixels_px = fpixels + 0 * face_ofs; - fpixels_nx = fpixels + 1 * face_ofs; - fpixels_py = fpixels + 2 * face_ofs; - fpixels_ny = fpixels + 3 * face_ofs; - fpixels_pz = fpixels + 4 * face_ofs; - fpixels_nz = fpixels + 5 * face_ofs; - } - else { - fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL; - } - - return GPU_texture_cube_create(w, 0, fpixels_px, fpixels_py, fpixels_pz, fpixels_nx, fpixels_ny, fpixels_nz, - tex_format, GPU_DATA_FLOAT, err_out); + BLI_assert(w > 0); + const float *fpixels_px, *fpixels_py, *fpixels_pz, *fpixels_nx, *fpixels_ny, *fpixels_nz; + const int channels = gpu_get_component_count(tex_format); + + if (fpixels) { + int face_ofs = w * w * channels; + fpixels_px = fpixels + 0 * face_ofs; + fpixels_nx = fpixels + 1 * face_ofs; + fpixels_py = fpixels + 2 * face_ofs; + fpixels_ny = fpixels + 3 * face_ofs; + fpixels_pz = fpixels + 4 * face_ofs; + fpixels_nz = fpixels + 5 * face_ofs; + } + else { + fpixels_px = fpixels_py = fpixels_pz = fpixels_nx = fpixels_ny = fpixels_nz = NULL; + } + + return GPU_texture_cube_create(w, + 0, + fpixels_px, + fpixels_py, + fpixels_pz, + fpixels_nx, + fpixels_ny, + fpixels_nz, + tex_format, + GPU_DATA_FLOAT, + err_out); } GPUTexture *GPU_texture_create_from_vertbuf(GPUVertBuf *vert) { - GPUVertFormat *format = &vert->format; - GPUVertAttr *attr = &format->attrs[0]; - - /* Detect incompatible cases (not supported by texture buffers) */ - BLI_assert(format->attr_len == 1 && vert->vbo_id != 0); - BLI_assert(attr->comp_len != 3); /* Not until OGL 4.0 */ - BLI_assert(attr->comp_type != GPU_COMP_I10); - BLI_assert(attr->fetch_mode != GPU_FETCH_INT_TO_FLOAT); - - uint byte_per_comp = attr->sz / attr->comp_len; - bool is_uint = ELEM(attr->comp_type, GPU_COMP_U8, GPU_COMP_U16, GPU_COMP_U32); - - /* Cannot fetch signed int or 32bit ints as normalized float. */ - if (attr->fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT) { - BLI_assert(is_uint || byte_per_comp <= 2); - } - - eGPUTextureFormat data_type; - switch (attr->fetch_mode) { - case GPU_FETCH_FLOAT: - switch (attr->comp_len) { - case 1: data_type = GPU_R32F; break; - case 2: data_type = GPU_RG32F; break; - // case 3: data_type = GPU_RGB32F; break; /* Not supported */ - default: data_type = GPU_RGBA32F; break; - } - break; - case GPU_FETCH_INT: - switch (attr->comp_len) { - case 1: - switch (byte_per_comp) { - case 1: data_type = (is_uint) ? GPU_R8UI : GPU_R8I; break; - case 2: data_type = (is_uint) ? GPU_R16UI : GPU_R16I; break; - default: data_type = (is_uint) ? GPU_R32UI : GPU_R32I; break; - } - break; - case 2: - switch (byte_per_comp) { - case 1: data_type = (is_uint) ? GPU_RG8UI : GPU_RG8I; break; - case 2: data_type = (is_uint) ? GPU_RG16UI : GPU_RG16I; break; - default: data_type = (is_uint) ? GPU_RG32UI : GPU_RG32I; break; - } - break; - default: - switch (byte_per_comp) { - case 1: data_type = (is_uint) ? GPU_RGBA8UI : GPU_RGBA8I; break; - case 2: data_type = (is_uint) ? GPU_RGBA16UI : GPU_RGBA16I; break; - default: data_type = (is_uint) ? GPU_RGBA32UI : GPU_RGBA32I; break; - } - break; - } - break; - case GPU_FETCH_INT_TO_FLOAT_UNIT: - switch (attr->comp_len) { - case 1: data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; break; - case 2: data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; break; - default: data_type = (byte_per_comp == 1) ? GPU_RGBA8 : GPU_RGBA16; break; - } - break; - default: - BLI_assert(0); - return NULL; - } - - return GPU_texture_create_buffer(data_type, vert->vbo_id); + GPUVertFormat *format = &vert->format; + GPUVertAttr *attr = &format->attrs[0]; + + /* Detect incompatible cases (not supported by texture buffers) */ + BLI_assert(format->attr_len == 1 && vert->vbo_id != 0); + BLI_assert(attr->comp_len != 3); /* Not until OGL 4.0 */ + BLI_assert(attr->comp_type != GPU_COMP_I10); + BLI_assert(attr->fetch_mode != GPU_FETCH_INT_TO_FLOAT); + + uint byte_per_comp = attr->sz / attr->comp_len; + bool is_uint = ELEM(attr->comp_type, GPU_COMP_U8, GPU_COMP_U16, GPU_COMP_U32); + + /* Cannot fetch signed int or 32bit ints as normalized float. */ + if (attr->fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT) { + BLI_assert(is_uint || byte_per_comp <= 2); + } + + eGPUTextureFormat data_type; + switch (attr->fetch_mode) { + case GPU_FETCH_FLOAT: + switch (attr->comp_len) { + case 1: + data_type = GPU_R32F; + break; + case 2: + data_type = GPU_RG32F; + break; + // case 3: data_type = GPU_RGB32F; break; /* Not supported */ + default: + data_type = GPU_RGBA32F; + break; + } + break; + case GPU_FETCH_INT: + switch (attr->comp_len) { + case 1: + switch (byte_per_comp) { + case 1: + data_type = (is_uint) ? GPU_R8UI : GPU_R8I; + break; + case 2: + data_type = (is_uint) ? GPU_R16UI : GPU_R16I; + break; + default: + data_type = (is_uint) ? GPU_R32UI : GPU_R32I; + break; + } + break; + case 2: + switch (byte_per_comp) { + case 1: + data_type = (is_uint) ? GPU_RG8UI : GPU_RG8I; + break; + case 2: + data_type = (is_uint) ? GPU_RG16UI : GPU_RG16I; + break; + default: + data_type = (is_uint) ? GPU_RG32UI : GPU_RG32I; + break; + } + break; + default: + switch (byte_per_comp) { + case 1: + data_type = (is_uint) ? GPU_RGBA8UI : GPU_RGBA8I; + break; + case 2: + data_type = (is_uint) ? GPU_RGBA16UI : GPU_RGBA16I; + break; + default: + data_type = (is_uint) ? GPU_RGBA32UI : GPU_RGBA32I; + break; + } + break; + } + break; + case GPU_FETCH_INT_TO_FLOAT_UNIT: + switch (attr->comp_len) { + case 1: + data_type = (byte_per_comp == 1) ? GPU_R8 : GPU_R16; + break; + case 2: + data_type = (byte_per_comp == 1) ? GPU_RG8 : GPU_RG16; + break; + default: + data_type = (byte_per_comp == 1) ? GPU_RGBA8 : GPU_RGBA16; + break; + } + break; + default: + BLI_assert(0); + return NULL; + } + + return GPU_texture_create_buffer(data_type, vert->vbo_id); } -void GPU_texture_add_mipmap( - GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl, const void *pixels) +void GPU_texture_add_mipmap(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + int miplvl, + const void *pixels) { - BLI_assert((int)tex->format > -1); - BLI_assert(tex->components > -1); - - gpu_validate_data_format(tex->format, gpu_data_format); - - GLenum internalformat = gpu_get_gl_internalformat(tex->format); - GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - - glBindTexture(tex->target, tex->bindcode); - - int size[3]; - GPU_texture_get_mipmap_size(tex, miplvl, size); - - switch (tex->target) { - case GL_TEXTURE_1D: - glTexImage1D(tex->target, miplvl, internalformat, size[0], 0, data_format, data_type, pixels); - break; - case GL_TEXTURE_2D: - case GL_TEXTURE_1D_ARRAY: - glTexImage2D(tex->target, miplvl, internalformat, size[0], size[1], 0, data_format, data_type, pixels); - break; - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - glTexImage3D(tex->target, miplvl, internalformat, size[0], size[1], size[2], 0, data_format, data_type, pixels); - break; - case GL_TEXTURE_2D_MULTISAMPLE: - /* Multisample textures cannot have mipmaps. */ - default: - BLI_assert(!"tex->target mode not supported"); - } - - glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, miplvl); - - glBindTexture(tex->target, 0); + BLI_assert((int)tex->format > -1); + BLI_assert(tex->components > -1); + + gpu_validate_data_format(tex->format, gpu_data_format); + + GLenum internalformat = gpu_get_gl_internalformat(tex->format); + GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + + glBindTexture(tex->target, tex->bindcode); + + int size[3]; + GPU_texture_get_mipmap_size(tex, miplvl, size); + + switch (tex->target) { + case GL_TEXTURE_1D: + glTexImage1D( + tex->target, miplvl, internalformat, size[0], 0, data_format, data_type, pixels); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_1D_ARRAY: + glTexImage2D(tex->target, + miplvl, + internalformat, + size[0], + size[1], + 0, + data_format, + data_type, + pixels); + break; + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + glTexImage3D(tex->target, + miplvl, + internalformat, + size[0], + size[1], + size[2], + 0, + data_format, + data_type, + pixels); + break; + case GL_TEXTURE_2D_MULTISAMPLE: + /* Multisample textures cannot have mipmaps. */ + default: + BLI_assert(!"tex->target mode not supported"); + } + + glTexParameteri(GPU_texture_target(tex), GL_TEXTURE_MAX_LEVEL, miplvl); + + glBindTexture(tex->target, 0); } -void GPU_texture_update_sub( - GPUTexture *tex, eGPUDataFormat gpu_data_format, const void *pixels, - int offset_x, int offset_y, int offset_z, int width, int height, int depth) +void GPU_texture_update_sub(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + const void *pixels, + int offset_x, + int offset_y, + int offset_z, + int width, + int height, + int depth) { - BLI_assert((int)tex->format > -1); - BLI_assert(tex->components > -1); - - GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - GLint alignment; - - /* The default pack size for textures is 4, which won't work for byte based textures */ - if (tex->bytesize == 1) { - glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } - - glBindTexture(tex->target, tex->bindcode); - switch (tex->target) { - case GL_TEXTURE_1D: - glTexSubImage1D(tex->target, 0, offset_x, width, data_format, data_type, pixels); - break; - case GL_TEXTURE_2D: - case GL_TEXTURE_2D_MULTISAMPLE: - case GL_TEXTURE_1D_ARRAY: - glTexSubImage2D( - tex->target, 0, offset_x, offset_y, - width, height, data_format, data_type, pixels); - break; - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY: - glTexSubImage3D( - tex->target, 0, offset_x, offset_y, offset_z, - width, height, depth, data_format, data_type, pixels); - break; - default: - BLI_assert(!"tex->target mode not supported"); - } - - if (tex->bytesize == 1) { - glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); - } - - glBindTexture(tex->target, 0); + BLI_assert((int)tex->format > -1); + BLI_assert(tex->components > -1); + + GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + GLint alignment; + + /* The default pack size for textures is 4, which won't work for byte based textures */ + if (tex->bytesize == 1) { + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + } + + glBindTexture(tex->target, tex->bindcode); + switch (tex->target) { + case GL_TEXTURE_1D: + glTexSubImage1D(tex->target, 0, offset_x, width, data_format, data_type, pixels); + break; + case GL_TEXTURE_2D: + case GL_TEXTURE_2D_MULTISAMPLE: + case GL_TEXTURE_1D_ARRAY: + glTexSubImage2D( + tex->target, 0, offset_x, offset_y, width, height, data_format, data_type, pixels); + break; + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + glTexSubImage3D(tex->target, + 0, + offset_x, + offset_y, + offset_z, + width, + height, + depth, + data_format, + data_type, + pixels); + break; + default: + BLI_assert(!"tex->target mode not supported"); + } + + if (tex->bytesize == 1) { + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); + } + + glBindTexture(tex->target, 0); } void *GPU_texture_read(GPUTexture *tex, eGPUDataFormat gpu_data_format, int miplvl) { - int size[3] = {0, 0, 0}; - GPU_texture_get_mipmap_size(tex, miplvl, size); - - gpu_validate_data_format(tex->format, gpu_data_format); - - size_t buf_size = gpu_texture_memory_footprint_compute(tex); - size_t samples_count = max_ii(1, tex->samples); - - samples_count *= size[0]; - samples_count *= max_ii(1, size[1]); - samples_count *= max_ii(1, size[2]); - samples_count *= (GPU_texture_cube(tex)) ? 6 : 1; - - switch (gpu_data_format) { - case GPU_DATA_FLOAT: - buf_size = sizeof(float) * samples_count * tex->components; - break; - case GPU_DATA_INT: - case GPU_DATA_UNSIGNED_INT: - buf_size = sizeof(int) * samples_count * tex->components; - break; - case GPU_DATA_UNSIGNED_INT_24_8: - case GPU_DATA_10_11_11_REV: - buf_size = sizeof(int) * samples_count; - break; - case GPU_DATA_UNSIGNED_BYTE: - break; - } - - void *buf = MEM_mallocN(buf_size, "GPU_texture_read"); - - GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - - glBindTexture(tex->target, tex->bindcode); - - if (GPU_texture_cube(tex)) { - int cube_face_size = buf_size / 6; - for (int i = 0; i < 6; ++i) { - glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, miplvl, data_format, data_type, - ((char *)buf) + cube_face_size * i); - } - } - else { - glGetTexImage(tex->target, miplvl, data_format, data_type, buf); - } - - glBindTexture(tex->target, 0); - - return buf; + int size[3] = {0, 0, 0}; + GPU_texture_get_mipmap_size(tex, miplvl, size); + + gpu_validate_data_format(tex->format, gpu_data_format); + + size_t buf_size = gpu_texture_memory_footprint_compute(tex); + size_t samples_count = max_ii(1, tex->samples); + + samples_count *= size[0]; + samples_count *= max_ii(1, size[1]); + samples_count *= max_ii(1, size[2]); + samples_count *= (GPU_texture_cube(tex)) ? 6 : 1; + + switch (gpu_data_format) { + case GPU_DATA_FLOAT: + buf_size = sizeof(float) * samples_count * tex->components; + break; + case GPU_DATA_INT: + case GPU_DATA_UNSIGNED_INT: + buf_size = sizeof(int) * samples_count * tex->components; + break; + case GPU_DATA_UNSIGNED_INT_24_8: + case GPU_DATA_10_11_11_REV: + buf_size = sizeof(int) * samples_count; + break; + case GPU_DATA_UNSIGNED_BYTE: + break; + } + + void *buf = MEM_mallocN(buf_size, "GPU_texture_read"); + + GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + + glBindTexture(tex->target, tex->bindcode); + + if (GPU_texture_cube(tex)) { + int cube_face_size = buf_size / 6; + for (int i = 0; i < 6; ++i) { + glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, + miplvl, + data_format, + data_type, + ((char *)buf) + cube_face_size * i); + } + } + else { + glGetTexImage(tex->target, miplvl, data_format, data_type, buf); + } + + glBindTexture(tex->target, 0); + + return buf; } -void GPU_texture_read_rect( - GPUTexture *tex, eGPUDataFormat gpu_data_format, - const rcti *rect, void *r_buf) +void GPU_texture_read_rect(GPUTexture *tex, + eGPUDataFormat gpu_data_format, + const rcti *rect, + void *r_buf) { - gpu_validate_data_format(tex->format, gpu_data_format); - - GPUFrameBuffer *cur_fb = GPU_framebuffer_active_get(); - GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); - GPU_framebuffer_texture_attach(tmp_fb, tex, 0, 0); - - GPU_framebuffer_bind(tmp_fb); - glReadBuffer(GL_COLOR_ATTACHMENT0); - - GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); - GLenum data_type = gpu_get_gl_datatype(gpu_data_format); - - glReadPixels(rect->xmin, rect->ymin, - BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), - data_format, data_type, r_buf); - - if (cur_fb) { - GPU_framebuffer_bind(cur_fb); - } - else { - GPU_framebuffer_restore(); - } - GPU_framebuffer_free(tmp_fb); + gpu_validate_data_format(tex->format, gpu_data_format); + + GPUFrameBuffer *cur_fb = GPU_framebuffer_active_get(); + GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); + GPU_framebuffer_texture_attach(tmp_fb, tex, 0, 0); + + GPU_framebuffer_bind(tmp_fb); + glReadBuffer(GL_COLOR_ATTACHMENT0); + + GLenum data_format = gpu_get_gl_dataformat(tex->format, &tex->format_flag); + GLenum data_type = gpu_get_gl_datatype(gpu_data_format); + + glReadPixels(rect->xmin, + rect->ymin, + BLI_rcti_size_x(rect), + BLI_rcti_size_y(rect), + data_format, + data_type, + r_buf); + + if (cur_fb) { + GPU_framebuffer_bind(cur_fb); + } + else { + GPU_framebuffer_restore(); + } + GPU_framebuffer_free(tmp_fb); } void GPU_texture_update(GPUTexture *tex, eGPUDataFormat data_format, const void *pixels) { - GPU_texture_update_sub(tex, data_format, pixels, 0, 0, 0, tex->w, tex->h, tex->d); + GPU_texture_update_sub(tex, data_format, pixels, 0, 0, 0, tex->w, tex->h, tex->d); } void GPU_invalid_tex_init(void) { - memory_usage = 0; - const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; - GG.invalid_tex_1D = GPU_texture_create_1d(1, GPU_RGBA8, color, NULL); - GG.invalid_tex_2D = GPU_texture_create_2d(1, 1, GPU_RGBA8, color, NULL); - GG.invalid_tex_3D = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, color, NULL); + memory_usage = 0; + const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f}; + GG.invalid_tex_1D = GPU_texture_create_1d(1, GPU_RGBA8, color, NULL); + GG.invalid_tex_2D = GPU_texture_create_2d(1, 1, GPU_RGBA8, color, NULL); + GG.invalid_tex_3D = GPU_texture_create_3d(1, 1, 1, GPU_RGBA8, color, NULL); } void GPU_invalid_tex_bind(int mode) { - switch (mode) { - case GL_TEXTURE_1D: - glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode); - break; - case GL_TEXTURE_2D: - glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode); - break; - case GL_TEXTURE_3D: - glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode); - break; - } + switch (mode) { + case GL_TEXTURE_1D: + glBindTexture(GL_TEXTURE_1D, GG.invalid_tex_1D->bindcode); + break; + case GL_TEXTURE_2D: + glBindTexture(GL_TEXTURE_2D, GG.invalid_tex_2D->bindcode); + break; + case GL_TEXTURE_3D: + glBindTexture(GL_TEXTURE_3D, GG.invalid_tex_3D->bindcode); + break; + } } void GPU_invalid_tex_free(void) { - if (GG.invalid_tex_1D) - GPU_texture_free(GG.invalid_tex_1D); - if (GG.invalid_tex_2D) - GPU_texture_free(GG.invalid_tex_2D); - if (GG.invalid_tex_3D) - GPU_texture_free(GG.invalid_tex_3D); + if (GG.invalid_tex_1D) + GPU_texture_free(GG.invalid_tex_1D); + if (GG.invalid_tex_2D) + GPU_texture_free(GG.invalid_tex_2D); + if (GG.invalid_tex_3D) + GPU_texture_free(GG.invalid_tex_3D); } void GPU_texture_bind(GPUTexture *tex, int number) { - BLI_assert(number >= 0); - - if (number >= GPU_max_textures()) { - fprintf(stderr, "Not enough texture slots.\n"); - return; - } - - if ((G.debug & G_DEBUG)) { - for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { - if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) { - fprintf(stderr, - "Feedback loop warning!: Attempting to bind " - "texture attached to current framebuffer!\n"); - BLI_assert(0); /* Should never happen! */ - break; - } - } - } - - glActiveTexture(GL_TEXTURE0 + number); - - if (tex->bindcode != 0) - glBindTexture(tex->target, tex->bindcode); - else - GPU_invalid_tex_bind(tex->target_base); - - tex->number = number; + BLI_assert(number >= 0); + + if (number >= GPU_max_textures()) { + fprintf(stderr, "Not enough texture slots.\n"); + return; + } + + if ((G.debug & G_DEBUG)) { + for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { + if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) { + fprintf(stderr, + "Feedback loop warning!: Attempting to bind " + "texture attached to current framebuffer!\n"); + BLI_assert(0); /* Should never happen! */ + break; + } + } + } + + glActiveTexture(GL_TEXTURE0 + number); + + if (tex->bindcode != 0) + glBindTexture(tex->target, tex->bindcode); + else + GPU_invalid_tex_bind(tex->target_base); + + tex->number = number; } void GPU_texture_unbind(GPUTexture *tex) { - if (tex->number == -1) - return; + if (tex->number == -1) + return; - glActiveTexture(GL_TEXTURE0 + tex->number); - glBindTexture(tex->target, 0); + glActiveTexture(GL_TEXTURE0 + tex->number); + glBindTexture(tex->target, 0); - tex->number = -1; + tex->number = -1; } int GPU_texture_bound_number(GPUTexture *tex) { - return tex->number; + return tex->number; } -#define WARN_NOT_BOUND(_tex) { \ - if (_tex->number == -1) { \ - fprintf(stderr, "Warning : Trying to set parameter on a texture not bound.\n"); \ - BLI_assert(0); \ - return; \ - } \ -} ((void)0) +#define WARN_NOT_BOUND(_tex) \ + { \ + if (_tex->number == -1) { \ + fprintf(stderr, "Warning : Trying to set parameter on a texture not bound.\n"); \ + BLI_assert(0); \ + return; \ + } \ + } \ + ((void)0) void GPU_texture_generate_mipmap(GPUTexture *tex) { - WARN_NOT_BOUND(tex); - - glActiveTexture(GL_TEXTURE0 + tex->number); - - if (GPU_texture_depth(tex)) { - /* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789). - * In this case we just create a complete texture with mipmaps manually without downsampling. - * You must initialize the texture levels using other methods like GPU_framebuffer_recursive_downsample(). */ - int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); - eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); - for (int i = 1; i < levels; ++i) { - GPU_texture_add_mipmap(tex, data_format, i, NULL); - } - glBindTexture(tex->target, tex->bindcode); - } - else { - glGenerateMipmap(tex->target_base); - } + WARN_NOT_BOUND(tex); + + glActiveTexture(GL_TEXTURE0 + tex->number); + + if (GPU_texture_depth(tex)) { + /* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789). + * In this case we just create a complete texture with mipmaps manually without downsampling. + * You must initialize the texture levels using other methods like GPU_framebuffer_recursive_downsample(). */ + int levels = 1 + floor(log2(max_ii(tex->w, tex->h))); + eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format); + for (int i = 1; i < levels; ++i) { + GPU_texture_add_mipmap(tex, data_format, i, NULL); + } + glBindTexture(tex->target, tex->bindcode); + } + else { + glGenerateMipmap(tex->target_base); + } } void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare) { - WARN_NOT_BOUND(tex); + WARN_NOT_BOUND(tex); - /* Could become an assertion ? (fclem) */ - if (!GPU_texture_depth(tex)) - return; + /* Could become an assertion ? (fclem) */ + if (!GPU_texture_depth(tex)) + return; - GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE; + GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE; - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode); + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode); } void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter) { - WARN_NOT_BOUND(tex); + WARN_NOT_BOUND(tex); - /* Stencil and integer format does not support filtering. */ - BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); + /* Stencil and integer format does not support filtering. */ + BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; + GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter); + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter); } void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter) { - WARN_NOT_BOUND(tex); + WARN_NOT_BOUND(tex); - /* Stencil and integer format does not support filtering. */ - BLI_assert((!use_filter && !use_mipmap) || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); + /* Stencil and integer format does not support filtering. */ + BLI_assert((!use_filter && !use_mipmap) || + !(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; - GLenum mipmap = ( - (use_filter) ? - (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR : - (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST); + GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST; + GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR : + (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST); - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter); } void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat) { - WARN_NOT_BOUND(tex); + WARN_NOT_BOUND(tex); - GLenum repeat = (use_repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE; + GLenum repeat = (use_repeat) ? GL_REPEAT : GL_CLAMP_TO_EDGE; - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat); - if (tex->target_base != GL_TEXTURE_1D) - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat); - if (tex->target_base == GL_TEXTURE_3D) - glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat); + if (tex->target_base != GL_TEXTURE_1D) + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat); + if (tex->target_base == GL_TEXTURE_3D) + glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat); } static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter) { - switch (filter) { - case GPU_NEAREST: - return GL_NEAREST; - case GPU_LINEAR: - return GL_LINEAR; - default: - BLI_assert(!"Unhandled filter mode"); - return GL_NEAREST; - } + switch (filter) { + case GPU_NEAREST: + return GL_NEAREST; + case GPU_LINEAR: + return GL_LINEAR; + default: + BLI_assert(!"Unhandled filter mode"); + return GL_NEAREST; + } } -void GPU_texture_filters(GPUTexture *tex, eGPUFilterFunction min_filter, eGPUFilterFunction mag_filter) +void GPU_texture_filters(GPUTexture *tex, + eGPUFilterFunction min_filter, + eGPUFilterFunction mag_filter) { - WARN_NOT_BOUND(tex); + WARN_NOT_BOUND(tex); - /* Stencil and integer format does not support filtering. */ - BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); - BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR); + /* Stencil and integer format does not support filtering. */ + BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex))); + BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR); - glActiveTexture(GL_TEXTURE0 + tex->number); - glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter)); - glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); + glActiveTexture(GL_TEXTURE0 + tex->number); + glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter)); + glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter)); } void GPU_texture_free(GPUTexture *tex) { - tex->refcount--; + tex->refcount--; - if (tex->refcount < 0) - fprintf(stderr, "GPUTexture: negative refcount\n"); + if (tex->refcount < 0) + fprintf(stderr, "GPUTexture: negative refcount\n"); - if (tex->refcount == 0) { - for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { - if (tex->fb[i] != NULL) { - GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]); - } - } + if (tex->refcount == 0) { + for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { + if (tex->fb[i] != NULL) { + GPU_framebuffer_texture_detach_slot(tex->fb[i], tex, tex->fb_attachment[i]); + } + } - if (tex->bindcode) - GPU_tex_free(tex->bindcode); + if (tex->bindcode) + GPU_tex_free(tex->bindcode); - gpu_texture_memory_footprint_remove(tex); + gpu_texture_memory_footprint_remove(tex); - MEM_freeN(tex); - } + MEM_freeN(tex); + } } void GPU_texture_ref(GPUTexture *tex) { - tex->refcount++; + tex->refcount++; } int GPU_texture_target(const GPUTexture *tex) { - return tex->target; + return tex->target; } int GPU_texture_width(const GPUTexture *tex) { - return tex->w; + return tex->w; } int GPU_texture_height(const GPUTexture *tex) { - return tex->h; + return tex->h; } int GPU_texture_layers(const GPUTexture *tex) { - return tex->d; + return tex->d; } eGPUTextureFormat GPU_texture_format(const GPUTexture *tex) { - return tex->format; + return tex->format; } int GPU_texture_samples(const GPUTexture *tex) { - return tex->samples; + return tex->samples; } bool GPU_texture_depth(const GPUTexture *tex) { - return (tex->format_flag & GPU_FORMAT_DEPTH) != 0; + return (tex->format_flag & GPU_FORMAT_DEPTH) != 0; } bool GPU_texture_stencil(const GPUTexture *tex) { - return (tex->format_flag & GPU_FORMAT_STENCIL) != 0; + return (tex->format_flag & GPU_FORMAT_STENCIL) != 0; } bool GPU_texture_integer(const GPUTexture *tex) { - return (tex->format_flag & GPU_FORMAT_INTEGER) != 0; + return (tex->format_flag & GPU_FORMAT_INTEGER) != 0; } bool GPU_texture_cube(const GPUTexture *tex) { - return (tex->format_flag & GPU_FORMAT_CUBE) != 0; + return (tex->format_flag & GPU_FORMAT_CUBE) != 0; } int GPU_texture_opengl_bindcode(const GPUTexture *tex) { - return tex->bindcode; + return tex->bindcode; } void GPU_texture_attach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb, int attachment) { - for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { - if (tex->fb[i] == NULL) { - tex->fb[i] = fb; - tex->fb_attachment[i] = attachment; - return; - } - } - - BLI_assert(!"Error: Texture: Not enough Framebuffer slots"); + for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { + if (tex->fb[i] == NULL) { + tex->fb[i] = fb; + tex->fb_attachment[i] = attachment; + return; + } + } + + BLI_assert(!"Error: Texture: Not enough Framebuffer slots"); } /* Return previous attachment point */ int GPU_texture_detach_framebuffer(GPUTexture *tex, GPUFrameBuffer *fb) { - for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { - if (tex->fb[i] == fb) { - tex->fb[i] = NULL; - return tex->fb_attachment[i]; - } - } - - BLI_assert(!"Error: Texture: Framebuffer is not attached"); - return 0; + for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; ++i) { + if (tex->fb[i] == fb) { + tex->fb[i] = NULL; + return tex->fb_attachment[i]; + } + } + + BLI_assert(!"Error: Texture: Framebuffer is not attached"); + return 0; } void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size) { - /* TODO assert if lvl is below the limit of 1px in each dimension. */ - int div = 1 << lvl; - size[0] = max_ii(1, tex->w / div); - - if (tex->target == GL_TEXTURE_1D_ARRAY) { - size[1] = tex->h; - } - else if (tex->h > 0) { - size[1] = max_ii(1, tex->h / div); - } - - if (tex->target == GL_TEXTURE_2D_ARRAY) { - size[2] = tex->d; - } - else if (tex->d > 0) { - size[2] = max_ii(1, tex->d / div); - } + /* TODO assert if lvl is below the limit of 1px in each dimension. */ + int div = 1 << lvl; + size[0] = max_ii(1, tex->w / div); + + if (tex->target == GL_TEXTURE_1D_ARRAY) { + size[1] = tex->h; + } + else if (tex->h > 0) { + size[1] = max_ii(1, tex->h / div); + } + + if (tex->target == GL_TEXTURE_2D_ARRAY) { + size[2] = tex->d; + } + else if (tex->d > 0) { + size[2] = max_ii(1, tex->d / div); + } } diff --git a/source/blender/gpu/intern/gpu_uniformbuffer.c b/source/blender/gpu/intern/gpu_uniformbuffer.c index a5559b2558a..651e3c1aaa7 100644 --- a/source/blender/gpu/intern/gpu_uniformbuffer.c +++ b/source/blender/gpu/intern/gpu_uniformbuffer.c @@ -35,28 +35,28 @@ #include "GPU_uniformbuffer.h" typedef enum eGPUUniformBufferFlag { - GPU_UBO_FLAG_INITIALIZED = (1 << 0), - GPU_UBO_FLAG_DIRTY = (1 << 1), + GPU_UBO_FLAG_INITIALIZED = (1 << 0), + GPU_UBO_FLAG_DIRTY = (1 << 1), } eGPUUniformBufferFlag; typedef enum eGPUUniformBufferType { - GPU_UBO_STATIC = 0, - GPU_UBO_DYNAMIC = 1, + GPU_UBO_STATIC = 0, + GPU_UBO_DYNAMIC = 1, } eGPUUniformBufferType; struct GPUUniformBuffer { - int size; /* in bytes */ - GLuint bindcode; /* opengl identifier for UBO */ - int bindpoint; /* current binding point */ - eGPUUniformBufferType type; + int size; /* in bytes */ + GLuint bindcode; /* opengl identifier for UBO */ + int bindpoint; /* current binding point */ + eGPUUniformBufferType type; }; #define GPUUniformBufferStatic GPUUniformBuffer typedef struct GPUUniformBufferDynamic { - GPUUniformBuffer buffer; - void *data; /* Continuous memory block to copy to GPU. */ - char flag; + GPUUniformBuffer buffer; + void *data; /* Continuous memory block to copy to GPU. */ + char flag; } GPUUniformBufferDynamic; /* Prototypes */ @@ -69,38 +69,38 @@ static void gpu_uniformbuffer_inputs_sort(struct ListBase *inputs); static void gpu_uniformbuffer_initialize(GPUUniformBuffer *ubo, const void *data) { - glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); - glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW); - glBindBuffer(GL_UNIFORM_BUFFER, 0); + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferData(GL_UNIFORM_BUFFER, ubo->size, data, GL_DYNAMIC_DRAW); + glBindBuffer(GL_UNIFORM_BUFFER, 0); } GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_out[256]) { - GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic"); - ubo->size = size; - ubo->bindpoint = -1; - - /* Generate Buffer object */ - ubo->bindcode = GPU_buf_alloc(); - - if (!ubo->bindcode) { - if (err_out) { - BLI_strncpy(err_out, "GPUUniformBuffer: UBO create failed", 256); - } - GPU_uniformbuffer_free(ubo); - return NULL; - } - - if (ubo->size > GPU_max_ubo_size()) { - if (err_out) { - BLI_strncpy(err_out, "GPUUniformBuffer: UBO too big", 256); - } - GPU_uniformbuffer_free(ubo); - return NULL; - } - - gpu_uniformbuffer_initialize(ubo, data); - return ubo; + GPUUniformBuffer *ubo = MEM_callocN(sizeof(GPUUniformBufferStatic), "GPUUniformBufferStatic"); + ubo->size = size; + ubo->bindpoint = -1; + + /* Generate Buffer object */ + ubo->bindcode = GPU_buf_alloc(); + + if (!ubo->bindcode) { + if (err_out) { + BLI_strncpy(err_out, "GPUUniformBuffer: UBO create failed", 256); + } + GPU_uniformbuffer_free(ubo); + return NULL; + } + + if (ubo->size > GPU_max_ubo_size()) { + if (err_out) { + BLI_strncpy(err_out, "GPUUniformBuffer: UBO too big", 256); + } + GPU_uniformbuffer_free(ubo); + return NULL; + } + + gpu_uniformbuffer_initialize(ubo, data); + return ubo; } /** @@ -111,59 +111,60 @@ GPUUniformBuffer *GPU_uniformbuffer_create(int size, const void *data, char err_ */ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_out[256]) { - /* There is no point on creating an UBO if there is no arguments. */ - if (BLI_listbase_is_empty(inputs)) { - return NULL; - } - - GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), "GPUUniformBufferDynamic"); - ubo->buffer.type = GPU_UBO_DYNAMIC; - ubo->buffer.bindpoint = -1; - ubo->flag = GPU_UBO_FLAG_DIRTY; - - /* Generate Buffer object. */ - ubo->buffer.bindcode = GPU_buf_alloc(); - - if (!ubo->buffer.bindcode) { - if (err_out) { - BLI_strncpy(err_out, "GPUUniformBuffer: UBO create failed", 256); - } - GPU_uniformbuffer_free(&ubo->buffer); - return NULL; - } - - if (ubo->buffer.size > GPU_max_ubo_size()) { - if (err_out) { - BLI_strncpy(err_out, "GPUUniformBuffer: UBO too big", 256); - } - GPU_uniformbuffer_free(&ubo->buffer); - return NULL; - } - - /* Make sure we comply to the ubo alignment requirements. */ - gpu_uniformbuffer_inputs_sort(inputs); - - for (LinkData *link = inputs->first; link; link = link->next) { - const eGPUType gputype = get_padded_gpu_type(link); - ubo->buffer.size += gputype * sizeof(float); - } - - /* Allocate the data. */ - ubo->data = MEM_mallocN(ubo->buffer.size, __func__); - - /* Now that we know the total ubo size we can start populating it. */ - float *offset = ubo->data; - for (LinkData *link = inputs->first; link; link = link->next) { - GPUInput *input = link->data; - memcpy(offset, input->vec, input->type * sizeof(float)); - offset += get_padded_gpu_type(link); - } - - /* Note since we may create the UBOs in the CPU in a different thread than the main drawing one, - * we don't create the UBO in the GPU here. This will happen when we first bind the UBO. - */ - - return &ubo->buffer; + /* There is no point on creating an UBO if there is no arguments. */ + if (BLI_listbase_is_empty(inputs)) { + return NULL; + } + + GPUUniformBufferDynamic *ubo = MEM_callocN(sizeof(GPUUniformBufferDynamic), + "GPUUniformBufferDynamic"); + ubo->buffer.type = GPU_UBO_DYNAMIC; + ubo->buffer.bindpoint = -1; + ubo->flag = GPU_UBO_FLAG_DIRTY; + + /* Generate Buffer object. */ + ubo->buffer.bindcode = GPU_buf_alloc(); + + if (!ubo->buffer.bindcode) { + if (err_out) { + BLI_strncpy(err_out, "GPUUniformBuffer: UBO create failed", 256); + } + GPU_uniformbuffer_free(&ubo->buffer); + return NULL; + } + + if (ubo->buffer.size > GPU_max_ubo_size()) { + if (err_out) { + BLI_strncpy(err_out, "GPUUniformBuffer: UBO too big", 256); + } + GPU_uniformbuffer_free(&ubo->buffer); + return NULL; + } + + /* Make sure we comply to the ubo alignment requirements. */ + gpu_uniformbuffer_inputs_sort(inputs); + + for (LinkData *link = inputs->first; link; link = link->next) { + const eGPUType gputype = get_padded_gpu_type(link); + ubo->buffer.size += gputype * sizeof(float); + } + + /* Allocate the data. */ + ubo->data = MEM_mallocN(ubo->buffer.size, __func__); + + /* Now that we know the total ubo size we can start populating it. */ + float *offset = ubo->data; + for (LinkData *link = inputs->first; link; link = link->next) { + GPUInput *input = link->data; + memcpy(offset, input->vec, input->type * sizeof(float)); + offset += get_padded_gpu_type(link); + } + + /* Note since we may create the UBOs in the CPU in a different thread than the main drawing one, + * we don't create the UBO in the GPU here. This will happen when we first bind the UBO. + */ + + return &ubo->buffer; } /** @@ -171,36 +172,36 @@ GPUUniformBuffer *GPU_uniformbuffer_dynamic_create(ListBase *inputs, char err_ou */ static void gpu_uniformbuffer_dynamic_free(GPUUniformBuffer *ubo_) { - BLI_assert(ubo_->type == GPU_UBO_DYNAMIC); - GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_; + BLI_assert(ubo_->type == GPU_UBO_DYNAMIC); + GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_; - ubo->buffer.size = 0; - if (ubo->data) { - MEM_freeN(ubo->data); - } + ubo->buffer.size = 0; + if (ubo->data) { + MEM_freeN(ubo->data); + } } void GPU_uniformbuffer_free(GPUUniformBuffer *ubo) { - if (ubo->type == GPU_UBO_DYNAMIC) { - gpu_uniformbuffer_dynamic_free(ubo); - } + if (ubo->type == GPU_UBO_DYNAMIC) { + gpu_uniformbuffer_dynamic_free(ubo); + } - GPU_buf_free(ubo->bindcode); - MEM_freeN(ubo); + GPU_buf_free(ubo->bindcode); + MEM_freeN(ubo); } static 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); + glBindBuffer(GL_UNIFORM_BUFFER, ubo->bindcode); + glBufferSubData(GL_UNIFORM_BUFFER, 0, ubo->size, data); + glBindBuffer(GL_UNIFORM_BUFFER, 0); } void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) { - BLI_assert(ubo->type == GPU_UBO_STATIC); - gpu_uniformbuffer_update(ubo, data); + BLI_assert(ubo->type == GPU_UBO_STATIC); + gpu_uniformbuffer_update(ubo, data); } /** @@ -209,18 +210,18 @@ void GPU_uniformbuffer_update(GPUUniformBuffer *ubo, const void *data) */ void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_) { - BLI_assert(ubo_->type == GPU_UBO_DYNAMIC); - GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_; - - if (ubo->flag & GPU_UBO_FLAG_INITIALIZED) { - gpu_uniformbuffer_update(ubo_, ubo->data); - } - else { - ubo->flag |= GPU_UBO_FLAG_INITIALIZED; - gpu_uniformbuffer_initialize(ubo_, ubo->data); - } - - ubo->flag &= ~GPU_UBO_FLAG_DIRTY; + BLI_assert(ubo_->type == GPU_UBO_DYNAMIC); + GPUUniformBufferDynamic *ubo = (GPUUniformBufferDynamic *)ubo_; + + if (ubo->flag & GPU_UBO_FLAG_INITIALIZED) { + gpu_uniformbuffer_update(ubo_, ubo->data); + } + else { + ubo->flag |= GPU_UBO_FLAG_INITIALIZED; + gpu_uniformbuffer_initialize(ubo_, ubo->data); + } + + ubo->flag &= ~GPU_UBO_FLAG_DIRTY; } /** @@ -229,18 +230,16 @@ void GPU_uniformbuffer_dynamic_update(GPUUniformBuffer *ubo_) */ static eGPUType get_padded_gpu_type(LinkData *link) { - GPUInput *input = link->data; - eGPUType gputype = input->type; - - /* Unless the vec3 is followed by a float we need to treat it as a vec4. */ - if (gputype == GPU_VEC3 && - (link->next != NULL) && - (((GPUInput *)link->next->data)->type != GPU_FLOAT)) - { - gputype = GPU_VEC4; - } - - return gputype; + GPUInput *input = link->data; + eGPUType gputype = input->type; + + /* Unless the vec3 is followed by a float we need to treat it as a vec4. */ + if (gputype == GPU_VEC3 && (link->next != NULL) && + (((GPUInput *)link->next->data)->type != GPU_FLOAT)) { + gputype = GPU_VEC4; + } + + return gputype; } /** @@ -249,9 +248,9 @@ static eGPUType get_padded_gpu_type(LinkData *link) */ static int inputs_cmp(const void *a, const void *b) { - const LinkData *link_a = a, *link_b = b; - const GPUInput *input_a = link_a->data, *input_b = link_b->data; - return input_a->type < input_b->type ? 1 : 0; + const LinkData *link_a = a, *link_b = b; + const GPUInput *input_a = link_a->data, *input_b = link_b->data; + return input_a->type < input_b->type ? 1 : 0; } /** @@ -260,82 +259,80 @@ static int inputs_cmp(const void *a, const void *b) */ static void gpu_uniformbuffer_inputs_sort(ListBase *inputs) { - /* Order them as vec4, vec3, vec2, float. */ - BLI_listbase_sort(inputs, inputs_cmp); - - /* Creates a lookup table for the different types; */ - LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL}; - eGPUType cur_type = MAX_UBO_GPU_TYPE + 1; - - for (LinkData *link = inputs->first; link; link = link->next) { - GPUInput *input = link->data; - if (input->type == cur_type) { - continue; - } - else { - inputs_lookup[input->type] = link; - cur_type = input->type; - } - } - - /* If there is no GPU_VEC3 there is no need for alignment. */ - if (inputs_lookup[GPU_VEC3] == NULL) { - return; - } - - LinkData *link = inputs_lookup[GPU_VEC3]; - while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) { - LinkData *link_next = link->next; - - /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for alignment. */ - if ((link_next == NULL) || - ((GPUInput *)link_next->data)->type == GPU_FLOAT) - { - break; - } - - /* If there is a float, move it next to current vec3. */ - if (inputs_lookup[GPU_FLOAT] != NULL) { - LinkData *float_input = inputs_lookup[GPU_FLOAT]; - inputs_lookup[GPU_FLOAT] = float_input->next; - - BLI_remlink(inputs, float_input); - BLI_insertlinkafter(inputs, link, float_input); - } - - link = link_next; - } + /* Order them as vec4, vec3, vec2, float. */ + BLI_listbase_sort(inputs, inputs_cmp); + + /* Creates a lookup table for the different types; */ + LinkData *inputs_lookup[MAX_UBO_GPU_TYPE + 1] = {NULL}; + eGPUType cur_type = MAX_UBO_GPU_TYPE + 1; + + for (LinkData *link = inputs->first; link; link = link->next) { + GPUInput *input = link->data; + if (input->type == cur_type) { + continue; + } + else { + inputs_lookup[input->type] = link; + cur_type = input->type; + } + } + + /* If there is no GPU_VEC3 there is no need for alignment. */ + if (inputs_lookup[GPU_VEC3] == NULL) { + return; + } + + LinkData *link = inputs_lookup[GPU_VEC3]; + while (link != NULL && ((GPUInput *)link->data)->type == GPU_VEC3) { + LinkData *link_next = link->next; + + /* If GPU_VEC3 is followed by nothing or a GPU_FLOAT, no need for alignment. */ + if ((link_next == NULL) || ((GPUInput *)link_next->data)->type == GPU_FLOAT) { + break; + } + + /* If there is a float, move it next to current vec3. */ + if (inputs_lookup[GPU_FLOAT] != NULL) { + LinkData *float_input = inputs_lookup[GPU_FLOAT]; + inputs_lookup[GPU_FLOAT] = float_input->next; + + BLI_remlink(inputs, float_input); + BLI_insertlinkafter(inputs, link, float_input); + } + + link = link_next; + } } void GPU_uniformbuffer_bind(GPUUniformBuffer *ubo, int number) { - if (number >= GPU_max_ubo_binds()) { - fprintf(stderr, "Not enough UBO slots.\n"); - return; - } - - if (ubo->type == GPU_UBO_DYNAMIC) { - GPUUniformBufferDynamic *ubo_dynamic = (GPUUniformBufferDynamic *)ubo; - if (ubo_dynamic->flag & GPU_UBO_FLAG_DIRTY) { - GPU_uniformbuffer_dynamic_update(ubo); - } - } - - if (ubo->bindcode != 0) { - glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode); - } - - ubo->bindpoint = number; + if (number >= GPU_max_ubo_binds()) { + fprintf(stderr, "Not enough UBO slots.\n"); + return; + } + + if (ubo->type == GPU_UBO_DYNAMIC) { + GPUUniformBufferDynamic *ubo_dynamic = (GPUUniformBufferDynamic *)ubo; + if (ubo_dynamic->flag & GPU_UBO_FLAG_DIRTY) { + GPU_uniformbuffer_dynamic_update(ubo); + } + } + + if (ubo->bindcode != 0) { + glBindBufferBase(GL_UNIFORM_BUFFER, number, ubo->bindcode); + } + + ubo->bindpoint = number; } void GPU_uniformbuffer_unbind(GPUUniformBuffer *ubo) { - ubo->bindpoint = -1; + ubo->bindpoint = -1; } int GPU_uniformbuffer_bindpoint(GPUUniformBuffer *ubo) { - return ubo->bindpoint; + return ubo->bindpoint; } #undef MAX_UBO_GPU_TYPE diff --git a/source/blender/gpu/intern/gpu_vertex_buffer.c b/source/blender/gpu/intern/gpu_vertex_buffer.c index dc6367308cd..f9823c18723 100644 --- a/source/blender/gpu/intern/gpu_vertex_buffer.c +++ b/source/blender/gpu/intern/gpu_vertex_buffer.c @@ -39,108 +39,110 @@ static uint vbo_memory_usage; static GLenum convert_usage_type_to_gl(GPUUsageType type) { - static const GLenum table[] = { - [GPU_USAGE_STREAM] = GL_STREAM_DRAW, - [GPU_USAGE_STATIC] = GL_STATIC_DRAW, - [GPU_USAGE_DYNAMIC] = GL_DYNAMIC_DRAW, - }; - return table[type]; + static const GLenum table[] = { + [GPU_USAGE_STREAM] = GL_STREAM_DRAW, + [GPU_USAGE_STATIC] = GL_STATIC_DRAW, + [GPU_USAGE_DYNAMIC] = GL_DYNAMIC_DRAW, + }; + return table[type]; } GPUVertBuf *GPU_vertbuf_create(GPUUsageType usage) { - GPUVertBuf *verts = MEM_mallocN(sizeof(GPUVertBuf), "GPUVertBuf"); - GPU_vertbuf_init(verts, usage); - return verts; + GPUVertBuf *verts = MEM_mallocN(sizeof(GPUVertBuf), "GPUVertBuf"); + GPU_vertbuf_init(verts, usage); + return verts; } GPUVertBuf *GPU_vertbuf_create_with_format_ex(const GPUVertFormat *format, GPUUsageType usage) { - GPUVertBuf *verts = GPU_vertbuf_create(usage); - GPU_vertformat_copy(&verts->format, format); - if (!format->packed) { - VertexFormat_pack(&verts->format); - } - return verts; - - /* this function might seem redundant, but there is potential for memory savings here... */ - /* TODO: implement those memory savings */ + GPUVertBuf *verts = GPU_vertbuf_create(usage); + GPU_vertformat_copy(&verts->format, format); + if (!format->packed) { + VertexFormat_pack(&verts->format); + } + return verts; + + /* this function might seem redundant, but there is potential for memory savings here... */ + /* TODO: implement those memory savings */ } void GPU_vertbuf_init(GPUVertBuf *verts, GPUUsageType usage) { - memset(verts, 0, sizeof(GPUVertBuf)); - verts->usage = usage; - verts->dirty = true; + memset(verts, 0, sizeof(GPUVertBuf)); + verts->usage = usage; + verts->dirty = true; } -void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, const GPUVertFormat *format, GPUUsageType usage) +void GPU_vertbuf_init_with_format_ex(GPUVertBuf *verts, + const GPUVertFormat *format, + GPUUsageType usage) { - GPU_vertbuf_init(verts, usage); - GPU_vertformat_copy(&verts->format, format); - if (!format->packed) { - VertexFormat_pack(&verts->format); - } + GPU_vertbuf_init(verts, usage); + GPU_vertformat_copy(&verts->format, format); + if (!format->packed) { + VertexFormat_pack(&verts->format); + } } void GPU_vertbuf_discard(GPUVertBuf *verts) { - if (verts->vbo_id) { - GPU_buf_free(verts->vbo_id); + if (verts->vbo_id) { + GPU_buf_free(verts->vbo_id); #if VRAM_USAGE - vbo_memory_usage -= GPU_vertbuf_size_get(verts); + vbo_memory_usage -= GPU_vertbuf_size_get(verts); #endif - } - if (verts->data) { - MEM_freeN(verts->data); - } - MEM_freeN(verts); + } + if (verts->data) { + MEM_freeN(verts->data); + } + MEM_freeN(verts); } uint GPU_vertbuf_size_get(const GPUVertBuf *verts) { - return vertex_buffer_size(&verts->format, verts->vertex_len); + return vertex_buffer_size(&verts->format, verts->vertex_len); } /* create a new allocation, discarding any existing data */ void GPU_vertbuf_data_alloc(GPUVertBuf *verts, uint v_len) { - GPUVertFormat *format = &verts->format; - if (!format->packed) { - VertexFormat_pack(format); - } + GPUVertFormat *format = &verts->format; + if (!format->packed) { + VertexFormat_pack(format); + } #if TRUST_NO_ONE - /* catch any unnecessary use */ - assert(verts->vertex_alloc != v_len || verts->data == NULL); + /* catch any unnecessary use */ + assert(verts->vertex_alloc != v_len || verts->data == NULL); #endif - /* discard previous data if any */ - if (verts->data) { - MEM_freeN(verts->data); - } + /* discard previous data if any */ + if (verts->data) { + MEM_freeN(verts->data); + } #if VRAM_USAGE - uint new_size = vertex_buffer_size(&verts->format, v_len); - vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); + uint new_size = vertex_buffer_size(&verts->format, v_len); + vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); #endif - verts->dirty = true; - verts->vertex_len = verts->vertex_alloc = v_len; - verts->data = MEM_mallocN(sizeof(GLubyte) * GPU_vertbuf_size_get(verts), "GPUVertBuf data"); + verts->dirty = true; + verts->vertex_len = verts->vertex_alloc = v_len; + verts->data = MEM_mallocN(sizeof(GLubyte) * GPU_vertbuf_size_get(verts), "GPUVertBuf data"); } /* resize buffer keeping existing data */ void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len) { #if TRUST_NO_ONE - assert(verts->data != NULL); - assert(verts->vertex_alloc != v_len); + assert(verts->data != NULL); + assert(verts->vertex_alloc != v_len); #endif #if VRAM_USAGE - uint new_size = vertex_buffer_size(&verts->format, v_len); - vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); + uint new_size = vertex_buffer_size(&verts->format, v_len); + vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); #endif - verts->dirty = true; - verts->vertex_len = verts->vertex_alloc = v_len; - verts->data = MEM_reallocN(verts->data, sizeof(GLubyte) * GPU_vertbuf_size_get(verts)); + verts->dirty = true; + verts->vertex_len = verts->vertex_alloc = v_len; + verts->data = MEM_reallocN(verts->data, sizeof(GLubyte) * GPU_vertbuf_size_get(verts)); } /* Set vertex count but does not change allocation. @@ -149,118 +151,120 @@ void GPU_vertbuf_data_resize(GPUVertBuf *verts, uint v_len) void GPU_vertbuf_data_len_set(GPUVertBuf *verts, uint v_len) { #if TRUST_NO_ONE - assert(verts->data != NULL); /* only for dynamic data */ - assert(v_len <= verts->vertex_alloc); + assert(verts->data != NULL); /* only for dynamic data */ + assert(v_len <= verts->vertex_alloc); #endif #if VRAM_USAGE - uint new_size = vertex_buffer_size(&verts->format, v_len); - vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); + uint new_size = vertex_buffer_size(&verts->format, v_len); + vbo_memory_usage += new_size - GPU_vertbuf_size_get(verts); #endif - verts->vertex_len = v_len; + verts->vertex_len = v_len; } void GPU_vertbuf_attr_set(GPUVertBuf *verts, uint a_idx, uint v_idx, const void *data) { - const GPUVertFormat *format = &verts->format; - const GPUVertAttr *a = &format->attrs[a_idx]; + const GPUVertFormat *format = &verts->format; + const GPUVertAttr *a = &format->attrs[a_idx]; #if TRUST_NO_ONE - assert(a_idx < format->attr_len); - assert(v_idx < verts->vertex_alloc); - assert(verts->data != NULL); + assert(a_idx < format->attr_len); + assert(v_idx < verts->vertex_alloc); + assert(verts->data != NULL); #endif - verts->dirty = true; - memcpy((GLubyte *)verts->data + a->offset + v_idx * format->stride, data, a->sz); + verts->dirty = true; + memcpy((GLubyte *)verts->data + a->offset + v_idx * format->stride, data, a->sz); } void GPU_vertbuf_attr_fill(GPUVertBuf *verts, uint a_idx, const void *data) { - const GPUVertFormat *format = &verts->format; - const GPUVertAttr *a = &format->attrs[a_idx]; + const GPUVertFormat *format = &verts->format; + const GPUVertAttr *a = &format->attrs[a_idx]; #if TRUST_NO_ONE - assert(a_idx < format->attr_len); + assert(a_idx < format->attr_len); #endif - const uint stride = a->sz; /* tightly packed input data */ + const uint stride = a->sz; /* tightly packed input data */ - GPU_vertbuf_attr_fill_stride(verts, a_idx, stride, data); + GPU_vertbuf_attr_fill_stride(verts, a_idx, stride, data); } void GPU_vertbuf_attr_fill_stride(GPUVertBuf *verts, uint a_idx, uint stride, const void *data) { - const GPUVertFormat *format = &verts->format; - const GPUVertAttr *a = &format->attrs[a_idx]; + const GPUVertFormat *format = &verts->format; + const GPUVertAttr *a = &format->attrs[a_idx]; #if TRUST_NO_ONE - assert(a_idx < format->attr_len); - assert(verts->data != NULL); + assert(a_idx < format->attr_len); + assert(verts->data != NULL); #endif - verts->dirty = true; - const uint vertex_len = verts->vertex_len; - - if (format->attr_len == 1 && stride == format->stride) { - /* we can copy it all at once */ - memcpy(verts->data, data, vertex_len * a->sz); - } - else { - /* we must copy it per vertex */ - for (uint v = 0; v < vertex_len; ++v) { - memcpy((GLubyte *)verts->data + a->offset + v * format->stride, (const GLubyte *)data + v * stride, a->sz); - } - } + verts->dirty = true; + const uint vertex_len = verts->vertex_len; + + if (format->attr_len == 1 && stride == format->stride) { + /* we can copy it all at once */ + memcpy(verts->data, data, vertex_len * a->sz); + } + else { + /* we must copy it per vertex */ + for (uint v = 0; v < vertex_len; ++v) { + memcpy((GLubyte *)verts->data + a->offset + v * format->stride, + (const GLubyte *)data + v * stride, + a->sz); + } + } } void GPU_vertbuf_attr_get_raw_data(GPUVertBuf *verts, uint a_idx, GPUVertBufRaw *access) { - const GPUVertFormat *format = &verts->format; - const GPUVertAttr *a = &format->attrs[a_idx]; + const GPUVertFormat *format = &verts->format; + const GPUVertAttr *a = &format->attrs[a_idx]; #if TRUST_NO_ONE - assert(a_idx < format->attr_len); - assert(verts->data != NULL); + assert(a_idx < format->attr_len); + assert(verts->data != NULL); #endif - verts->dirty = true; + verts->dirty = true; - access->size = a->sz; - access->stride = format->stride; - access->data = (GLubyte *)verts->data + a->offset; - access->data_init = access->data; + access->size = a->sz; + access->stride = format->stride; + access->data = (GLubyte *)verts->data + a->offset; + access->data_init = access->data; #if TRUST_NO_ONE - access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride); + access->_data_end = access->data_init + (size_t)(verts->vertex_alloc * format->stride); #endif } static void VertBuffer_upload_data(GPUVertBuf *verts) { - uint buffer_sz = GPU_vertbuf_size_get(verts); - - /* orphan the vbo to avoid sync */ - glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage)); - /* upload data */ - glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); - - if (verts->usage == GPU_USAGE_STATIC) { - MEM_freeN(verts->data); - verts->data = NULL; - } - verts->dirty = false; + uint buffer_sz = GPU_vertbuf_size_get(verts); + + /* orphan the vbo to avoid sync */ + glBufferData(GL_ARRAY_BUFFER, buffer_sz, NULL, convert_usage_type_to_gl(verts->usage)); + /* upload data */ + glBufferSubData(GL_ARRAY_BUFFER, 0, buffer_sz, verts->data); + + if (verts->usage == GPU_USAGE_STATIC) { + MEM_freeN(verts->data); + verts->data = NULL; + } + verts->dirty = false; } void GPU_vertbuf_use(GPUVertBuf *verts) { - /* only create the buffer the 1st time */ - if (verts->vbo_id == 0) { - verts->vbo_id = GPU_buf_alloc(); - } - glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); - if (verts->dirty) { - VertBuffer_upload_data(verts); - } + /* only create the buffer the 1st time */ + if (verts->vbo_id == 0) { + verts->vbo_id = GPU_buf_alloc(); + } + glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); + if (verts->dirty) { + VertBuffer_upload_data(verts); + } } uint GPU_vertbuf_get_memory_usage(void) { - return vbo_memory_usage; + return vbo_memory_usage; } diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c index d4b975a01ae..388773afbbc 100644 --- a/source/blender/gpu/intern/gpu_vertex_format.c +++ b/source/blender/gpu/intern/gpu_vertex_format.c @@ -41,439 +41,453 @@ void GPU_vertformat_clear(GPUVertFormat *format) { #if TRUST_NO_ONE - memset(format, 0, sizeof(GPUVertFormat)); + memset(format, 0, sizeof(GPUVertFormat)); #else - format->attr_len = 0; - format->packed = false; - format->name_offset = 0; - format->name_len = 0; - - for (uint i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) { - format->attrs[i].name_len = 0; - } + format->attr_len = 0; + format->packed = false; + format->name_offset = 0; + format->name_len = 0; + + for (uint i = 0; i < GPU_VERT_ATTR_MAX_LEN; i++) { + format->attrs[i].name_len = 0; + } #endif } void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src) { - /* copy regular struct fields */ - memcpy(dest, src, sizeof(GPUVertFormat)); - - for (uint i = 0; i < dest->attr_len; i++) { - for (uint j = 0; j < dest->attrs[i].name_len; j++) { - dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src)); - } - } + /* copy regular struct fields */ + memcpy(dest, src, sizeof(GPUVertFormat)); + + for (uint i = 0; i < dest->attr_len; i++) { + for (uint j = 0; j < dest->attrs[i].name_len; j++) { + dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src)); + } + } } static GLenum convert_comp_type_to_gl(GPUVertCompType type) { - static const GLenum table[] = { - [GPU_COMP_I8] = GL_BYTE, - [GPU_COMP_U8] = GL_UNSIGNED_BYTE, - [GPU_COMP_I16] = GL_SHORT, - [GPU_COMP_U16] = GL_UNSIGNED_SHORT, - [GPU_COMP_I32] = GL_INT, - [GPU_COMP_U32] = GL_UNSIGNED_INT, - - [GPU_COMP_F32] = GL_FLOAT, - - [GPU_COMP_I10] = GL_INT_2_10_10_10_REV, - }; - return table[type]; + static const GLenum table[] = { + [GPU_COMP_I8] = GL_BYTE, + [GPU_COMP_U8] = GL_UNSIGNED_BYTE, + [GPU_COMP_I16] = GL_SHORT, + [GPU_COMP_U16] = GL_UNSIGNED_SHORT, + [GPU_COMP_I32] = GL_INT, + [GPU_COMP_U32] = GL_UNSIGNED_INT, + + [GPU_COMP_F32] = GL_FLOAT, + + [GPU_COMP_I10] = GL_INT_2_10_10_10_REV, + }; + return table[type]; } static uint comp_sz(GPUVertCompType type) { #if TRUST_NO_ONE - assert(type <= GPU_COMP_F32); /* other types have irregular sizes (not bytes) */ + assert(type <= GPU_COMP_F32); /* other types have irregular sizes (not bytes) */ #endif - const GLubyte sizes[] = {1, 1, 2, 2, 4, 4, 4}; - return sizes[type]; + const GLubyte sizes[] = {1, 1, 2, 2, 4, 4, 4}; + return sizes[type]; } static uint attr_sz(const GPUVertAttr *a) { - if (a->comp_type == GPU_COMP_I10) { - return 4; /* always packed as 10_10_10_2 */ - } - return a->comp_len * comp_sz(a->comp_type); + if (a->comp_type == GPU_COMP_I10) { + return 4; /* always packed as 10_10_10_2 */ + } + return a->comp_len * comp_sz(a->comp_type); } static uint attr_align(const GPUVertAttr *a) { - if (a->comp_type == GPU_COMP_I10) { - return 4; /* always packed as 10_10_10_2 */ - } - uint c = comp_sz(a->comp_type); - if (a->comp_len == 3 && c <= 2) { - return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */ - } - else { - return c; /* most fetches are ok if components are naturally aligned */ - } + if (a->comp_type == GPU_COMP_I10) { + return 4; /* always packed as 10_10_10_2 */ + } + uint c = comp_sz(a->comp_type); + if (a->comp_len == 3 && c <= 2) { + return 4 * c; /* AMD HW can't fetch these well, so pad it out (other vendors too?) */ + } + else { + return c; /* most fetches are ok if components are naturally aligned */ + } } uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len) { #if TRUST_NO_ONE - assert(format->packed && format->stride > 0); + assert(format->packed && format->stride > 0); #endif - return format->stride * vertex_len; + return format->stride * vertex_len; } static const char *copy_attr_name(GPUVertFormat *format, const char *name, const char *suffix) { - /* strncpy does 110% of what we need; let's do exactly 100% */ - char *name_copy = format->names + format->name_offset; - uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset; - bool terminated = false; - - for (uint i = 0; i < available; ++i) { - const char c = name[i]; - name_copy[i] = c; - if (c == '\0') { - if (suffix) { - for (uint j = 0; j < available; ++j) { - const char s = suffix[j]; - name_copy[i + j] = s; - if (s == '\0') { - terminated = true; - format->name_offset += (i + j + 1); - break; - } - } - } - else { - terminated = true; - format->name_offset += (i + 1); - } - break; - } - } + /* strncpy does 110% of what we need; let's do exactly 100% */ + char *name_copy = format->names + format->name_offset; + uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset; + bool terminated = false; + + for (uint i = 0; i < available; ++i) { + const char c = name[i]; + name_copy[i] = c; + if (c == '\0') { + if (suffix) { + for (uint j = 0; j < available; ++j) { + const char s = suffix[j]; + name_copy[i + j] = s; + if (s == '\0') { + terminated = true; + format->name_offset += (i + j + 1); + break; + } + } + } + else { + terminated = true; + format->name_offset += (i + 1); + } + break; + } + } #if TRUST_NO_ONE - assert(terminated); - assert(format->name_offset <= GPU_VERT_ATTR_NAMES_BUF_LEN); + assert(terminated); + assert(format->name_offset <= GPU_VERT_ATTR_NAMES_BUF_LEN); #else - (void)terminated; + (void)terminated; #endif - return name_copy; + return name_copy; } -uint GPU_vertformat_attr_add( - GPUVertFormat *format, const char *name, - GPUVertCompType comp_type, uint comp_len, GPUVertFetchMode fetch_mode) +uint GPU_vertformat_attr_add(GPUVertFormat *format, + const char *name, + GPUVertCompType comp_type, + uint comp_len, + GPUVertFetchMode fetch_mode) { #if TRUST_NO_ONE - assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ - assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ - assert(!format->packed); /* packed means frozen/locked */ - assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16); - - switch (comp_type) { - case GPU_COMP_F32: - /* float type can only kept as float */ - assert(fetch_mode == GPU_FETCH_FLOAT); - break; - case GPU_COMP_I10: - /* 10_10_10 format intended for normals (xyz) or colors (rgb) - * extra component packed.w can be manually set to { -2, -1, 0, 1 } */ - assert(comp_len == 3 || comp_len == 4); - assert(fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT); /* not strictly required, may relax later */ - break; - default: - /* integer types can be kept as int or converted/normalized to float */ - assert(fetch_mode != GPU_FETCH_FLOAT); - /* only support float matrices (see Batch_update_program_bindings) */ - assert(comp_len != 8 && comp_len != 12 && comp_len != 16); - } + assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(format->attr_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(!format->packed); /* packed means frozen/locked */ + assert((comp_len >= 1 && comp_len <= 4) || comp_len == 8 || comp_len == 12 || comp_len == 16); + + switch (comp_type) { + case GPU_COMP_F32: + /* float type can only kept as float */ + assert(fetch_mode == GPU_FETCH_FLOAT); + break; + case GPU_COMP_I10: + /* 10_10_10 format intended for normals (xyz) or colors (rgb) + * extra component packed.w can be manually set to { -2, -1, 0, 1 } */ + assert(comp_len == 3 || comp_len == 4); + assert(fetch_mode == + GPU_FETCH_INT_TO_FLOAT_UNIT); /* not strictly required, may relax later */ + break; + default: + /* integer types can be kept as int or converted/normalized to float */ + assert(fetch_mode != GPU_FETCH_FLOAT); + /* only support float matrices (see Batch_update_program_bindings) */ + assert(comp_len != 8 && comp_len != 12 && comp_len != 16); + } #endif - format->name_len++; /* multiname support */ - - const uint attr_id = format->attr_len++; - GPUVertAttr *attr = &format->attrs[attr_id]; - - attr->name[attr->name_len++] = copy_attr_name(format, name, NULL); - attr->comp_type = comp_type; - attr->gl_comp_type = convert_comp_type_to_gl(comp_type); - attr->comp_len = (comp_type == GPU_COMP_I10) ? 4 : comp_len; /* system needs 10_10_10_2 to be 4 or BGRA */ - attr->sz = attr_sz(attr); - attr->offset = 0; /* offsets & stride are calculated later (during pack) */ - attr->fetch_mode = fetch_mode; - - return attr_id; + format->name_len++; /* multiname support */ + + const uint attr_id = format->attr_len++; + GPUVertAttr *attr = &format->attrs[attr_id]; + + attr->name[attr->name_len++] = copy_attr_name(format, name, NULL); + attr->comp_type = comp_type; + attr->gl_comp_type = convert_comp_type_to_gl(comp_type); + attr->comp_len = (comp_type == GPU_COMP_I10) ? + 4 : + comp_len; /* system needs 10_10_10_2 to be 4 or BGRA */ + attr->sz = attr_sz(attr); + attr->offset = 0; /* offsets & stride are calculated later (during pack) */ + attr->fetch_mode = fetch_mode; + + return attr_id; } void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias) { - GPUVertAttr *attr = &format->attrs[format->attr_len - 1]; + GPUVertAttr *attr = &format->attrs[format->attr_len - 1]; #if TRUST_NO_ONE - assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ - assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); + assert(format->name_len < GPU_VERT_ATTR_MAX_LEN); /* there's room for more */ + assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); #endif - format->name_len++; /* multiname support */ - attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL); + format->name_len++; /* multiname support */ + attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL); } int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name) { - for (int i = 0; i < format->attr_len; i++) { - const GPUVertAttr *attr = &format->attrs[i]; - for (int j = 0; j < attr->name_len; j++) { - if (STREQ(name, attr->name[j])) { - return i; - } - } - } - return -1; + for (int i = 0; i < format->attr_len; i++) { + const GPUVertAttr *attr = &format->attrs[i]; + for (int j = 0; j < attr->name_len; j++) { + if (STREQ(name, attr->name[j])) { + return i; + } + } + } + return -1; } void GPU_vertformat_triple_load(GPUVertFormat *format) { #if TRUST_NO_ONE - assert(!format->packed); - assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); - assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); + assert(!format->packed); + assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); + assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN); #endif - VertexFormat_pack(format); - - uint old_attr_len = format->attr_len; - for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) { - GPUVertAttr *attr = &format->attrs[a_idx]; - /* Duplicate attr twice */ - for (int i = 1; i < 3; ++i) { - GPUVertAttr *dst_attr = &format->attrs[format->attr_len]; - memcpy(dst_attr, attr, sizeof(GPUVertAttr)); - /* Increase offset to the next vertex. */ - dst_attr->offset += format->stride * i; - /* Only copy first name for now. */ - dst_attr->name_len = 0; - dst_attr->name[dst_attr->name_len++] = copy_attr_name(format, attr->name[0], (i == 1) ? "1" : "2"); - format->attr_len++; - } + VertexFormat_pack(format); + + uint old_attr_len = format->attr_len; + for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) { + GPUVertAttr *attr = &format->attrs[a_idx]; + /* Duplicate attr twice */ + for (int i = 1; i < 3; ++i) { + GPUVertAttr *dst_attr = &format->attrs[format->attr_len]; + memcpy(dst_attr, attr, sizeof(GPUVertAttr)); + /* Increase offset to the next vertex. */ + dst_attr->offset += format->stride * i; + /* Only copy first name for now. */ + dst_attr->name_len = 0; + dst_attr->name[dst_attr->name_len++] = copy_attr_name( + format, attr->name[0], (i == 1) ? "1" : "2"); + format->attr_len++; + } #if TRUST_NO_ONE - assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); + assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES); #endif - /* Add alias to first attr. */ - format->name_len++; - attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0"); - } + /* Add alias to first attr. */ + format->name_len++; + attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0"); + } } uint padding(uint offset, uint alignment) { - const uint mod = offset % alignment; - return (mod == 0) ? 0 : (alignment - mod); + const uint mod = offset % alignment; + return (mod == 0) ? 0 : (alignment - mod); } #if PACK_DEBUG static void show_pack(uint a_idx, uint sz, uint pad) { - const char c = 'A' + a_idx; - for (uint i = 0; i < pad; ++i) { - putchar('-'); - } - for (uint i = 0; i < sz; ++i) { - putchar(c); - } + const char c = 'A' + a_idx; + for (uint i = 0; i < pad; ++i) { + putchar('-'); + } + for (uint i = 0; i < sz; ++i) { + putchar(c); + } } #endif void VertexFormat_pack(GPUVertFormat *format) { - /* For now, attributes are packed in the order they were added, - * making sure each attribute is naturally aligned (add padding where necessary) - * Later we can implement more efficient packing w/ reordering - * (keep attribute ID order, adjust their offsets to reorder in buffer). */ + /* For now, attributes are packed in the order they were added, + * making sure each attribute is naturally aligned (add padding where necessary) + * Later we can implement more efficient packing w/ reordering + * (keep attribute ID order, adjust their offsets to reorder in buffer). */ - /* TODO: realloc just enough to hold the final combo string. And just enough to - * hold used attributes, not all 16. */ + /* TODO: realloc just enough to hold the final combo string. And just enough to + * hold used attributes, not all 16. */ - GPUVertAttr *a0 = &format->attrs[0]; - a0->offset = 0; - uint offset = a0->sz; + GPUVertAttr *a0 = &format->attrs[0]; + a0->offset = 0; + uint offset = a0->sz; #if PACK_DEBUG - show_pack(0, a0->sz, 0); + show_pack(0, a0->sz, 0); #endif - for (uint a_idx = 1; a_idx < format->attr_len; ++a_idx) { - GPUVertAttr *a = &format->attrs[a_idx]; - uint mid_padding = padding(offset, attr_align(a)); - offset += mid_padding; - a->offset = offset; - offset += a->sz; + for (uint a_idx = 1; a_idx < format->attr_len; ++a_idx) { + GPUVertAttr *a = &format->attrs[a_idx]; + uint mid_padding = padding(offset, attr_align(a)); + offset += mid_padding; + a->offset = offset; + offset += a->sz; #if PACK_DEBUG - show_pack(a_idx, a->sz, mid_padding); + show_pack(a_idx, a->sz, mid_padding); #endif - } + } - uint end_padding = padding(offset, attr_align(a0)); + uint end_padding = padding(offset, attr_align(a0)); #if PACK_DEBUG - show_pack(0, 0, end_padding); - putchar('\n'); + show_pack(0, 0, end_padding); + putchar('\n'); #endif - format->stride = offset + end_padding; - format->packed = true; + format->stride = offset + end_padding; + format->packed = true; } static uint calc_input_component_size(const GPUShaderInput *input) { - int size = input->size; - switch (input->gl_type) { - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_UNSIGNED_INT_VEC2: - return size * 2; - case GL_FLOAT_VEC3: - case GL_INT_VEC3: - case GL_UNSIGNED_INT_VEC3: - return size * 3; - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_INT_VEC4: - case GL_UNSIGNED_INT_VEC4: - return size * 4; - case GL_FLOAT_MAT3: - return size * 9; - case GL_FLOAT_MAT4: - return size * 16; - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT3x2: - return size * 6; - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT4x2: - return size * 8; - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x3: - return size * 12; - default: - return size; - } + int size = input->size; + switch (input->gl_type) { + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + return size * 2; + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + return size * 3; + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + return size * 4; + case GL_FLOAT_MAT3: + return size * 9; + case GL_FLOAT_MAT4: + return size * 16; + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return size * 6; + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT4x2: + return size * 8; + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + return size * 12; + default: + return size; + } } -static void get_fetch_mode_and_comp_type( - int gl_type, - GPUVertCompType *r_comp_type, - uint *r_gl_comp_type, - GPUVertFetchMode *r_fetch_mode) +static void get_fetch_mode_and_comp_type(int gl_type, + GPUVertCompType *r_comp_type, + uint *r_gl_comp_type, + GPUVertFetchMode *r_fetch_mode) { - switch (gl_type) { - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - case GL_FLOAT_MAT2x3: - case GL_FLOAT_MAT2x4: - case GL_FLOAT_MAT3x2: - case GL_FLOAT_MAT3x4: - case GL_FLOAT_MAT4x2: - case GL_FLOAT_MAT4x3: - *r_comp_type = GPU_COMP_F32; - *r_gl_comp_type = GL_FLOAT; - *r_fetch_mode = GPU_FETCH_FLOAT; - break; - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - *r_comp_type = GPU_COMP_I32; - *r_gl_comp_type = GL_INT; - *r_fetch_mode = GPU_FETCH_INT; - break; - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_VEC2: - case GL_UNSIGNED_INT_VEC3: - case GL_UNSIGNED_INT_VEC4: - *r_comp_type = GPU_COMP_U32; - *r_gl_comp_type = GL_UNSIGNED_INT; - *r_fetch_mode = GPU_FETCH_INT; - break; - default: - BLI_assert(0); - } + switch (gl_type) { + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + *r_comp_type = GPU_COMP_F32; + *r_gl_comp_type = GL_FLOAT; + *r_fetch_mode = GPU_FETCH_FLOAT; + break; + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + *r_comp_type = GPU_COMP_I32; + *r_gl_comp_type = GL_INT; + *r_fetch_mode = GPU_FETCH_INT; + break; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + *r_comp_type = GPU_COMP_U32; + *r_gl_comp_type = GL_UNSIGNED_INT; + *r_fetch_mode = GPU_FETCH_INT; + break; + default: + BLI_assert(0); + } } void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface) { - const char *name_buffer = shaderface->name_buffer; - - for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) { - const GPUShaderInput *input = shaderface->attr_buckets[i]; - if (input == NULL) { - continue; - } - - const GPUShaderInput *next = input; - while (next != NULL) { - input = next; - next = input->next; - - format->name_len++; /* multiname support */ - format->attr_len++; - - GPUVertAttr *attr = &format->attrs[input->location]; - - attr->name[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset, NULL); - attr->offset = 0; /* offsets & stride are calculated later (during pack) */ - attr->comp_len = calc_input_component_size(input); - attr->sz = attr->comp_len * 4; - get_fetch_mode_and_comp_type(input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode); - } - } + const char *name_buffer = shaderface->name_buffer; + + for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) { + const GPUShaderInput *input = shaderface->attr_buckets[i]; + if (input == NULL) { + continue; + } + + const GPUShaderInput *next = input; + while (next != NULL) { + input = next; + next = input->next; + + format->name_len++; /* multiname support */ + format->attr_len++; + + GPUVertAttr *attr = &format->attrs[input->location]; + + attr->name[attr->name_len++] = copy_attr_name( + format, name_buffer + input->name_offset, NULL); + attr->offset = 0; /* offsets & stride are calculated later (during pack) */ + attr->comp_len = calc_input_component_size(input); + attr->sz = attr->comp_len * 4; + get_fetch_mode_and_comp_type( + input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode); + } + } } - /* OpenGL ES packs in a different order as desktop GL but component conversion is the same. * Of the code here, only struct GPUPackedNormal needs to change. */ -#define SIGNED_INT_10_MAX 511 +#define SIGNED_INT_10_MAX 511 #define SIGNED_INT_10_MIN -512 static int clampi(int x, int min_allowed, int max_allowed) { #if TRUST_NO_ONE - assert(min_allowed <= max_allowed); + assert(min_allowed <= max_allowed); #endif - if (x < min_allowed) { - return min_allowed; - } - else if (x > max_allowed) { - return max_allowed; - } - else { - return x; - } + if (x < min_allowed) { + return min_allowed; + } + else if (x > max_allowed) { + return max_allowed; + } + else { + return x; + } } static int quantize(float x) { - int qx = x * 511.0f; - return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX); + int qx = x * 511.0f; + return clampi(qx, SIGNED_INT_10_MIN, SIGNED_INT_10_MAX); } static int convert_i16(short x) { - /* 16-bit signed --> 10-bit signed */ - /* TODO: round? */ - return x >> 6; + /* 16-bit signed --> 10-bit signed */ + /* TODO: round? */ + return x >> 6; } GPUPackedNormal GPU_normal_convert_i10_v3(const float data[3]) { - GPUPackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]), }; - return n; + GPUPackedNormal n = { + .x = quantize(data[0]), + .y = quantize(data[1]), + .z = quantize(data[2]), + }; + return n; } GPUPackedNormal GPU_normal_convert_i10_s3(const short data[3]) { - GPUPackedNormal n = { .x = convert_i16(data[0]), .y = convert_i16(data[1]), .z = convert_i16(data[2]), }; - return n; + GPUPackedNormal n = { + .x = convert_i16(data[0]), + .y = convert_i16(data[1]), + .z = convert_i16(data[2]), + }; + return n; } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 9a39b724b6a..74c2959ee00 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -34,7 +34,6 @@ #include "DNA_vec_types.h" #include "DNA_userdef_types.h" - #include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_immediate.h" @@ -55,36 +54,39 @@ static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *) #define MAX_ENGINE_BUFFER_SHARING 5 typedef struct ViewportTempTexture { - struct ViewportTempTexture *next, *prev; - void *user[MAX_ENGINE_BUFFER_SHARING]; - GPUTexture *texture; + struct ViewportTempTexture *next, *prev; + void *user[MAX_ENGINE_BUFFER_SHARING]; + GPUTexture *texture; } ViewportTempTexture; struct GPUViewport { - int size[2]; - int samples; - int flag; + int size[2]; + int samples; + int flag; - ListBase data; /* ViewportEngineData wrapped in LinkData */ - uint data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */ + ListBase data; /* ViewportEngineData wrapped in LinkData */ + uint data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */ - DefaultFramebufferList *fbl; - DefaultTextureList *txl; + DefaultFramebufferList *fbl; + DefaultTextureList *txl; - ViewportMemoryPool vmempool; /* Used for rendering data structure. */ - struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */ + ViewportMemoryPool vmempool; /* Used for rendering data structure. */ + struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */ - ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */ + ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */ - /* Profiling data */ - double cache_time; + /* Profiling data */ + double cache_time; }; enum { - DO_UPDATE = (1 << 0), + DO_UPDATE = (1 << 0), }; -static void gpu_viewport_buffers_free(FramebufferList *fbl, int fbl_len, TextureList *txl, int txl_len); +static void gpu_viewport_buffers_free(FramebufferList *fbl, + int fbl_len, + TextureList *txl, + int txl_len); static void gpu_viewport_storage_free(StorageList *stl, int stl_len); static void gpu_viewport_passes_free(PassList *psl, int psl_len); static void gpu_viewport_texture_pool_free(GPUViewport *viewport); @@ -92,174 +94,173 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport); void GPU_viewport_tag_update(GPUViewport *viewport) { - viewport->flag |= DO_UPDATE; + viewport->flag |= DO_UPDATE; } bool GPU_viewport_do_update(GPUViewport *viewport) { - bool ret = (viewport->flag & DO_UPDATE); - viewport->flag &= ~DO_UPDATE; - return ret; + bool ret = (viewport->flag & DO_UPDATE); + viewport->flag &= ~DO_UPDATE; + return ret; } GPUViewport *GPU_viewport_create(void) { - GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); - viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList"); - viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList"); - viewport->idatalist = DRW_instance_data_list_create(); + GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); + viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList"); + viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList"); + viewport->idatalist = DRW_instance_data_list_create(); - viewport->size[0] = viewport->size[1] = -1; + viewport->size[0] = viewport->size[1] = -1; - return viewport; + return viewport; } GPUViewport *GPU_viewport_create_from_offscreen(struct GPUOffScreen *ofs) { - GPUViewport *viewport = GPU_viewport_create(); - GPUTexture *color, *depth; - GPUFrameBuffer *fb; - viewport->size[0] = GPU_offscreen_width(ofs); - viewport->size[1] = GPU_offscreen_height(ofs); - - GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); - - if (GPU_texture_samples(color)) { - viewport->txl->multisample_color = color; - viewport->txl->multisample_depth = depth; - viewport->fbl->multisample_fb = fb; - gpu_viewport_default_fb_create(viewport); - } - else { - viewport->fbl->default_fb = fb; - viewport->txl->color = color; - viewport->txl->depth = depth; - GPU_framebuffer_ensure_config(&viewport->fbl->color_only_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(viewport->txl->color) - }); - GPU_framebuffer_ensure_config(&viewport->fbl->depth_only_fb, { - GPU_ATTACHMENT_TEXTURE(viewport->txl->depth), - GPU_ATTACHMENT_NONE - }); - } - - return viewport; + GPUViewport *viewport = GPU_viewport_create(); + GPUTexture *color, *depth; + GPUFrameBuffer *fb; + viewport->size[0] = GPU_offscreen_width(ofs); + viewport->size[1] = GPU_offscreen_height(ofs); + + GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); + + if (GPU_texture_samples(color)) { + viewport->txl->multisample_color = color; + viewport->txl->multisample_depth = depth; + viewport->fbl->multisample_fb = fb; + gpu_viewport_default_fb_create(viewport); + } + else { + viewport->fbl->default_fb = fb; + viewport->txl->color = color; + viewport->txl->depth = depth; + GPU_framebuffer_ensure_config( + &viewport->fbl->color_only_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(viewport->txl->color)}); + GPU_framebuffer_ensure_config( + &viewport->fbl->depth_only_fb, + {GPU_ATTACHMENT_TEXTURE(viewport->txl->depth), GPU_ATTACHMENT_NONE}); + } + + return viewport; } /** * Clear vars assigned from offscreen, so we don't free data owned by `GPUOffScreen`. */ void GPU_viewport_clear_from_offscreen(GPUViewport *viewport) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - - if (dfbl->multisample_fb) { - /* GPUViewport expect the final result to be in default_fb but - * GPUOffscreen wants it in its multisample_fb, so we sync it back. */ - GPU_framebuffer_blit(dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); - dfbl->multisample_fb = NULL; - dtxl->multisample_color = NULL; - dtxl->multisample_depth = NULL; - } - else { - viewport->fbl->default_fb = NULL; - dtxl->color = NULL; - dtxl->depth = NULL; - } + DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; + + if (dfbl->multisample_fb) { + /* GPUViewport expect the final result to be in default_fb but + * GPUOffscreen wants it in its multisample_fb, so we sync it back. */ + GPU_framebuffer_blit( + dfbl->default_fb, 0, dfbl->multisample_fb, 0, GPU_COLOR_BIT | GPU_DEPTH_BIT); + dfbl->multisample_fb = NULL; + dtxl->multisample_color = NULL; + dtxl->multisample_depth = NULL; + } + else { + viewport->fbl->default_fb = NULL; + dtxl->color = NULL; + dtxl->depth = NULL; + } } void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) { - LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData"); - ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); - int fbl_len, txl_len, psl_len, stl_len; + LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData"); + ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); + int fbl_len, txl_len, psl_len, stl_len; - DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); + DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); - data->engine_type = engine_type; + data->engine_type = engine_type; - data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList"); - data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList"); - data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList"); - data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList"); + data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList"); + data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList"); + data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList"); + data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList"); - ld->data = data; - BLI_addtail(&viewport->data, ld); + ld->data = data; + BLI_addtail(&viewport->data, ld); - return data; + return data; } static void gpu_viewport_engines_data_free(GPUViewport *viewport) { - int fbl_len, txl_len, psl_len, stl_len; + int fbl_len, txl_len, psl_len, stl_len; - LinkData *next; - for (LinkData *link = viewport->data.first; link; link = next) { - next = link->next; - ViewportEngineData *data = link->data; - DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); + LinkData *next; + for (LinkData *link = viewport->data.first; link; link = next) { + next = link->next; + ViewportEngineData *data = link->data; + DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); - gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); - gpu_viewport_passes_free(data->psl, psl_len); - gpu_viewport_storage_free(data->stl, stl_len); + gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); + gpu_viewport_passes_free(data->psl, psl_len); + gpu_viewport_storage_free(data->stl, stl_len); - MEM_freeN(data->fbl); - MEM_freeN(data->txl); - MEM_freeN(data->psl); - MEM_freeN(data->stl); + MEM_freeN(data->fbl); + MEM_freeN(data->txl); + MEM_freeN(data->psl); + MEM_freeN(data->stl); - /* We could handle this in the DRW module */ - if (data->text_draw_cache) { - extern void DRW_text_cache_destroy(struct DRWTextStore *dt); - DRW_text_cache_destroy(data->text_draw_cache); - data->text_draw_cache = NULL; - } + /* We could handle this in the DRW module */ + if (data->text_draw_cache) { + extern void DRW_text_cache_destroy(struct DRWTextStore * dt); + DRW_text_cache_destroy(data->text_draw_cache); + data->text_draw_cache = NULL; + } - MEM_freeN(data); + MEM_freeN(data); - BLI_remlink(&viewport->data, link); - MEM_freeN(link); - } + BLI_remlink(&viewport->data, link); + MEM_freeN(link); + } - gpu_viewport_texture_pool_free(viewport); + gpu_viewport_texture_pool_free(viewport); } void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type) { - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *vdata = link->data; - if (vdata->engine_type == engine_type) { - return vdata; - } - } - return NULL; + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *vdata = link->data; + if (vdata->engine_type == engine_type) { + return vdata; + } + } + return NULL; } ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport) { - return &viewport->vmempool; + return &viewport->vmempool; } struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport) { - return viewport->idatalist; + return viewport->idatalist; } void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport) { - return viewport->fbl; + return viewport->fbl; } void *GPU_viewport_texture_list_get(GPUViewport *viewport) { - return viewport->txl; + return viewport->txl; } void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) { - size[0] = viewport->size[0]; - size[1] = viewport->size[1]; + size[0] = viewport->size[0]; + size[1] = viewport->size[1]; } /** @@ -268,367 +269,370 @@ void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) */ void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]) { - viewport->size[0] = size[0]; - viewport->size[1] = size[1]; + viewport->size[0] = size[0]; + viewport->size[1] = size[1]; } double *GPU_viewport_cache_time_get(GPUViewport *viewport) { - return &viewport->cache_time; + return &viewport->cache_time; } /** * Try to find a texture corresponding to params into the texture pool. * If no texture was found, create one and add it to the pool. */ -GPUTexture *GPU_viewport_texture_pool_query(GPUViewport *viewport, void *engine, int width, int height, int format) +GPUTexture *GPU_viewport_texture_pool_query( + GPUViewport *viewport, void *engine, int width, int height, int format) { - GPUTexture *tex; - - for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) { - if ((GPU_texture_format(tmp_tex->texture) == format) && - (GPU_texture_width(tmp_tex->texture) == width) && - (GPU_texture_height(tmp_tex->texture) == height)) - { - /* Search if the engine is not already using this texture */ - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) { - if (tmp_tex->user[i] == engine) { - break; - } - - if (tmp_tex->user[i] == NULL) { - tmp_tex->user[i] = engine; - return tmp_tex->texture; - } - } - } - } - - tex = GPU_texture_create_2d(width, height, format, NULL, NULL); - GPU_texture_bind(tex, 0); - /* Doing filtering for depth does not make sense when not doing shadow mapping, - * and enabling texture filtering on integer texture make them unreadable. */ - bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex); - GPU_texture_filter_mode(tex, do_filter); - GPU_texture_unbind(tex); - - ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture"); - tmp_tex->texture = tex; - tmp_tex->user[0] = engine; - BLI_addtail(&viewport->tex_pool, tmp_tex); - - return tex; + GPUTexture *tex; + + for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) { + if ((GPU_texture_format(tmp_tex->texture) == format) && + (GPU_texture_width(tmp_tex->texture) == width) && + (GPU_texture_height(tmp_tex->texture) == height)) { + /* Search if the engine is not already using this texture */ + for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) { + if (tmp_tex->user[i] == engine) { + break; + } + + if (tmp_tex->user[i] == NULL) { + tmp_tex->user[i] = engine; + return tmp_tex->texture; + } + } + } + } + + tex = GPU_texture_create_2d(width, height, format, NULL, NULL); + GPU_texture_bind(tex, 0); + /* Doing filtering for depth does not make sense when not doing shadow mapping, + * and enabling texture filtering on integer texture make them unreadable. */ + bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex); + GPU_texture_filter_mode(tex, do_filter); + GPU_texture_unbind(tex); + + ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture"); + tmp_tex->texture = tex; + tmp_tex->user[0] = engine; + BLI_addtail(&viewport->tex_pool, tmp_tex); + + return tex; } static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport) { - ViewportTempTexture *tmp_tex_next; - - for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) { - tmp_tex_next = tmp_tex->next; - bool no_user = true; - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) { - if (tmp_tex->user[i] != NULL) { - tmp_tex->user[i] = NULL; - no_user = false; - } - } - - if (no_user) { - GPU_texture_free(tmp_tex->texture); - BLI_freelinkN(&viewport->tex_pool, tmp_tex); - } - } + ViewportTempTexture *tmp_tex_next; + + for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) { + tmp_tex_next = tmp_tex->next; + bool no_user = true; + for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; ++i) { + if (tmp_tex->user[i] != NULL) { + tmp_tex->user[i] = NULL; + no_user = false; + } + } + + if (no_user) { + GPU_texture_free(tmp_tex->texture); + BLI_freelinkN(&viewport->tex_pool, tmp_tex); + } + } } static void gpu_viewport_texture_pool_free(GPUViewport *viewport) { - for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) { - GPU_texture_free(tmp_tex->texture); - } + for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex->next) { + GPU_texture_free(tmp_tex->texture); + } - BLI_freelistN(&viewport->tex_pool); + BLI_freelistN(&viewport->tex_pool); } bool GPU_viewport_engines_data_validate(GPUViewport *viewport, uint hash) { - bool dirty = false; + bool dirty = false; - if (viewport->data_hash != hash) { - gpu_viewport_engines_data_free(viewport); - dirty = true; - } + if (viewport->data_hash != hash) { + gpu_viewport_engines_data_free(viewport); + dirty = true; + } - viewport->data_hash = hash; + viewport->data_hash = hash; - return dirty; + return dirty; } void GPU_viewport_cache_release(GPUViewport *viewport) { - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *data = link->data; - int psl_len; - DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL); - gpu_viewport_passes_free(data->psl, psl_len); - } + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + int psl_len; + DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL); + gpu_viewport_passes_free(data->psl, psl_len); + } } static void gpu_viewport_default_fb_create(GPUViewport *viewport) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - int *size = viewport->size; - bool ok = true; - - dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA8, NULL, NULL); - dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); - - if (!(dtxl->depth && dtxl->color)) { - ok = false; - goto cleanup; - } - - GPU_framebuffer_ensure_config(&dfbl->default_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_TEXTURE(dtxl->color) - }); - - GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->depth), - GPU_ATTACHMENT_NONE - }); - - GPU_framebuffer_ensure_config(&dfbl->color_only_fb, { - GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color) - }); - - ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); - ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); + DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; + int *size = viewport->size; + bool ok = true; + + dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA8, NULL, NULL); + dtxl->depth = GPU_texture_create_2d(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, NULL); + + if (!(dtxl->depth && dtxl->color)) { + ok = false; + goto cleanup; + } + + GPU_framebuffer_ensure_config( + &dfbl->default_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + + GPU_framebuffer_ensure_config(&dfbl->depth_only_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_NONE}); + + GPU_framebuffer_ensure_config(&dfbl->color_only_fb, + {GPU_ATTACHMENT_NONE, GPU_ATTACHMENT_TEXTURE(dtxl->color)}); + + ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL); cleanup: - if (!ok) { - GPU_viewport_free(viewport); - DRW_opengl_context_disable(); - return; - } + if (!ok) { + GPU_viewport_free(viewport); + DRW_opengl_context_disable(); + return; + } - GPU_framebuffer_restore(); + GPU_framebuffer_restore(); } static void gpu_viewport_default_multisample_fb_create(GPUViewport *viewport) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - int *size = viewport->size; - int samples = viewport->samples; - bool ok = true; + DefaultFramebufferList *dfbl = viewport->fbl; + DefaultTextureList *dtxl = viewport->txl; + int *size = viewport->size; + int samples = viewport->samples; + bool ok = true; - dtxl->multisample_color = GPU_texture_create_2d_multisample(size[0], size[1], GPU_RGBA8, NULL, samples, NULL); - dtxl->multisample_depth = GPU_texture_create_2d_multisample(size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, samples, NULL); + dtxl->multisample_color = GPU_texture_create_2d_multisample( + size[0], size[1], GPU_RGBA8, NULL, samples, NULL); + dtxl->multisample_depth = GPU_texture_create_2d_multisample( + size[0], size[1], GPU_DEPTH24_STENCIL8, NULL, samples, NULL); - if (!(dtxl->multisample_depth && dtxl->multisample_color)) { - ok = false; - goto cleanup; - } + if (!(dtxl->multisample_depth && dtxl->multisample_color)) { + ok = false; + goto cleanup; + } - GPU_framebuffer_ensure_config(&dfbl->multisample_fb, { - GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth), - GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color) - }); + GPU_framebuffer_ensure_config(&dfbl->multisample_fb, + {GPU_ATTACHMENT_TEXTURE(dtxl->multisample_depth), + GPU_ATTACHMENT_TEXTURE(dtxl->multisample_color)}); - ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL); + ok = ok && GPU_framebuffer_check_valid(dfbl->multisample_fb, NULL); cleanup: - if (!ok) { - GPU_viewport_free(viewport); - DRW_opengl_context_disable(); - return; - } + if (!ok) { + GPU_viewport_free(viewport); + DRW_opengl_context_disable(); + return; + } - GPU_framebuffer_restore(); + GPU_framebuffer_restore(); } void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) { - DefaultFramebufferList *dfbl = viewport->fbl; - int fbl_len, txl_len; - - /* add one pixel because of scissor test */ - int rect_w = BLI_rcti_size_x(rect) + 1; - int rect_h = BLI_rcti_size_y(rect) + 1; - - DRW_opengl_context_enable(); - - if (dfbl->default_fb) { - if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || U.ogl_multisamples != viewport->samples) { - gpu_viewport_buffers_free( - (FramebufferList *)viewport->fbl, default_fbl_len, - (TextureList *)viewport->txl, default_txl_len); - - for (LinkData *link = viewport->data.first; link; link = link->next) { - ViewportEngineData *data = link->data; - DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL); - gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); - } - - gpu_viewport_texture_pool_free(viewport); - } - } - - viewport->size[0] = rect_w; - viewport->size[1] = rect_h; - viewport->samples = U.ogl_multisamples; - - gpu_viewport_texture_pool_clear_users(viewport); - - /* Multisample Buffer */ - if (viewport->samples > 0) { - if (!dfbl->default_fb) { - gpu_viewport_default_multisample_fb_create(viewport); - } - } - - if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport); - } + DefaultFramebufferList *dfbl = viewport->fbl; + int fbl_len, txl_len; + + /* add one pixel because of scissor test */ + int rect_w = BLI_rcti_size_x(rect) + 1; + int rect_h = BLI_rcti_size_y(rect) + 1; + + DRW_opengl_context_enable(); + + if (dfbl->default_fb) { + if (rect_w != viewport->size[0] || rect_h != viewport->size[1] || + U.ogl_multisamples != viewport->samples) { + gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, + default_fbl_len, + (TextureList *)viewport->txl, + default_txl_len); + + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL); + gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len); + } + + gpu_viewport_texture_pool_free(viewport); + } + } + + viewport->size[0] = rect_w; + viewport->size[1] = rect_h; + viewport->samples = U.ogl_multisamples; + + gpu_viewport_texture_pool_clear_users(viewport); + + /* Multisample Buffer */ + if (viewport->samples > 0) { + if (!dfbl->default_fb) { + gpu_viewport_default_multisample_fb_create(viewport); + } + } + + if (!dfbl->default_fb) { + gpu_viewport_default_fb_create(viewport); + } } void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect) { - DefaultFramebufferList *dfbl = viewport->fbl; + DefaultFramebufferList *dfbl = viewport->fbl; - if (dfbl->default_fb == NULL) - return; + if (dfbl->default_fb == NULL) + return; - DefaultTextureList *dtxl = viewport->txl; + DefaultTextureList *dtxl = viewport->txl; - GPUTexture *color = dtxl->color; + GPUTexture *color = dtxl->color; - const float w = (float)GPU_texture_width(color); - const float h = (float)GPU_texture_height(color); + const float w = (float)GPU_texture_width(color); + const float h = (float)GPU_texture_height(color); - BLI_assert(w == BLI_rcti_size_x(rect) + 1); - BLI_assert(h == BLI_rcti_size_y(rect) + 1); + BLI_assert(w == BLI_rcti_size_x(rect) + 1); + BLI_assert(h == BLI_rcti_size_y(rect) + 1); - /* wmOrtho for the screen has this same offset */ - const float halfx = GLA_PIXEL_OFS / w; - const float halfy = GLA_PIXEL_OFS / h; + /* wmOrtho for the screen has this same offset */ + const float halfx = GLA_PIXEL_OFS / w; + const float halfy = GLA_PIXEL_OFS / h; - float x1 = rect->xmin; - float x2 = rect->xmin + w; - float y1 = rect->ymin; - float y2 = rect->ymin + h; + float x1 = rect->xmin; + float x2 = rect->xmin + w; + float y1 = rect->ymin; + float y2 = rect->ymin + h; - GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); - GPU_shader_bind(shader); + GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR); + GPU_shader_bind(shader); - GPU_texture_bind(color, 0); - glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), halfx, halfy, 1.0f + halfx, 1.0f + halfy); - glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x1, y1, x2, y2); - glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f); + GPU_texture_bind(color, 0); + glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0); + glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), + halfx, + halfy, + 1.0f + halfx, + 1.0f + halfy); + glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x1, y1, x2, y2); + glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f); - GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); + GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4); - GPU_texture_unbind(color); + GPU_texture_unbind(color); } void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) { - GPU_framebuffer_restore(); - DRW_opengl_context_disable(); + GPU_framebuffer_restore(); + DRW_opengl_context_disable(); } - GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport) { - DefaultFramebufferList *dfbl = viewport->fbl; + DefaultFramebufferList *dfbl = viewport->fbl; - if (dfbl->default_fb) { - DefaultTextureList *dtxl = viewport->txl; - return dtxl->color; - } + if (dfbl->default_fb) { + DefaultTextureList *dtxl = viewport->txl; + return dtxl->color; + } - return NULL; + return NULL; } -static void gpu_viewport_buffers_free( - FramebufferList *fbl, int fbl_len, - TextureList *txl, int txl_len) +static void gpu_viewport_buffers_free(FramebufferList *fbl, + int fbl_len, + TextureList *txl, + int txl_len) { - for (int i = 0; i < fbl_len; i++) { - GPUFrameBuffer *fb = fbl->framebuffers[i]; - if (fb) { - GPU_framebuffer_free(fb); - fbl->framebuffers[i] = NULL; - } - } - for (int i = 0; i < txl_len; i++) { - GPUTexture *tex = txl->textures[i]; - if (tex) { - GPU_texture_free(tex); - txl->textures[i] = NULL; - } - } + for (int i = 0; i < fbl_len; i++) { + GPUFrameBuffer *fb = fbl->framebuffers[i]; + if (fb) { + GPU_framebuffer_free(fb); + fbl->framebuffers[i] = NULL; + } + } + for (int i = 0; i < txl_len; i++) { + GPUTexture *tex = txl->textures[i]; + if (tex) { + GPU_texture_free(tex); + txl->textures[i] = NULL; + } + } } static void gpu_viewport_storage_free(StorageList *stl, int stl_len) { - for (int i = 0; i < stl_len; i++) { - void *storage = stl->storage[i]; - if (storage) { - MEM_freeN(storage); - stl->storage[i] = NULL; - } - } + for (int i = 0; i < stl_len; i++) { + void *storage = stl->storage[i]; + if (storage) { + MEM_freeN(storage); + stl->storage[i] = NULL; + } + } } static void gpu_viewport_passes_free(PassList *psl, int psl_len) { - for (int i = 0; i < psl_len; i++) { - struct DRWPass *pass = psl->passes[i]; - if (pass) { - DRW_pass_free(pass); - psl->passes[i] = NULL; - } - } + for (int i = 0; i < psl_len; i++) { + struct DRWPass *pass = psl->passes[i]; + if (pass) { + DRW_pass_free(pass); + psl->passes[i] = NULL; + } + } } /* Must be executed inside Drawmanager Opengl Context. */ void GPU_viewport_free(GPUViewport *viewport) { - gpu_viewport_engines_data_free(viewport); - - gpu_viewport_buffers_free( - (FramebufferList *)viewport->fbl, default_fbl_len, - (TextureList *)viewport->txl, default_txl_len); - - gpu_viewport_texture_pool_free(viewport); - - MEM_freeN(viewport->fbl); - MEM_freeN(viewport->txl); - - if (viewport->vmempool.calls != NULL) { - BLI_mempool_destroy(viewport->vmempool.calls); - } - if (viewport->vmempool.states != NULL) { - BLI_mempool_destroy(viewport->vmempool.states); - } - if (viewport->vmempool.shgroups != NULL) { - BLI_mempool_destroy(viewport->vmempool.shgroups); - } - if (viewport->vmempool.uniforms != NULL) { - BLI_mempool_destroy(viewport->vmempool.uniforms); - } - if (viewport->vmempool.passes != NULL) { - BLI_mempool_destroy(viewport->vmempool.passes); - } - - DRW_instance_data_list_free(viewport->idatalist); - MEM_freeN(viewport->idatalist); - - MEM_freeN(viewport); + gpu_viewport_engines_data_free(viewport); + + gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, + default_fbl_len, + (TextureList *)viewport->txl, + default_txl_len); + + gpu_viewport_texture_pool_free(viewport); + + MEM_freeN(viewport->fbl); + MEM_freeN(viewport->txl); + + if (viewport->vmempool.calls != NULL) { + BLI_mempool_destroy(viewport->vmempool.calls); + } + if (viewport->vmempool.states != NULL) { + BLI_mempool_destroy(viewport->vmempool.states); + } + if (viewport->vmempool.shgroups != NULL) { + BLI_mempool_destroy(viewport->vmempool.shgroups); + } + if (viewport->vmempool.uniforms != NULL) { + BLI_mempool_destroy(viewport->vmempool.uniforms); + } + if (viewport->vmempool.passes != NULL) { + BLI_mempool_destroy(viewport->vmempool.passes); + } + + DRW_instance_data_list_free(viewport->idatalist); + MEM_freeN(viewport->idatalist); + + MEM_freeN(viewport); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_frag.glsl index 620568db500..5a36b414229 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_frag.glsl @@ -8,9 +8,9 @@ out vec4 fragColor; void main() { - /* Should be 0.8 but minimize the AA on the edges. */ - float dist = (length(uv) - 0.78) * scale; + /* Should be 0.8 but minimize the AA on the edges. */ + float dist = (length(uv) - 0.78) * scale; - fragColor = color; - fragColor.a *= smoothstep(-0.09, 1.09, dist); + fragColor = color; + fragColor.a *= smoothstep(-0.09, 1.09, dist); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl index 816e12342a1..d20ddcd27c0 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_area_borders_vert.glsl @@ -9,29 +9,28 @@ in vec2 pos; out vec2 uv; - void main() { - int corner_id = (gl_VertexID / cornerLen) % 4; - - vec2 final_pos = pos * scale; - - if (corner_id == 0) { - uv = pos + vec2(1.0, 1.0); - final_pos += rect.yw; /* top right */ - } - else if (corner_id == 1) { - uv = pos + vec2(-1.0, 1.0); - final_pos += rect.xw; /* top left */ - } - else if (corner_id == 2) { - uv = pos + vec2(-1.0, -1.0); - final_pos += rect.xz; /* bottom left */ - } - else { - uv = pos + vec2(1.0, -1.0); - final_pos += rect.yz; /* bottom right */ - } - - gl_Position = (ModelViewProjectionMatrix * vec4(final_pos, 0.0, 1.0)); + int corner_id = (gl_VertexID / cornerLen) % 4; + + vec2 final_pos = pos * scale; + + if (corner_id == 0) { + uv = pos + vec2(1.0, 1.0); + final_pos += rect.yw; /* top right */ + } + else if (corner_id == 1) { + uv = pos + vec2(-1.0, 1.0); + final_pos += rect.xw; /* top left */ + } + else if (corner_id == 2) { + uv = pos + vec2(-1.0, -1.0); + final_pos += rect.xz; /* bottom left */ + } + else { + uv = pos + vec2(1.0, -1.0); + final_pos += rect.yz; /* bottom right */ + } + + gl_Position = (ModelViewProjectionMatrix * vec4(final_pos, 0.0, 1.0)); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl index 0fddbddddc5..5c6b8f0a1a1 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_edges_vert.glsl @@ -14,18 +14,18 @@ flat out vec4 finalColor; /* TODO: Port drawing to draw manager and * remove constants duplications. */ -#define VERT_UV_SELECT (1 << 3) -#define EDGE_UV_SELECT (1 << 5) +#define VERT_UV_SELECT (1 << 3) +#define EDGE_UV_SELECT (1 << 5) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); #ifdef SMOOTH_COLOR - bool is_select = (flag & VERT_UV_SELECT) != 0; + bool is_select = (flag & VERT_UV_SELECT) != 0; #else - bool is_select = (flag & EDGE_UV_SELECT) != 0; + bool is_select = (flag & EDGE_UV_SELECT) != 0; #endif - finalColor = (is_select) ? selectColor : edgeColor; + finalColor = (is_select) ? selectColor : edgeColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl index e0d168e8095..7a94fc088c4 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_facedots_vert.glsl @@ -10,10 +10,10 @@ out vec4 finalColor; /* TODO: Port drawing to draw manager and * remove constants duplications. */ -#define FACE_UV_SELECT (1 << 7) +#define FACE_UV_SELECT (1 << 7) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - finalColor = ((flag & FACE_UV_SELECT) != 0) ? selectColor : vertColor; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + finalColor = ((flag & FACE_UV_SELECT) != 0) ? selectColor : vertColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl index 1d25c8fe345..6fc41271cf5 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_faces_vert.glsl @@ -11,16 +11,16 @@ flat out vec4 finalColor; /* TODO: Port drawing to draw manager and * remove constants duplications. */ -#define FACE_UV_ACTIVE (1 << 6) -#define FACE_UV_SELECT (1 << 7) +#define FACE_UV_ACTIVE (1 << 6) +#define FACE_UV_SELECT (1 << 7) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - bool is_selected = (flag & FACE_UV_SELECT) != 0; - bool is_active = (flag & FACE_UV_ACTIVE) != 0; + bool is_selected = (flag & FACE_UV_SELECT) != 0; + bool is_active = (flag & FACE_UV_ACTIVE) != 0; - finalColor = (is_selected) ? selectColor : faceColor; - finalColor = (is_active) ? activeColor : finalColor; + finalColor = (is_selected) ? selectColor : faceColor; + finalColor = (is_active) ? activeColor : finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl index 50166bc4e95..3f3bfa5410c 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_points_vert.glsl @@ -15,30 +15,30 @@ out vec4 radii; /* TODO: Port drawing to draw manager and * remove constants duplications. */ -#define VERT_UV_SELECT (1 << 3) -#define VERT_UV_PINNED (1 << 4) +#define VERT_UV_SELECT (1 << 3) +#define VERT_UV_PINNED (1 << 4) void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - gl_PointSize = pointSize; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_PointSize = pointSize; - bool is_selected = (flag & VERT_UV_SELECT) != 0; - bool is_pinned = (flag & VERT_UV_PINNED) != 0; + bool is_selected = (flag & VERT_UV_SELECT) != 0; + bool is_pinned = (flag & VERT_UV_PINNED) != 0; - vec4 deselect_col = (is_pinned) ? pinnedColor : vertColor; - fillColor = (is_selected) ? selectColor : deselect_col; - outlineColor = (is_pinned) ? pinnedColor : vec4(fillColor.rgb, 0.0); + vec4 deselect_col = (is_pinned) ? pinnedColor : vertColor; + fillColor = (is_selected) ? selectColor : deselect_col; + outlineColor = (is_pinned) ? pinnedColor : vec4(fillColor.rgb, 0.0); - // calculate concentric radii in pixels - float radius = 0.5 * pointSize; + // calculate concentric radii in pixels + float radius = 0.5 * pointSize; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; - radii[2] = radius - outlineWidth; - radii[3] = radius - outlineWidth - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; - // convert to PointCoord units - radii /= pointSize; + // convert to PointCoord units + radii /= pointSize; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl index c575e06ed3b..810784e2fbc 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_edituvs_stretch_vert.glsl @@ -16,64 +16,64 @@ noperspective out vec4 finalColor; vec3 weight_to_rgb(float weight) { - vec3 r_rgb; - float blend = ((weight / 2.0) + 0.5); + vec3 r_rgb; + float blend = ((weight / 2.0) + 0.5); - if (weight <= 0.25) { /* blue->cyan */ - r_rgb[0] = 0.0; - r_rgb[1] = blend * weight * 4.0; - r_rgb[2] = blend; - } - else if (weight <= 0.50) { /* cyan->green */ - r_rgb[0] = 0.0; - r_rgb[1] = blend; - r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); - } - else if (weight <= 0.75) { /* green->yellow */ - r_rgb[0] = blend * ((weight - 0.50) * 4.0); - r_rgb[1] = blend; - r_rgb[2] = 0.0; - } - else if (weight <= 1.0) { /* yellow->red */ - r_rgb[0] = blend; - r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); - r_rgb[2] = 0.0; - } - else { - /* exceptional value, unclamped or nan, - * avoid uninitialized memory use */ - r_rgb[0] = 1.0; - r_rgb[1] = 0.0; - r_rgb[2] = 1.0; - } + if (weight <= 0.25) { /* blue->cyan */ + r_rgb[0] = 0.0; + r_rgb[1] = blend * weight * 4.0; + r_rgb[2] = blend; + } + else if (weight <= 0.50) { /* cyan->green */ + r_rgb[0] = 0.0; + r_rgb[1] = blend; + r_rgb[2] = blend * (1.0 - ((weight - 0.25) * 4.0)); + } + else if (weight <= 0.75) { /* green->yellow */ + r_rgb[0] = blend * ((weight - 0.50) * 4.0); + r_rgb[1] = blend; + r_rgb[2] = 0.0; + } + else if (weight <= 1.0) { /* yellow->red */ + r_rgb[0] = blend; + r_rgb[1] = blend * (1.0 - ((weight - 0.75) * 4.0)); + r_rgb[2] = 0.0; + } + else { + /* exceptional value, unclamped or nan, + * avoid uninitialized memory use */ + r_rgb[0] = 1.0; + r_rgb[1] = 0.0; + r_rgb[2] = 1.0; + } - return r_rgb; + return r_rgb; } -#define M_PI 3.1415926535897932 +#define M_PI 3.1415926535897932 /* Adapted from BLI_math_vector.h */ float angle_normalized_v2v2(vec2 v1, vec2 v2) { - v1 = normalize(v1 * aspect); - v2 = normalize(v2 * aspect); - /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ - bool q = (dot(v1, v2) >= 0.0); - vec2 v = (q) ? (v1 - v2) : (v1 + v2); - float a = 2.0 * asin(length(v) / 2.0); - return (q) ? a : M_PI - a; + v1 = normalize(v1 * aspect); + v2 = normalize(v2 * aspect); + /* this is the same as acos(dot_v3v3(v1, v2)), but more accurate */ + bool q = (dot(v1, v2) >= 0.0); + vec2 v = (q) ? (v1 - v2) : (v1 + v2); + float a = 2.0 * asin(length(v) / 2.0); + return (q) ? a : M_PI - a; } void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); #ifdef STRETCH_ANGLE - float uv_angle = angle_normalized_v2v2(uv_adj.xy, uv_adj.zw) / M_PI; - float stretch = 1.0 - abs(uv_angle - angle); - stretch = stretch; - stretch = 1.0 - stretch * stretch; + float uv_angle = angle_normalized_v2v2(uv_adj.xy, uv_adj.zw) / M_PI; + float stretch = 1.0 - abs(uv_angle - angle); + stretch = stretch; + stretch = 1.0 - stretch * stretch; #endif - finalColor = vec4(weight_to_rgb(stretch), 1.0); + finalColor = vec4(weight_to_rgb(stretch), 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl index 769e2b0e37c..df2507c0dc9 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_flat_color_vert.glsl @@ -8,6 +8,6 @@ flat out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl index a64f9c375c0..036fc0aaeec 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_multi_rect_vert.glsl @@ -13,36 +13,39 @@ flat out vec4 finalColor; void main() { - /* Rendering 2 triangle per icon. */ - int i = gl_VertexID / 6; - int v = gl_VertexID % 6; - - vec4 pos = calls_data[i*3]; - vec4 tex = calls_data[i*3+1]; - finalColor = calls_data[i*3+2]; - - /* TODO Remove this */ - if (v == 2) v = 4; - else if (v == 3) v = 0; - else if (v == 5) v = 2; - - if (v == 0) { - pos.xy = pos.xw; - tex.xy = tex.xw; - } - else if (v == 1) { - pos.xy = pos.xz; - tex.xy = tex.xz; - } - else if (v == 2) { - pos.xy = pos.yw; - tex.xy = tex.yw; - } - else { - pos.xy = pos.yz; - tex.xy = tex.yz; - } - - gl_Position = vec4(pos.xy, 0.0f, 1.0f); - texCoord_interp = tex.xy; + /* Rendering 2 triangle per icon. */ + int i = gl_VertexID / 6; + int v = gl_VertexID % 6; + + vec4 pos = calls_data[i * 3]; + vec4 tex = calls_data[i * 3 + 1]; + finalColor = calls_data[i * 3 + 2]; + + /* TODO Remove this */ + if (v == 2) + v = 4; + else if (v == 3) + v = 0; + else if (v == 5) + v = 2; + + if (v == 0) { + pos.xy = pos.xw; + tex.xy = tex.xw; + } + else if (v == 1) { + pos.xy = pos.xz; + tex.xy = tex.xz; + } + else if (v == 2) { + pos.xy = pos.yw; + tex.xy = tex.yw; + } + else { + pos.xy = pos.yz; + tex.xy = tex.yz; + } + + gl_Position = vec4(pos.xy, 0.0f, 1.0f); + texCoord_interp = tex.xy; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl index 015082186b5..fcd877a37eb 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_rect_vert.glsl @@ -11,25 +11,25 @@ out vec2 texCoord_interp; void main() { - vec2 uv; - vec2 co; - if (gl_VertexID == 0) { - co = rect_geom.xw; - uv = rect_icon.xw; - } - else if (gl_VertexID == 1) { - co = rect_geom.xy; - uv = rect_icon.xy; - } - else if (gl_VertexID == 2) { - co = rect_geom.zw; - uv = rect_icon.zw; - } - else { - co = rect_geom.zy; - uv = rect_icon.zy; - } + vec2 uv; + vec2 co; + if (gl_VertexID == 0) { + co = rect_geom.xw; + uv = rect_icon.xw; + } + else if (gl_VertexID == 1) { + co = rect_geom.xy; + uv = rect_icon.xy; + } + else if (gl_VertexID == 2) { + co = rect_geom.zw; + uv = rect_icon.zw; + } + else { + co = rect_geom.zy; + uv = rect_icon.zy; + } - gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f); - texCoord_interp = uv; + gl_Position = ModelViewProjectionMatrix * vec4(co, 0.0f, 1.0f); + texCoord_interp = uv; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl index 0881f2b150f..cdb066c9c52 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl @@ -8,7 +8,7 @@ out vec2 texCoord_interp; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f); - gl_Position.z = 1.0; - texCoord_interp = texCoord; + gl_Position = ModelViewProjectionMatrix * vec4(pos.xy, 0.0f, 1.0f); + gl_Position.z = 1.0; + texCoord_interp = texCoord; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl index 3c5b0d1ca0a..185a4c8c59f 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl @@ -8,11 +8,11 @@ uniform float dash_width; /* Simple mode, discarding non-dash parts (so no need for blending at all). */ -uniform float dash_factor; /* if > 1.0, solid line. */ +uniform float dash_factor; /* if > 1.0, solid line. */ /* More advanced mode, allowing for complex, multi-colored patterns. Enabled when colors_len > 0. */ /* Note: max number of steps/colors in pattern is 32! */ -uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ +uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ uniform vec4 colors[32]; noperspective in float distance_along_line; @@ -22,33 +22,33 @@ out vec4 fragColor; void main() { - /* Multi-color option. */ - if (colors_len > 0) { - /* Solid line case, simple. */ - if (colors_len == 1) { - fragColor = colors[0]; - } - /* Actually dashed line... */ - else { - float normalized_distance = fract(distance_along_line / dash_width); - fragColor = colors[int(normalized_distance * colors_len)]; - } - } - /* Single color option. */ - else { - /* Solid line case, simple. */ - if (dash_factor >= 1.0f) { - fragColor = color_geom; - } - /* Actually dashed line... */ - else { - float normalized_distance = fract(distance_along_line / dash_width); - if (normalized_distance <= dash_factor) { - fragColor = color_geom; - } - else { - discard; - } - } - } + /* Multi-color option. */ + if (colors_len > 0) { + /* Solid line case, simple. */ + if (colors_len == 1) { + fragColor = colors[0]; + } + /* Actually dashed line... */ + else { + float normalized_distance = fract(distance_along_line / dash_width); + fragColor = colors[int(normalized_distance * colors_len)]; + } + } + /* Single color option. */ + else { + /* Solid line case, simple. */ + if (dash_factor >= 1.0f) { + fragColor = color_geom; + } + /* Actually dashed line... */ + else { + float normalized_distance = fract(distance_along_line / dash_width); + if (normalized_distance <= dash_factor) { + fragColor = color_geom; + } + else { + discard; + } + } + } } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl index 1e5a75c37b8..11f67172e89 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_geom.glsl @@ -5,14 +5,13 @@ * Dashed is performed in screen space. */ - /* Make to be used with dynamic batching so no Model Matrix needed */ uniform mat4 ModelViewProjectionMatrix; uniform vec2 viewport_size; /* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */ -uniform float dash_factor; /* if > 1.0, solid line. */ -uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ +uniform float dash_factor; /* if > 1.0, solid line. */ +uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ layout(lines) in; @@ -24,41 +23,41 @@ noperspective out vec4 color_geom; void main() { - vec4 v1 = gl_in[0].gl_Position; - vec4 v2 = gl_in[1].gl_Position; + vec4 v1 = gl_in[0].gl_Position; + vec4 v2 = gl_in[1].gl_Position; - gl_Position = v1; - color_geom = color_vert[0]; - distance_along_line = 0.0f; + gl_Position = v1; + color_geom = color_vert[0]; + distance_along_line = 0.0f; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - gl_Position = v2; - color_geom = color_vert[1]; - if ((colors_len == 1) || (dash_factor >= 1.0f)) { - /* Solid line, optimize out distance computation! */ - distance_along_line = 0.0f; - } - else { - vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. - p1 = p1 * viewport_size; // <- 'virtual' screen coordinates. + gl_Position = v2; + color_geom = color_vert[1]; + if ((colors_len == 1) || (dash_factor >= 1.0f)) { + /* Solid line, optimize out distance computation! */ + distance_along_line = 0.0f; + } + else { + vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. + p1 = p1 * viewport_size; // <- 'virtual' screen coordinates. - vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. - p2 = p2 * viewport_size; // <- 'virtual' screen coordinates. + vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. + p2 = p2 * viewport_size; // <- 'virtual' screen coordinates. - distance_along_line = distance(p1, p2); - } + distance_along_line = distance(p1, p2); + } #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); - /* Note: we could also use similar approach as diag_stripes_frag, but this would give us dashed 'anchored' - * to the screen, and not to one end of the line... */ + /* Note: we could also use similar approach as diag_stripes_frag, but this would give us dashed 'anchored' + * to the screen, and not to one end of the line... */ } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl index f5c611586aa..933a0976c6e 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_uniform_color_vert.glsl @@ -16,6 +16,6 @@ out vec4 color_vert; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - color_vert = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + color_vert = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl index 5a4da5cc9d4..434917f8052 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_width_geom.glsl @@ -6,11 +6,11 @@ uniform mat4 ModelViewProjectionMatrix; uniform vec2 viewport_size; /* Width of the generated 'line'. */ -uniform float width; /* in pixels, screen space. */ +uniform float width; /* in pixels, screen space. */ /* Uniforms from fragment shader, used here to optimize out useless computation in case of solid line. */ -uniform float dash_factor; /* if > 1.0, solid line. */ -uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ +uniform float dash_factor; /* if > 1.0, solid line. */ +uniform int colors_len; /* Enabled if > 0, 1 for solid line. */ layout(lines) in; @@ -19,41 +19,41 @@ noperspective out float distance_along_line; void main() { - vec4 v1 = gl_in[0].gl_Position; - vec4 v2 = gl_in[1].gl_Position; + vec4 v1 = gl_in[0].gl_Position; + vec4 v2 = gl_in[1].gl_Position; - /* Width, from 2D screen space in pixels, to ModelViewProjection space of each input vertices. */ - float w1 = (width / viewport_size) * v1.w * 2.0; - float w2 = (width / viewport_size) * v2.w * 2.0; + /* Width, from 2D screen space in pixels, to ModelViewProjection space of each input vertices. */ + float w1 = (width / viewport_size) * v1.w * 2.0; + float w2 = (width / viewport_size) * v2.w * 2.0; - /* Normalized vector parallel to screen and orthogonal to line. */ - vec4 wdir = normalize(vec4(v1.y - v2.y, v2.x - v1.x, 0.0, 0.0)) + /* Normalized vector parallel to screen and orthogonal to line. */ + vec4 wdir = normalize(vec4(v1.y - v2.y, v2.x - v1.x, 0.0, 0.0)) - distance_along_line = 0.0f; - gl_Position = v1 + (wdir * w1); - EmitVertex(); + distance_along_line = 0.0f; + gl_Position = v1 + (wdir * w1); + EmitVertex(); - gl_Position = v1 - (wdir * w1); - EmitVertex(); + gl_Position = v1 - (wdir * w1); + EmitVertex(); - if ((colors_len == 1) || (dash_factor >= 1.0f)) { - /* Solid line, optimize out distance computation! */ - distance_along_line = 0.0f; - } - else { - vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. - p1 = p1 * viewport_size; // <- 'virtual' screen coordinates. + if ((colors_len == 1) || (dash_factor >= 1.0f)) { + /* Solid line, optimize out distance computation! */ + distance_along_line = 0.0f; + } + else { + vec2 p1 = (v1.xy / v1.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. + p1 = p1 * viewport_size; // <- 'virtual' screen coordinates. - vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. - p2 = p2 * viewport_size; // <- 'virtual' screen coordinates. + vec2 p2 = (v2.xy / v2.w) * 0.5 + 0.5; // <- device coordinates in [0..1] range. + p2 = p2 * viewport_size; // <- 'virtual' screen coordinates. - distance_along_line = distance(p1, p2); - } - gl_Position = v2 + (wdir * w2); - EmitVertex(); + distance_along_line = distance(p1, p2); + } + gl_Position = v2 + (wdir * w2); + EmitVertex(); - gl_Position = v2 - (wdir * w2); - EmitVertex(); + gl_Position = v2 - (wdir * w2); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl index 1497f9eeeb1..f07bd7f1d6f 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_frag.glsl @@ -4,7 +4,8 @@ in vec4 finalColor; out vec4 fragColor; -void main() { - fragColor = finalColor; - fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient)); +void main() +{ + fragColor = finalColor; + fragColor.a *= smoothstep(1.0, 0.1, abs(colorGradient)); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl index 220adba817a..4567429f645 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_nodelink_vert.glsl @@ -20,26 +20,26 @@ in ivec4 colid_doarrow; uniform vec4 colors[6]; -#define colStart colors[colid_doarrow[0]] -#define colEnd colors[colid_doarrow[1]] -#define colShadow colors[colid_doarrow[2]] -#define doArrow (colid_doarrow[3] != 0) +# define colStart colors[colid_doarrow[0]] +# define colEnd colors[colid_doarrow[1]] +# define colShadow colors[colid_doarrow[2]] +# define doArrow (colid_doarrow[3] != 0) #else /* Single curve drawcall, use uniform. */ uniform vec2 bezierPts[4]; -#define P0 bezierPts[0] -#define P1 bezierPts[1] -#define P2 bezierPts[2] -#define P3 bezierPts[3] +# define P0 bezierPts[0] +# define P1 bezierPts[1] +# define P2 bezierPts[2] +# define P3 bezierPts[3] uniform vec4 colors[3]; uniform bool doArrow; -#define colShadow colors[0] -#define colStart colors[1] -#define colEnd colors[2] +# define colShadow colors[0] +# define colStart colors[1] +# define colEnd colors[2] #endif @@ -52,56 +52,51 @@ out vec4 finalColor; void main(void) { - float t = uv.x; - float t2 = t * t; - float t2_3 = 3.0 * t2; - float one_minus_t = 1.0 - t; - float one_minus_t2 = one_minus_t * one_minus_t; - float one_minus_t2_3 = 3.0 * one_minus_t2; - - vec2 point = (P0 * one_minus_t2 * one_minus_t + - P1 * one_minus_t2_3 * t + - P2 * t2_3 * one_minus_t + - P3 * t2 * t); - - vec2 tangent = ((P1 - P0) * one_minus_t2_3 + - (P2 - P1) * 6.0 * (t - t2) + - (P3 - P2) * t2_3); - - /* tangent space at t */ - tangent = normalize(tangent); - vec2 normal = tangent.yx * vec2(-1.0, 1.0); - - /* Position vertex on the curve tangent space */ - point += (pos.x * tangent + pos.y * normal) * arrowSize; - - gl_Position = ModelViewProjectionMatrix * vec4(point, 0.0, 1.0); - - vec2 exp_axis = expand.x * tangent + expand.y * normal; - - /* rotate & scale the expand axis */ - exp_axis = ModelViewProjectionMatrix[0].xy * exp_axis.xx + - ModelViewProjectionMatrix[1].xy * exp_axis.yy; - - - float expand_dist = (uv.y * 2.0 - 1.0); - colorGradient = expand_dist; - - if (gl_VertexID < MID_VERTEX) { - /* Shadow pass */ - finalColor = colShadow; - } - else { - /* Second pass */ - finalColor = mix(colStart, colEnd, uv.x); - expand_dist *= 0.5; - } - - /* Expand into a line */ - gl_Position.xy += exp_axis * expandSize * expand_dist; - - /* if arrow */ - if (expand.y != 1.0 && !doArrow) { - gl_Position.xy *= 0.0; - } + float t = uv.x; + float t2 = t * t; + float t2_3 = 3.0 * t2; + float one_minus_t = 1.0 - t; + float one_minus_t2 = one_minus_t * one_minus_t; + float one_minus_t2_3 = 3.0 * one_minus_t2; + + vec2 point = (P0 * one_minus_t2 * one_minus_t + P1 * one_minus_t2_3 * t + + P2 * t2_3 * one_minus_t + P3 * t2 * t); + + vec2 tangent = ((P1 - P0) * one_minus_t2_3 + (P2 - P1) * 6.0 * (t - t2) + (P3 - P2) * t2_3); + + /* tangent space at t */ + tangent = normalize(tangent); + vec2 normal = tangent.yx * vec2(-1.0, 1.0); + + /* Position vertex on the curve tangent space */ + point += (pos.x * tangent + pos.y * normal) * arrowSize; + + gl_Position = ModelViewProjectionMatrix * vec4(point, 0.0, 1.0); + + vec2 exp_axis = expand.x * tangent + expand.y * normal; + + /* rotate & scale the expand axis */ + exp_axis = ModelViewProjectionMatrix[0].xy * exp_axis.xx + + ModelViewProjectionMatrix[1].xy * exp_axis.yy; + + float expand_dist = (uv.y * 2.0 - 1.0); + colorGradient = expand_dist; + + if (gl_VertexID < MID_VERTEX) { + /* Shadow pass */ + finalColor = colShadow; + } + else { + /* Second pass */ + finalColor = mix(colStart, colEnd, uv.x); + expand_dist *= 0.5; + } + + /* Expand into a line */ + gl_Position.xy += exp_axis * expandSize * expand_dist; + + /* if arrow */ + if (expand.y != 1.0 && !doArrow) { + gl_Position.xy *= 0.0; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl index 1f833cfb7be..a7681353d49 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl @@ -5,17 +5,18 @@ uniform float size; in vec2 pos; out vec2 radii; -void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - gl_PointSize = size; +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_PointSize = size; - // calculate concentric radii in pixels - float radius = 0.5 * size; + // calculate concentric radii in pixels + float radius = 0.5 * size; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; - // convert to PointCoord units - radii /= size; + // convert to PointCoord units + radii /= size; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl index 99bdeb22904..a3439ebe3c4 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl @@ -6,19 +6,20 @@ uniform float outlineWidth; in vec2 pos; out vec4 radii; -void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - gl_PointSize = size; +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_PointSize = size; - // calculate concentric radii in pixels - float radius = 0.5 * size; + // calculate concentric radii in pixels + float radius = 0.5 * size; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; - radii[2] = radius - outlineWidth; - radii[3] = radius - outlineWidth - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; - // convert to PointCoord units - radii /= size; + // convert to PointCoord units + radii /= size; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl index 5fad95236df..287bd351534 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl @@ -8,20 +8,21 @@ in vec4 color; out vec4 radii; out vec4 fillColor; -void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - gl_PointSize = size; - fillColor = color; +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_PointSize = size; + fillColor = color; - // calculate concentric radii in pixels - float radius = 0.5 * size; + // calculate concentric radii in pixels + float radius = 0.5 * size; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; - radii[2] = radius - outlineWidth; - radii[3] = radius - outlineWidth - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; - // convert to PointCoord units - radii /= size; + // convert to PointCoord units + radii /= size; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl index d6aacf0cdc5..469370b9173 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl @@ -8,7 +8,7 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - gl_PointSize = size; - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_PointSize = size; + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl index 145ed16248a..181b1bf3fad 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_dithered_frag.glsl @@ -4,17 +4,15 @@ out vec4 fragColor; /* 4x4 bayer matrix prepared for 8bit UNORM precision error. */ #define P(x) (((x + 0.5) * (1.0 / 16.0) - 0.5) * (1.0 / 255.0)) -const vec4 dither_mat4x4[4] = vec4[4]( - vec4( P(0.0), P(8.0), P(2.0), P(10.0)), - vec4(P(12.0), P(4.0), P(14.0), P(6.0)), - vec4( P(3.0), P(11.0), P(1.0), P(9.0)), - vec4(P(15.0), P(7.0), P(13.0), P(5.0)) -); +const vec4 dither_mat4x4[4] = vec4[4](vec4(P(0.0), P(8.0), P(2.0), P(10.0)), + vec4(P(12.0), P(4.0), P(14.0), P(6.0)), + vec4(P(3.0), P(11.0), P(1.0), P(9.0)), + vec4(P(15.0), P(7.0), P(13.0), P(5.0))); void main() { - ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4; - ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2; - float dither_noise = dither_mat4x4[tx1.x][tx1.y]; - fragColor = finalColor + dither_noise; + ivec2 tx1 = ivec2(gl_FragCoord.xy) % 4; + ivec2 tx2 = ivec2(gl_FragCoord.xy) % 2; + float dither_noise = dither_mat4x4[tx1.x][tx1.y]; + fragColor = finalColor + dither_noise; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl index 4a4bfb6a616..4f275c5b220 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_frag.glsl @@ -4,5 +4,5 @@ out vec4 fragColor; void main() { - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl index fe91f4d0902..fcf436d50af 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_smooth_color_vert.glsl @@ -8,6 +8,6 @@ noperspective out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl index b3b897da3c6..de6547715f3 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_vert.glsl @@ -10,5 +10,5 @@ in vec2 pos; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl index a356014d025..18f58d52f32 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_frag.glsl @@ -8,33 +8,31 @@ out vec4 fragColor; vec4 do_checkerboard() { - float size = checkerColorAndSize.z; - vec2 phase = mod(gl_FragCoord.xy, size * 2.0); - - if ((phase.x > size && phase.y < size) || - (phase.x < size && phase.y > size)) - { - return vec4(checkerColorAndSize.xxx, 1.0); - } - else { - return vec4(checkerColorAndSize.yyy, 1.0); - } + float size = checkerColorAndSize.z; + vec2 phase = mod(gl_FragCoord.xy, size * 2.0); + + if ((phase.x > size && phase.y < size) || (phase.x < size && phase.y > size)) { + return vec4(checkerColorAndSize.xxx, 1.0); + } + else { + return vec4(checkerColorAndSize.yyy, 1.0); + } } void main() { - if (min(1.0, -butCo) > discardFac) { - discard; - } + if (min(1.0, -butCo) > discardFac) { + discard; + } - fragColor = finalColor; + fragColor = finalColor; - if (butCo > 0.5) { - vec4 checker = do_checkerboard(); - fragColor = mix(checker, fragColor, fragColor.a); - } + if (butCo > 0.5) { + vec4 checker = do_checkerboard(); + fragColor = mix(checker, fragColor, fragColor.a); + } - if (butCo > 0.0) { - fragColor.a = 1.0; - } + if (butCo > 0.0) { + fragColor.a = 1.0; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl index ff51e0266d7..e17c5cda000 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_base_vert.glsl @@ -12,38 +12,70 @@ /* 4bits for corner id */ #define CORNER_VEC_OFS 2u #define CORNER_VEC_RANGE BIT_RANGE(4) -const vec2 cornervec[36] = vec2[36]( - vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0), - vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0), - vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0), - vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0) -); +const vec2 cornervec[36] = vec2[36](vec2(0.0, 1.0), + vec2(0.02, 0.805), + vec2(0.067, 0.617), + vec2(0.169, 0.45), + vec2(0.293, 0.293), + vec2(0.45, 0.169), + vec2(0.617, 0.076), + vec2(0.805, 0.02), + vec2(1.0, 0.0), + vec2(-1.0, 0.0), + vec2(-0.805, 0.02), + vec2(-0.617, 0.067), + vec2(-0.45, 0.169), + vec2(-0.293, 0.293), + vec2(-0.169, 0.45), + vec2(-0.076, 0.617), + vec2(-0.02, 0.805), + vec2(0.0, 1.0), + vec2(0.0, -1.0), + vec2(-0.02, -0.805), + vec2(-0.067, -0.617), + vec2(-0.169, -0.45), + vec2(-0.293, -0.293), + vec2(-0.45, -0.169), + vec2(-0.617, -0.076), + vec2(-0.805, -0.02), + vec2(-1.0, 0.0), + vec2(1.0, 0.0), + vec2(0.805, -0.02), + vec2(0.617, -0.067), + vec2(0.45, -0.169), + vec2(0.293, -0.293), + vec2(0.169, -0.45), + vec2(0.076, -0.617), + vec2(0.02, -0.805), + vec2(0.0, -1.0)); /* 4bits for jitter id */ #define JIT_OFS 6u #define JIT_RANGE BIT_RANGE(4) -const vec2 jit[9] = vec2[9]( - vec2( 0.468813, -0.481430), vec2(-0.155755, -0.352820), - vec2( 0.219306, -0.238501), vec2(-0.393286, -0.110949), - vec2(-0.024699, 0.013908), vec2( 0.343805, 0.147431), - vec2(-0.272855, 0.269918), vec2( 0.095909, 0.388710), - vec2( 0.0, 0.0) -); +const vec2 jit[9] = vec2[9](vec2(0.468813, -0.481430), + vec2(-0.155755, -0.352820), + vec2(0.219306, -0.238501), + vec2(-0.393286, -0.110949), + vec2(-0.024699, 0.013908), + vec2(0.343805, 0.147431), + vec2(-0.272855, 0.269918), + vec2(0.095909, 0.388710), + vec2(0.0, 0.0)); /* 2bits for other flags */ -#define INNER_FLAG uint(1 << 10) /* is inner vert */ -#define EMBOSS_FLAG uint(1 << 11) /* is emboss vert */ +#define INNER_FLAG uint(1 << 10) /* is inner vert */ +#define EMBOSS_FLAG uint(1 << 11) /* is emboss vert */ /* 2bits for color */ #define COLOR_OFS 12u #define COLOR_RANGE BIT_RANGE(2) -#define COLOR_INNER 0u -#define COLOR_EDGE 1u -#define COLOR_EMBOSS 2u +#define COLOR_INNER 0u +#define COLOR_EDGE 1u +#define COLOR_EMBOSS 2u /* 2bits for trias type */ -#define TRIA_FLAG uint(1 << 14) /* is tria vert */ -#define TRIA_FIRST INNER_FLAG /* is first tria (reuse INNER_FLAG) */ +#define TRIA_FLAG uint(1 << 14) /* is tria vert */ +#define TRIA_FIRST INNER_FLAG /* is first tria (reuse INNER_FLAG) */ /* We can reuse the CORNER_* bits for tria */ #define TRIA_VEC_RANGE BIT_RANGE(6) @@ -53,36 +85,62 @@ const vec2 jit[9] = vec2[9]( * (The array is still stored in the registry, but indexing is done in the uniform buffer.) */ uniform vec2 triavec[43] = vec2[43]( - /* ROUNDBOX_TRIA_ARROWS */ - vec2(-0.170000, 0.400000), vec2(-0.050000, 0.520000), vec2( 0.250000, 0.000000), vec2( 0.470000, -0.000000), vec2(-0.170000, -0.400000), vec2(-0.050000, -0.520000), - vec2( 0.170000, 0.400000), vec2( 0.050000, 0.520000), vec2(-0.250000, 0.000000), vec2(-0.470000, -0.000000), vec2( 0.170000, -0.400000), vec2( 0.050000, -0.520000), - - /* ROUNDBOX_TRIA_SCROLL - circle tria (triangle strip) */ - vec2(0.000000, 1.000000), - vec2(0.382684, 0.923879), vec2(-0.382683, 0.923880), - vec2(0.707107, 0.707107), vec2(-0.707107, 0.707107), - vec2(0.923879, 0.382684), vec2(-0.923879, 0.382684), - vec2(1.000000, 0.000000), vec2(-1.000000, 0.000000), - vec2(0.923879, -0.382684), vec2(-0.923879, -0.382684), - vec2(0.707107, -0.707107), vec2(-0.707107, -0.707107), - vec2(0.382684, -0.923879), vec2(-0.382683, -0.923880), - vec2(0.000000, -1.000000), - - /* ROUNDBOX_TRIA_MENU - menu arrows */ - vec2(-0.51, 0.07), vec2(-0.4, 0.18), vec2(-0.05, -0.39), - vec2(-0.05, -0.17), vec2(0.41, 0.07), vec2(0.3, 0.18), - - - /* ROUNDBOX_TRIA_CHECK - check mark */ - vec2(-0.67000, 0.020000), vec2(-0.500000, 0.190000), vec2(-0.130000, -0.520000), - vec2(-0.130000, -0.170000), vec2(0.720000, 0.430000), vec2(0.530000, 0.590000), - - /* ROUNDBOX_TRIA_HOLD_ACTION_ARROW - hold action arrows */ + /* ROUNDBOX_TRIA_ARROWS */ + vec2(-0.170000, 0.400000), + vec2(-0.050000, 0.520000), + vec2(0.250000, 0.000000), + vec2(0.470000, -0.000000), + vec2(-0.170000, -0.400000), + vec2(-0.050000, -0.520000), + vec2(0.170000, 0.400000), + vec2(0.050000, 0.520000), + vec2(-0.250000, 0.000000), + vec2(-0.470000, -0.000000), + vec2(0.170000, -0.400000), + vec2(0.050000, -0.520000), + + /* ROUNDBOX_TRIA_SCROLL - circle tria (triangle strip) */ + vec2(0.000000, 1.000000), + vec2(0.382684, 0.923879), + vec2(-0.382683, 0.923880), + vec2(0.707107, 0.707107), + vec2(-0.707107, 0.707107), + vec2(0.923879, 0.382684), + vec2(-0.923879, 0.382684), + vec2(1.000000, 0.000000), + vec2(-1.000000, 0.000000), + vec2(0.923879, -0.382684), + vec2(-0.923879, -0.382684), + vec2(0.707107, -0.707107), + vec2(-0.707107, -0.707107), + vec2(0.382684, -0.923879), + vec2(-0.382683, -0.923880), + vec2(0.000000, -1.000000), + + /* ROUNDBOX_TRIA_MENU - menu arrows */ + vec2(-0.51, 0.07), + vec2(-0.4, 0.18), + vec2(-0.05, -0.39), + vec2(-0.05, -0.17), + vec2(0.41, 0.07), + vec2(0.3, 0.18), + + /* ROUNDBOX_TRIA_CHECK - check mark */ + vec2(-0.67000, 0.020000), + vec2(-0.500000, 0.190000), + vec2(-0.130000, -0.520000), + vec2(-0.130000, -0.170000), + vec2(0.720000, 0.430000), + vec2(0.530000, 0.590000), + +/* ROUNDBOX_TRIA_HOLD_ACTION_ARROW - hold action arrows */ #define OX (-0.32) #define OY (0.1) #define SC (0.35 * 2) -// vec2(-0.5 + SC, 1.0 + OY), vec2( 0.5, 1.0 + OY), vec2( 0.5, 0.0 + OY + SC), - vec2((0.5 - SC) + OX, 1.0 + OY), vec2(-0.5 + OX, 1.0 + OY), vec2(-0.5 + OX, SC + OY) + // vec2(-0.5 + SC, 1.0 + OY), vec2( 0.5, 1.0 + OY), vec2( 0.5, 0.0 + OY + SC), + vec2((0.5 - SC) + OX, 1.0 + OY), + vec2(-0.5 + OX, 1.0 + OY), + vec2(-0.5 + OX, SC + OY) #undef OX #undef OY #undef SC @@ -92,30 +150,30 @@ uniform mat4 ModelViewProjectionMatrix; #define MAX_PARAM 11 #ifdef USE_INSTANCE -#define MAX_INSTANCE 6 +# define MAX_INSTANCE 6 uniform vec4 parameters[MAX_PARAM * MAX_INSTANCE]; #else uniform vec4 parameters[MAX_PARAM]; #endif /* gl_InstanceID is 0 if not drawing instances. */ -#define recti parameters[gl_InstanceID * MAX_PARAM + 0] -#define rect parameters[gl_InstanceID * MAX_PARAM + 1] -#define radsi parameters[gl_InstanceID * MAX_PARAM + 2].x -#define rads parameters[gl_InstanceID * MAX_PARAM + 2].y -#define faci parameters[gl_InstanceID * MAX_PARAM + 2].zw -#define roundCorners parameters[gl_InstanceID * MAX_PARAM + 3] -#define colorInner1 parameters[gl_InstanceID * MAX_PARAM + 4] -#define colorInner2 parameters[gl_InstanceID * MAX_PARAM + 5] -#define colorEdge parameters[gl_InstanceID * MAX_PARAM + 6] -#define colorEmboss parameters[gl_InstanceID * MAX_PARAM + 7] -#define colorTria parameters[gl_InstanceID * MAX_PARAM + 8] -#define tria1Center parameters[gl_InstanceID * MAX_PARAM + 9].xy -#define tria2Center parameters[gl_InstanceID * MAX_PARAM + 9].zw -#define tria1Size parameters[gl_InstanceID * MAX_PARAM + 10].x -#define tria2Size parameters[gl_InstanceID * MAX_PARAM + 10].y -#define shadeDir parameters[gl_InstanceID * MAX_PARAM + 10].z -#define alphaDiscard parameters[gl_InstanceID * MAX_PARAM + 10].w +#define recti parameters[gl_InstanceID * MAX_PARAM + 0] +#define rect parameters[gl_InstanceID * MAX_PARAM + 1] +#define radsi parameters[gl_InstanceID * MAX_PARAM + 2].x +#define rads parameters[gl_InstanceID * MAX_PARAM + 2].y +#define faci parameters[gl_InstanceID * MAX_PARAM + 2].zw +#define roundCorners parameters[gl_InstanceID * MAX_PARAM + 3] +#define colorInner1 parameters[gl_InstanceID * MAX_PARAM + 4] +#define colorInner2 parameters[gl_InstanceID * MAX_PARAM + 5] +#define colorEdge parameters[gl_InstanceID * MAX_PARAM + 6] +#define colorEmboss parameters[gl_InstanceID * MAX_PARAM + 7] +#define colorTria parameters[gl_InstanceID * MAX_PARAM + 8] +#define tria1Center parameters[gl_InstanceID * MAX_PARAM + 9].xy +#define tria2Center parameters[gl_InstanceID * MAX_PARAM + 9].zw +#define tria1Size parameters[gl_InstanceID * MAX_PARAM + 10].x +#define tria2Size parameters[gl_InstanceID * MAX_PARAM + 10].y +#define shadeDir parameters[gl_InstanceID * MAX_PARAM + 10].z +#define alphaDiscard parameters[gl_InstanceID * MAX_PARAM + 10].w /* We encode alpha check and discard factor together. */ #define doAlphaCheck (alphaDiscard < 0.0) @@ -129,86 +187,86 @@ flat out float discardFac; vec2 do_widget(void) { - uint cflag = vflag & CNR_FLAG_RANGE; - uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE; - - vec2 v = cornervec[cflag * 9u + vofs]; - - bool is_inner = (vflag & INNER_FLAG) != 0u; - - /* Scale by corner radius */ - v *= roundCorners[cflag] * ((is_inner) ? radsi : rads); - - /* Position to corner */ - vec4 rct = (is_inner) ? recti : rect; - if (cflag == BOTTOM_LEFT) - v += rct.xz; - else if (cflag == BOTTOM_RIGHT) - v += rct.yz; - else if (cflag == TOP_RIGHT) - v += rct.yw; - else /* (cflag == TOP_LEFT) */ - v += rct.xw; - - vec2 uv = faci * (v - recti.xz); - - /* compute uv and color gradient */ - uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE; - if (color_id == COLOR_INNER) { - float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0); - - if (doAlphaCheck) { - finalColor = colorInner1; - butCo = uv.x; - } - else { - finalColor = mix(colorInner2, colorInner1, fac); - butCo = -abs(uv.x); - } - } - else if (color_id == COLOR_EDGE) { - finalColor = colorEdge; - butCo = -abs(uv.x); - } - else /* (color_id == COLOR_EMBOSS) */ { - finalColor = colorEmboss; - butCo = -abs(uv.x); - } - - bool is_emboss = (vflag & EMBOSS_FLAG) != 0u; - v.y -= (is_emboss) ? 1.0f : 0.0; - - return v; + uint cflag = vflag & CNR_FLAG_RANGE; + uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE; + + vec2 v = cornervec[cflag * 9u + vofs]; + + bool is_inner = (vflag & INNER_FLAG) != 0u; + + /* Scale by corner radius */ + v *= roundCorners[cflag] * ((is_inner) ? radsi : rads); + + /* Position to corner */ + vec4 rct = (is_inner) ? recti : rect; + if (cflag == BOTTOM_LEFT) + v += rct.xz; + else if (cflag == BOTTOM_RIGHT) + v += rct.yz; + else if (cflag == TOP_RIGHT) + v += rct.yw; + else /* (cflag == TOP_LEFT) */ + v += rct.xw; + + vec2 uv = faci * (v - recti.xz); + + /* compute uv and color gradient */ + uint color_id = (vflag >> COLOR_OFS) & COLOR_RANGE; + if (color_id == COLOR_INNER) { + float fac = clamp((shadeDir > 0.0) ? uv.y : uv.x, 0.0, 1.0); + + if (doAlphaCheck) { + finalColor = colorInner1; + butCo = uv.x; + } + else { + finalColor = mix(colorInner2, colorInner1, fac); + butCo = -abs(uv.x); + } + } + else if (color_id == COLOR_EDGE) { + finalColor = colorEdge; + butCo = -abs(uv.x); + } + else /* (color_id == COLOR_EMBOSS) */ { + finalColor = colorEmboss; + butCo = -abs(uv.x); + } + + bool is_emboss = (vflag & EMBOSS_FLAG) != 0u; + v.y -= (is_emboss) ? 1.0f : 0.0; + + return v; } vec2 do_tria() { - uint vofs = vflag & TRIA_VEC_RANGE; + uint vofs = vflag & TRIA_VEC_RANGE; - vec2 v = triavec[vofs]; + vec2 v = triavec[vofs]; - finalColor = colorTria; - butCo = -1.0; + finalColor = colorTria; + butCo = -1.0; - bool is_tria_first = (vflag & TRIA_FIRST) != 0u; + bool is_tria_first = (vflag & TRIA_FIRST) != 0u; - if (is_tria_first) - v = v * tria1Size + tria1Center; - else - v = v * tria2Size + tria2Center; + if (is_tria_first) + v = v * tria1Size + tria1Center; + else + v = v * tria2Size + tria2Center; - return v; + return v; } void main() { - discardFac = discardFactor; - bool is_tria = (vflag & TRIA_FLAG) != 0u; + discardFac = discardFactor; + bool is_tria = (vflag & TRIA_FLAG) != 0u; - vec2 v = (is_tria) ? do_tria() : do_widget(); + vec2 v = (is_tria) ? do_tria() : do_widget(); - /* Antialiasing offset */ - v += jit[(vflag >> JIT_OFS) & JIT_RANGE]; + /* Antialiasing offset */ + v += jit[(vflag >> JIT_OFS) & JIT_RANGE]; - gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl index fc4d055a903..e8a6a43191e 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl @@ -7,7 +7,7 @@ uniform float alpha; void main() { - fragColor = vec4(0.0); - /* Manual curve fit of the falloff curve of previous drawing method. */ - fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277); + fragColor = vec4(0.0); + /* Manual curve fit of the falloff curve of previous drawing method. */ + fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277); } diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl index f6be496ac4f..99f80f6a7f2 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl @@ -12,23 +12,53 @@ /* 4bits for corner id */ #define CORNER_VEC_OFS 2u #define CORNER_VEC_RANGE BIT_RANGE(4) -const vec2 cornervec[36] = vec2[36]( - vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0), - vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0), - vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0), - vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0) -); +const vec2 cornervec[36] = vec2[36](vec2(0.0, 1.0), + vec2(0.02, 0.805), + vec2(0.067, 0.617), + vec2(0.169, 0.45), + vec2(0.293, 0.293), + vec2(0.45, 0.169), + vec2(0.617, 0.076), + vec2(0.805, 0.02), + vec2(1.0, 0.0), + vec2(-1.0, 0.0), + vec2(-0.805, 0.02), + vec2(-0.617, 0.067), + vec2(-0.45, 0.169), + vec2(-0.293, 0.293), + vec2(-0.169, 0.45), + vec2(-0.076, 0.617), + vec2(-0.02, 0.805), + vec2(0.0, 1.0), + vec2(0.0, -1.0), + vec2(-0.02, -0.805), + vec2(-0.067, -0.617), + vec2(-0.169, -0.45), + vec2(-0.293, -0.293), + vec2(-0.45, -0.169), + vec2(-0.617, -0.076), + vec2(-0.805, -0.02), + vec2(-1.0, 0.0), + vec2(1.0, 0.0), + vec2(0.805, -0.02), + vec2(0.617, -0.067), + vec2(0.45, -0.169), + vec2(0.293, -0.293), + vec2(0.169, -0.45), + vec2(0.076, -0.617), + vec2(0.02, -0.805), + vec2(0.0, -1.0)); -#define INNER_FLAG uint(1 << 10) /* is inner vert */ +#define INNER_FLAG uint(1 << 10) /* is inner vert */ uniform mat4 ModelViewProjectionMatrix; uniform vec4 parameters[4]; /* radi and rad per corner */ -#define recti parameters[0] -#define rect parameters[1] -#define radsi parameters[2].x -#define rads parameters[2].y +#define recti parameters[0] +#define rect parameters[1] +#define radsi parameters[2].x +#define rads parameters[2].y #define roundCorners parameters[3] in uint vflag; @@ -37,28 +67,28 @@ out float shadowFalloff; void main() { - uint cflag = vflag & CNR_FLAG_RANGE; - uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE; + uint cflag = vflag & CNR_FLAG_RANGE; + uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE; - vec2 v = cornervec[cflag * 9u + vofs]; + vec2 v = cornervec[cflag * 9u + vofs]; - bool is_inner = (vflag & INNER_FLAG) != 0u; + bool is_inner = (vflag & INNER_FLAG) != 0u; - shadowFalloff = (is_inner) ? 1.0 : 0.0; + shadowFalloff = (is_inner) ? 1.0 : 0.0; - /* Scale by corner radius */ - v *= roundCorners[cflag] * ((is_inner) ? radsi : rads); + /* Scale by corner radius */ + v *= roundCorners[cflag] * ((is_inner) ? radsi : rads); - /* Position to corner */ - vec4 rct = (is_inner) ? recti : rect; - if (cflag == BOTTOM_LEFT) - v += rct.xz; - else if (cflag == BOTTOM_RIGHT) - v += rct.yz; - else if (cflag == TOP_RIGHT) - v += rct.yw; - else /* (cflag == TOP_LEFT) */ - v += rct.xw; + /* Position to corner */ + vec4 rct = (is_inner) ? recti : rect; + if (cflag == BOTTOM_LEFT) + v += rct.xz; + else if (cflag == BOTTOM_RIGHT) + v += rct.yz; + else if (cflag == TOP_RIGHT) + v += rct.yw; + else /* (cflag == TOP_LEFT) */ + v += rct.xw; - gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(v, 0.0, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl index 84e44837264..16424ece2b6 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl @@ -7,6 +7,6 @@ in vec3 pos; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - gl_ClipDistance[0] = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_ClipDistance[0] = dot(ModelMatrix * vec4(pos, 1.0), ClipPlane); } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl index d4e6f697936..5b6a890ccc8 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_flat_color_vert.glsl @@ -15,20 +15,19 @@ flat out vec4 finalColor; void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; #if defined(USE_COLOR_U32) - finalColor = vec4( - ((color ) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 24) ) * (1.0f / 255.0f)); + finalColor = vec4(((color)&uint(0xFF)) * (1.0f / 255.0f), + ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 24)) * (1.0f / 255.0f)); #else - finalColor = color; + finalColor = color; #endif #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl index 29bdd03f7e3..03bee1b4e06 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundline_geom.glsl @@ -7,19 +7,19 @@ layout(line_strip, max_vertices = 2) out; void main() { - vec3 vert = gl_in[0].gl_Position.xyz; + vec3 vert = gl_in[0].gl_Position.xyz; - gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0); + gl_Position = ViewProjectionMatrix * vec4(vert.xyz, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0); + gl_Position = ViewProjectionMatrix * vec4(vert.xy, 0.0, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(vec3(vert.xy, 0.0)); + world_clip_planes_calc_clip_distance(vec3(vert.xy, 0.0)); #endif - EmitVertex(); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl index b08d87cdfa6..6786b7b7405 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_groundpoint_vert.glsl @@ -6,11 +6,11 @@ in vec3 pos; void main() { - vec4 pos_4d = vec4(pos.xy, 0.0, 1.0); - gl_Position = ViewProjectionMatrix * pos_4d; - gl_PointSize = 2.0; + vec4 pos_4d = vec4(pos.xy, 0.0, 1.0); + gl_Position = ViewProjectionMatrix * pos_4d; + gl_PointSize = 2.0; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(pos_4d.xyz); + world_clip_planes_calc_clip_distance(pos_4d.xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl index eb877ab20b6..0fb8d06e317 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_image_vert.glsl @@ -7,6 +7,6 @@ out vec2 texCoord_interp; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f); - texCoord_interp = texCoord; + gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f); + texCoord_interp = texCoord; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl index 84fbf977846..9fe63c65054 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_legacy_vert.glsl @@ -17,10 +17,10 @@ noperspective out vec4 color_geom; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - /* Hack - prevent stupid GLSL compiler to optimize out unused viewport_size uniform, which gives crash! */ - distance_along_line = viewport_size.x * 0.000001f - viewport_size.x * 0.0000009f; + /* Hack - prevent stupid GLSL compiler to optimize out unused viewport_size uniform, which gives crash! */ + distance_along_line = viewport_size.x * 0.000001f - viewport_size.x * 0.0000009f; - color_geom = color; + color_geom = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl index 791f634c6cd..47ca09b5e72 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_line_dashed_uniform_color_vert.glsl @@ -20,10 +20,10 @@ out vec4 color_vert; void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - color_vert = color; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; + color_vert = color; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl index e6b8fed7265..7fa571343a2 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_smooth_color_vert.glsl @@ -16,7 +16,7 @@ out vec4 finalColor; void main() { - normal = normalize(NormalMatrix * nor); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = color; + normal = normalize(NormalMatrix * nor); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl index a3f447a85f9..252fee87015 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_normal_vert.glsl @@ -8,6 +8,6 @@ out vec3 normal; void main() { - normal = normalize(NormalMatrix * nor); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + normal = normalize(NormalMatrix * nor); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl index 4196dbbad02..12594b04da9 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_passthrough_vert.glsl @@ -7,10 +7,10 @@ in vec3 pos; void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = pos_4d; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl index 2fe9c0623fa..776656fc2df 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl @@ -7,6 +7,6 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl index f39c10e8310..f5b6d2ea3ed 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl @@ -8,22 +8,23 @@ uniform float size; in vec3 pos; out vec2 radii; -void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - gl_PointSize = size; +void main() +{ + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; + gl_PointSize = size; - // calculate concentric radii in pixels - float radius = 0.5 * size; + // calculate concentric radii in pixels + float radius = 0.5 * size; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; - // convert to PointCoord units - radii /= size; + // convert to PointCoord units + radii /= size; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl index e14032a9694..8bd344ed0e7 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl @@ -9,24 +9,25 @@ uniform float outlineWidth; in vec3 pos; out vec4 radii; -void main() { - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; - gl_PointSize = size; +void main() +{ + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; + gl_PointSize = size; - // calculate concentric radii in pixels - float radius = 0.5 * size; + // calculate concentric radii in pixels + float radius = 0.5 * size; - // start at the outside and progress toward the center - radii[0] = radius; - radii[1] = radius - 1.0; - radii[2] = radius - outlineWidth; - radii[3] = radius - outlineWidth - 1.0; + // start at the outside and progress toward the center + radii[0] = radius; + radii[1] = radius - 1.0; + radii[2] = radius - outlineWidth; + radii[3] = radius - outlineWidth - 1.0; - // convert to PointCoord units - radii /= size; + // convert to PointCoord units + radii /= size; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl index e14b9535c89..3bc72535266 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl @@ -8,7 +8,7 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - gl_PointSize = size; - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_PointSize = size; + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl index e4f173ab617..fc61be936fe 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_varying_size_vert.glsl @@ -6,6 +6,6 @@ in float size; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - gl_PointSize = size; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_PointSize = size; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl index bdb26981399..0d58909efd8 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_selection_id_vert.glsl @@ -13,14 +13,14 @@ flat out uint id; void main() { #ifndef UNIFORM_ID - id = offset + color; + id = offset + color; #endif - vec4 pos_4d = vec4(pos, 1.0); - gl_Position = ModelViewProjectionMatrix * pos_4d; + vec4 pos_4d = vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * pos_4d; #ifdef USE_WORLD_CLIP_PLANES - /* Warning: ModelMatrix is typically used but select drawing is different. */ - world_clip_planes_calc_clip_distance(pos); + /* Warning: ModelMatrix is typically used but select drawing is different. */ + world_clip_planes_calc_clip_distance(pos); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl index 41fdefd22e8..7bd44ba9b88 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_frag.glsl @@ -4,5 +4,5 @@ out vec4 fragColor; void main() { - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl index 955ce07780c..4eafb7b7be3 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_smooth_color_vert.glsl @@ -12,10 +12,10 @@ out vec4 finalColor; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl index 9fc748b292b..70bb881ffea 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_vert.glsl @@ -9,9 +9,9 @@ in vec3 pos; void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl index 6964b2a0c39..e34b86ac1ce 100644 --- a/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_cfg_world_clip_lib.glsl @@ -1,25 +1,25 @@ #ifdef USE_WORLD_CLIP_PLANES -#if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER) +# if defined(GPU_VERTEX_SHADER) || defined(GPU_GEOMETRY_SHADER) uniform vec4 WorldClipPlanes[6]; void world_clip_planes_calc_clip_distance(vec3 wpos) { - gl_ClipDistance[0] = dot(WorldClipPlanes[0].xyz, wpos) + WorldClipPlanes[0].w; - gl_ClipDistance[1] = dot(WorldClipPlanes[1].xyz, wpos) + WorldClipPlanes[1].w; - gl_ClipDistance[2] = dot(WorldClipPlanes[2].xyz, wpos) + WorldClipPlanes[2].w; - gl_ClipDistance[3] = dot(WorldClipPlanes[3].xyz, wpos) + WorldClipPlanes[3].w; - gl_ClipDistance[4] = dot(WorldClipPlanes[4].xyz, wpos) + WorldClipPlanes[4].w; - gl_ClipDistance[5] = dot(WorldClipPlanes[5].xyz, wpos) + WorldClipPlanes[5].w; + gl_ClipDistance[0] = dot(WorldClipPlanes[0].xyz, wpos) + WorldClipPlanes[0].w; + gl_ClipDistance[1] = dot(WorldClipPlanes[1].xyz, wpos) + WorldClipPlanes[1].w; + gl_ClipDistance[2] = dot(WorldClipPlanes[2].xyz, wpos) + WorldClipPlanes[2].w; + gl_ClipDistance[3] = dot(WorldClipPlanes[3].xyz, wpos) + WorldClipPlanes[3].w; + gl_ClipDistance[4] = dot(WorldClipPlanes[4].xyz, wpos) + WorldClipPlanes[4].w; + gl_ClipDistance[5] = dot(WorldClipPlanes[5].xyz, wpos) + WorldClipPlanes[5].w; } -#endif +# endif -#define world_clip_planes_set_clip_distance(c) \ -{ \ - gl_ClipDistance[0] = (c)[0]; \ - gl_ClipDistance[1] = (c)[1]; \ - gl_ClipDistance[2] = (c)[2]; \ - gl_ClipDistance[3] = (c)[3]; \ - gl_ClipDistance[4] = (c)[4]; \ - gl_ClipDistance[5] = (c)[5]; \ -} +# define world_clip_planes_set_clip_distance(c) \ + { \ + gl_ClipDistance[0] = (c)[0]; \ + gl_ClipDistance[1] = (c)[1]; \ + gl_ClipDistance[2] = (c)[2]; \ + gl_ClipDistance[3] = (c)[3]; \ + gl_ClipDistance[4] = (c)[4]; \ + gl_ClipDistance[5] = (c)[5]; \ + } #endif diff --git a/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl index 545f6d19e21..156b6cb75ab 100644 --- a/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_checker_frag.glsl @@ -7,14 +7,12 @@ out vec4 fragColor; void main() { - vec2 phase = mod(gl_FragCoord.xy, (size*2)); + vec2 phase = mod(gl_FragCoord.xy, (size * 2)); - if ((phase.x > size && phase.y < size) || - (phase.x < size && phase.y > size)) - { - fragColor = color1; - } - else { - fragColor = color2; - } + if ((phase.x > size && phase.y < size) || (phase.x < size && phase.y > size)) { + fragColor = color1; + } + else { + fragColor = color2; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl index 60e71e19004..1b9fd48c77a 100644 --- a/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_depth_only_frag.glsl @@ -1,6 +1,6 @@ void main() { - // no color output, only depth (line below is implicit) - // gl_FragDepth = gl_FragCoord.z; + // no color output, only depth (line below is implicit) + // gl_FragDepth = gl_FragCoord.z; } diff --git a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl index beb71c58100..48979af4ad0 100644 --- a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl @@ -8,13 +8,12 @@ out vec4 fragColor; void main() { - float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2)); + float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2)); - if (phase < size1) - { - fragColor = color1; - } - else { - fragColor = color2; - } + if (phase < size1) { + fragColor = color1; + } + else { + fragColor = color2; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl index 4ed7ed56c11..a71dfba575b 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_ortho_vert.glsl @@ -11,7 +11,7 @@ uniform vec4 frontColor; uniform vec4 backColor; uniform vec4 silhouetteColor; -uniform vec3 eye; // direction we are looking +uniform vec3 eye; // direction we are looking uniform mat4 ModelViewProjectionMatrix; @@ -31,24 +31,24 @@ const vec4 nowhere = vec4(vec3(0.0), 1.0); void main() { - bool face_1_front = dot(N1, eye) > 0.0; - bool face_2_front = dot(N2, eye) > 0.0; - - vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0); - - if (face_1_front && face_2_front) { - // front-facing edge - gl_Position = drawFront ? position : nowhere; - finalColor = frontColor; - } - else if (face_1_front || face_2_front) { - // exactly one face is front-facing, silhouette edge - gl_Position = drawSilhouette ? position : nowhere; - finalColor = silhouetteColor; - } - else { - // back-facing edge - gl_Position = drawBack ? position : nowhere; - finalColor = backColor; - } + bool face_1_front = dot(N1, eye) > 0.0; + bool face_2_front = dot(N2, eye) > 0.0; + + vec4 position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + if (face_1_front && face_2_front) { + // front-facing edge + gl_Position = drawFront ? position : nowhere; + finalColor = frontColor; + } + else if (face_1_front || face_2_front) { + // exactly one face is front-facing, silhouette edge + gl_Position = drawSilhouette ? position : nowhere; + finalColor = silhouetteColor; + } + else { + // back-facing edge + gl_Position = drawBack ? position : nowhere; + finalColor = backColor; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl index e7632fcad15..3de14704781 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_geom.glsl @@ -30,31 +30,31 @@ flat out vec4 finalColor; void emitLine(vec4 color) { - gl_Position = ProjectionMatrix * MV_pos[0]; - EmitVertex(); - gl_Position = ProjectionMatrix * MV_pos[1]; - finalColor = color; - EmitVertex(); - EndPrimitive(); + gl_Position = ProjectionMatrix * MV_pos[0]; + EmitVertex(); + gl_Position = ProjectionMatrix * MV_pos[1]; + finalColor = color; + EmitVertex(); + EndPrimitive(); } void main() { - float finalEdgeClass = max(edgeClass[0], edgeClass[1]); - - if (finalEdgeClass > 0.0f) { - // front-facing edge - if (drawFront) - emitLine(frontColor); - } - else if (finalEdgeClass < 0.0f) { - // back-facing edge - if (drawBack) - emitLine(backColor); - } - else { - // exactly one face is front-facing, silhouette edge - if (drawSilhouette) - emitLine(silhouetteColor); - } + float finalEdgeClass = max(edgeClass[0], edgeClass[1]); + + if (finalEdgeClass > 0.0f) { + // front-facing edge + if (drawFront) + emitLine(frontColor); + } + else if (finalEdgeClass < 0.0f) { + // back-facing edge + if (drawBack) + emitLine(backColor); + } + else { + // exactly one face is front-facing, silhouette edge + if (drawSilhouette) + emitLine(silhouetteColor); + } } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl index 30b3bdb890d..ffd52a0a225 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_legacy_vert.glsl @@ -42,27 +42,27 @@ const vec4 invisible = vec4(0.0); bool front(vec3 N) { - vec4 xformed = ModelViewMatrix * vec4(pos, 1.0); - return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0; + vec4 xformed = ModelViewMatrix * vec4(pos, 1.0); + return dot(NormalMatrix * N, normalize(-xformed.xyz)) > 0.0; } void main() { - bool face_1_front = front(N1); - bool face_2_front = front(N2); - - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - - if (face_1_front && face_2_front) { - // front-facing edge - finalColor = drawFront ? frontColor : invisible; - } - else if (face_1_front || face_2_front) { - // exactly one face is front-facing, silhouette edge - finalColor = drawSilhouette ? silhouetteColor : invisible; - } - else { - // back-facing edge - finalColor = drawBack ? backColor : invisible; - } + bool face_1_front = front(N1); + bool face_2_front = front(N2); + + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + + if (face_1_front && face_2_front) { + // front-facing edge + finalColor = drawFront ? frontColor : invisible; + } + else if (face_1_front || face_2_front) { + // exactly one face is front-facing, silhouette edge + finalColor = drawSilhouette ? silhouetteColor : invisible; + } + else { + // back-facing edge + finalColor = drawBack ? backColor : invisible; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl index e1fb78dd1a9..c8b722e1d7e 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_front_back_persp_vert.glsl @@ -14,7 +14,7 @@ uniform mat4 ModelViewMatrix; uniform mat3 NormalMatrix; in vec3 pos; -in vec3 N1, N2; // normals of faces this edge joins (object coords) +in vec3 N1, N2; // normals of faces this edge joins (object coords) out vec4 MV_pos; out float edgeClass; @@ -23,22 +23,22 @@ out float edgeClass; bool front(vec3 N, vec3 eye) { - return dot(NormalMatrix * N, eye) > 0.0; + return dot(NormalMatrix * N, eye) > 0.0; } void main() { - MV_pos = ModelViewMatrix * vec4(pos, 1.0); + MV_pos = ModelViewMatrix * vec4(pos, 1.0); - vec3 eye = normalize(-MV_pos.xyz); + vec3 eye = normalize(-MV_pos.xyz); - bool face_1_front = front(N1, eye); - bool face_2_front = front(N2, eye); + bool face_1_front = front(N1, eye); + bool face_2_front = front(N2, eye); - if (face_1_front && face_2_front) - edgeClass = 1.0; // front-facing edge - else if (face_1_front || face_2_front) - edgeClass = 0.0; // exactly one face is front-facing, silhouette edge - else - edgeClass = -1.0; // back-facing edge + if (face_1_front && face_2_front) + edgeClass = 1.0; // front-facing edge + else if (face_1_front || face_2_front) + edgeClass = 0.0; // exactly one face is front-facing, silhouette edge + else + edgeClass = -1.0; // back-facing edge } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl index 0538c037dcf..7b35f67dd54 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_frag.glsl @@ -4,17 +4,18 @@ const float transitionWidth = 1.0; uniform vec4 fillColor = vec4(0); -uniform vec4 outlineColor = vec4(0,0,0,1); +uniform vec4 outlineColor = vec4(0, 0, 0, 1); noperspective in vec3 distanceToOutline; out vec4 FragColor; -void main() { - float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z); +void main() +{ + float edgeness = min(min(distanceToOutline.x, distanceToOutline.y), distanceToOutline.z); #if SMOOTH - FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness)); + FragColor = mix(outlineColor, fillColor, smoothstep(0, transitionWidth, edgeness)); #else - FragColor = (edgeness <= 0) ? outlineColor : fillColor; + FragColor = (edgeness <= 0) ? outlineColor : fillColor; #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl index ad0dccb6c81..48fff1629fd 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_geom.glsl @@ -1,5 +1,5 @@ layout(triangles) in; -layout(triangle_strip, max_vertices=3) out; +layout(triangle_strip, max_vertices = 3) out; uniform float outlineWidth = 1.0; uniform vec2 viewportSize; @@ -10,58 +10,63 @@ in float widthModulator[]; noperspective out vec3 distanceToOutline; // project to screen space -vec2 proj(int axis) { - vec4 pos = pos_xformed[axis]; - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +vec2 proj(int axis) +{ + vec4 pos = pos_xformed[axis]; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } -float dist(vec2 pos[3], int v) { - // current vertex position - vec2 vpos = pos[v]; - // endpoints of opposite edge - vec2 e1 = pos[(v + 1) % 3]; - vec2 e2 = pos[(v + 2) % 3]; +float dist(vec2 pos[3], int v) +{ + // current vertex position + vec2 vpos = pos[v]; + // endpoints of opposite edge + vec2 e1 = pos[(v + 1) % 3]; + vec2 e2 = pos[(v + 2) % 3]; - float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify - return abs_det / distance(e2, e1); + float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify + return abs_det / distance(e2, e1); } vec3 distance[3]; -void clearEdge(int v) { - float distant = 10 * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] += distant; +void clearEdge(int v) +{ + float distant = 10 * outlineWidth; + for (int i = 0; i < 3; ++i) + distance[i][v] += distant; } -void modulateEdge(int v) { - float offset = min(widthModulator[v],1) * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] -= offset; +void modulateEdge(int v) +{ + float offset = min(widthModulator[v], 1) * outlineWidth; + for (int i = 0; i < 3; ++i) + distance[i][v] -= offset; } -void main() { - vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); +void main() +{ + vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); - for (int v = 0; v < 3; ++v) - distance[v] = vec3(0); + for (int v = 0; v < 3; ++v) + distance[v] = vec3(0); - for (int v = 0; v < 3; ++v) { - if (widthModulator[v] > 0) { - distance[v][v] = dist(pos, v); - modulateEdge(v); - } - } + for (int v = 0; v < 3; ++v) { + if (widthModulator[v] > 0) { + distance[v][v] = dist(pos, v); + modulateEdge(v); + } + } - for (int v = 0; v < 3; ++v) - if (widthModulator[v] <= 0) - clearEdge(v); + for (int v = 0; v < 3; ++v) + if (widthModulator[v] <= 0) + clearEdge(v); - for (int v = 0; v < 3; ++v) { - gl_Position = pos_xformed[v]; - distanceToOutline = distance[v]; - EmitVertex(); - } + for (int v = 0; v < 3; ++v) { + gl_Position = pos_xformed[v]; + distanceToOutline = distance[v]; + EmitVertex(); + } - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl index ec692e210c2..12f5a2c7811 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_simple_geom.glsl @@ -1,5 +1,5 @@ layout(triangles) in; -layout(triangle_strip, max_vertices=3) out; +layout(triangle_strip, max_vertices = 3) out; uniform float outlineWidth = 1.0; uniform vec2 viewportSize; @@ -7,46 +7,50 @@ uniform vec2 viewportSize; noperspective out vec3 distanceToOutline; // project to screen space -vec2 proj(int axis) { - vec4 pos = gl_in[axis].gl_Position; - return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; +vec2 proj(int axis) +{ + vec4 pos = gl_in[axis].gl_Position; + return (0.5 * (pos.xy / pos.w) + 0.5) * viewportSize; } -float dist(vec2 pos[3], int v) { - // current vertex position - vec2 vpos = pos[v]; - // endpoints of opposite edge - vec2 e1 = pos[(v + 1) % 3]; - vec2 e2 = pos[(v + 2) % 3]; +float dist(vec2 pos[3], int v) +{ + // current vertex position + vec2 vpos = pos[v]; + // endpoints of opposite edge + vec2 e1 = pos[(v + 1) % 3]; + vec2 e2 = pos[(v + 2) % 3]; - float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify - return abs_det / distance(e2, e1); + float abs_det = length(cross(vec3(vpos - e1, 0), vec3(vpos - e2, 0))); // could simplify + return abs_det / distance(e2, e1); } vec3 distance[3]; -void modulateEdge(int v) { - float offset = 0.5 * outlineWidth; - for (int i = 0; i < 3; ++i) - distance[i][v] -= offset; +void modulateEdge(int v) +{ + float offset = 0.5 * outlineWidth; + for (int i = 0; i < 3; ++i) + distance[i][v] -= offset; } -void main() { - vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); +void main() +{ + vec2 pos[3] = vec2[3](proj(0), proj(1), proj(2)); - for (int v = 0; v < 3; ++v) - distance[v] = vec3(0); + for (int v = 0; v < 3; ++v) + distance[v] = vec3(0); - for (int v = 0; v < 3; ++v) { - distance[v][v] = dist(pos, v); - modulateEdge(v); - } + for (int v = 0; v < 3; ++v) { + distance[v][v] = dist(pos, v); + modulateEdge(v); + } - for (int v = 0; v < 3; ++v) { - gl_Position = gl_in[v].gl_Position; - distanceToOutline = distance[v]; - EmitVertex(); - } + for (int v = 0; v < 3; ++v) { + gl_Position = gl_in[v].gl_Position; + distanceToOutline = distance[v]; + EmitVertex(); + } - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl index fb1d0aafe05..33615ac36e5 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl @@ -7,7 +7,8 @@ in float edgeWidthModulator; out vec4 pos_xformed; out float widthModulator; -void main() { - pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0); - widthModulator = edgeWidthModulator; +void main() +{ + pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0); + widthModulator = edgeWidthModulator; } diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl index cefae1021d2..d1a36c3ee38 100644 --- a/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl @@ -4,8 +4,8 @@ out vec4 fragColor; void main() { - if (finalColor.a > 0.0) - fragColor = finalColor; - else - discard; + if (finalColor.a > 0.0) + fragColor = finalColor; + else + discard; } diff --git a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl index d738ed5ddb2..6c214534812 100644 --- a/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_flat_color_frag.glsl @@ -4,5 +4,5 @@ out vec4 fragColor; void main() { - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl b/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl index aa6f30531ae..8e1287c483a 100644 --- a/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_flat_id_frag.glsl @@ -4,5 +4,5 @@ out uint fragId; void main() { - fragId = finalId; + fragId = finalId; } diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl index 705b79cbf56..f62040589e5 100644 --- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl +++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl @@ -7,9 +7,11 @@ uniform int osd_active_uv_offset; layout(lines_adjacency) in; layout(triangle_strip, max_vertices = 4) out; -in block { - VertexData v; -} inpt[]; +in block +{ + VertexData v; +} +inpt[]; /* compatibility */ out vec3 varnormal; @@ -18,98 +20,98 @@ out vec3 varposition; uniform bool osd_flat_shading; uniform int osd_fvar_count; -#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \ - { \ - vec2 v[4]; \ - int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \ - for (int i = 0; i < 4; ++i) { \ - int index = (primOffset + i) * osd_fvar_count + fvarOffset; \ - v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \ - texelFetch(FVarDataBuffer, index + 1).s); \ - } \ - result = mix(mix(v[0], v[1], tessCoord.s), \ - mix(v[3], v[2], tessCoord.s), \ - tessCoord.t); \ - } - -# define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \ - { \ - vec2 tmp; \ - INTERP_FACE_VARYING_2(tmp, fvarOffset, tessCoord); \ - result = vec3(tmp, 0); \ - } +#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \ + { \ + vec2 v[4]; \ + int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \ + for (int i = 0; i < 4; ++i) { \ + int index = (primOffset + i) * osd_fvar_count + fvarOffset; \ + v[i] = vec2(texelFetch(FVarDataBuffer, index).s, texelFetch(FVarDataBuffer, index + 1).s); \ + } \ + result = mix(mix(v[0], v[1], tessCoord.s), mix(v[3], v[2], tessCoord.s), tessCoord.t); \ + } + +#define INTERP_FACE_VARYING_ATT_2(result, fvarOffset, tessCoord) \ + { \ + vec2 tmp; \ + INTERP_FACE_VARYING_2(tmp, fvarOffset, tessCoord); \ + result = vec3(tmp, 0); \ + } uniform samplerBuffer FVarDataBuffer; uniform isamplerBuffer FVarDataOffsetBuffer; -out block { - VertexData v; -} outpt; +out block +{ + VertexData v; +} +outpt; void set_mtface_vertex_attrs(vec2 st); void emit_flat(int index, vec3 normal) { - outpt.v.position = inpt[index].v.position; - outpt.v.normal = normal; + outpt.v.position = inpt[index].v.position; + outpt.v.normal = normal; - /* Compatibility */ - varnormal = outpt.v.normal; - varposition = outpt.v.position.xyz; + /* Compatibility */ + varnormal = outpt.v.normal; + varposition = outpt.v.position.xyz; - /* TODO(sergey): Only uniform subdivisions atm. */ - vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1)); - vec2 st = quadst[index]; + /* TODO(sergey): Only uniform subdivisions atm. */ + vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1)); + vec2 st = quadst[index]; - INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); + INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); - set_mtface_vertex_attrs(st); + set_mtface_vertex_attrs(st); - gl_Position = ProjectionMatrix * inpt[index].v.position; - EmitVertex(); + gl_Position = ProjectionMatrix * inpt[index].v.position; + EmitVertex(); } void emit_smooth(int index) { - outpt.v.position = inpt[index].v.position; - outpt.v.normal = inpt[index].v.normal; + outpt.v.position = inpt[index].v.position; + outpt.v.normal = inpt[index].v.normal; - /* Compatibility */ - varnormal = outpt.v.normal; - varposition = outpt.v.position.xyz; + /* Compatibility */ + varnormal = outpt.v.normal; + varposition = outpt.v.position.xyz; - /* TODO(sergey): Only uniform subdivisions atm. */ - vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1)); - vec2 st = quadst[index]; + /* TODO(sergey): Only uniform subdivisions atm. */ + vec2 quadst[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(1, 1), vec2(0, 1)); + vec2 st = quadst[index]; - INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); + INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st); - set_mtface_vertex_attrs(st); + set_mtface_vertex_attrs(st); - gl_Position = ProjectionMatrix * inpt[index].v.position; - EmitVertex(); + gl_Position = ProjectionMatrix * inpt[index].v.position; + EmitVertex(); } void main() { - gl_PrimitiveID = gl_PrimitiveIDIn; - - if (osd_flat_shading) { - vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz; - vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz; - vec3 flat_normal = normalize(cross(B, A)); - emit_flat(0, flat_normal); - emit_flat(1, flat_normal); - emit_flat(3, flat_normal); - emit_flat(2, flat_normal); - } - else { - emit_smooth(0); - emit_smooth(1); - emit_smooth(3); - emit_smooth(2); - } - EndPrimitive(); + gl_PrimitiveID = gl_PrimitiveIDIn; + + if (osd_flat_shading) { + vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz; + vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz; + vec3 flat_normal = normalize(cross(B, A)); + emit_flat(0, flat_normal); + emit_flat(1, flat_normal); + emit_flat(3, flat_normal); + emit_flat(2, flat_normal); + } + else { + emit_smooth(0); + emit_smooth(1); + emit_smooth(3); + emit_smooth(2); + } + EndPrimitive(); } -void set_mtface_vertex_attrs(vec2 st) { +void set_mtface_vertex_attrs(vec2 st) +{ diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl index 328fbbe26a1..946fc752e17 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_frag.glsl @@ -29,138 +29,152 @@ in vec2 texCoord_interp; out vec4 fragColor; #define texture2D texture -void set_color(in vec4 color, in vec4 color2, in vec4 tcolor, in float mixv, in float factor, - in int tmix, in int flip, out vec4 ocolor) +void set_color(in vec4 color, + in vec4 color2, + in vec4 tcolor, + in float mixv, + in float factor, + in int tmix, + in int flip, + out vec4 ocolor) { - /* full color A */ - if (mixv == 1.0) { - if (tmix == 1) { - if (flip == 0) { - ocolor = color; - } - else { - ocolor = tcolor; - } - } - else { - if (flip == 0) { - ocolor = color; - } - else { - ocolor = color2; - } - } - } - /* full color B */ - else if (mixv == 0.0) { - if (tmix == 1) { - if (flip == 0) { - ocolor = tcolor; - } - else { - ocolor = color; - } - } - else { - if (flip == 0) { - ocolor = color2; - } - else { - ocolor = color; - } - } - } - /* mix of colors */ - else { - if (tmix == 1) { - if (flip == 0) { - ocolor = mix(color, tcolor, factor); - } - else { - ocolor = mix(tcolor, color, factor); - } - } - else { - if (flip == 0) { - ocolor = mix(color, color2, factor); - } - else { - ocolor = mix(color2, color, factor); - } - } - } + /* full color A */ + if (mixv == 1.0) { + if (tmix == 1) { + if (flip == 0) { + ocolor = color; + } + else { + ocolor = tcolor; + } + } + else { + if (flip == 0) { + ocolor = color; + } + else { + ocolor = color2; + } + } + } + /* full color B */ + else if (mixv == 0.0) { + if (tmix == 1) { + if (flip == 0) { + ocolor = tcolor; + } + else { + ocolor = color; + } + } + else { + if (flip == 0) { + ocolor = color2; + } + else { + ocolor = color; + } + } + } + /* mix of colors */ + else { + if (tmix == 1) { + if (flip == 0) { + ocolor = mix(color, tcolor, factor); + } + else { + ocolor = mix(tcolor, color, factor); + } + } + else { + if (flip == 0) { + ocolor = mix(color, color2, factor); + } + else { + ocolor = mix(color2, color, factor); + } + } + } } void main() { - vec2 t_center = vec2(0.5, 0.5); - mat2 matrot_tex = mat2(cos(t_angle), -sin(t_angle), sin(t_angle), cos(t_angle)); - vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + t_offset; - vec4 tmp_color = texture2D(myTexture, rot_tex * t_scale); - vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * t_opacity); - vec4 chesscolor; + vec2 t_center = vec2(0.5, 0.5); + mat2 matrot_tex = mat2(cos(t_angle), -sin(t_angle), sin(t_angle), cos(t_angle)); + vec2 rot_tex = (matrot_tex * (texCoord_interp - t_center)) + t_center + t_offset; + vec4 tmp_color = texture2D(myTexture, rot_tex * t_scale); + vec4 text_color = vec4(tmp_color[0], tmp_color[1], tmp_color[2], tmp_color[3] * t_opacity); + vec4 chesscolor; - /* solid fill */ - if (fill_type == SOLID) { - if (t_mix == 1) { - fragColor = mix(color, text_color, mix_factor); - } - else { - fragColor = color; - } - } - else { - vec2 center = vec2(0.5, 0.5) + g_shift; - mat2 matrot = mat2(cos(g_angle), -sin(g_angle), sin(g_angle), cos(g_angle)); - vec2 rot = (((matrot * (texCoord_interp - center)) + center) * g_scale) + g_shift; - /* gradient */ - if (fill_type == GRADIENT) { - set_color(color, color2, text_color, mix_factor, rot.x - mix_factor + 0.5, t_mix, t_flip, fragColor); - } - /* radial gradient */ - if (fill_type == RADIAL) { - float in_rad = g_radius * mix_factor; - float ex_rad = g_radius - in_rad; - float intensity = 0; - float distance = length((center - texCoord_interp) * g_scale); - if (distance > g_radius) { - discard; - } - if (distance > in_rad) { - intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0); - } - set_color(color, color2, text_color, mix_factor, intensity, t_mix, t_flip, fragColor); - } - /* chessboard */ - if (fill_type == CHESS) { - vec2 pos = rot / g_boxsize; - if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) { - if (t_flip == 0) { - chesscolor = color; - } - else { - chesscolor = color2; - } - } - else { - if (t_flip == 0) { - chesscolor = color2; - } - else { - chesscolor = color; - } - } - /* mix with texture */ - if (t_mix == 1) { - fragColor = mix(chesscolor, text_color, mix_factor); - } - else { - fragColor = chesscolor; - } - } - /* texture */ - if (fill_type == TEXTURE) { - fragColor = text_color; - } - } + /* solid fill */ + if (fill_type == SOLID) { + if (t_mix == 1) { + fragColor = mix(color, text_color, mix_factor); + } + else { + fragColor = color; + } + } + else { + vec2 center = vec2(0.5, 0.5) + g_shift; + mat2 matrot = mat2(cos(g_angle), -sin(g_angle), sin(g_angle), cos(g_angle)); + vec2 rot = (((matrot * (texCoord_interp - center)) + center) * g_scale) + g_shift; + /* gradient */ + if (fill_type == GRADIENT) { + set_color(color, + color2, + text_color, + mix_factor, + rot.x - mix_factor + 0.5, + t_mix, + t_flip, + fragColor); + } + /* radial gradient */ + if (fill_type == RADIAL) { + float in_rad = g_radius * mix_factor; + float ex_rad = g_radius - in_rad; + float intensity = 0; + float distance = length((center - texCoord_interp) * g_scale); + if (distance > g_radius) { + discard; + } + if (distance > in_rad) { + intensity = clamp(((distance - in_rad) / ex_rad), 0.0, 1.0); + } + set_color(color, color2, text_color, mix_factor, intensity, t_mix, t_flip, fragColor); + } + /* chessboard */ + if (fill_type == CHESS) { + vec2 pos = rot / g_boxsize; + if ((fract(pos.x) < 0.5 && fract(pos.y) < 0.5) || + (fract(pos.x) > 0.5 && fract(pos.y) > 0.5)) { + if (t_flip == 0) { + chesscolor = color; + } + else { + chesscolor = color2; + } + } + else { + if (t_flip == 0) { + chesscolor = color2; + } + else { + chesscolor = color; + } + } + /* mix with texture */ + if (t_mix == 1) { + fragColor = mix(chesscolor, text_color, mix_factor); + } + else { + fragColor = chesscolor; + } + } + /* texture */ + if (fill_type == TEXTURE) { + fragColor = text_color; + } + } } diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl index 2bc381a3689..5e469fec42e 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_fill_vert.glsl @@ -6,6 +6,6 @@ out vec2 texCoord_interp; void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); - texCoord_interp = texCoord; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + texCoord_interp = texCoord; } diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl index 7bb7693d202..fc3f47c0aaa 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_frag.glsl @@ -5,16 +5,16 @@ out vec4 fragColor; void main() { - const vec2 center = vec2(0, 0.5); - vec4 tColor = vec4(mColor); - /* if alpha < 0, then encap */ - if (mColor.a < 0) { - tColor.a = tColor.a * -1.0; - float dist = length(mTexCoord - center); - if (dist > 0.25) { - discard; - } - } - /* Solid */ - fragColor = tColor; + const vec2 center = vec2(0, 0.5); + vec4 tColor = vec4(mColor); + /* if alpha < 0, then encap */ + if (mColor.a < 0) { + tColor.a = tColor.a * -1.0; + float dist = length(mTexCoord - center); + if (dist > 0.25) { + discard; + } + } + /* Solid */ + fragColor = tColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl index 6c7e2d17e06..fcef4c266e8 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_geom.glsl @@ -16,203 +16,211 @@ out vec2 mTexCoord; #define GP_XRAY_FRONT 0 #define GP_XRAY_3DSPACE 1 -#define GP_XRAY_BACK 2 +#define GP_XRAY_BACK 2 #define GPENCIL_FLATCAP 1 /* project 3d point to 2d on screen space */ vec2 toScreenSpace(vec4 vertex) { - return vec2(vertex.xy / vertex.w) * Viewport; + return vec2(vertex.xy / vertex.w) * Viewport; } /* get zdepth value */ float getZdepth(vec4 point) { - if (xraymode == GP_XRAY_FRONT) { - return 0.0; - } - if (xraymode == GP_XRAY_3DSPACE) { - return (point.z / point.w); - } - if (xraymode == GP_XRAY_BACK) { - return 1.0; - } - - /* in front by default */ - return 0.0; + if (xraymode == GP_XRAY_FRONT) { + return 0.0; + } + if (xraymode == GP_XRAY_3DSPACE) { + return (point.z / point.w); + } + if (xraymode == GP_XRAY_BACK) { + return 1.0; + } + + /* in front by default */ + return 0.0; } /* check equality but with a small tolerance */ bool is_equal(vec4 p1, vec4 p2) { - float limit = 0.0001; - float x = abs(p1.x - p2.x); - float y = abs(p1.y - p2.y); - float z = abs(p1.z - p2.z); + float limit = 0.0001; + float x = abs(p1.x - p2.x); + float y = abs(p1.y - p2.y); + float z = abs(p1.z - p2.z); - if ((x < limit) && (y < limit) && (z < limit)) { - return true; - } + if ((x < limit) && (y < limit) && (z < limit)) { + return true; + } - return false; + return false; } void main(void) { - float MiterLimit = 0.75; - - /* receive 4 points */ - vec4 P0 = gl_in[0].gl_Position; - vec4 P1 = gl_in[1].gl_Position; - vec4 P2 = gl_in[2].gl_Position; - vec4 P3 = gl_in[3].gl_Position; - - /* get the four vertices passed to the shader */ - vec2 sp0 = toScreenSpace(P0); // start of previous segment - vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment - vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment - vec2 sp3 = toScreenSpace(P3); // end of next segment - - /* culling outside viewport */ - vec2 area = Viewport * 4.0; - if (sp1.x < -area.x || sp1.x > area.x) return; - if (sp1.y < -area.y || sp1.y > area.y) return; - if (sp2.x < -area.x || sp2.x > area.x) return; - if (sp2.y < -area.y || sp2.y > area.y) return; - - /* determine the direction of each of the 3 segments (previous, current, next) */ - vec2 v0 = normalize(sp1 - sp0); - vec2 v1 = normalize(sp2 - sp1); - vec2 v2 = normalize(sp3 - sp2); - - /* determine the normal of each of the 3 segments (previous, current, next) */ - vec2 n0 = vec2(-v0.y, v0.x); - vec2 n1 = vec2(-v1.y, v1.x); - vec2 n2 = vec2(-v2.y, v2.x); - - /* determine miter lines by averaging the normals of the 2 segments */ - vec2 miter_a = normalize(n0 + n1); // miter at start of current segment - vec2 miter_b = normalize(n1 + n2); // miter at end of current segment - - /* determine the length of the miter by projecting it onto normal and then inverse it */ - float an1 = dot(miter_a, n1); - float bn1 = dot(miter_b, n2); - if (an1 == 0) an1 = 1; - if (bn1 == 0) bn1 = 1; - float length_a = finalThickness[1] / an1; - float length_b = finalThickness[2] / bn1; - if (length_a <= 0.0) length_a = 0.01; - if (length_b <= 0.0) length_b = 0.01; - - /* prevent excessively long miters at sharp corners */ - if (dot(v0, v1) < -MiterLimit) { - miter_a = n1; - length_a = finalThickness[1]; - - /* close the gap */ - if (dot(v0, n1) > 0) { - mTexCoord = vec2(0, 0); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0.5); - mColor = finalColor[1]; - gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - EndPrimitive(); - } - else { - mTexCoord = vec2(0, 1); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 1); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0.5); - mColor = finalColor[1]; - gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - EndPrimitive(); - } - } - - if (dot(v1, v2) < -MiterLimit) { - miter_b = n1; - length_b = finalThickness[2]; - } - - /* generate the start endcap (alpha < 0 used as endcap flag)*/ - float extend = (fill_stroke > 0) ? 2 : 1 ; - if ((caps_start != GPENCIL_FLATCAP) && is_equal(P0,P2)) { - mTexCoord = vec2(1, 0.5); - mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ; - vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0 * extend; - gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0); - mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ; - gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 1); - mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0) ; - gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - } - - /* generate the triangle strip */ - mTexCoord = vec2(0, 0); - mColor = finalColor[1]; - gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 1); - mColor = finalColor[1]; - gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0); - mColor = finalColor[2]; - gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 1); - mColor = finalColor[2]; - gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - /* generate the end endcap (alpha < 0 used as endcap flag)*/ - if ((caps_end != GPENCIL_FLATCAP) && is_equal(P1,P3)) { - mTexCoord = vec2(0, 1); - mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ; - gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = vec2(0, 0); - mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ; - gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - - mTexCoord = vec2(1, 0.5); - mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0) ; - vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0 * extend; - gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0); - EmitVertex(); - } - - EndPrimitive(); + float MiterLimit = 0.75; + + /* receive 4 points */ + vec4 P0 = gl_in[0].gl_Position; + vec4 P1 = gl_in[1].gl_Position; + vec4 P2 = gl_in[2].gl_Position; + vec4 P3 = gl_in[3].gl_Position; + + /* get the four vertices passed to the shader */ + vec2 sp0 = toScreenSpace(P0); // start of previous segment + vec2 sp1 = toScreenSpace(P1); // end of previous segment, start of current segment + vec2 sp2 = toScreenSpace(P2); // end of current segment, start of next segment + vec2 sp3 = toScreenSpace(P3); // end of next segment + + /* culling outside viewport */ + vec2 area = Viewport * 4.0; + if (sp1.x < -area.x || sp1.x > area.x) + return; + if (sp1.y < -area.y || sp1.y > area.y) + return; + if (sp2.x < -area.x || sp2.x > area.x) + return; + if (sp2.y < -area.y || sp2.y > area.y) + return; + + /* determine the direction of each of the 3 segments (previous, current, next) */ + vec2 v0 = normalize(sp1 - sp0); + vec2 v1 = normalize(sp2 - sp1); + vec2 v2 = normalize(sp3 - sp2); + + /* determine the normal of each of the 3 segments (previous, current, next) */ + vec2 n0 = vec2(-v0.y, v0.x); + vec2 n1 = vec2(-v1.y, v1.x); + vec2 n2 = vec2(-v2.y, v2.x); + + /* determine miter lines by averaging the normals of the 2 segments */ + vec2 miter_a = normalize(n0 + n1); // miter at start of current segment + vec2 miter_b = normalize(n1 + n2); // miter at end of current segment + + /* determine the length of the miter by projecting it onto normal and then inverse it */ + float an1 = dot(miter_a, n1); + float bn1 = dot(miter_b, n2); + if (an1 == 0) + an1 = 1; + if (bn1 == 0) + bn1 = 1; + float length_a = finalThickness[1] / an1; + float length_b = finalThickness[2] / bn1; + if (length_a <= 0.0) + length_a = 0.01; + if (length_b <= 0.0) + length_b = 0.01; + + /* prevent excessively long miters at sharp corners */ + if (dot(v0, v1) < -MiterLimit) { + miter_a = n1; + length_a = finalThickness[1]; + + /* close the gap */ + if (dot(v0, n1) > 0) { + mTexCoord = vec2(0, 0); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0.5); + mColor = finalColor[1]; + gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + EndPrimitive(); + } + else { + mTexCoord = vec2(0, 1); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - finalThickness[1] * n1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 1); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - finalThickness[1] * n0) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0.5); + mColor = finalColor[1]; + gl_Position = vec4(sp1 / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + EndPrimitive(); + } + } + + if (dot(v1, v2) < -MiterLimit) { + miter_b = n1; + length_b = finalThickness[2]; + } + + /* generate the start endcap (alpha < 0 used as endcap flag)*/ + float extend = (fill_stroke > 0) ? 2 : 1; + if ((caps_start != GPENCIL_FLATCAP) && is_equal(P0, P2)) { + mTexCoord = vec2(1, 0.5); + mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); + vec2 svn1 = normalize(sp1 - sp2) * length_a * 4.0 * extend; + gl_Position = vec4((sp1 + svn1) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0); + mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); + gl_Position = vec4((sp1 - (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 1); + mColor = vec4(finalColor[1].rgb, finalColor[1].a * -1.0); + gl_Position = vec4((sp1 + (length_a * 2.0) * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + } + + /* generate the triangle strip */ + mTexCoord = vec2(0, 0); + mColor = finalColor[1]; + gl_Position = vec4((sp1 + length_a * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 1); + mColor = finalColor[1]; + gl_Position = vec4((sp1 - length_a * miter_a) / Viewport, getZdepth(P1), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0); + mColor = finalColor[2]; + gl_Position = vec4((sp2 + length_b * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 1); + mColor = finalColor[2]; + gl_Position = vec4((sp2 - length_b * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + /* generate the end endcap (alpha < 0 used as endcap flag)*/ + if ((caps_end != GPENCIL_FLATCAP) && is_equal(P1, P3)) { + mTexCoord = vec2(0, 1); + mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); + gl_Position = vec4((sp2 + (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = vec2(0, 0); + mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); + gl_Position = vec4((sp2 - (length_b * 2.0) * miter_b) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + + mTexCoord = vec2(1, 0.5); + mColor = vec4(finalColor[2].rgb, finalColor[2].a * -1.0); + vec2 svn2 = normalize(sp2 - sp1) * length_b * 4.0 * extend; + gl_Position = vec4((sp2 + svn2) / Viewport, getZdepth(P2), 1.0); + EmitVertex(); + } + + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl index 968f913d4e4..07b4ae52110 100644 --- a/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_gpencil_stroke_vert.glsl @@ -1,7 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; uniform mat4 ProjectionMatrix; -uniform float pixsize; /* rv3d->pixsize */ +uniform float pixsize; /* rv3d->pixsize */ uniform int keep_size; uniform float objscale; uniform float pixfactor; @@ -19,14 +19,15 @@ float defaultpixsize = pixsize * (1000.0 / pixfactor); void main(void) { - gl_Position = ModelViewProjectionMatrix * vec4( pos, 1.0 ); - finalColor = color; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + finalColor = color; - if (keep_size == TRUE) { - finalThickness = thickness; - } - else { - float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : (thickness / defaultpixsize); - finalThickness = max(size * objscale, 1.0); - } + if (keep_size == TRUE) { + finalThickness = thickness; + } + else { + float size = (ProjectionMatrix[3][3] == 0.0) ? (thickness / (gl_Position.z * defaultpixsize)) : + (thickness / defaultpixsize); + finalThickness = max(size * objscale, 1.0); + } } diff --git a/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl index e2af83ec529..cf71d4ac0c5 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_alpha_color_frag.glsl @@ -7,8 +7,8 @@ uniform sampler2D image; void main() { - fragColor = texture(image, texCoord_interp).r * color.rgba; - /* Premul by alpha (not texture alpha) - * Use blending function GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); */ - fragColor.rgb *= color.a; + fragColor = texture(image, texCoord_interp).r * color.rgba; + /* Premul by alpha (not texture alpha) + * Use blending function GPU_blend_set_func(GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); */ + fragColor.rgb *= color.a; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl index ef8935cc7ba..6dc7a1618e1 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_color_frag.glsl @@ -7,5 +7,5 @@ uniform sampler2D image; void main() { - fragColor = texture(image, texCoord_interp) * color; + fragColor = texture(image, texCoord_interp) * color; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl index 10f4dfd5a87..0f2749362b9 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_depth_copy_frag.glsl @@ -6,7 +6,7 @@ uniform sampler2D image; void main() { - float depth = texture(image, texCoord_interp).r; - fragColor = vec4(depth); - gl_FragDepth = depth; + float depth = texture(image, texCoord_interp).r; + fragColor = vec4(depth); + gl_FragDepth = depth; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl index bcbe1f577fd..017b21076c8 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_depth_linear_frag.glsl @@ -8,9 +8,9 @@ uniform sampler2D image; void main() { - float depth = texture(image, texCoord_interp).r; + float depth = texture(image, texCoord_interp).r; - /* normalize */ - fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear)))); - fragColor.a = 1.0f; + /* normalize */ + fragColor.rgb = vec3((2.0f * znear) / (zfar + znear - (depth * (zfar - znear)))); + fragColor.a = 1.0f; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl index 1ac0d68b35f..dfbaaeda7b5 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_desaturate_frag.glsl @@ -8,7 +8,7 @@ uniform sampler2D image; void main() { - vec4 tex = texture(image, texCoord_interp); - tex.rgb = ((0.3333333 * factor) * vec3(tex.r + tex.g + tex.b)) + (tex.rgb * (1.0 - factor)); - fragColor = tex * color; + vec4 tex = texture(image, texCoord_interp); + tex.rgb = ((0.3333333 * factor) * vec3(tex.r + tex.g + tex.b)) + (tex.rgb * (1.0 - factor)); + fragColor = tex * color; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl index 6eeab8ca7e8..aff6ddf01bf 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_frag.glsl @@ -6,5 +6,5 @@ uniform sampler2D image; void main() { - fragColor = texture(image, texCoord_interp); + fragColor = texture(image, texCoord_interp); } diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl index d95645f58e5..9b9d8149e09 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl @@ -1,8 +1,8 @@ /* Keep these in sync with GPU_shader.h */ -#define INTERLACE_ROW 0 -#define INTERLACE_COLUMN 1 -#define INTERLACE_CHECKERBOARD 2 +#define INTERLACE_ROW 0 +#define INTERLACE_COLUMN 1 +#define INTERLACE_CHECKERBOARD 2 in vec2 texCoord_interp; out vec4 fragColor; @@ -13,22 +13,23 @@ uniform sampler2D image_b; bool interlace() { - if (interlace_id == INTERLACE_CHECKERBOARD) { - return (int(gl_FragCoord.x + gl_FragCoord.y) & 1) != 0; - } - else if (interlace_id == INTERLACE_ROW) { - return (int(gl_FragCoord.y) & 1) != 0; - } - else if (interlace_id == INTERLACE_COLUMN) { - return (int(gl_FragCoord.x) & 1) != 0; - } + if (interlace_id == INTERLACE_CHECKERBOARD) { + return (int(gl_FragCoord.x + gl_FragCoord.y) & 1) != 0; + } + else if (interlace_id == INTERLACE_ROW) { + return (int(gl_FragCoord.y) & 1) != 0; + } + else if (interlace_id == INTERLACE_COLUMN) { + return (int(gl_FragCoord.x) & 1) != 0; + } } void main() { - if (interlace()) { - fragColor = texture(image_a, texCoord_interp); - } else { - fragColor = texture(image_b, texCoord_interp); - } + if (interlace()) { + fragColor = texture(image_a, texCoord_interp); + } + else { + fragColor = texture(image_b, texCoord_interp); + } } diff --git a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl index 97eb3afc177..d843550cd9a 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_linear_frag.glsl @@ -9,22 +9,23 @@ out vec4 fragColor; float linearrgb_to_srgb(float c) { - if (c < 0.0031308) - return (c < 0.0) ? 0.0 : c * 12.92; - else - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + if (c < 0.0031308) + return (c < 0.0) ? 0.0 : c * 12.92; + else + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; } void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) { - col_to.r = linearrgb_to_srgb(col_from.r); - col_to.g = linearrgb_to_srgb(col_from.g); - col_to.b = linearrgb_to_srgb(col_from.b); - col_to.a = col_from.a; + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; } -void main() { - fragColor = texture(image, texCoord_interp.st); +void main() +{ + fragColor = texture(image, texCoord_interp.st); - linearrgb_to_srgb(fragColor, fragColor); + linearrgb_to_srgb(fragColor, fragColor); } diff --git a/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl index 4a45d03175e..e5078d722b4 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_mask_uniform_color_frag.glsl @@ -7,6 +7,6 @@ uniform vec4 color; void main() { - fragColor.a = texture(image, texCoord_interp).a * color.a; - fragColor.rgb = color.rgb; + fragColor.a = texture(image, texCoord_interp).a * color.a; + fragColor.rgb = color.rgb; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl index 51092d56e5e..613352b4ac8 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_modulate_alpha_frag.glsl @@ -7,6 +7,6 @@ uniform sampler2D image; void main() { - fragColor = texture(image, texCoord_interp); - fragColor.a *= alpha; + fragColor = texture(image, texCoord_interp); + fragColor.a *= alpha; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl index f763b491b59..ca425374a1b 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_multisample_resolve_frag.glsl @@ -5,115 +5,115 @@ uniform sampler2DMS colorMulti; out vec4 fragColor; #if SAMPLES > 16 -#error "Too many samples" +# error "Too many samples" #endif void main() { - ivec2 texel = ivec2(gl_FragCoord.xy); + ivec2 texel = ivec2(gl_FragCoord.xy); - bvec4 b1, b2, b3, b4; - vec4 w1, w2, w3, w4; - vec4 d1, d2, d3, d4; - vec4 c1, c2, c3, c4, c5, c6, c7, c8; - vec4 c9, c10, c11, c12, c13, c14, c15, c16; - d1 = d2 = d3 = d4 = vec4(0.5); - w1 = w2 = w3 = w4 = vec4(0.0); - c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0); - c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0); + bvec4 b1, b2, b3, b4; + vec4 w1, w2, w3, w4; + vec4 d1, d2, d3, d4; + vec4 c1, c2, c3, c4, c5, c6, c7, c8; + vec4 c9, c10, c11, c12, c13, c14, c15, c16; + d1 = d2 = d3 = d4 = vec4(0.5); + w1 = w2 = w3 = w4 = vec4(0.0); + c1 = c2 = c3 = c4 = c5 = c6 = c7 = c8 = vec4(0.0); + c9 = c10 = c11 = c12 = c13 = c14 = c15 = c16 = vec4(0.0); #ifdef USE_DEPTH - /* Depth */ - d1.x = texelFetch(depthMulti, texel, 0).r; - d1.y = texelFetch(depthMulti, texel, 1).r; + /* Depth */ + d1.x = texelFetch(depthMulti, texel, 0).r; + d1.y = texelFetch(depthMulti, texel, 1).r; # if SAMPLES > 2 - d1.z = texelFetch(depthMulti, texel, 2).r; - d1.w = texelFetch(depthMulti, texel, 3).r; + d1.z = texelFetch(depthMulti, texel, 2).r; + d1.w = texelFetch(depthMulti, texel, 3).r; # endif # if SAMPLES > 4 - d2.x = texelFetch(depthMulti, texel, 4).r; - d2.y = texelFetch(depthMulti, texel, 5).r; - d2.z = texelFetch(depthMulti, texel, 6).r; - d2.w = texelFetch(depthMulti, texel, 7).r; + d2.x = texelFetch(depthMulti, texel, 4).r; + d2.y = texelFetch(depthMulti, texel, 5).r; + d2.z = texelFetch(depthMulti, texel, 6).r; + d2.w = texelFetch(depthMulti, texel, 7).r; # endif # if SAMPLES > 8 - d3.x = texelFetch(depthMulti, texel, 8).r; - d3.y = texelFetch(depthMulti, texel, 9).r; - d3.z = texelFetch(depthMulti, texel, 10).r; - d3.w = texelFetch(depthMulti, texel, 11).r; - d4.x = texelFetch(depthMulti, texel, 12).r; - d4.y = texelFetch(depthMulti, texel, 13).r; - d4.z = texelFetch(depthMulti, texel, 14).r; - d4.w = texelFetch(depthMulti, texel, 15).r; + d3.x = texelFetch(depthMulti, texel, 8).r; + d3.y = texelFetch(depthMulti, texel, 9).r; + d3.z = texelFetch(depthMulti, texel, 10).r; + d3.w = texelFetch(depthMulti, texel, 11).r; + d4.x = texelFetch(depthMulti, texel, 12).r; + d4.y = texelFetch(depthMulti, texel, 13).r; + d4.z = texelFetch(depthMulti, texel, 14).r; + d4.w = texelFetch(depthMulti, texel, 15).r; # endif #endif - /* COLOR */ - b1 = notEqual(d1, vec4(1.0)); - if (any(b1)) { - c1 = texelFetch(colorMulti, texel, 0); - c2 = texelFetch(colorMulti, texel, 1); + /* COLOR */ + b1 = notEqual(d1, vec4(1.0)); + if (any(b1)) { + c1 = texelFetch(colorMulti, texel, 0); + c2 = texelFetch(colorMulti, texel, 1); #if SAMPLES > 2 - c3 = texelFetch(colorMulti, texel, 2); - c4 = texelFetch(colorMulti, texel, 3); + c3 = texelFetch(colorMulti, texel, 2); + c4 = texelFetch(colorMulti, texel, 3); #endif - w1 = vec4(b1); - } + w1 = vec4(b1); + } #if SAMPLES > 4 - b2 = notEqual(d2, vec4(1.0)); - if (any(b2)) { - c5 = texelFetch(colorMulti, texel, 4); - c6 = texelFetch(colorMulti, texel, 5); - c7 = texelFetch(colorMulti, texel, 6); - c8 = texelFetch(colorMulti, texel, 7); - w2 = vec4(b2); - } + b2 = notEqual(d2, vec4(1.0)); + if (any(b2)) { + c5 = texelFetch(colorMulti, texel, 4); + c6 = texelFetch(colorMulti, texel, 5); + c7 = texelFetch(colorMulti, texel, 6); + c8 = texelFetch(colorMulti, texel, 7); + w2 = vec4(b2); + } #endif #if SAMPLES > 8 - b3 = notEqual(d3, vec4(1.0)); - if (any(b3)) { - c9 = texelFetch(colorMulti, texel, 8); - c10 = texelFetch(colorMulti, texel, 9); - c11 = texelFetch(colorMulti, texel, 10); - c12 = texelFetch(colorMulti, texel, 11); - w3 = vec4(b3); - } - b4 = notEqual(d4, vec4(1.0)); - if (any(b4)) { - c13 = texelFetch(colorMulti, texel, 12); - c14 = texelFetch(colorMulti, texel, 13); - c15 = texelFetch(colorMulti, texel, 14); - c16 = texelFetch(colorMulti, texel, 15); - w4 = vec4(b4); - } + b3 = notEqual(d3, vec4(1.0)); + if (any(b3)) { + c9 = texelFetch(colorMulti, texel, 8); + c10 = texelFetch(colorMulti, texel, 9); + c11 = texelFetch(colorMulti, texel, 10); + c12 = texelFetch(colorMulti, texel, 11); + w3 = vec4(b3); + } + b4 = notEqual(d4, vec4(1.0)); + if (any(b4)) { + c13 = texelFetch(colorMulti, texel, 12); + c14 = texelFetch(colorMulti, texel, 13); + c15 = texelFetch(colorMulti, texel, 14); + c16 = texelFetch(colorMulti, texel, 15); + w4 = vec4(b4); + } #endif #ifdef USE_DEPTH # if SAMPLES > 8 - d1 = min(d1, min(d3, d4)); + d1 = min(d1, min(d3, d4)); # endif # if SAMPLES > 4 - d1 = min(d1, d2); - d1 = min(d1, d2); + d1 = min(d1, d2); + d1 = min(d1, d2); # endif # if SAMPLES > 2 - d1.xy = min(d1.xy, d1.zw); + d1.xy = min(d1.xy, d1.zw); # endif - gl_FragDepth = min(d1.x, d1.y); + gl_FragDepth = min(d1.x, d1.y); #endif - c1 = c1 + c2; + c1 = c1 + c2; #if SAMPLES > 2 - c1 += c3 + c4; + c1 += c3 + c4; #endif #if SAMPLES > 4 - c1 += c5 + c6 + c7 + c8; + c1 += c5 + c6 + c7 + c8; #endif #if SAMPLES > 8 - c1 += c9 + c10 + c11 + c12 + c13 + c14 + c15 + c16; + c1 += c9 + c10 + c11 + c12 + c13 + c14 + c15 + c16; #endif - const float inv_samples = 1.0 / float(SAMPLES); + const float inv_samples = 1.0 / float(SAMPLES); - fragColor = c1 * inv_samples; + fragColor = c1 * inv_samples; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl index 64662247d69..ed69184ef14 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl @@ -8,9 +8,8 @@ uniform vec4 shuffle; void main() { - vec4 sample = texture(image, texCoord_interp); - fragColor = vec4(sample.r * shuffle.r + - sample.g * shuffle.g + - sample.b * shuffle.b + - sample.a * shuffle.a) * color; + vec4 sample = texture(image, texCoord_interp); + fragColor = vec4(sample.r * shuffle.r + sample.g * shuffle.g + sample.b * shuffle.b + + sample.a * shuffle.a) * + color; } diff --git a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl index 37686092700..becf0fbd133 100644 --- a/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_image_varying_color_frag.glsl @@ -7,5 +7,5 @@ uniform sampler2D image; void main() { - fragColor = texture(image, texCoord_interp) * finalColor; + fragColor = texture(image, texCoord_interp) * finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl index 6a6da3dd104..31b359dbe6d 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl @@ -18,40 +18,40 @@ flat out vec4 finalColor; void main() { - vec3 pPos; - - if (pos == 1.0) { - pPos = vec3(corners[0].xy, depth); - } - else if (pos == 2.0) { - pPos = vec3(corners[0].zw, depth); - } - else if (pos == 3.0) { - pPos = vec3(corners[1].xy, depth); - } - else if (pos == 4.0) { - pPos = vec3(corners[1].zw, depth); - } - else if (pos == 5.0) { - pPos = vec3(tria.xy, depth); - } - else if (pos == 6.0) { - vec2 ofs = tria.xy - corners[0].xy; - ofs.x = -ofs.x; - pPos = vec3(corners[1].zw + ofs, depth); - } - else if (pos == 7.0) { - pPos = vec3(tria.zw, depth); - } - else { - pPos = vec3(0.0); - } - - gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0); - - finalColor = vec4(color, 1.0); + vec3 pPos; + + if (pos == 1.0) { + pPos = vec3(corners[0].xy, depth); + } + else if (pos == 2.0) { + pPos = vec3(corners[0].zw, depth); + } + else if (pos == 3.0) { + pPos = vec3(corners[1].xy, depth); + } + else if (pos == 4.0) { + pPos = vec3(corners[1].zw, depth); + } + else if (pos == 5.0) { + pPos = vec3(tria.xy, depth); + } + else if (pos == 6.0) { + vec2 ofs = tria.xy - corners[0].xy; + ofs.x = -ofs.x; + pPos = vec3(corners[1].zw + ofs, depth); + } + else if (pos == 7.0) { + pPos = vec3(tria.zw, depth); + } + else { + pPos = vec3(0.0); + } + + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pPos, 1.0); + + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * vec4(pPos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * vec4(pPos, 1.0)).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl index 2097b900666..d9a0ffbbdac 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl @@ -16,15 +16,15 @@ flat out vec4 finalColor; void main() { - float len = end - start; - vec3 sta = vec3(0.0, 0.0, -start); - vec4 pos_4d = vec4(pos * -len + sta, 1.0); + float len = end - start; + vec3 sta = vec3(0.0, 0.0, -start); + vec4 pos_4d = vec4(pos * -len + sta, 1.0); - gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; - gl_PointSize = size; - finalColor = vec4(color, 1.0); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; + gl_PointSize = size; + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((InstanceModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((InstanceModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl index c19598ea8ab..f3bda2cf27d 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl @@ -27,39 +27,39 @@ flat out vec4 finalColor; void emitLine(vec4 color) { - gl_Position = ProjectionMatrix * MV_pos[0]; + gl_Position = ProjectionMatrix * MV_pos[0]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[0].gl_ClipDistance); #endif - EmitVertex(); + EmitVertex(); - gl_Position = ProjectionMatrix * MV_pos[1]; + gl_Position = ProjectionMatrix * MV_pos[1]; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); + world_clip_planes_set_clip_distance(gl_in[1].gl_ClipDistance); #endif - finalColor = color; - EmitVertex(); + finalColor = color; + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } void main() { - float finalEdgeClass = max(edgeClass[0], edgeClass[1]); + float finalEdgeClass = max(edgeClass[0], edgeClass[1]); - if (finalEdgeClass > 0.0f) { - // front-facing edge - if (drawFront) - emitLine(vec4(fCol[0], 0.75)); - } - else if (finalEdgeClass < 0.0f) { - // back-facing edge - if (drawBack) - emitLine(vec4(fCol[0], 0.5)); - } - else { - // exactly one face is front-facing, silhouette edge - if (drawSilhouette) - emitLine(vec4(fCol[0], 1.0)); - } + if (finalEdgeClass > 0.0f) { + // front-facing edge + if (drawFront) + emitLine(vec4(fCol[0], 0.75)); + } + else if (finalEdgeClass < 0.0f) { + // back-facing edge + if (drawBack) + emitLine(vec4(fCol[0], 0.5)); + } + else { + // exactly one face is front-facing, silhouette edge + if (drawSilhouette) + emitLine(vec4(fCol[0], 1.0)); + } } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl index 3877c63d00a..d9e73f81c45 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl @@ -14,7 +14,7 @@ uniform mat4 ViewMatrix; uniform mat4 ProjectionMatrix; in vec3 pos; -in vec3 N1, N2; // normals of faces this edge joins (object coords) +in vec3 N1, N2; // normals of faces this edge joins (object coords) /* Instance attrs */ in vec3 color; @@ -28,41 +28,41 @@ out vec3 fCol; bool front(mat3 NormalMatrix, vec3 N, vec3 eye) { - return dot(NormalMatrix * N, eye) > 0.0; + return dot(NormalMatrix * N, eye) > 0.0; } void main() { - vec3 eye; + vec3 eye; - mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix; + mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix; - vec4 pos_4d = vec4(pos, 1.0); - MV_pos = ModelViewMatrix * pos_4d; + vec4 pos_4d = vec4(pos, 1.0); + MV_pos = ModelViewMatrix * pos_4d; - mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix))); + mat3 NormalMatrix = transpose(inverse(mat3(ModelViewMatrix))); - /* if persp */ - if (ProjectionMatrix[3][3] == 0.0) { - eye = normalize(-MV_pos.xyz); - } - else { - eye = vec3(0.0, 0.0, 1.0); - } + /* if persp */ + if (ProjectionMatrix[3][3] == 0.0) { + eye = normalize(-MV_pos.xyz); + } + else { + eye = vec3(0.0, 0.0, 1.0); + } - bool face_1_front = front(NormalMatrix, N1, eye); - bool face_2_front = front(NormalMatrix, N2, eye); + bool face_1_front = front(NormalMatrix, N1, eye); + bool face_2_front = front(NormalMatrix, N2, eye); - if (face_1_front && face_2_front) - edgeClass = 1.0; // front-facing edge - else if (face_1_front || face_2_front) - edgeClass = 0.0; // exactly one face is front-facing, silhouette edge - else - edgeClass = -1.0; // back-facing edge + if (face_1_front && face_2_front) + edgeClass = 1.0; // front-facing edge + else if (face_1_front || face_2_front) + edgeClass = 0.0; // exactly one face is front-facing, silhouette edge + else + edgeClass = -1.0; // back-facing edge - fCol = color; + fCol = color; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((InstanceModelMatrix * vec4(pos, 1.0)).xyz); + world_clip_planes_calc_clip_distance((InstanceModelMatrix * vec4(pos, 1.0)).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl index 087fec80537..9b1a08d8d86 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl @@ -15,13 +15,13 @@ flat out vec4 finalColor; void main() { - mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix; - /* This is slow and run per vertex, but it's still faster than - * doing it per instance on CPU and sending it on via instance attr. */ - mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); + mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * InstanceModelMatrix; + /* This is slow and run per vertex, but it's still faster than + * doing it per instance on CPU and sending it on via instance attr. */ + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * InstanceModelMatrix))); - gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); - normal = NormalMatrix * nor; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + normal = NormalMatrix * nor; - finalColor = color; + finalColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl index 17799281f32..13c4a7a310e 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_vert.glsl @@ -17,24 +17,24 @@ flat out vec4 finalColor; void main() { - vec3 offset = vec3(0.0); + vec3 offset = vec3(0.0); #ifdef AXIS_NAME - if (pos.z == 0.0) - offset = vec3(1.125, 0.0, 0.0); - else if (pos.z == 1.0) - offset = vec3(0.0, 1.125, 0.0); - else - offset = vec3(0.0, 0.0, 1.125); - offset *= size; + if (pos.z == 0.0) + offset = vec3(1.125, 0.0, 0.0); + else if (pos.z == 1.0) + offset = vec3(0.0, 1.125, 0.0); + else + offset = vec3(0.0, 0.0, 1.125); + offset *= size; #endif - vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; - vec4 pos_4d = InstanceModelMatrix * vec4(offset, 1.0) + vec4(screen_pos * size, 0.0); - gl_Position = ViewProjectionMatrix * pos_4d; - finalColor = vec4(color, 1.0); + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + vec4 pos_4d = InstanceModelMatrix * vec4(offset, 1.0) + vec4(screen_pos * size, 0.0); + gl_Position = ViewProjectionMatrix * pos_4d; + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl index d2b85976d73..c7368f78890 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl @@ -15,19 +15,18 @@ flat out vec4 finalColor; 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]; + 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(world_pos) * pixel_size; - vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; - gl_Position = ViewProjectionMatrix * vec4(world_pos + screen_pos * size * pix_size, 1.0); - finalColor = vec4(color, 1.0); + float pix_size = mul_project_m4_v3_zfac(world_pos) * pixel_size; + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + gl_Position = ViewProjectionMatrix * vec4(world_pos + screen_pos * size * pix_size, 1.0); + finalColor = vec4(color, 1.0); #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance(world_pos); + world_clip_planes_calc_clip_distance(world_pos); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl index 6a55684c93c..3e52e43beae 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl @@ -18,12 +18,12 @@ flat out vec4 finalColor; void main() { - finalColor = color; + finalColor = color; - vec4 pos_4d = vec4(pos * size, 1.0); - gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; + vec4 pos_4d = vec4(pos * size, 1.0); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * pos_4d; #ifdef USE_WORLD_CLIP_PLANES - world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz); + world_clip_planes_calc_clip_distance((ModelMatrix * InstanceModelMatrix * pos_4d).xyz); #endif } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl index 777c1498eec..edcff5e5d87 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_variying_size_variying_id_vert.glsl @@ -18,6 +18,6 @@ flat out uint finalId; void main() { - gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0); - finalId = uint(baseId + callId); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * size, 1.0); + finalId = uint(baseId + callId); } diff --git a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl index 803dc4b3bcf..eeca6e972fa 100644 --- a/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_instance_vert.glsl @@ -9,5 +9,5 @@ in mat4 InstanceModelMatrix; void main() { - gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0); + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl index 1c12a4f942d..1c4039bc590 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl @@ -11,77 +11,79 @@ out vec4 fragColor; const float diagonal_scale = sqrt(0.5); const float minmax_bias = 0.7; -const float minmax_scale = sqrt(1.0 / (1.0 + 1.0/minmax_bias)); +const float minmax_scale = sqrt(1.0 / (1.0 + 1.0 / minmax_bias)); -bool test(int bit) { - return (finalFlags & bit) != 0; +bool test(int bit) +{ + return (finalFlags & bit) != 0; } -void main() { - vec2 pos = gl_PointCoord - vec2(0.5); - vec2 absPos = abs(pos); - float radius = (absPos.x + absPos.y) * diagonal_scale; - - float outline_dist = -1.0; - - /* Diamond outline */ - if (test(0x1)) { - outline_dist = max(outline_dist, radius - radii[0]); - } - - /* Circle outline */ - if (test(0x2)) { - radius = length(absPos); - - outline_dist = max(outline_dist, radius - radii[1]); - } - - /* Top & Bottom clamp */ - if (test(0x4)) { - outline_dist = max(outline_dist, absPos.y - radii[2]); - } - - /* Left & Right clamp */ - if (test(0x8)) { - outline_dist = max(outline_dist, absPos.x - radii[2]); - } - - float alpha = 1 - smoothstep(thresholds[0], thresholds[1], abs(outline_dist)); - - /* Inside the outline. */ - if (outline_dist < 0) { - /* Middle dot */ - if (test(0x10)) { - alpha = max(alpha, 1 - smoothstep(thresholds[2], thresholds[3], radius)); - } - - /* Up and down arrow-like shading. */ - if (test(0x300)) { - float ypos = -1.0; - - /* Up arrow (maximum) */ - if (test(0x100)) { - ypos = max(ypos, pos.y); - } - /* Down arrow (minimum) */ - if (test(0x200)) { - ypos = max(ypos, -pos.y); - } - - /* Arrow shape threshold. */ - float minmax_dist = (ypos - radii[3]) - absPos.x * minmax_bias; - float minmax_step = smoothstep(thresholds[0], thresholds[1], minmax_dist * minmax_scale); - - /* Reduced alpha for uncertain extremes. */ - float minmax_alpha = test(0x400) ? 0.55 : 0.85; - - alpha = max(alpha, minmax_step * minmax_alpha); - } - - fragColor = mix(finalColor, finalOutlineColor, alpha); - } - /* Outside the outline. */ - else { - fragColor = vec4(finalOutlineColor.rgb, finalOutlineColor.a * alpha); - } +void main() +{ + vec2 pos = gl_PointCoord - vec2(0.5); + vec2 absPos = abs(pos); + float radius = (absPos.x + absPos.y) * diagonal_scale; + + float outline_dist = -1.0; + + /* Diamond outline */ + if (test(0x1)) { + outline_dist = max(outline_dist, radius - radii[0]); + } + + /* Circle outline */ + if (test(0x2)) { + radius = length(absPos); + + outline_dist = max(outline_dist, radius - radii[1]); + } + + /* Top & Bottom clamp */ + if (test(0x4)) { + outline_dist = max(outline_dist, absPos.y - radii[2]); + } + + /* Left & Right clamp */ + if (test(0x8)) { + outline_dist = max(outline_dist, absPos.x - radii[2]); + } + + float alpha = 1 - smoothstep(thresholds[0], thresholds[1], abs(outline_dist)); + + /* Inside the outline. */ + if (outline_dist < 0) { + /* Middle dot */ + if (test(0x10)) { + alpha = max(alpha, 1 - smoothstep(thresholds[2], thresholds[3], radius)); + } + + /* Up and down arrow-like shading. */ + if (test(0x300)) { + float ypos = -1.0; + + /* Up arrow (maximum) */ + if (test(0x100)) { + ypos = max(ypos, pos.y); + } + /* Down arrow (minimum) */ + if (test(0x200)) { + ypos = max(ypos, -pos.y); + } + + /* Arrow shape threshold. */ + float minmax_dist = (ypos - radii[3]) - absPos.x * minmax_bias; + float minmax_step = smoothstep(thresholds[0], thresholds[1], minmax_dist * minmax_scale); + + /* Reduced alpha for uncertain extremes. */ + float minmax_alpha = test(0x400) ? 0.55 : 0.85; + + alpha = max(alpha, minmax_step * minmax_alpha); + } + + fragColor = mix(finalColor, finalOutlineColor, alpha); + } + /* Outside the outline. */ + else { + fragColor = vec4(finalOutlineColor.rgb, finalOutlineColor.a * alpha); + } } diff --git a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl index 26eb864821a..8dc92a2b415 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl @@ -22,62 +22,65 @@ flat out int finalFlags; flat out vec4 radii; flat out vec4 thresholds; -bool test(int bit) { - return (flags & bit) != 0; +bool test(int bit) +{ + return (flags & bit) != 0; } -vec2 line_thresholds(float width) { - return vec2(max(0, width - line_falloff), width); +vec2 line_thresholds(float width) +{ + return vec2(max(0, width - line_falloff), width); } -void main() { - gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); - /* Align to pixel grid if the viewport size is known. */ - if (ViewportSize.x > 0) { - vec2 scale = ViewportSize * 0.5; - vec2 px_pos = (gl_Position.xy + 1) * scale; - vec2 adj_pos = round(px_pos - 0.5) + 0.5; - gl_Position.xy = adj_pos / scale - 1; - } + /* Align to pixel grid if the viewport size is known. */ + if (ViewportSize.x > 0) { + vec2 scale = ViewportSize * 0.5; + vec2 px_pos = (gl_Position.xy + 1) * scale; + vec2 adj_pos = round(px_pos - 0.5) + 0.5; + gl_Position.xy = adj_pos / scale - 1; + } - /* Pass through parameters. */ - finalColor = color; - finalOutlineColor = outlineColor; - finalFlags = flags; + /* Pass through parameters. */ + finalColor = color; + finalOutlineColor = outlineColor; + finalFlags = flags; - if (!test(0xF)) { - finalFlags |= 1; - } + if (!test(0xF)) { + finalFlags |= 1; + } - /* Size-dependent line thickness. */ - float half_width = (0.06 + (size - 10) * 0.04); - float line_width = half_width + line_falloff; + /* Size-dependent line thickness. */ + float half_width = (0.06 + (size - 10) * 0.04); + float line_width = half_width + line_falloff; - /* Outline thresholds. */ - thresholds.xy = line_thresholds(line_width); + /* Outline thresholds. */ + thresholds.xy = line_thresholds(line_width); - /* Inner dot thresholds. */ - thresholds.zw = line_thresholds(line_width * 1.6); + /* Inner dot thresholds. */ + thresholds.zw = line_thresholds(line_width * 1.6); - /* Extend the primitive size by half line width on either side; odd for symmetry. */ - float ext_radius = round(0.5 * size) + thresholds.x; + /* Extend the primitive size by half line width on either side; odd for symmetry. */ + float ext_radius = round(0.5 * size) + thresholds.x; - gl_PointSize = ceil(ext_radius + thresholds.y) * 2 + 1; + gl_PointSize = ceil(ext_radius + thresholds.y) * 2 + 1; - /* Diamond radius. */ - radii[0] = ext_radius * diagonal_scale; + /* Diamond radius. */ + radii[0] = ext_radius * diagonal_scale; - /* Circle radius. */ - radii[1] = ext_radius * circle_scale; + /* Circle radius. */ + radii[1] = ext_radius * circle_scale; - /* Square radius. */ - radii[2] = round(ext_radius * square_scale); + /* Square radius. */ + radii[2] = round(ext_radius * square_scale); - /* Min/max cutout offset. */ - radii[3] = -line_falloff; + /* Min/max cutout offset. */ + radii[3] = -line_falloff; - /* Convert to PointCoord units. */ - radii /= gl_PointSize; - thresholds /= gl_PointSize; + /* Convert to PointCoord units. */ + radii /= gl_PointSize; + thresholds /= gl_PointSize; } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 034f93cc273..545629dbfa0 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -13,1468 +13,1680 @@ uniform mat4 ModelMatrixInverse; float convert_rgba_to_float(vec4 color) { - return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); + return dot(color.rgb, vec3(0.2126, 0.7152, 0.0722)); } float exp_blender(float f) { - return pow(2.71828182846, f); + return pow(2.71828182846, f); } float compatible_pow(float x, float y) { - if (y == 0.0) /* x^0 -> 1, including 0^0 */ - return 1.0; + if (y == 0.0) /* x^0 -> 1, including 0^0 */ + return 1.0; - /* glsl pow doesn't accept negative x */ - if (x < 0.0) { - if (mod(-y, 2.0) == 0.0) - return pow(-x, y); - else - return -pow(-x, y); - } - else if (x == 0.0) - return 0.0; + /* glsl pow doesn't accept negative x */ + if (x < 0.0) { + if (mod(-y, 2.0) == 0.0) + return pow(-x, y); + else + return -pow(-x, y); + } + else if (x == 0.0) + return 0.0; - return pow(x, y); + return pow(x, y); } void rgb_to_hsv(vec4 rgb, out vec4 outcol) { - float cmax, cmin, h, s, v, cdelta; - vec3 c; + 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; + 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; - } + 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) - rgb.xyz) / cdelta; + if (s == 0.0) { + h = 0.0; + } + else { + c = (vec3(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]; + 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; + h /= 6.0; - if (h < 0.0) - h += 1.0; - } + if (h < 0.0) + h += 1.0; + } - outcol = vec4(h, s, v, rgb.w); + outcol = vec4(h, s, v, rgb.w); } void hsv_to_rgb(vec4 hsv, out vec4 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 = vec4(rgb, hsv.w); + 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 = vec4(rgb, hsv.w); } float srgb_to_linearrgb(float c) { - if (c < 0.04045) - return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); - else - return pow((c + 0.055) * (1.0 / 1.055), 2.4); + if (c < 0.04045) + return (c < 0.0) ? 0.0 : c * (1.0 / 12.92); + else + return pow((c + 0.055) * (1.0 / 1.055), 2.4); } float linearrgb_to_srgb(float c) { - if (c < 0.0031308) - return (c < 0.0) ? 0.0 : c * 12.92; - else - return 1.055 * pow(c, 1.0 / 2.4) - 0.055; + if (c < 0.0031308) + return (c < 0.0) ? 0.0 : c * 12.92; + else + return 1.055 * pow(c, 1.0 / 2.4) - 0.055; } void srgb_to_linearrgb(vec4 col_from, out vec4 col_to) { - col_to.r = srgb_to_linearrgb(col_from.r); - col_to.g = srgb_to_linearrgb(col_from.g); - col_to.b = srgb_to_linearrgb(col_from.b); - col_to.a = col_from.a; + col_to.r = srgb_to_linearrgb(col_from.r); + col_to.g = srgb_to_linearrgb(col_from.g); + col_to.b = srgb_to_linearrgb(col_from.b); + col_to.a = col_from.a; } void linearrgb_to_srgb(vec4 col_from, out vec4 col_to) { - col_to.r = linearrgb_to_srgb(col_from.r); - col_to.g = linearrgb_to_srgb(col_from.g); - col_to.b = linearrgb_to_srgb(col_from.b); - col_to.a = col_from.a; + col_to.r = linearrgb_to_srgb(col_from.r); + col_to.g = linearrgb_to_srgb(col_from.g); + col_to.b = linearrgb_to_srgb(col_from.b); + col_to.a = col_from.a; } void color_to_normal_new_shading(vec3 color, out vec3 normal) { - normal = vec3(2.0) * color - vec3(1.0); + normal = vec3(2.0) * color - vec3(1.0); } void color_to_blender_normal_new_shading(vec3 color, out vec3 normal) { - normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); + normal = vec3(2.0, -2.0, -2.0) * color - vec3(1.0); } #ifndef M_PI -#define M_PI 3.14159265358979323846 +# define M_PI 3.14159265358979323846 #endif #ifndef M_1_PI -#define M_1_PI 0.318309886183790671538 +# define M_1_PI 0.318309886183790671538 #endif /*********** SHADER NODES ***************/ -void particle_info( - vec4 sprops, vec4 loc, vec3 vel, vec3 avel, - out float index, out float random, out float age, - out float life_time, out vec3 location, - out float size, out vec3 velocity, out vec3 angular_velocity) -{ - index = sprops.x; - random = loc.w; - age = sprops.y; - life_time = sprops.z; - size = sprops.w; - - location = loc.xyz; - velocity = vel; - angular_velocity = avel; +void particle_info(vec4 sprops, + vec4 loc, + vec3 vel, + vec3 avel, + out float index, + out float random, + out float age, + out float life_time, + out vec3 location, + out float size, + out vec3 velocity, + out vec3 angular_velocity) +{ + index = sprops.x; + random = loc.w; + age = sprops.y; + life_time = sprops.z; + size = sprops.w; + + location = loc.xyz; + velocity = vel; + angular_velocity = avel; } void vect_normalize(vec3 vin, out vec3 vout) { - vout = normalize(vin); + vout = normalize(vin); } void direction_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) { - vout = (mat * vec4(vin, 0.0)).xyz; + vout = (mat * vec4(vin, 0.0)).xyz; } void mat3_mul(vec3 vin, mat3 mat, out vec3 vout) { - vout = mat * vin; + vout = mat * vin; } void point_transform_m4v3(vec3 vin, mat4 mat, out vec3 vout) { - vout = (mat * vec4(vin, 1.0)).xyz; + vout = (mat * vec4(vin, 1.0)).xyz; } void point_texco_remap_square(vec3 vin, out vec3 vout) { - vout = vin * 2.0 - 1.0; + vout = vin * 2.0 - 1.0; } void point_texco_clamp(vec3 vin, sampler2D ima, out vec3 vout) { - vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); - vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); + vec2 half_texel_size = 0.5 / vec2(textureSize(ima, 0).xy); + vout = clamp(vin, half_texel_size.xyy, 1.0 - half_texel_size.xyy); } void point_map_to_sphere(vec3 vin, out vec3 vout) { - float len = length(vin); - float v, u; - if (len > 0.0) { - if (vin.x == 0.0 && vin.y == 0.0) - u = 0.0; - else - u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; + float len = length(vin); + float v, u; + if (len > 0.0) { + if (vin.x == 0.0 && vin.y == 0.0) + u = 0.0; + else + u = (1.0 - atan(vin.x, vin.y) / M_PI) / 2.0; - v = 1.0 - acos(vin.z / len) / M_PI; - } - else - v = u = 0.0; + v = 1.0 - acos(vin.z / len) / M_PI; + } + else + v = u = 0.0; - vout = vec3(u, v, 0.0); + vout = vec3(u, v, 0.0); } void point_map_to_tube(vec3 vin, out vec3 vout) { - float u, v; - v = (vin.z + 1.0) * 0.5; - float len = sqrt(vin.x * vin.x + vin.y * vin[1]); - if (len > 0.0) - u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; - else - v = u = 0.0; + float u, v; + v = (vin.z + 1.0) * 0.5; + float len = sqrt(vin.x * vin.x + vin.y * vin[1]); + if (len > 0.0) + u = (1.0 - (atan(vin.x / len, vin.y / len) / M_PI)) * 0.5; + else + v = u = 0.0; - vout = vec3(u, v, 0.0); + vout = vec3(u, v, 0.0); } -void mapping(vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) +void mapping( + vec3 vec, vec4 m0, vec4 m1, vec4 m2, vec4 m3, vec3 minvec, vec3 maxvec, out vec3 outvec) { - mat4 mat = mat4(m0, m1, m2, m3); - outvec = (mat * vec4(vec, 1.0)).xyz; - outvec = clamp(outvec, minvec, maxvec); + mat4 mat = mat4(m0, m1, m2, m3); + outvec = (mat * vec4(vec, 1.0)).xyz; + outvec = clamp(outvec, minvec, maxvec); } void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist) { - outdepth = abs(co.z); - outdist = length(co); - outview = normalize(co); + outdepth = abs(co.z); + outdist = length(co); + outview = normalize(co); } void math_add(float val1, float val2, out float outval) { - outval = val1 + val2; + outval = val1 + val2; } void math_subtract(float val1, float val2, out float outval) { - outval = val1 - val2; + outval = val1 - val2; } void math_multiply(float val1, float val2, out float outval) { - outval = val1 * val2; + outval = val1 * val2; } void math_divide(float val1, float val2, out float outval) { - if (val2 == 0.0) - outval = 0.0; - else - outval = val1 / val2; + if (val2 == 0.0) + outval = 0.0; + else + outval = val1 / val2; } void math_sine(float val, out float outval) { - outval = sin(val); + outval = sin(val); } void math_cosine(float val, out float outval) { - outval = cos(val); + outval = cos(val); } void math_tangent(float val, out float outval) { - outval = tan(val); + outval = tan(val); } void math_asin(float val, out float outval) { - if (val <= 1.0 && val >= -1.0) - outval = asin(val); - else - outval = 0.0; + if (val <= 1.0 && val >= -1.0) + outval = asin(val); + else + outval = 0.0; } void math_acos(float val, out float outval) { - if (val <= 1.0 && val >= -1.0) - outval = acos(val); - else - outval = 0.0; + if (val <= 1.0 && val >= -1.0) + outval = acos(val); + else + outval = 0.0; } void math_atan(float val, out float outval) { - outval = atan(val); + outval = atan(val); } void math_pow(float val1, float val2, out float outval) { - if (val1 >= 0.0) { - outval = compatible_pow(val1, val2); - } - else { - float val2_mod_1 = mod(abs(val2), 1.0); + if (val1 >= 0.0) { + outval = compatible_pow(val1, val2); + } + else { + float val2_mod_1 = mod(abs(val2), 1.0); - if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) - outval = compatible_pow(val1, floor(val2 + 0.5)); - else - outval = 0.0; - } + if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) + outval = compatible_pow(val1, floor(val2 + 0.5)); + else + outval = 0.0; + } } void math_log(float val1, float val2, out float outval) { - if (val1 > 0.0 && val2 > 0.0) - outval = log2(val1) / log2(val2); - else - outval = 0.0; + if (val1 > 0.0 && val2 > 0.0) + outval = log2(val1) / log2(val2); + else + outval = 0.0; } void math_max(float val1, float val2, out float outval) { - outval = max(val1, val2); + outval = max(val1, val2); } void math_min(float val1, float val2, out float outval) { - outval = min(val1, val2); + outval = min(val1, val2); } void math_round(float val, out float outval) { - outval = floor(val + 0.5); + outval = floor(val + 0.5); } void math_less_than(float val1, float val2, out float outval) { - if (val1 < val2) - outval = 1.0; - else - outval = 0.0; + if (val1 < val2) + outval = 1.0; + else + outval = 0.0; } void math_greater_than(float val1, float val2, out float outval) { - if (val1 > val2) - outval = 1.0; - else - outval = 0.0; + if (val1 > val2) + outval = 1.0; + else + outval = 0.0; } void math_modulo(float val1, float val2, out float outval) { - if (val2 == 0.0) - outval = 0.0; - else - outval = mod(val1, val2); + if (val2 == 0.0) + outval = 0.0; + else + outval = mod(val1, val2); - /* change sign to match C convention, mod in GLSL will take absolute for negative numbers, - * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */ - outval = (val1 > 0.0) ? outval : outval - val2; + /* change sign to match C convention, mod in GLSL will take absolute for negative numbers, + * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */ + outval = (val1 > 0.0) ? outval : outval - val2; } void math_abs(float val1, out float outval) { - outval = abs(val1); + outval = abs(val1); } void math_atan2(float val1, float val2, out float outval) { - outval = atan(val1, val2); + outval = atan(val1, val2); } void math_floor(float val, out float outval) { - outval = floor(val); + outval = floor(val); } void math_ceil(float val, out float outval) { - outval = ceil(val); + outval = ceil(val); } void math_fract(float val, out float outval) { - outval = val - floor(val); + outval = val - floor(val); } void math_sqrt(float val, out float outval) { - if (val > 0.0) - outval = sqrt(val); - else - outval = 0.0; + if (val > 0.0) + outval = sqrt(val); + else + outval = 0.0; } void squeeze(float val, float width, float center, out float outval) { - outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); + outval = 1.0 / (1.0 + pow(2.71828183, -((val - center) * width))); } void vec_math_add(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = v1 + v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; + outvec = v1 + v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; } void vec_math_sub(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = v1 - v2; - outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; + outvec = v1 - v2; + outval = (abs(outvec[0]) + abs(outvec[1]) + abs(outvec[2])) * 0.333333; } void vec_math_average(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = v1 + v2; - outval = length(outvec); - outvec = normalize(outvec); + outvec = v1 + v2; + outval = length(outvec); + outvec = normalize(outvec); } void vec_math_mix(float strength, vec3 v1, vec3 v2, out vec3 outvec) { - outvec = strength * v1 + (1 - strength) * v2; + outvec = strength * v1 + (1 - strength) * v2; } void vec_math_dot(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = vec3(0); - outval = dot(v1, v2); + outvec = vec3(0); + outval = dot(v1, v2); } void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval) { - outvec = cross(v1, v2); - outval = length(outvec); - outvec /= outval; + outvec = cross(v1, v2); + outval = length(outvec); + outvec /= outval; } void vec_math_normalize(vec3 v, out vec3 outvec, out float outval) { - outval = length(v); - outvec = normalize(v); + outval = length(v); + outvec = normalize(v); } void vec_math_negate(vec3 v, out vec3 outv) { - outv = -v; + outv = -v; } void invert_z(vec3 v, out vec3 outv) { - v.z = -v.z; - outv = v; + v.z = -v.z; + outv = v; } void normal_new_shading(vec3 nor, vec3 dir, out vec3 outnor, out float outdot) { - outnor = dir; - outdot = dot(normalize(nor), dir); + outnor = dir; + outdot = dot(normalize(nor), dir); } void curves_vec(float fac, vec3 vec, sampler1DArray curvemap, float layer, out vec3 outvec) { - vec4 co = vec4(vec * 0.5 + 0.5, layer); - outvec.x = texture(curvemap, co.xw).x; - outvec.y = texture(curvemap, co.yw).y; - outvec.z = texture(curvemap, co.zw).z; - outvec = mix(vec, outvec, fac); + vec4 co = vec4(vec * 0.5 + 0.5, layer); + outvec.x = texture(curvemap, co.xw).x; + outvec.y = texture(curvemap, co.yw).y; + outvec.z = texture(curvemap, co.zw).z; + outvec = mix(vec, outvec, fac); } /* ext is vec4(in_x, in_dy, out_x, out_dy). */ float curve_extrapolate(float x, float y, vec4 ext) { - if (x < 0.0) { - return y + x * ext.y; - } - else if (x > 1.0) { - return y + (x - 1.0) * ext.w; - } - else { - return y; - } + if (x < 0.0) { + return y + x * ext.y; + } + else if (x > 1.0) { + return y + (x - 1.0) * ext.w; + } + else { + return y; + } } #define RANGE_RESCALE(x, min, range) ((x - min) * range) -void curves_rgb( - float fac, vec4 col, sampler1DArray curvemap, float layer, - vec4 range, vec4 ext_r, vec4 ext_g, vec4 ext_b, vec4 ext_a, - out vec4 outcol) +void curves_rgb(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_r, + vec4 ext_g, + vec4 ext_b, + vec4 ext_a, + out vec4 outcol) { - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; - samp.r = curve_extrapolate(co.x, samp.r, ext_a); - samp.g = curve_extrapolate(co.y, samp.g, ext_a); - samp.b = curve_extrapolate(co.z, samp.b, ext_a); + samp.r = curve_extrapolate(co.x, samp.r, ext_a); + samp.g = curve_extrapolate(co.y, samp.g, ext_a); + samp.b = curve_extrapolate(co.z, samp.b, ext_a); - vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); - co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); + vec3 rgb_min = vec3(ext_r.x, ext_g.x, ext_b.x); + co.xyz = RANGE_RESCALE(samp.rgb, rgb_min, range.rgb); - samp.r = texture(curvemap, co.xw).r; - samp.g = texture(curvemap, co.yw).g; - samp.b = texture(curvemap, co.zw).b; + samp.r = texture(curvemap, co.xw).r; + samp.g = texture(curvemap, co.yw).g; + samp.b = texture(curvemap, co.zw).b; - outcol.r = curve_extrapolate(co.x, samp.r, ext_r); - outcol.g = curve_extrapolate(co.y, samp.g, ext_g); - outcol.b = curve_extrapolate(co.z, samp.b, ext_b); - outcol.a = col.a; + outcol.r = curve_extrapolate(co.x, samp.r, ext_r); + outcol.g = curve_extrapolate(co.y, samp.g, ext_g); + outcol.b = curve_extrapolate(co.z, samp.b, ext_b); + outcol.a = col.a; - outcol = mix(col, outcol, fac); + outcol = mix(col, outcol, fac); } -void curves_rgb_opti( - float fac, vec4 col, sampler1DArray curvemap, float layer, - vec4 range, vec4 ext_a, - out vec4 outcol) +void curves_rgb_opti(float fac, + vec4 col, + sampler1DArray curvemap, + float layer, + vec4 range, + vec4 ext_a, + out vec4 outcol) { - vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); - vec3 samp; - samp.r = texture(curvemap, co.xw).a; - samp.g = texture(curvemap, co.yw).a; - samp.b = texture(curvemap, co.zw).a; + vec4 co = vec4(RANGE_RESCALE(col.rgb, ext_a.x, range.a), layer); + vec3 samp; + samp.r = texture(curvemap, co.xw).a; + samp.g = texture(curvemap, co.yw).a; + samp.b = texture(curvemap, co.zw).a; - outcol.r = curve_extrapolate(co.x, samp.r, ext_a); - outcol.g = curve_extrapolate(co.y, samp.g, ext_a); - outcol.b = curve_extrapolate(co.z, samp.b, ext_a); - outcol.a = col.a; + outcol.r = curve_extrapolate(co.x, samp.r, ext_a); + outcol.g = curve_extrapolate(co.y, samp.g, ext_a); + outcol.b = curve_extrapolate(co.z, samp.b, ext_a); + outcol.a = col.a; - outcol = mix(col, outcol, fac); + outcol = mix(col, outcol, fac); } void set_value(float val, out float outval) { - outval = val; + outval = val; } void set_rgb(vec3 col, out vec3 outcol) { - outcol = col; + outcol = col; } void set_rgba(vec4 col, out vec4 outcol) { - outcol = col; + outcol = col; } void set_value_zero(out float outval) { - outval = 0.0; + outval = 0.0; } void set_value_one(out float outval) { - outval = 1.0; + outval = 1.0; } void set_rgb_zero(out vec3 outval) { - outval = vec3(0.0); + outval = vec3(0.0); } void set_rgb_one(out vec3 outval) { - outval = vec3(1.0); + outval = vec3(1.0); } void set_rgba_zero(out vec4 outval) { - outval = vec4(0.0); + outval = vec4(0.0); } void set_rgba_one(out vec4 outval) { - outval = vec4(1.0); + outval = vec4(1.0); } void brightness_contrast(vec4 col, float brightness, float contrast, out vec4 outcol) { - float a = 1.0 + contrast; - float b = brightness - contrast * 0.5; + float a = 1.0 + contrast; + float b = brightness - contrast * 0.5; - outcol.r = max(a * col.r + b, 0.0); - outcol.g = max(a * col.g + b, 0.0); - outcol.b = max(a * col.b + b, 0.0); - outcol.a = col.a; + outcol.r = max(a * col.r + b, 0.0); + outcol.g = max(a * col.g + b, 0.0); + outcol.b = max(a * col.b + b, 0.0); + outcol.a = col.a; } void mix_blend(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col2, fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col2, fac); + outcol.a = col1.a; } void mix_add(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 + col2, fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 + col2, fac); + outcol.a = col1.a; } void mix_mult(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 * col2, fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 * col2, fac); + outcol.a = col1.a; } void mix_screen(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); - outcol.a = col1.a; + outcol = vec4(1.0) - (vec4(facm) + fac * (vec4(1.0) - col2)) * (vec4(1.0) - col1); + outcol.a = col1.a; } void mix_overlay(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = col1; + outcol = col1; - if (outcol.r < 0.5) - outcol.r *= facm + 2.0 * fac * col2.r; - else - outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); + if (outcol.r < 0.5) + outcol.r *= facm + 2.0 * fac * col2.r; + else + outcol.r = 1.0 - (facm + 2.0 * fac * (1.0 - col2.r)) * (1.0 - outcol.r); - if (outcol.g < 0.5) - outcol.g *= facm + 2.0 * fac * col2.g; - else - outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); + if (outcol.g < 0.5) + outcol.g *= facm + 2.0 * fac * col2.g; + else + outcol.g = 1.0 - (facm + 2.0 * fac * (1.0 - col2.g)) * (1.0 - outcol.g); - if (outcol.b < 0.5) - outcol.b *= facm + 2.0 * fac * col2.b; - else - outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); + if (outcol.b < 0.5) + outcol.b *= facm + 2.0 * fac * col2.b; + else + outcol.b = 1.0 - (facm + 2.0 * fac * (1.0 - col2.b)) * (1.0 - outcol.b); } void mix_sub(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, col1 - col2, fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, col1 - col2, fac); + outcol.a = col1.a; } void mix_div(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = col1; + outcol = col1; - if (col2.r != 0.0) outcol.r = facm * outcol.r + fac * outcol.r / col2.r; - if (col2.g != 0.0) outcol.g = facm * outcol.g + fac * outcol.g / col2.g; - if (col2.b != 0.0) outcol.b = facm * outcol.b + fac * outcol.b / col2.b; + if (col2.r != 0.0) + outcol.r = facm * outcol.r + fac * outcol.r / col2.r; + if (col2.g != 0.0) + outcol.g = facm * outcol.g + fac * outcol.g / col2.g; + if (col2.b != 0.0) + outcol.b = facm * outcol.b + fac * outcol.b / col2.b; } void mix_diff(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = mix(col1, abs(col1 - col2), fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol = mix(col1, abs(col1 - col2), fac); + outcol.a = col1.a; } void mix_dark(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = min(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = min(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; } void mix_light(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol.rgb = max(col1.rgb, col2.rgb * fac); - outcol.a = col1.a; + fac = clamp(fac, 0.0, 1.0); + outcol.rgb = max(col1.rgb, col2.rgb * fac); + outcol.a = col1.a; } void mix_dodge(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - outcol = col1; - - if (outcol.r != 0.0) { - float tmp = 1.0 - fac * col2.r; - if (tmp <= 0.0) - outcol.r = 1.0; - else if ((tmp = outcol.r / tmp) > 1.0) - outcol.r = 1.0; - else - outcol.r = tmp; - } - if (outcol.g != 0.0) { - float tmp = 1.0 - fac * col2.g; - if (tmp <= 0.0) - outcol.g = 1.0; - else if ((tmp = outcol.g / tmp) > 1.0) - outcol.g = 1.0; - else - outcol.g = tmp; - } - if (outcol.b != 0.0) { - float tmp = 1.0 - fac * col2.b; - if (tmp <= 0.0) - outcol.b = 1.0; - else if ((tmp = outcol.b / tmp) > 1.0) - outcol.b = 1.0; - else - outcol.b = tmp; - } + fac = clamp(fac, 0.0, 1.0); + outcol = col1; + + if (outcol.r != 0.0) { + float tmp = 1.0 - fac * col2.r; + if (tmp <= 0.0) + outcol.r = 1.0; + else if ((tmp = outcol.r / tmp) > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + } + if (outcol.g != 0.0) { + float tmp = 1.0 - fac * col2.g; + if (tmp <= 0.0) + outcol.g = 1.0; + else if ((tmp = outcol.g / tmp) > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + } + if (outcol.b != 0.0) { + float tmp = 1.0 - fac * col2.b; + if (tmp <= 0.0) + outcol.b = 1.0; + else if ((tmp = outcol.b / tmp) > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; + } } void mix_burn(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float tmp, facm = 1.0 - fac; - - outcol = col1; - - tmp = facm + fac * col2.r; - if (tmp <= 0.0) - outcol.r = 0.0; - else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) - outcol.r = 0.0; - else if (tmp > 1.0) - outcol.r = 1.0; - else - outcol.r = tmp; - - tmp = facm + fac * col2.g; - if (tmp <= 0.0) - outcol.g = 0.0; - else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) - outcol.g = 0.0; - else if (tmp > 1.0) - outcol.g = 1.0; - else - outcol.g = tmp; - - tmp = facm + fac * col2.b; - if (tmp <= 0.0) - outcol.b = 0.0; - else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) - outcol.b = 0.0; - else if (tmp > 1.0) - outcol.b = 1.0; - else - outcol.b = tmp; + fac = clamp(fac, 0.0, 1.0); + float tmp, facm = 1.0 - fac; + + outcol = col1; + + tmp = facm + fac * col2.r; + if (tmp <= 0.0) + outcol.r = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol.r) / tmp)) < 0.0) + outcol.r = 0.0; + else if (tmp > 1.0) + outcol.r = 1.0; + else + outcol.r = tmp; + + tmp = facm + fac * col2.g; + if (tmp <= 0.0) + outcol.g = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol.g) / tmp)) < 0.0) + outcol.g = 0.0; + else if (tmp > 1.0) + outcol.g = 1.0; + else + outcol.g = tmp; + + tmp = facm + fac * col2.b; + if (tmp <= 0.0) + outcol.b = 0.0; + else if ((tmp = (1.0 - (1.0 - outcol.b) / tmp)) < 0.0) + outcol.b = 0.0; + else if (tmp > 1.0) + outcol.b = 1.0; + else + outcol.b = tmp; } void mix_hue(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = col1; + outcol = col1; - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv_to_rgb(hsv, tmp); + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv_to_rgb(hsv, tmp); - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } } void mix_sat(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = col1; + outcol = col1; - vec4 hsv, hsv2; - rgb_to_hsv(outcol, hsv); + vec4 hsv, hsv2; + rgb_to_hsv(outcol, hsv); - if (hsv.y != 0.0) { - rgb_to_hsv(col2, hsv2); + if (hsv.y != 0.0) { + rgb_to_hsv(col2, hsv2); - hsv.y = facm * hsv.y + fac * hsv2.y; - hsv_to_rgb(hsv, outcol); - } + hsv.y = facm * hsv.y + fac * hsv2.y; + hsv_to_rgb(hsv, outcol); + } } void mix_val(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - vec4 hsv, hsv2; - rgb_to_hsv(col1, hsv); - rgb_to_hsv(col2, hsv2); + vec4 hsv, hsv2; + rgb_to_hsv(col1, hsv); + rgb_to_hsv(col2, hsv2); - hsv.z = facm * hsv.z + fac * hsv2.z; - hsv_to_rgb(hsv, outcol); + hsv.z = facm * hsv.z + fac * hsv2.z; + hsv_to_rgb(hsv, outcol); } void mix_color(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - outcol = col1; + outcol = col1; - vec4 hsv, hsv2, tmp; - rgb_to_hsv(col2, hsv2); + vec4 hsv, hsv2, tmp; + rgb_to_hsv(col2, hsv2); - if (hsv2.y != 0.0) { - rgb_to_hsv(outcol, hsv); - hsv.x = hsv2.x; - hsv.y = hsv2.y; - hsv_to_rgb(hsv, tmp); + if (hsv2.y != 0.0) { + rgb_to_hsv(outcol, hsv); + hsv.x = hsv2.x; + hsv.y = hsv2.y; + hsv_to_rgb(hsv, tmp); - outcol = mix(outcol, tmp, fac); - outcol.a = col1.a; - } + outcol = mix(outcol, tmp, fac); + outcol.a = col1.a; + } } void mix_soft(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); - float facm = 1.0 - fac; + fac = clamp(fac, 0.0, 1.0); + float facm = 1.0 - fac; - vec4 one = vec4(1.0); - vec4 scr = one - (one - col2) * (one - col1); - outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); + vec4 one = vec4(1.0); + vec4 scr = one - (one - col2) * (one - col1); + outcol = facm * col1 + fac * ((one - col1) * col2 * col1 + col1 * scr); } void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol) { - fac = clamp(fac, 0.0, 1.0); + fac = clamp(fac, 0.0, 1.0); - outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); + outcol = col1 + fac * (2.0 * (col2 - vec4(0.5))); } -void valtorgb_opti_constant(float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +void valtorgb_opti_constant( + float fac, float edge, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) { - outcol = (fac > edge) ? color2 : color1; - outalpha = outcol.a; + outcol = (fac > edge) ? color2 : color1; + outalpha = outcol.a; } -void valtorgb_opti_linear(float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) +void valtorgb_opti_linear( + float fac, vec2 mulbias, vec4 color1, vec4 color2, out vec4 outcol, out float outalpha) { - fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); - outcol = mix(color1, color2, fac); - outalpha = outcol.a; + fac = clamp(fac * mulbias.x + mulbias.y, 0.0, 1.0); + outcol = mix(color1, color2, fac); + outalpha = outcol.a; } void valtorgb(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) { - outcol = texture(colormap, vec2(fac, layer)); - outalpha = outcol.a; + outcol = texture(colormap, vec2(fac, layer)); + outalpha = outcol.a; } -void valtorgb_nearest(float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) +void valtorgb_nearest( + float fac, sampler1DArray colormap, float layer, out vec4 outcol, out float outalpha) { - fac = clamp(fac, 0.0, 1.0); - outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); - outalpha = outcol.a; + fac = clamp(fac, 0.0, 1.0); + outcol = texelFetch(colormap, ivec2(fac * (textureSize(colormap, 0).x - 1), layer), 0); + outalpha = outcol.a; } void rgbtobw(vec4 color, out float outval) { - vec3 factors = vec3(0.2126, 0.7152, 0.0722); - outval = dot(color.rgb, factors); + vec3 factors = vec3(0.2126, 0.7152, 0.0722); + outval = dot(color.rgb, factors); } void invert(float fac, vec4 col, out vec4 outcol) { - outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); - outcol.w = col.w; + outcol.xyz = mix(col.xyz, vec3(1.0) - col.xyz, fac); + outcol.w = col.w; } void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec) { - out_vec = clamp(vec, min, max); + out_vec = clamp(vec, min, max); } void clamp_val(float value, float min, float max, out float out_value) { - out_value = clamp(value, min, max); + out_value = clamp(value, min, max); } void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol) { - vec4 hsv; + vec4 hsv; - rgb_to_hsv(col, hsv); + rgb_to_hsv(col, hsv); - hsv[0] = fract(hsv[0] + hue + 0.5); - hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); - hsv[2] = hsv[2] * value; + hsv[0] = fract(hsv[0] + hue + 0.5); + hsv[1] = clamp(hsv[1] * sat, 0.0, 1.0); + hsv[2] = hsv[2] * value; - hsv_to_rgb(hsv, outcol); + hsv_to_rgb(hsv, outcol); - outcol = mix(col, outcol, fac); + outcol = mix(col, outcol, fac); } void separate_rgb(vec4 col, out float r, out float g, out float b) { - r = col.r; - g = col.g; - b = col.b; + r = col.r; + g = col.g; + b = col.b; } void combine_rgb(float r, float g, float b, out vec4 col) { - col = vec4(r, g, b, 1.0); + col = vec4(r, g, b, 1.0); } void separate_xyz(vec3 vec, out float x, out float y, out float z) { - x = vec.r; - y = vec.g; - z = vec.b; + x = vec.r; + y = vec.g; + z = vec.b; } void combine_xyz(float x, float y, float z, out vec3 vec) { - vec = vec3(x, y, z); + vec = vec3(x, y, z); } void separate_hsv(vec4 col, out float h, out float s, out float v) { - vec4 hsv; + vec4 hsv; - rgb_to_hsv(col, hsv); - h = hsv[0]; - s = hsv[1]; - v = hsv[2]; + rgb_to_hsv(col, hsv); + h = hsv[0]; + s = hsv[1]; + v = hsv[2]; } void combine_hsv(float h, float s, float v, out vec4 col) { - hsv_to_rgb(vec4(h, s, v, 1.0), col); + hsv_to_rgb(vec4(h, s, v, 1.0), col); } void output_node(vec4 rgb, float alpha, out vec4 outrgb) { - outrgb = vec4(rgb.rgb, alpha); + outrgb = vec4(rgb.rgb, alpha); } /*********** TEXTURES ***************/ void texco_norm(vec3 normal, out vec3 outnormal) { - /* corresponds to shi->orn, which is negated so cancels - out blender normal negation */ - outnormal = normalize(normal); + /* corresponds to shi->orn, which is negated so cancels + out blender normal negation */ + outnormal = normalize(normal); } vec3 mtex_2d_mapping(vec3 vec) { - return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); + return vec3(vec.xy * 0.5 + vec2(0.5), vec.z); } /** helper method to extract the upper left 3x3 matrix from a 4x4 matrix */ mat3 to_mat3(mat4 m4) { - mat3 m3; - m3[0] = m4[0].xyz; - m3[1] = m4[1].xyz; - m3[2] = m4[2].xyz; - return m3; + mat3 m3; + m3[0] = m4[0].xyz; + m3[1] = m4[1].xyz; + m3[2] = m4[2].xyz; + return m3; } /*********** NEW SHADER UTILITIES **************/ float fresnel_dielectric_0(float eta) { - /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ - float A = (eta - 1.0) / (eta + 1.0); + /* compute fresnel reflactance at normal incidence => cosi = 1.0 */ + float A = (eta - 1.0) / (eta + 1.0); - return A * A; + return A * A; } float fresnel_dielectric_cos(float cosi, float eta) { - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - float c = abs(cosi); - float g = eta * eta - 1.0 + c * c; - float result; + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + float c = abs(cosi); + float g = eta * eta - 1.0 + c * c; + float result; - if (g > 0.0) { - g = sqrt(g); - float A = (g - c) / (g + c); - float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); - result = 0.5 * A * A * (1.0 + B * B); - } - else { - result = 1.0; /* TIR (no refracted component) */ - } + if (g > 0.0) { + g = sqrt(g); + float A = (g - c) / (g + c); + float B = (c * (g + c) - 1.0) / (c * (g - c) + 1.0); + result = 0.5 * A * A * (1.0 + B * B); + } + else { + result = 1.0; /* TIR (no refracted component) */ + } - return result; + return result; } float fresnel_dielectric(vec3 Incoming, vec3 Normal, float eta) { - /* compute fresnel reflectance without explicitly computing - * the refracted direction */ - return fresnel_dielectric_cos(dot(Incoming, Normal), eta); + /* compute fresnel reflectance without explicitly computing + * the refracted direction */ + return fresnel_dielectric_cos(dot(Incoming, Normal), eta); } float hypot(float x, float y) { - return sqrt(x * x + y * y); + return sqrt(x * x + y * y); } void generated_from_orco(vec3 orco, out vec3 generated) { #ifdef VOLUMETRICS -#ifdef MESH_SHADER - generated = volumeObjectLocalCoord; -#else - generated = worldPosition; -#endif +# ifdef MESH_SHADER + generated = volumeObjectLocalCoord; +# else + generated = worldPosition; +# endif #else - generated = orco; + generated = orco; #endif } int floor_to_int(float x) { - return int(floor(x)); + return int(floor(x)); } int quick_floor(float x) { - return int(x) - ((x < 0) ? 1 : 0); + return int(x) - ((x < 0) ? 1 : 0); } float integer_noise(int n) { - int nn; - n = (n + 1013) & 0x7fffffff; - n = (n >> 13) ^ n; - nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; - return 0.5 * (float(nn) / 1073741824.0); + int nn; + n = (n + 1013) & 0x7fffffff; + n = (n >> 13) ^ n; + nn = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff; + return 0.5 * (float(nn) / 1073741824.0); } uint hash(uint kx, uint ky, uint kz) { #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) #define final(a, b, c) \ -{ \ - c ^= b; c -= rot(b, 14); \ - a ^= c; a -= rot(c, 11); \ - b ^= a; b -= rot(a, 25); \ - c ^= b; c -= rot(b, 16); \ - a ^= c; a -= rot(c, 4); \ - b ^= a; b -= rot(a, 14); \ - c ^= b; c -= rot(b, 24); \ -} - // now hash the data! - uint a, b, c, len = 3u; - a = b = c = 0xdeadbeefu + (len << 2u) + 13u; - - c += kz; - b += ky; - a += kx; - final (a, b, c); - - return c; + { \ + c ^= b; \ + c -= rot(b, 14); \ + a ^= c; \ + a -= rot(c, 11); \ + b ^= a; \ + b -= rot(a, 25); \ + c ^= b; \ + c -= rot(b, 16); \ + a ^= c; \ + a -= rot(c, 4); \ + b ^= a; \ + b -= rot(a, 14); \ + c ^= b; \ + c -= rot(b, 24); \ + } + // now hash the data! + uint a, b, c, len = 3u; + a = b = c = 0xdeadbeefu + (len << 2u) + 13u; + + c += kz; + b += ky; + a += kx; + final(a, b, c); + + return c; #undef rot #undef final } uint hash(int kx, int ky, int kz) { - return hash(uint(kx), uint(ky), uint(kz)); + return hash(uint(kx), uint(ky), uint(kz)); } float bits_to_01(uint bits) { - return (float(bits) / 4294967295.0); + return (float(bits) / 4294967295.0); } float cellnoise(vec3 p) { - int ix = quick_floor(p.x); - int iy = quick_floor(p.y); - int iz = quick_floor(p.z); + int ix = quick_floor(p.x); + int iy = quick_floor(p.y); + int iz = quick_floor(p.z); - return bits_to_01(hash(uint(ix), uint(iy), uint(iz))); + return bits_to_01(hash(uint(ix), uint(iy), uint(iz))); } vec3 cellnoise_color(vec3 p) { - float r = cellnoise(p.xyz); - float g = cellnoise(p.yxz); - float b = cellnoise(p.yzx); + float r = cellnoise(p.xyz); + float g = cellnoise(p.yxz); + float b = cellnoise(p.yzx); - return vec3(r, g, b); + return vec3(r, g, b); } float floorfrac(float x, out int i) { - i = floor_to_int(x); - return x - i; + i = floor_to_int(x); + return x - i; } /* bsdfs */ vec3 tint_from_color(vec3 color) { - float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ - return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ + float lum = dot(color, vec3(0.3, 0.6, 0.1)); /* luminance approx. */ + return (lum > 0) ? color / lum : vec3(1.0); /* normalize lum. to isolate hue+sat */ } -void convert_metallic_to_specular_tinted( - vec3 basecol, vec3 basecol_tint, float metallic, float specular_fac, float specular_tint, - out vec3 diffuse, out vec3 f0) +void convert_metallic_to_specular_tinted(vec3 basecol, + vec3 basecol_tint, + float metallic, + float specular_fac, + float specular_tint, + out vec3 diffuse, + out vec3 f0) { - vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); - f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); - diffuse = basecol * (1.0 - metallic); + vec3 tmp_col = mix(vec3(1.0), basecol_tint, specular_tint); + f0 = mix((0.08 * specular_fac) * tmp_col, basecol, metallic); + diffuse = basecol * (1.0 - metallic); } vec3 principled_sheen(float NV, vec3 basecol_tint, float sheen_tint) { - float f = 1.0 - NV; - /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, therefore we need to clamp value. */ - f = clamp(f, 0.0, 1.0); - /* Empirical approximation (manual curve fitting). Can be refined. */ - float sheen = f*f*f*0.077 + f*0.01 + 0.00026; - return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); + float f = 1.0 - NV; + /* Temporary fix for T59784. Normal map seems to contain NaNs for tangent space normal maps, therefore we need to clamp value. */ + f = clamp(f, 0.0, 1.0); + /* Empirical approximation (manual curve fitting). Can be refined. */ + float sheen = f * f * f * 0.077 + f * 0.01 + 0.00026; + return sheen * mix(vec3(1.0), basecol_tint, sheen_tint); } #ifndef VOLUMETRICS void node_bsdf_diffuse(vec4 color, float roughness, vec3 N, out Closure result) { - N = normalize(N); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.ssr_normal = normal_encode(vN, viewCameraVec); - eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); - result.radiance *= color.rgb; + N = normalize(N); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + eevee_closure_diffuse(N, color.rgb, 1.0, result.radiance); + result.radiance *= color.rgb; } void node_bsdf_glossy(vec4 color, float roughness, vec3 N, float ssr_id, out Closure result) { - N = normalize(N); - vec3 out_spec, ssr_spec; - eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec * color.rgb; - result.ssr_data = vec4(ssr_spec * color.rgb, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); -} - -void node_bsdf_anisotropic( - vec4 color, float roughness, float anisotropy, float rotation, vec3 N, vec3 T, - out Closure result) -{ - node_bsdf_glossy(color, roughness, N, -1, result); -} - -void node_bsdf_glass(vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) -{ - N = normalize(N); - vec3 out_spec, out_refr, ssr_spec; - vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : color.rgb; /* Simulate 2 transmission event */ - eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - out_refr *= refr_color; - out_spec *= color.rgb; - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); + N = normalize(N); + vec3 out_spec, ssr_spec; + eevee_closure_glossy(N, vec3(1.0), int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec * color.rgb; + result.ssr_data = vec4(ssr_spec * color.rgb, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +} + +void node_bsdf_anisotropic(vec4 color, + float roughness, + float anisotropy, + float rotation, + vec3 N, + vec3 T, + out Closure result) +{ + node_bsdf_glossy(color, roughness, N, -1, result); +} + +void node_bsdf_glass( + vec4 color, float roughness, float ior, vec3 N, float ssr_id, out Closure result) +{ + N = normalize(N); + vec3 out_spec, out_refr, ssr_spec; + vec3 refr_color = (refractionDepth > 0.0) ? color.rgb * color.rgb : + color.rgb; /* Simulate 2 transmission event */ + eevee_closure_glass( + N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + out_refr *= refr_color; + out_spec *= color.rgb; + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + result.ssr_data = vec4(ssr_spec * color.rgb * fresnel, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); } void node_bsdf_toon(vec4 color, float size, float tsmooth, vec3 N, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_bsdf_principled( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - N = normalize(N); - ior = max(ior, 1e-5); - metallic = saturate(metallic); - transmission = saturate(transmission); - float dielectric = 1.0 - metallic; - transmission *= dielectric; - sheen *= dielectric; - subsurface_color *= dielectric; - - vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - /* Far from being accurate, but 2 glossy evaluation is too expensive. - * Most noticeable difference is at grazing angles since the bsdf lut - * f0 color interpolation is done on top of this interpolation. */ - vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); - float fresnel = F_eta(ior, NV); - vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; - f0 = mix(f0, spec_col, transmission); - - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - - float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface; - eevee_closure_principled(N, mixed_ss_base_color, f0, int(ssr_id), roughness, - CN, clearcoat * 0.25, clearcoat_roughness, 1.0, sss_scalef, ior, - out_diff, out_trans, out_spec, out_refr, ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission event */ - out_refr *= refr_color * (1.0 - fresnel) * transmission; - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_refr; - result.radiance += out_diff * out_sheen; /* Coarse approx. */ -#ifndef USE_SSS - result.radiance += (out_diff + out_trans) * mixed_ss_base_color * (1.0 - transmission); -#endif - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); -#ifdef USE_SSS - result.sss_data.a = sss_scalef; - result.sss_data.rgb = out_diff + out_trans; -# ifdef USE_SSS_ALBEDO - result.sss_albedo.rgb = mixed_ss_base_color; -# else - result.sss_data.rgb *= mixed_ss_base_color; + node_bsdf_diffuse(color, 0.0, N, result); +} + +void node_bsdf_principled(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + ior = max(ior, 1e-5); + metallic = saturate(metallic); + transmission = saturate(transmission); + float dielectric = 1.0 - metallic; + transmission *= dielectric; + sheen *= dielectric; + subsurface_color *= dielectric; + + vec3 diffuse, f0, out_diff, out_spec, out_trans, out_refr, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + /* Far from being accurate, but 2 glossy evaluation is too expensive. + * Most noticeable difference is at grazing angles since the bsdf lut + * f0 color interpolation is done on top of this interpolation. */ + vec3 f0_glass = mix(vec3(1.0), base_color.rgb, specular_tint); + float fresnel = F_eta(ior, NV); + vec3 spec_col = F_color_blend(ior, fresnel, f0_glass) * fresnel; + f0 = mix(f0, spec_col, transmission); + + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + + float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface; + eevee_closure_principled(N, + mixed_ss_base_color, + f0, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + sss_scalef, + ior, + out_diff, + out_trans, + out_spec, + out_refr, + ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission event */ + out_refr *= refr_color * (1.0 - fresnel) * transmission; + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_refr; + result.radiance += out_diff * out_sheen; /* Coarse approx. */ +# ifndef USE_SSS + result.radiance += (out_diff + out_trans) * mixed_ss_base_color * (1.0 - transmission); +# endif + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +# ifdef USE_SSS + result.sss_data.a = sss_scalef; + result.sss_data.rgb = out_diff + out_trans; +# ifdef USE_SSS_ALBEDO + result.sss_albedo.rgb = mixed_ss_base_color; +# else + result.sss_data.rgb *= mixed_ss_base_color; +# endif + result.sss_data.rgb *= (1.0 - transmission); # endif - result.sss_data.rgb *= (1.0 - transmission); -#endif -} - -void node_bsdf_principled_dielectric( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - N = normalize(N); - metallic = saturate(metallic); - float dielectric = 1.0 - metallic; - - vec3 diffuse, f0, out_diff, out_spec, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - eevee_closure_default(N, diffuse, f0, int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec + out_diff * (diffuse + out_sheen); - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); -} - -void node_bsdf_principled_metallic( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - N = normalize(N); - vec3 out_spec, ssr_spec; - - eevee_closure_glossy(N, base_color.rgb, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); -} - -void node_bsdf_principled_clearcoat( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - vec3 out_spec, ssr_spec; - N = normalize(N); - - eevee_closure_clearcoat(N, base_color.rgb, int(ssr_id), roughness, CN, clearcoat * 0.25, clearcoat_roughness, - 1.0, out_spec, ssr_spec); - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); } -void node_bsdf_principled_subsurface( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - metallic = saturate(metallic); - N = normalize(N); - - vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; - vec3 ctint = tint_from_color(base_color.rgb); - convert_metallic_to_specular_tinted(base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); - - subsurface_color = subsurface_color * (1.0 - metallic); - vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); - float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface; - - float NV = dot(N, cameraVec); - vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); - - eevee_closure_skin(N, mixed_ss_base_color, f0, int(ssr_id), roughness, 1.0, sss_scalef, - out_diff, out_trans, out_spec, ssr_spec); - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = out_spec; - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); -#ifdef USE_SSS - result.sss_data.a = sss_scalef; - result.sss_data.rgb = out_diff + out_trans; -# ifdef USE_SSS_ALBEDO - result.sss_albedo.rgb = mixed_ss_base_color; +void node_bsdf_principled_dielectric(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + metallic = saturate(metallic); + float dielectric = 1.0 - metallic; + + vec3 diffuse, f0, out_diff, out_spec, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + eevee_closure_default(N, diffuse, f0, int(ssr_id), roughness, 1.0, out_diff, out_spec, ssr_spec); + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec + out_diff * (diffuse + out_sheen); + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +} + +void node_bsdf_principled_metallic(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + N = normalize(N); + vec3 out_spec, ssr_spec; + + eevee_closure_glossy(N, base_color.rgb, int(ssr_id), roughness, 1.0, out_spec, ssr_spec); + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +} + +void node_bsdf_principled_clearcoat(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + vec3 out_spec, ssr_spec; + N = normalize(N); + + eevee_closure_clearcoat(N, + base_color.rgb, + int(ssr_id), + roughness, + CN, + clearcoat * 0.25, + clearcoat_roughness, + 1.0, + out_spec, + ssr_spec); + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +} + +void node_bsdf_principled_subsurface(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + metallic = saturate(metallic); + N = normalize(N); + + vec3 diffuse, f0, out_diff, out_spec, out_trans, ssr_spec; + vec3 ctint = tint_from_color(base_color.rgb); + convert_metallic_to_specular_tinted( + base_color.rgb, ctint, metallic, specular, specular_tint, diffuse, f0); + + subsurface_color = subsurface_color * (1.0 - metallic); + vec3 mixed_ss_base_color = mix(diffuse, subsurface_color.rgb, subsurface); + float sss_scalef = dot(sss_scale, vec3(1.0 / 3.0)) * subsurface; + + float NV = dot(N, cameraVec); + vec3 out_sheen = sheen * principled_sheen(NV, ctint, sheen_tint); + + eevee_closure_skin(N, + mixed_ss_base_color, + f0, + int(ssr_id), + roughness, + 1.0, + sss_scalef, + out_diff, + out_trans, + out_spec, + ssr_spec); + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = out_spec; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); +# ifdef USE_SSS + result.sss_data.a = sss_scalef; + result.sss_data.rgb = out_diff + out_trans; +# ifdef USE_SSS_ALBEDO + result.sss_albedo.rgb = mixed_ss_base_color; +# else + result.sss_data.rgb *= mixed_ss_base_color; +# endif # else - result.sss_data.rgb *= mixed_ss_base_color; + result.radiance += (out_diff + out_trans) * mixed_ss_base_color; # endif -#else - result.radiance += (out_diff + out_trans) * mixed_ss_base_color; -#endif - result.radiance += out_diff * out_sheen; -} - -void node_bsdf_principled_glass( - vec4 base_color, float subsurface, vec3 subsurface_radius, vec4 subsurface_color, float metallic, float specular, - float specular_tint, float roughness, float anisotropic, float anisotropic_rotation, float sheen, float sheen_tint, float clearcoat, - float clearcoat_roughness, float ior, float transmission, float transmission_roughness, vec3 N, vec3 CN, vec3 T, vec3 I, float ssr_id, - float sss_id, vec3 sss_scale, out Closure result) -{ - ior = max(ior, 1e-5); - N = normalize(N); - - vec3 f0, out_spec, out_refr, ssr_spec; - f0 = mix(vec3(1.0), base_color.rgb, specular_tint); - - eevee_closure_glass(N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); - - vec3 refr_color = base_color.rgb; - refr_color *= (refractionDepth > 0.0) ? refr_color : vec3(1.0); /* Simulate 2 transmission events */ - out_refr *= refr_color; - - float fresnel = F_eta(ior, dot(N, cameraVec)); - vec3 spec_col = F_color_blend(ior, fresnel, f0); - out_spec *= spec_col; - ssr_spec *= spec_col * fresnel; - - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.radiance = mix(out_refr, out_spec, fresnel); - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); + result.radiance += out_diff * out_sheen; +} + +void node_bsdf_principled_glass(vec4 base_color, + float subsurface, + vec3 subsurface_radius, + vec4 subsurface_color, + float metallic, + float specular, + float specular_tint, + float roughness, + float anisotropic, + float anisotropic_rotation, + float sheen, + float sheen_tint, + float clearcoat, + float clearcoat_roughness, + float ior, + float transmission, + float transmission_roughness, + vec3 N, + vec3 CN, + vec3 T, + vec3 I, + float ssr_id, + float sss_id, + vec3 sss_scale, + out Closure result) +{ + ior = max(ior, 1e-5); + N = normalize(N); + + vec3 f0, out_spec, out_refr, ssr_spec; + f0 = mix(vec3(1.0), base_color.rgb, specular_tint); + + eevee_closure_glass( + N, vec3(1.0), int(ssr_id), roughness, 1.0, ior, out_spec, out_refr, ssr_spec); + + vec3 refr_color = base_color.rgb; + refr_color *= (refractionDepth > 0.0) ? refr_color : + vec3(1.0); /* Simulate 2 transmission events */ + out_refr *= refr_color; + + float fresnel = F_eta(ior, dot(N, cameraVec)); + vec3 spec_col = F_color_blend(ior, fresnel, f0); + out_spec *= spec_col; + ssr_spec *= spec_col * fresnel; + + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.radiance = mix(out_refr, out_spec, fresnel); + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); } void node_bsdf_translucent(vec4 color, vec3 N, out Closure result) { - node_bsdf_diffuse(color, 0.0, -N, result); + node_bsdf_diffuse(color, 0.0, -N, result); } void node_bsdf_transparent(vec4 color, out Closure result) { - /* this isn't right */ - result = CLOSURE_DEFAULT; - result.radiance = vec3(0.0); - result.opacity = clamp(1.0 - dot(color.rgb, vec3(0.3333334)), 0.0, 1.0); - result.ssr_id = TRANSPARENT_CLOSURE_FLAG; + /* this isn't right */ + result = CLOSURE_DEFAULT; + result.radiance = vec3(0.0); + result.opacity = clamp(1.0 - dot(color.rgb, vec3(0.3333334)), 0.0, 1.0); + result.ssr_id = TRANSPARENT_CLOSURE_FLAG; } void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out Closure result) { - node_bsdf_diffuse(color, 0.0, N, result); -} - -void node_subsurface_scattering( - vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, float sss_id, - out Closure result) -{ -#if defined(USE_SSS) - N = normalize(N); - vec3 out_diff, out_trans; - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.ssr_data = vec4(0.0); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = -1; - result.sss_data.a = scale; - eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); - result.sss_data.rgb = out_diff + out_trans; -# ifdef USE_SSS_ALBEDO - /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ - result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur); - result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur); + node_bsdf_diffuse(color, 0.0, N, result); +} + +void node_subsurface_scattering(vec4 color, + float scale, + vec3 radius, + float sharpen, + float texture_blur, + vec3 N, + float sss_id, + out Closure result) +{ +# if defined(USE_SSS) + N = normalize(N); + vec3 out_diff, out_trans; + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.ssr_data = vec4(0.0); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = -1; + result.sss_data.a = scale; + eevee_closure_subsurface(N, color.rgb, 1.0, scale, out_diff, out_trans); + result.sss_data.rgb = out_diff + out_trans; +# ifdef USE_SSS_ALBEDO + /* Not perfect for texture_blur not exactly equal to 0.0 or 1.0. */ + result.sss_albedo.rgb = mix(color.rgb, vec3(1.0), texture_blur); + result.sss_data.rgb *= mix(vec3(1.0), color.rgb, texture_blur); +# else + result.sss_data.rgb *= color.rgb; +# endif # else - result.sss_data.rgb *= color.rgb; + node_bsdf_diffuse(color, 0.0, N, result); # endif -#else - node_bsdf_diffuse(color, 0.0, N, result); -#endif } void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Closure result) { - N = normalize(N); - vec3 out_refr; - color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ - eevee_closure_refraction(N, roughness, ior, out_refr); - vec3 vN = mat3(ViewMatrix) * N; - result = CLOSURE_DEFAULT; - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.radiance = out_refr * color.rgb; - result.ssr_id = REFRACT_CLOSURE_FLAG; + N = normalize(N); + vec3 out_refr; + color.rgb *= (refractionDepth > 0.0) ? color.rgb : vec3(1.0); /* Simulate 2 absorption event. */ + eevee_closure_refraction(N, roughness, ior, out_refr); + vec3 vN = mat3(ViewMatrix) * N; + result = CLOSURE_DEFAULT; + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.radiance = out_refr * color.rgb; + result.ssr_id = REFRACT_CLOSURE_FLAG; } -void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) +void node_ambient_occlusion( + vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao) { - vec3 bent_normal; - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); - result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); - result_color = result_ao * color; + vec3 bent_normal; + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal); + result_color = result_ao * color; } #endif /* VOLUMETRICS */ @@ -1484,40 +1696,40 @@ void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 re void node_emission(vec4 color, float strength, vec3 vN, out Closure result) { #ifndef VOLUMETRICS - color *= strength; - result = CLOSURE_DEFAULT; - result.radiance = color.rgb; - result.opacity = color.a; - result.ssr_normal = normal_encode(vN, viewCameraVec); + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; + result.ssr_normal = normal_encode(vN, viewCameraVec); #else - result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); + result = Closure(vec3(0.0), vec3(0.0), color.rgb * strength, 0.0); #endif } void node_wireframe(float size, vec2 barycentric, vec3 barycentric_dist, out float fac) { - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; - size *= 0.5; - vec3 s = step(-size, -barys * barycentric_dist); + size *= 0.5; + vec3 s = step(-size, -barys * barycentric_dist); - fac = max(s.x, max(s.y, s.z)); + fac = max(s.x, max(s.y, s.z)); } void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) { - vec3 barys = barycentric.xyy; - barys.z = 1.0 - barycentric.x - barycentric.y; + vec3 barys = barycentric.xyy; + barys.z = 1.0 - barycentric.x - barycentric.y; - size *= (1.0 / 3.0); - vec3 dx = dFdx(barys); - vec3 dy = dFdy(barys); - vec3 deltas = sqrt(dx * dx + dy * dy); + size *= (1.0 / 3.0); + vec3 dx = dFdx(barys); + vec3 dy = dFdy(barys); + vec3 deltas = sqrt(dx * dx + dy * dy); - vec3 s = step(-deltas * size, -barys); + vec3 s = step(-deltas * size, -barys); - fac = max(s.x, max(s.y, s.z)); + fac = max(s.x, max(s.y, s.z)); } /* background */ @@ -1525,16 +1737,16 @@ void node_wireframe_screenspace(float size, vec2 barycentric, out float fac) void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) { #ifdef MESH_SHADER - worldvec = worldPosition; + worldvec = worldPosition; #else - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); # if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - worldvec = (ViewMatrixInverse * co).xyz; + worldvec = (ViewMatrixInverse * co).xyz; # else - worldvec = (ModelViewMatrixInverse * co).xyz; + worldvec = (ModelViewMatrixInverse * co).xyz; # endif #endif } @@ -1542,12 +1754,12 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec) void node_background(vec4 color, float strength, out Closure result) { #ifndef VOLUMETRICS - color *= strength; - result = CLOSURE_DEFAULT; - result.radiance = color.rgb; - result.opacity = color.a; + color *= strength; + result = CLOSURE_DEFAULT; + result.radiance = color.rgb; + result.opacity = color.a; #else - result = CLOSURE_DEFAULT; + result = CLOSURE_DEFAULT; #endif } @@ -1556,100 +1768,100 @@ void node_background(vec4 color, float strength, out Closure result) void node_volume_scatter(vec4 color, float density, float anisotropy, out Closure result) { #ifdef VOLUMETRICS - result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); + result = Closure(vec3(0.0), color.rgb * density, vec3(0.0), anisotropy); #else - result = CLOSURE_DEFAULT; + result = CLOSURE_DEFAULT; #endif } void node_volume_absorption(vec4 color, float density, out Closure result) { #ifdef VOLUMETRICS - result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); + result = Closure((1.0 - color.rgb) * density, vec3(0.0), vec3(0.0), 0.0); #else - result = CLOSURE_DEFAULT; + result = CLOSURE_DEFAULT; #endif } void node_blackbody(float temperature, sampler1DArray spectrummap, float layer, out vec4 color) { - if (temperature >= 12000.0) { - color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); - } - else if (temperature < 965.0) { - color = vec4(4.70366907, 0.0, 0.0, 1.0); - } - else { - float t = (temperature - 965.0) / (12000.0 - 965.0); - color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); - } -} - -void node_volume_principled( - vec4 color, - float density, - float anisotropy, - vec4 absorption_color, - float emission_strength, - vec4 emission_color, - float blackbody_intensity, - vec4 blackbody_tint, - float temperature, - float density_attribute, - vec4 color_attribute, - float temperature_attribute, - sampler1DArray spectrummap, - float layer, - out Closure result) + if (temperature >= 12000.0) { + color = vec4(0.826270103, 0.994478524, 1.56626022, 1.0); + } + else if (temperature < 965.0) { + color = vec4(4.70366907, 0.0, 0.0, 1.0); + } + else { + float t = (temperature - 965.0) / (12000.0 - 965.0); + color = vec4(texture(spectrummap, vec2(t, layer)).rgb, 1.0); + } +} + +void node_volume_principled(vec4 color, + float density, + float anisotropy, + vec4 absorption_color, + float emission_strength, + vec4 emission_color, + float blackbody_intensity, + vec4 blackbody_tint, + float temperature, + float density_attribute, + vec4 color_attribute, + float temperature_attribute, + sampler1DArray spectrummap, + float layer, + out Closure result) { #ifdef VOLUMETRICS - vec3 absorption_coeff = vec3(0.0); - vec3 scatter_coeff = vec3(0.0); - vec3 emission_coeff = vec3(0.0); - - /* Compute density. */ - density = max(density, 0.0); - - if (density > 1e-5) { - density = max(density * density_attribute, 0.0); - } - - if (density > 1e-5) { - /* Compute scattering and absorption coefficients. */ - vec3 scatter_color = color.rgb * color_attribute.rgb; - - scatter_coeff = scatter_color * density; - absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); - absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * density; - } - - /* Compute emission. */ - emission_strength = max(emission_strength, 0.0); - - if (emission_strength > 1e-5) { - emission_coeff += emission_strength * emission_color.rgb; - } - - if (blackbody_intensity > 1e-3) { - /* Add temperature from attribute. */ - float T = max(temperature * max(temperature_attribute, 0.0), 0.0); - - /* Stefan-Boltzman law. */ - float T2 = T * T; - float T4 = T2 * T2; - float sigma = 5.670373e-8 * 1e-6 / M_PI; - float intensity = sigma * mix(1.0, T4, blackbody_intensity); - - if (intensity > 1e-5) { - vec4 bb; - node_blackbody(T, spectrummap, layer, bb); - emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; - } - } - - result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); + vec3 absorption_coeff = vec3(0.0); + vec3 scatter_coeff = vec3(0.0); + vec3 emission_coeff = vec3(0.0); + + /* Compute density. */ + density = max(density, 0.0); + + if (density > 1e-5) { + density = max(density * density_attribute, 0.0); + } + + if (density > 1e-5) { + /* Compute scattering and absorption coefficients. */ + vec3 scatter_color = color.rgb * color_attribute.rgb; + + scatter_coeff = scatter_color * density; + absorption_color.rgb = sqrt(max(absorption_color.rgb, 0.0)); + absorption_coeff = max(1.0 - scatter_color, 0.0) * max(1.0 - absorption_color.rgb, 0.0) * + density; + } + + /* Compute emission. */ + emission_strength = max(emission_strength, 0.0); + + if (emission_strength > 1e-5) { + emission_coeff += emission_strength * emission_color.rgb; + } + + if (blackbody_intensity > 1e-3) { + /* Add temperature from attribute. */ + float T = max(temperature * max(temperature_attribute, 0.0), 0.0); + + /* Stefan-Boltzman law. */ + float T2 = T * T; + float T4 = T2 * T2; + float sigma = 5.670373e-8 * 1e-6 / M_PI; + float intensity = sigma * mix(1.0, T4, blackbody_intensity); + + if (intensity > 1e-5) { + vec4 bb; + node_blackbody(T, spectrummap, layer, bb); + emission_coeff += bb.rgb * blackbody_tint.rgb * intensity; + } + } + + result = Closure(absorption_coeff, scatter_coeff, emission_coeff, anisotropy); #else - result = CLOSURE_DEFAULT; + result = CLOSURE_DEFAULT; #endif } @@ -1657,60 +1869,60 @@ void node_volume_principled( void node_mix_shader(float fac, Closure shader1, Closure shader2, out Closure shader) { - shader = closure_mix(shader1, shader2, fac); + shader = closure_mix(shader1, shader2, fac); } void node_add_shader(Closure shader1, Closure shader2, out Closure shader) { - shader = closure_add(shader1, shader2); + shader = closure_add(shader1, shader2); } /* fresnel */ void node_fresnel(float ior, vec3 N, vec3 I, out float result) { - N = normalize(N); - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + N = normalize(N); + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - float eta = max(ior, 0.00001); - result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); + float eta = max(ior, 0.00001); + result = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? eta : 1.0 / eta); } /* layer_weight */ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float facing) { - N = normalize(N); + N = normalize(N); - /* fresnel */ - float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + /* fresnel */ + float eta = max(1.0 - blend, 0.00001); + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); + fresnel = fresnel_dielectric(I_view, N, (gl_FrontFacing) ? 1.0 / eta : eta); - /* facing */ - facing = abs(dot(I_view, N)); - if (blend != 0.5) { - blend = clamp(blend, 0.0, 0.99999); - blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); - facing = pow(facing, blend); - } - facing = 1.0 - facing; + /* facing */ + facing = abs(dot(I_view, N)); + if (blend != 0.5) { + blend = clamp(blend, 0.0, 0.99999); + blend = (blend < 0.5) ? 2.0 * blend : 0.5 / (1.0 - blend); + facing = pow(facing, blend); + } + facing = 1.0 - facing; } /* gamma */ void node_gamma(vec4 col, float gamma, out vec4 outcol) { - outcol = col; + outcol = col; - if (col.r > 0.0) - outcol.r = compatible_pow(col.r, gamma); - if (col.g > 0.0) - outcol.g = compatible_pow(col.g, gamma); - if (col.b > 0.0) - outcol.b = compatible_pow(col.b, gamma); + if (col.r > 0.0) + outcol.r = compatible_pow(col.r, gamma); + if (col.g > 0.0) + outcol.g = compatible_pow(col.g, gamma); + if (col.b > 0.0) + outcol.b = compatible_pow(col.b, gamma); } /* geometry */ @@ -1718,13 +1930,13 @@ void node_gamma(vec4 col, float gamma, out vec4 outcol) void node_attribute_volume_density(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) { #if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; + vec3 cos = volumeObjectLocalCoord; #else - vec3 cos = vec3(0.0); + vec3 cos = vec3(0.0); #endif - outvec = texture(tex, cos).aaa; - outcol = vec4(outvec, 1.0); - outf = dot(vec3(1.0 / 3.0), outvec); + outvec = texture(tex, cos).aaa; + outcol = vec4(outvec, 1.0); + outf = dot(vec3(1.0 / 3.0), outvec); } uniform vec3 volumeColor = vec3(1.0); @@ -1732,353 +1944,401 @@ uniform vec3 volumeColor = vec3(1.0); void node_attribute_volume_color(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) { #if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; + vec3 cos = volumeObjectLocalCoord; #else - vec3 cos = vec3(0.0); + vec3 cos = vec3(0.0); #endif - vec4 value = texture(tex, cos).rgba; - /* Density is premultiplied for interpolation, divide it out here. */ - if (value.a > 1e-8) - value.rgb /= value.a; + vec4 value = texture(tex, cos).rgba; + /* Density is premultiplied for interpolation, divide it out here. */ + if (value.a > 1e-8) + value.rgb /= value.a; - outvec = value.rgb * volumeColor; - outcol = vec4(outvec, 1.0); - outf = dot(vec3(1.0 / 3.0), outvec); + outvec = value.rgb * volumeColor; + outcol = vec4(outvec, 1.0); + outf = dot(vec3(1.0 / 3.0), outvec); } void node_attribute_volume_flame(sampler3D tex, out vec4 outcol, out vec3 outvec, out float outf) { #if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; + vec3 cos = volumeObjectLocalCoord; #else - vec3 cos = vec3(0.0); + vec3 cos = vec3(0.0); #endif - outf = texture(tex, cos).r; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); + outf = texture(tex, cos).r; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); } -void node_attribute_volume_temperature(sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) +void node_attribute_volume_temperature( + sampler3D tex, vec2 temperature, out vec4 outcol, out vec3 outvec, out float outf) { #if defined(MESH_SHADER) && defined(VOLUMETRICS) - vec3 cos = volumeObjectLocalCoord; + vec3 cos = volumeObjectLocalCoord; #else - vec3 cos = vec3(0.0); + vec3 cos = vec3(0.0); #endif - float flame = texture(tex, cos).r; + float flame = texture(tex, cos).r; - outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x): 0.0; - outvec = vec3(outf, outf, outf); - outcol = vec4(outf, outf, outf, 1.0); + outf = (flame > 0.01) ? temperature.x + flame * (temperature.y - temperature.x) : 0.0; + outvec = vec3(outf, outf, outf); + outcol = vec4(outf, outf, outf, 1.0); } void node_attribute(vec3 attr, out vec4 outcol, out vec3 outvec, out float outf) { - outcol = vec4(attr, 1.0); - outvec = attr; - outf = dot(vec3(1.0 / 3.0), attr); + outcol = vec4(attr, 1.0); + outvec = attr; + outf = dot(vec3(1.0 / 3.0), attr); } void node_uvmap(vec3 attr_uv, out vec3 outvec) { - outvec = attr_uv; + outvec = attr_uv; } void tangent_orco_x(vec3 orco_in, out vec3 orco_out) { - orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); + orco_out = orco_in.xzy * vec3(0.0, -0.5, 0.5) + vec3(0.0, 0.25, -0.25); } void tangent_orco_y(vec3 orco_in, out vec3 orco_out) { - orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); + orco_out = orco_in.zyx * vec3(-0.5, 0.0, 0.5) + vec3(0.25, 0.0, -0.25); } void tangent_orco_z(vec3 orco_in, out vec3 orco_out) { - orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); + orco_out = orco_in.yxz * vec3(-0.5, 0.5, 0.0) + vec3(0.25, -0.25, 0.0); } void node_tangentmap(vec4 attr_tangent, mat4 toworld, out vec3 tangent) { - tangent = normalize((toworld * vec4(attr_tangent.xyz, 0.0)).xyz); + tangent = normalize((toworld * vec4(attr_tangent.xyz, 0.0)).xyz); } void node_tangent(vec3 N, vec3 orco, mat4 objmat, mat4 toworld, out vec3 T) { #ifndef VOLUMETRICS - N = normalize(gl_FrontFacing ? worldNormal : -worldNormal); + N = normalize(gl_FrontFacing ? worldNormal : -worldNormal); #else - N = (toworld * vec4(N, 0.0)).xyz; + N = (toworld * vec4(N, 0.0)).xyz; #endif - T = (objmat * vec4(orco, 0.0)).xyz; - T = cross(N, normalize(cross(T, N))); -} - -void node_geometry( - vec3 I, vec3 N, vec3 orco, mat4 objmat, mat4 toworld, vec2 barycentric, - out vec3 position, out vec3 normal, out vec3 tangent, - out vec3 true_normal, out vec3 incoming, out vec3 parametric, - out float backfacing, out float pointiness) -{ - /* handle perspective/orthographic */ - vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - incoming = -(toworld * vec4(I_view, 0.0)).xyz; + T = (objmat * vec4(orco, 0.0)).xyz; + T = cross(N, normalize(cross(T, N))); +} + +void node_geometry(vec3 I, + vec3 N, + vec3 orco, + mat4 objmat, + mat4 toworld, + vec2 barycentric, + out vec3 position, + out vec3 normal, + out vec3 tangent, + out vec3 true_normal, + out vec3 incoming, + out vec3 parametric, + out float backfacing, + out float pointiness) +{ + /* handle perspective/orthographic */ + vec3 I_view = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + incoming = -(toworld * vec4(I_view, 0.0)).xyz; #if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - position = -incoming; - true_normal = normal = incoming; - tangent = parametric = vec3(0.0); - vec3(0.0); - backfacing = 0.0; - pointiness = 0.0; + position = -incoming; + true_normal = normal = incoming; + tangent = parametric = vec3(0.0); + vec3(0.0); + backfacing = 0.0; + pointiness = 0.0; #else - position = worldPosition; + position = worldPosition; # ifndef VOLUMETRICS - normal = normalize(gl_FrontFacing ? worldNormal : -worldNormal); - vec3 B = dFdx(worldPosition); - vec3 T = dFdy(worldPosition); - true_normal = normalize(cross(B, T)); + normal = normalize(gl_FrontFacing ? worldNormal : -worldNormal); + vec3 B = dFdx(worldPosition); + vec3 T = dFdy(worldPosition); + true_normal = normalize(cross(B, T)); # else - normal = (toworld * vec4(N, 0.0)).xyz; - true_normal = normal; + normal = (toworld * vec4(N, 0.0)).xyz; + true_normal = normal; # endif - tangent_orco_z(orco, orco); - node_tangent(N, orco, objmat, toworld, tangent); + tangent_orco_z(orco, orco); + node_tangent(N, orco, objmat, toworld, tangent); - parametric = vec3(barycentric, 0.0); - backfacing = (gl_FrontFacing) ? 0.0 : 1.0; - pointiness = 0.5; + parametric = vec3(barycentric, 0.0); + backfacing = (gl_FrontFacing) ? 0.0 : 1.0; + pointiness = 0.5; #endif } void generated_texco(vec3 I, vec3 attr_orco, out vec3 generated) { - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - co.xyz = normalize(co.xyz); + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + co.xyz = normalize(co.xyz); #if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - generated = (ViewMatrixInverse * co).xyz; + generated = (ViewMatrixInverse * co).xyz; #else - generated_from_orco(attr_orco, generated); + generated_from_orco(attr_orco, generated); #endif } -void node_tex_coord( - vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, - vec3 attr_orco, vec3 attr_uv, - out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, - out vec3 camera, out vec3 window, out vec3 reflection) -{ - generated = attr_orco; - normal = normalize(NormalMatrixInverse * N); - uv = attr_uv; - object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; - camera = vec3(I.xy, -I.z); - vec4 projvec = ProjectionMatrix * vec4(I, 1.0); - window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); - - vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); - vec3 view_reflection = reflect(shade_I, normalize(N)); - reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; -} - -void node_tex_coord_background( - vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac, - vec3 attr_orco, vec3 attr_uv, - out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, - out vec3 camera, out vec3 window, out vec3 reflection) -{ - vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (ProjectionMatrixInverse * v); - - vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); - - co = normalize(co); +void node_tex_coord(vec3 I, + vec3 N, + mat4 viewinvmat, + mat4 obinvmat, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + generated = attr_orco; + normal = normalize(NormalMatrixInverse * N); + uv = attr_uv; + object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; + camera = vec3(I.xy, -I.z); + vec4 projvec = ProjectionMatrix * vec4(I, 1.0); + window = vec3(mtex_2d_mapping(projvec.xyz / projvec.w).xy * camerafac.xy + camerafac.zw, 0.0); + + vec3 shade_I = (ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + vec3 view_reflection = reflect(shade_I, normalize(N)); + reflection = (viewinvmat * vec4(view_reflection, 0.0)).xyz; +} + +void node_tex_coord_background(vec3 I, + vec3 N, + mat4 viewinvmat, + mat4 obinvmat, + vec4 camerafac, + vec3 attr_orco, + vec3 attr_uv, + out vec3 generated, + out vec3 normal, + out vec3 uv, + out vec3 object, + out vec3 camera, + out vec3 window, + out vec3 reflection) +{ + vec4 v = (ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); + vec4 co_homogenous = (ProjectionMatrixInverse * v); + + vec4 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0); + + co = normalize(co); #if defined(WORLD_BACKGROUND) || defined(PROBE_CAPTURE) - vec3 coords = (ViewMatrixInverse * co).xyz; + vec3 coords = (ViewMatrixInverse * co).xyz; #else - vec3 coords = (ModelViewMatrixInverse * co).xyz; + vec3 coords = (ModelViewMatrixInverse * co).xyz; #endif - generated = coords; - normal = -coords; - uv = vec3(attr_uv.xy, 0.0); - object = coords; + generated = coords; + normal = -coords; + uv = vec3(attr_uv.xy, 0.0); + object = coords; - camera = vec3(co.xy, -co.z); - window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); + camera = vec3(co.xy, -co.z); + window = vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0); - reflection = -coords; + reflection = -coords; } #if defined(WORLD_BACKGROUND) || (defined(PROBE_CAPTURE) && !defined(MESH_SHADER)) -#define node_tex_coord node_tex_coord_background +# define node_tex_coord node_tex_coord_background #endif /* textures */ float calc_gradient(vec3 p, int gradient_type) { - float x, y, z; - x = p.x; - y = p.y; - z = p.z; - if (gradient_type == 0) { /* linear */ - return x; - } - else if (gradient_type == 1) { /* quadratic */ - float r = max(x, 0.0); - return r * r; - } - else if (gradient_type == 2) { /* easing */ - float r = min(max(x, 0.0), 1.0); - float t = r * r; - return (3.0 * t - 2.0 * t * r); - } - else if (gradient_type == 3) { /* diagonal */ - return (x + y) * 0.5; - } - else if (gradient_type == 4) { /* radial */ - return atan(y, x) / (M_PI * 2) + 0.5; - } - else { - /* Bias a little bit for the case where p is a unit length vector, - * to get exactly zero instead of a small random value depending - * on float precision. */ - float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); - if (gradient_type == 5) { /* quadratic sphere */ - return r * r; - } - else if (gradient_type == 6) { /* sphere */ - return r; - } - } - return 0.0; + float x, y, z; + x = p.x; + y = p.y; + z = p.z; + if (gradient_type == 0) { /* linear */ + return x; + } + else if (gradient_type == 1) { /* quadratic */ + float r = max(x, 0.0); + return r * r; + } + else if (gradient_type == 2) { /* easing */ + float r = min(max(x, 0.0), 1.0); + float t = r * r; + return (3.0 * t - 2.0 * t * r); + } + else if (gradient_type == 3) { /* diagonal */ + return (x + y) * 0.5; + } + else if (gradient_type == 4) { /* radial */ + return atan(y, x) / (M_PI * 2) + 0.5; + } + else { + /* Bias a little bit for the case where p is a unit length vector, + * to get exactly zero instead of a small random value depending + * on float precision. */ + float r = max(0.999999 - sqrt(x * x + y * y + z * z), 0.0); + if (gradient_type == 5) { /* quadratic sphere */ + return r * r; + } + else if (gradient_type == 6) { /* sphere */ + return r; + } + } + return 0.0; } void node_tex_gradient(vec3 co, float gradient_type, out vec4 color, out float fac) { - float f = calc_gradient(co, int(gradient_type)); - f = clamp(f, 0.0, 1.0); + float f = calc_gradient(co, int(gradient_type)); + f = clamp(f, 0.0, 1.0); - color = vec4(f, f, f, 1.0); - fac = f; + color = vec4(f, f, f, 1.0); + fac = f; } -void node_tex_checker(vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) +void node_tex_checker( + vec3 co, vec4 color1, vec4 color2, float scale, out vec4 color, out float fac) { - vec3 p = co * scale; + vec3 p = co * scale; - /* Prevent precision issues on unit coordinates. */ - p = (p + 0.000001) * 0.999999; + /* Prevent precision issues on unit coordinates. */ + p = (p + 0.000001) * 0.999999; - int xi = int(abs(floor(p.x))); - int yi = int(abs(floor(p.y))); - int zi = int(abs(floor(p.z))); + int xi = int(abs(floor(p.x))); + int yi = int(abs(floor(p.y))); + int zi = int(abs(floor(p.z))); - bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); + bool check = ((mod(xi, 2) == mod(yi, 2)) == bool(mod(zi, 2))); - color = check ? color1 : color2; - fac = check ? 1.0 : 0.0; + color = check ? color1 : color2; + fac = check ? 1.0 : 0.0; } -vec2 calc_brick_texture(vec3 p, float mortar_size, float mortar_smooth, float bias, - float brick_width, float row_height, - float offset_amount, int offset_frequency, - float squash_amount, int squash_frequency) +vec2 calc_brick_texture(vec3 p, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + int offset_frequency, + float squash_amount, + int squash_frequency) { - int bricknum, rownum; - float offset = 0.0; - float x, y; + int bricknum, rownum; + float offset = 0.0; + float x, y; - rownum = floor_to_int(p.y / row_height); + rownum = floor_to_int(p.y / row_height); - if (offset_frequency != 0 && squash_frequency != 0) { - brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ - offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ - } + if (offset_frequency != 0 && squash_frequency != 0) { + brick_width *= (rownum % squash_frequency != 0) ? 1.0 : squash_amount; /* squash */ + offset = (rownum % offset_frequency != 0) ? 0.0 : (brick_width * offset_amount); /* offset */ + } - bricknum = floor_to_int((p.x + offset) / brick_width); + bricknum = floor_to_int((p.x + offset) / brick_width); - x = (p.x + offset) - brick_width * bricknum; - y = p.y - row_height * rownum; + x = (p.x + offset) - brick_width * bricknum; + y = p.y - row_height * rownum; - float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); + float tint = clamp((integer_noise((rownum << 16) + (bricknum & 0xFFFF)) + bias), 0.0, 1.0); - float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); - if (min_dist >= mortar_size) { - return vec2(tint, 0.0); - } - else if (mortar_smooth == 0.0) { - return vec2(tint, 1.0); - } - else { - min_dist = 1.0 - min_dist/mortar_size; - return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); - } + float min_dist = min(min(x, y), min(brick_width - x, row_height - y)); + if (min_dist >= mortar_size) { + return vec2(tint, 0.0); + } + else if (mortar_smooth == 0.0) { + return vec2(tint, 1.0); + } + else { + min_dist = 1.0 - min_dist / mortar_size; + return vec2(tint, smoothstep(0.0, mortar_smooth, min_dist)); + } } void node_tex_brick(vec3 co, - vec4 color1, vec4 color2, - vec4 mortar, float scale, - float mortar_size, float mortar_smooth, float bias, - float brick_width, float row_height, - float offset_amount, float offset_frequency, - float squash_amount, float squash_frequency, - out vec4 color, out float fac) -{ - vec2 f2 = calc_brick_texture(co * scale, - mortar_size, mortar_smooth, bias, - brick_width, row_height, - offset_amount, int(offset_frequency), - squash_amount, int(squash_frequency)); - float tint = f2.x; - float f = f2.y; - if (f != 1.0) { - float facm = 1.0 - tint; - color1 = facm * color1 + tint * color2; - } - color = mix(color1, mortar, f); - fac = f; + vec4 color1, + vec4 color2, + vec4 mortar, + float scale, + float mortar_size, + float mortar_smooth, + float bias, + float brick_width, + float row_height, + float offset_amount, + float offset_frequency, + float squash_amount, + float squash_frequency, + out vec4 color, + out float fac) +{ + vec2 f2 = calc_brick_texture(co * scale, + mortar_size, + mortar_smooth, + bias, + brick_width, + row_height, + offset_amount, + int(offset_frequency), + squash_amount, + int(squash_frequency)); + float tint = f2.x; + float f = f2.y; + if (f != 1.0) { + float facm = 1.0 - tint; + color1 = facm * color1 + tint * color2; + } + color = mix(color1, mortar, f); + fac = f; } void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac) { - color = vec4(1.0); - fac = 1.0; + color = vec4(1.0); + fac = 1.0; } void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv) { - vec3 nco = normalize(co); - uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; - uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; + vec3 nco = normalize(co); + uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5; + uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5; - /* Fix pole bleeding */ - float half_height = clamp_size / float(textureSize(ima, 0).y); - uv.y = clamp(uv.y, half_height, 1.0 - half_height); - uv.z = 0.0; + /* Fix pole bleeding */ + float half_height = clamp_size / float(textureSize(ima, 0).y); + uv.y = clamp(uv.y, half_height, 1.0 - half_height); + uv.z = 0.0; } void node_tex_environment_mirror_ball(vec3 co, out vec3 uv) { - vec3 nco = normalize(co); - nco.y -= 1.0; + vec3 nco = normalize(co); + nco.y -= 1.0; - float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); - nco /= max(1e-8, div); + float div = 2.0 * sqrt(max(-0.5 * nco.y, 0.0)); + nco /= max(1e-8, div); - uv = 0.5 * nco.xzz + 0.5; + uv = 0.5 * nco.xzz + 0.5; } void node_tex_environment_empty(vec3 co, out vec4 color) { - color = vec4(1.0, 0.0, 1.0, 1.0); + color = vec4(1.0, 0.0, 1.0, 1.0); } /* 16bits floats limits. Higher/Lower values produce +/-inf. */ @@ -2086,200 +2346,185 @@ void node_tex_environment_empty(vec3 co, out vec4 color) void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - color = safe_color(texture(ima, co.xy)); - alpha = color.a; + color = safe_color(texture(ima, co.xy)); + alpha = color.a; } void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - color = safe_color(textureLod(ima, co.xy, 0.0)); - alpha = color.a; + color = safe_color(textureLod(ima, co.xy, 0.0)); + alpha = color.a; } void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); - color = safe_color(texelFetch(ima, pix, 0)); - alpha = color.a; + ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy); + color = safe_color(texelFetch(ima, pix, 0)); + alpha = color.a; } /* @arg f: signed distance to texel center. */ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3) { - vec2 f2 = f * f; - vec2 f3 = f2 * f; - /* Bspline coefs (optimized) */ - w3 = f3 / 6.0; - w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; - w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; - w2 = 1.0 - w0 - w1 - w3; + vec2 f2 = f * f; + vec2 f3 = f2 * f; + /* Bspline coefs (optimized) */ + w3 = f3 / 6.0; + w0 = -w3 + f2 * 0.5 - f * 0.5 + 1.0 / 6.0; + w1 = f3 * 0.5 - f2 * 1.0 + 2.0 / 3.0; + w2 = 1.0 - w0 - w1 - w3; } -void node_tex_image_cubic_ex(vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) +void node_tex_image_cubic_ex( + vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha) { - vec2 tex_size = vec2(textureSize(ima, 0).xy); + vec2 tex_size = vec2(textureSize(ima, 0).xy); - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); #if 1 /* Optimized version using 4 filtered tap. */ - vec2 s0 = w0 + w1; - vec2 s1 = w2 + w3; + vec2 s0 = w0 + w1; + vec2 s1 = w2 + w3; - vec2 f0 = w1 / (w0 + w1); - vec2 f1 = w3 / (w2 + w3); + vec2 f0 = w1 / (w0 + w1); + vec2 f1 = w3 / (w2 + w3); - vec4 final_co; - final_co.xy = tc - 1.0 + f0; - final_co.zw = tc + 1.0 + f1; + vec4 final_co; + final_co.xy = tc - 1.0 + f0; + final_co.zw = tc + 1.0 + f1; - if (do_extend == 1.0) { - final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); - } - final_co /= tex_size.xyxy; + if (do_extend == 1.0) { + final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5); + } + final_co /= tex_size.xyxy; - color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; - color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; - color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; - color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; + color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y; + color += safe_color(textureLod(ima, final_co.zy, 0.0)) * s1.x * s0.y; + color += safe_color(textureLod(ima, final_co.xw, 0.0)) * s0.x * s1.y; + color += safe_color(textureLod(ima, final_co.zw, 0.0)) * s1.x * s1.y; #else /* Reference bruteforce 16 tap. */ - color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2( 0.0, -1.0)), 0) * w1.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2( 1.0, -1.0)), 0) * w2.x * w0.y; - color += texelFetch(ima, ivec2(tc + vec2( 2.0, -1.0)), 0) * w3.x * w0.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2( 0.0, 0.0)), 0) * w1.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2( 1.0, 0.0)), 0) * w2.x * w1.y; - color += texelFetch(ima, ivec2(tc + vec2( 2.0, 0.0)), 0) * w3.x * w1.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2( 0.0, 1.0)), 0) * w1.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2( 1.0, 1.0)), 0) * w2.x * w2.y; - color += texelFetch(ima, ivec2(tc + vec2( 2.0, 1.0)), 0) * w3.x * w2.y; - - color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2( 0.0, 2.0)), 0) * w1.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2( 1.0, 2.0)), 0) * w2.x * w3.y; - color += texelFetch(ima, ivec2(tc + vec2( 2.0, 2.0)), 0) * w3.x * w3.y; + color = texelFetch(ima, ivec2(tc + vec2(-1.0, -1.0)), 0) * w0.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, -1.0)), 0) * w1.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, -1.0)), 0) * w2.x * w0.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, -1.0)), 0) * w3.x * w0.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 0.0)), 0) * w0.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 0.0)), 0) * w1.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 0.0)), 0) * w2.x * w1.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 0.0)), 0) * w3.x * w1.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 1.0)), 0) * w0.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 1.0)), 0) * w1.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 1.0)), 0) * w2.x * w2.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 1.0)), 0) * w3.x * w2.y; + + color += texelFetch(ima, ivec2(tc + vec2(-1.0, 2.0)), 0) * w0.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(0.0, 2.0)), 0) * w1.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(1.0, 2.0)), 0) * w2.x * w3.y; + color += texelFetch(ima, ivec2(tc + vec2(2.0, 2.0)), 0) * w3.x * w3.y; #endif - alpha = color.a; + alpha = color.a; } void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); } void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); + node_tex_image_cubic_ex(co, ima, 1.0, color, alpha); } void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha) { - /* use cubic for now */ - node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); -} - -void tex_box_sample_linear(vec3 texco, - vec3 N, - sampler2D ima, - out vec4 color1, - out vec4 color2, - out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - color1 = texture(ima, uv); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - color2 = texture(ima, uv); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - color3 = texture(ima, uv); -} - -void tex_box_sample_nearest(vec3 texco, - vec3 N, - sampler2D ima, - out vec4 color1, - out vec4 color2, - out vec4 color3) -{ - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color1 = texelFetch(ima, pix, 0); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color2 = texelFetch(ima, pix, 0); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - pix = ivec2(uv.xy * textureSize(ima, 0).xy); - color3 = texelFetch(ima, pix, 0); -} - -void tex_box_sample_cubic(vec3 texco, - vec3 N, - sampler2D ima, - out vec4 color1, - out vec4 color2, - out vec4 color3) -{ - float alpha; - /* X projection */ - vec2 uv = texco.yz; - if (N.x < 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); - /* Y projection */ - uv = texco.xz; - if (N.y > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); - /* Z projection */ - uv = texco.yx; - if (N.z > 0.0) { - uv.x = 1.0 - uv.x; - } - node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); -} - -void tex_box_sample_smart(vec3 texco, - vec3 N, - sampler2D ima, - out vec4 color1, - out vec4 color2, - out vec4 color3) -{ - tex_box_sample_cubic(texco, N, ima, color1, color2, color3); + /* use cubic for now */ + node_tex_image_cubic_ex(co, ima, 0.0, color, alpha); +} + +void tex_box_sample_linear( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + color1 = texture(ima, uv); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + color2 = texture(ima, uv); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + color3 = texture(ima, uv); +} + +void tex_box_sample_nearest( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + ivec2 pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color1 = texelFetch(ima, pix, 0); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color2 = texelFetch(ima, pix, 0); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + pix = ivec2(uv.xy * textureSize(ima, 0).xy); + color3 = texelFetch(ima, pix, 0); +} + +void tex_box_sample_cubic( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + float alpha; + /* X projection */ + vec2 uv = texco.yz; + if (N.x < 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha); + /* Y projection */ + uv = texco.xz; + if (N.y > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha); + /* Z projection */ + uv = texco.yx; + if (N.z > 0.0) { + uv.x = 1.0 - uv.x; + } + node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha); +} + +void tex_box_sample_smart( + vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3) +{ + tex_box_sample_cubic(texco, N, ima, color1, color2, color3); } void node_tex_image_box(vec3 texco, @@ -2292,298 +2537,303 @@ void node_tex_image_box(vec3 texco, out vec4 color, out float alpha) { - /* project from direction vector to barycentric coordinates in triangles */ - N = abs(N); - N /= dot(N, vec3(1.0)); - - /* basic idea is to think of this as a triangle, each corner representing - * one of the 3 faces of the cube. in the corners we have single textures, - * in between we blend between two textures, and in the middle we a blend - * between three textures. - * - * the Nxyz values are the barycentric coordinates in an equilateral - * triangle, which in case of blending, in the middle has a smaller - * equilateral triangle where 3 textures blend. this divides things into - * 7 zones, with an if () test for each zone - * EDIT: Now there is only 4 if's. */ - - float limit = 0.5 + 0.5 * blend; - - vec3 weight; - weight = N.xyz / (N.xyx + N.yzz); - weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); - - /* test for mixes between two textures */ - if (N.z < (1.0 - limit) * (N.y + N.x)) { - weight.z = 0.0; - weight.y = 1.0 - weight.x; - } - else if (N.x < (1.0 - limit) * (N.y + N.z)) { - weight.x = 0.0; - weight.z = 1.0 - weight.y; - } - else if (N.y < (1.0 - limit) * (N.x + N.z)) { - weight.y = 0.0; - weight.x = 1.0 - weight.z; - } - else { - /* last case, we have a mix between three */ - weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); - } - - color = weight.x * color1 + weight.y * color2 + weight.z * color3; - alpha = color.a; + /* project from direction vector to barycentric coordinates in triangles */ + N = abs(N); + N /= dot(N, vec3(1.0)); + + /* basic idea is to think of this as a triangle, each corner representing + * one of the 3 faces of the cube. in the corners we have single textures, + * in between we blend between two textures, and in the middle we a blend + * between three textures. + * + * the Nxyz values are the barycentric coordinates in an equilateral + * triangle, which in case of blending, in the middle has a smaller + * equilateral triangle where 3 textures blend. this divides things into + * 7 zones, with an if () test for each zone + * EDIT: Now there is only 4 if's. */ + + float limit = 0.5 + 0.5 * blend; + + vec3 weight; + weight = N.xyz / (N.xyx + N.yzz); + weight = clamp((weight - 0.5 * (1.0 - blend)) / max(1e-8, blend), 0.0, 1.0); + + /* test for mixes between two textures */ + if (N.z < (1.0 - limit) * (N.y + N.x)) { + weight.z = 0.0; + weight.y = 1.0 - weight.x; + } + else if (N.x < (1.0 - limit) * (N.y + N.z)) { + weight.x = 0.0; + weight.z = 1.0 - weight.y; + } + else if (N.y < (1.0 - limit) * (N.x + N.z)) { + weight.y = 0.0; + weight.x = 1.0 - weight.z; + } + else { + /* last case, we have a mix between three */ + weight = ((2.0 - limit) * N + (limit - 1.0)) / max(1e-8, blend); + } + + color = weight.x * color1 + weight.y * color2 + weight.z * color3; + alpha = color.a; } void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) { - vec2 tex_size = vec2(textureSize(ima, 0).xy); - vec2 minco = min(co.xy, 1.0 - co.xy); - minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); - float fac = minco.x * minco.y; + vec2 tex_size = vec2(textureSize(ima, 0).xy); + vec2 minco = min(co.xy, 1.0 - co.xy); + minco = clamp(minco * tex_size + 0.5, 0.0, 1.0); + float fac = minco.x * minco.y; - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; } void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) { - vec4 minco = vec4(co.xy, 1.0 - co.xy); - color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; - alpha = color.a; + vec4 minco = vec4(co.xy, 1.0 - co.xy); + color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor; + alpha = color.a; } void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) { - vec2 tex_size = vec2(textureSize(ima, 0).xy); - - co.xy *= tex_size; - /* texel center */ - vec2 tc = floor(co.xy - 0.5) + 0.5; - vec2 w0, w1, w2, w3; - cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); - - /* TODO Optimize this part. I'm sure there is a smarter way to do that. - * Could do that when sampling? */ -#define CLIP_CUBIC_SAMPLE(samp, size) (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) - ivec2 itex_size = textureSize(ima, 0).xy; - float fac; - fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0, -1.0), itex_size) * w1.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0, -1.0), itex_size) * w2.x * w0.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0, -1.0), itex_size) * w3.x * w0.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0, 0.0), itex_size) * w1.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0, 0.0), itex_size) * w2.x * w1.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0, 0.0), itex_size) * w3.x * w1.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0, 1.0), itex_size) * w1.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0, 1.0), itex_size) * w2.x * w2.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0, 1.0), itex_size) * w3.x * w2.y; - - fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 0.0, 2.0), itex_size) * w1.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 1.0, 2.0), itex_size) * w2.x * w3.y; - fac += CLIP_CUBIC_SAMPLE(tc + vec2( 2.0, 2.0), itex_size) * w3.x * w3.y; + vec2 tex_size = vec2(textureSize(ima, 0).xy); + + co.xy *= tex_size; + /* texel center */ + vec2 tc = floor(co.xy - 0.5) + 0.5; + vec2 w0, w1, w2, w3; + cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3); + + /* TODO Optimize this part. I'm sure there is a smarter way to do that. + * Could do that when sampling? */ +#define CLIP_CUBIC_SAMPLE(samp, size) \ + (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size)))) + ivec2 itex_size = textureSize(ima, 0).xy; + float fac; + fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y; + + fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y; + fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y; #undef CLIP_CUBIC_SAMPLE - color = mix(vec4(0.0), icolor, fac); - alpha = color.a; + color = mix(vec4(0.0), icolor, fac); + alpha = color.a; } void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha) { - tex_clip_cubic(co, ima, icolor, color, alpha); + tex_clip_cubic(co, ima, icolor, color, alpha); } void node_tex_image_empty(vec3 co, out vec4 color, out float alpha) { - color = vec4(0.0); - alpha = 0.0; -} - -void node_tex_magic(vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) -{ - vec3 p = co * scale; - float x = sin((p.x + p.y + p.z) * 5.0); - float y = cos((-p.x + p.y - p.z) * 5.0); - float z = -cos((-p.x - p.y + p.z) * 5.0); - - if (depth > 0) { - x *= distortion; - y *= distortion; - z *= distortion; - y = -cos(x - y + z); - y *= distortion; - if (depth > 1) { - x = cos(x - y - z); - x *= distortion; - if (depth > 2) { - z = sin(-x - y - z); - z *= distortion; - if (depth > 3) { - x = -cos(-x + y - z); - x *= distortion; - if (depth > 4) { - y = -sin(-x + y + z); - y *= distortion; - if (depth > 5) { - y = -cos(-x + y + z); - y *= distortion; - if (depth > 6) { - x = cos(x + y + z); - x *= distortion; - if (depth > 7) { - z = sin(x + y - z); - z *= distortion; - if (depth > 8) { - x = -cos(-x - y + z); - x *= distortion; - if (depth > 9) { - y = -sin(x - y + z); - y *= distortion; - } - } - } - } - } - } - } - } - } - } - if (distortion != 0.0) { - distortion *= 2.0; - x /= distortion; - y /= distortion; - z /= distortion; - } - - color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); - fac = (color.x + color.y + color.z) / 3.0; + color = vec4(0.0); + alpha = 0.0; +} + +void node_tex_magic( + vec3 co, float scale, float distortion, float depth, out vec4 color, out float fac) +{ + vec3 p = co * scale; + float x = sin((p.x + p.y + p.z) * 5.0); + float y = cos((-p.x + p.y - p.z) * 5.0); + float z = -cos((-p.x - p.y + p.z) * 5.0); + + if (depth > 0) { + x *= distortion; + y *= distortion; + z *= distortion; + y = -cos(x - y + z); + y *= distortion; + if (depth > 1) { + x = cos(x - y - z); + x *= distortion; + if (depth > 2) { + z = sin(-x - y - z); + z *= distortion; + if (depth > 3) { + x = -cos(-x + y - z); + x *= distortion; + if (depth > 4) { + y = -sin(-x + y + z); + y *= distortion; + if (depth > 5) { + y = -cos(-x + y + z); + y *= distortion; + if (depth > 6) { + x = cos(x + y + z); + x *= distortion; + if (depth > 7) { + z = sin(x + y - z); + z *= distortion; + if (depth > 8) { + x = -cos(-x - y + z); + x *= distortion; + if (depth > 9) { + y = -sin(x - y + z); + y *= distortion; + } + } + } + } + } + } + } + } + } + } + if (distortion != 0.0) { + distortion *= 2.0; + x /= distortion; + y /= distortion; + z /= distortion; + } + + color = vec4(0.5 - x, 0.5 - y, 0.5 - z, 1.0); + fac = (color.x + color.y + color.z) / 3.0; } float noise_fade(float t) { - return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); } float noise_scale3(float result) { - return 0.9820 * result; + return 0.9820 * result; } float noise_nerp(float t, float a, float b) { - return (1.0 - t) * a + t * b; + return (1.0 - t) * a + t * b; } float noise_grad(uint hash, float x, float y, float z) { - uint h = hash & 15u; - float u = h < 8u ? x : y; - float vt = ((h == 12u) || (h == 14u)) ? x : z; - float v = h < 4u ? y : vt; - return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); + uint h = hash & 15u; + float u = h < 8u ? x : y; + float vt = ((h == 12u) || (h == 14u)) ? x : z; + float v = h < 4u ? y : vt; + return (((h & 1u) != 0u) ? -u : u) + (((h & 2u) != 0u) ? -v : v); } float noise_perlin(float x, float y, float z) { - int X; float fx = floorfrac(x, X); - int Y; float fy = floorfrac(y, Y); - int Z; float fz = floorfrac(z, Z); + int X; + float fx = floorfrac(x, X); + int Y; + float fy = floorfrac(y, Y); + int Z; + float fz = floorfrac(z, Z); - float u = noise_fade(fx); - float v = noise_fade(fy); - float w = noise_fade(fz); + float u = noise_fade(fx); + float v = noise_fade(fy); + float w = noise_fade(fz); - float noise_u[2], noise_v[2]; + float noise_u[2], noise_v[2]; - noise_u[0] = noise_nerp(u, - noise_grad(hash(X, Y, Z), fx, fy, fz), - noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)); + noise_u[0] = noise_nerp( + u, noise_grad(hash(X, Y, Z), fx, fy, fz), noise_grad(hash(X + 1, Y, Z), fx - 1.0, fy, fz)); - noise_u[1] = noise_nerp(u, - noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz), - noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); + noise_u[1] = noise_nerp(u, + noise_grad(hash(X, Y + 1, Z), fx, fy - 1.0, fz), + noise_grad(hash(X + 1, Y + 1, Z), fx - 1.0, fy - 1.0, fz)); - noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); + noise_v[0] = noise_nerp(v, noise_u[0], noise_u[1]); - noise_u[0] = noise_nerp(u, - noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0), - noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); + noise_u[0] = noise_nerp(u, + noise_grad(hash(X, Y, Z + 1), fx, fy, fz - 1.0), + noise_grad(hash(X + 1, Y, Z + 1), fx - 1.0, fy, fz - 1.0)); - noise_u[1] = noise_nerp(u, - noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), - noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); + noise_u[1] = noise_nerp(u, + noise_grad(hash(X, Y + 1, Z + 1), fx, fy - 1.0, fz - 1.0), + noise_grad(hash(X + 1, Y + 1, Z + 1), fx - 1.0, fy - 1.0, fz - 1.0)); - noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); + noise_v[1] = noise_nerp(v, noise_u[0], noise_u[1]); - return noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); + return noise_scale3(noise_nerp(w, noise_v[0], noise_v[1])); } float noise(vec3 p) { - return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; + return 0.5 * noise_perlin(p.x, p.y, p.z) + 0.5; } float snoise(vec3 p) { - return noise_perlin(p.x, p.y, p.z); + return noise_perlin(p.x, p.y, p.z); } float noise_turbulence(vec3 p, float octaves, int hard) { - float fscale = 1.0; - float amp = 1.0; - float sum = 0.0; - octaves = clamp(octaves, 0.0, 16.0); - int n = int(octaves); - for (int i = 0; i <= n; i++) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - sum += t * amp; - amp *= 0.5; - fscale *= 2.0; - } - float rmd = octaves - floor(octaves); - if (rmd != 0.0) { - float t = noise(fscale * p); - if (hard != 0) { - t = abs(2.0 * t - 1.0); - } - float sum2 = sum + t * amp; - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); - return (1.0 - rmd) * sum + rmd * sum2; - } - else { - sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); - return sum; - } -} - -void node_tex_noise(vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) -{ - vec3 p = co * scale; - int hard = 0; - if (distortion != 0.0) { - vec3 r, offset = vec3(13.5, 13.5, 13.5); - r.x = noise(p + offset) * distortion; - r.y = noise(p) * distortion; - r.z = noise(p - offset) * distortion; - p += r; - } - - fac = noise_turbulence(p, detail, hard); - color = vec4(fac, - noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), - noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), - 1); + float fscale = 1.0; + float amp = 1.0; + float sum = 0.0; + octaves = clamp(octaves, 0.0, 16.0); + int n = int(octaves); + for (int i = 0; i <= n; i++) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + sum += t * amp; + amp *= 0.5; + fscale *= 2.0; + } + float rmd = octaves - floor(octaves); + if (rmd != 0.0) { + float t = noise(fscale * p); + if (hard != 0) { + t = abs(2.0 * t - 1.0); + } + float sum2 = sum + t * amp; + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + sum2 *= (float(1 << (n + 1)) / float((1 << (n + 2)) - 1)); + return (1.0 - rmd) * sum + rmd * sum2; + } + else { + sum *= (float(1 << n) / float((1 << (n + 1)) - 1)); + return sum; + } +} + +void node_tex_noise( + vec3 co, float scale, float detail, float distortion, out vec4 color, out float fac) +{ + vec3 p = co * scale; + int hard = 0; + if (distortion != 0.0) { + vec3 r, offset = vec3(13.5, 13.5, 13.5); + r.x = noise(p + offset) * distortion; + r.y = noise(p) * distortion; + r.z = noise(p - offset) * distortion; + p += r; + } + + fac = noise_turbulence(p, detail, hard); + color = vec4(fac, + noise_turbulence(vec3(p.y, p.x, p.z), detail, hard), + noise_turbulence(vec3(p.y, p.z, p.x), detail, hard), + 1); } /* Musgrave fBm @@ -2597,22 +2847,22 @@ void node_tex_noise(vec3 co, float scale, float detail, float distortion, out ve float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) { - float rmd; - float value = 0.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); + float rmd; + float value = 0.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); - for (int i = 0; i < int(octaves); i++) { - value += snoise(p) * pwr; - pwr *= pwHL; - p *= lacunarity; - } + for (int i = 0; i < int(octaves); i++) { + value += snoise(p) * pwr; + pwr *= pwHL; + p *= lacunarity; + } - rmd = octaves - floor(octaves); - if (rmd != 0.0) - value += rmd * snoise(p) * pwr; + rmd = octaves - floor(octaves); + if (rmd != 0.0) + value += rmd * snoise(p) * pwr; - return value; + return value; } /* Musgrave Multifractal @@ -2624,22 +2874,22 @@ float noise_musgrave_fBm(vec3 p, float H, float lacunarity, float octaves) float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octaves) { - float rmd; - float value = 1.0; - float pwr = 1.0; - float pwHL = pow(lacunarity, -H); + float rmd; + float value = 1.0; + float pwr = 1.0; + float pwHL = pow(lacunarity, -H); - for (int i = 0; i < int(octaves); i++) { - value *= (pwr * snoise(p) + 1.0); - pwr *= pwHL; - p *= lacunarity; - } + for (int i = 0; i < int(octaves); i++) { + value *= (pwr * snoise(p) + 1.0); + pwr *= pwHL; + p *= lacunarity; + } - rmd = octaves - floor(octaves); - if (rmd != 0.0) - value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ + rmd = octaves - floor(octaves); + if (rmd != 0.0) + value *= (rmd * pwr * snoise(p) + 1.0); /* correct? */ - return value; + return value; } /* Musgrave Heterogeneous Terrain @@ -2652,28 +2902,28 @@ float noise_musgrave_multi_fractal(vec3 p, float H, float lacunarity, float octa float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float octaves, float offset) { - float value, increment, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; + float value, increment, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; - /* first unscaled octave of function; later octaves are scaled */ - value = offset + snoise(p); - p *= lacunarity; + /* first unscaled octave of function; later octaves are scaled */ + value = offset + snoise(p); + p *= lacunarity; - for (int i = 1; i < int(octaves); i++) { - increment = (snoise(p) + offset) * pwr * value; - value += increment; - pwr *= pwHL; - p *= lacunarity; - } + for (int i = 1; i < int(octaves); i++) { + increment = (snoise(p) + offset) * pwr * value; + value += increment; + pwr *= pwHL; + p *= lacunarity; + } - rmd = octaves - floor(octaves); - if (rmd != 0.0) { - increment = (snoise(p) + offset) * pwr * value; - value += rmd * increment; - } + rmd = octaves - floor(octaves); + if (rmd != 0.0) { + increment = (snoise(p) + offset) * pwr * value; + value += rmd * increment; + } - return value; + return value; } /* Hybrid Additive/Multiplicative Multifractal Terrain @@ -2684,32 +2934,33 @@ float noise_musgrave_hetero_terrain(vec3 p, float H, float lacunarity, float oct * offset: raises the terrain from `sea level' */ -float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_hybrid_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) { - float result, signal, weight, rmd; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; + float result, signal, weight, rmd; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; - result = snoise(p) + offset; - weight = gain * result; - p *= lacunarity; + result = snoise(p) + offset; + weight = gain * result; + p *= lacunarity; - for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { - if (weight > 1.0) - weight = 1.0; + for (int i = 1; (weight > 0.001f) && (i < int(octaves)); i++) { + if (weight > 1.0) + weight = 1.0; - signal = (snoise(p) + offset) * pwr; - pwr *= pwHL; - result += weight * signal; - weight *= gain * signal; - p *= lacunarity; - } + signal = (snoise(p) + offset) * pwr; + pwr *= pwHL; + result += weight * signal; + weight *= gain * signal; + p *= lacunarity; + } - rmd = octaves - floor(octaves); - if (rmd != 0.0) - result += rmd * ((snoise(p) + offset) * pwr); + rmd = octaves - floor(octaves); + if (rmd != 0.0) + result += rmd * ((snoise(p) + offset) * pwr); - return result; + return result; } /* Ridged Multifractal Terrain @@ -2720,28 +2971,29 @@ float noise_musgrave_hybrid_multi_fractal(vec3 p, float H, float lacunarity, flo * offset: raises the terrain from `sea level' */ -float noise_musgrave_ridged_multi_fractal(vec3 p, float H, float lacunarity, float octaves, float offset, float gain) +float noise_musgrave_ridged_multi_fractal( + vec3 p, float H, float lacunarity, float octaves, float offset, float gain) { - float result, signal, weight; - float pwHL = pow(lacunarity, -H); - float pwr = pwHL; + float result, signal, weight; + float pwHL = pow(lacunarity, -H); + float pwr = pwHL; - signal = offset - abs(snoise(p)); - signal *= signal; - result = signal; - weight = 1.0; + signal = offset - abs(snoise(p)); + signal *= signal; + result = signal; + weight = 1.0; - for (int i = 1; i < int(octaves); i++) { - p *= lacunarity; - weight = clamp(signal * gain, 0.0, 1.0); - signal = offset - abs(snoise(p)); - signal *= signal; - signal *= weight; - result += signal * pwr; - pwr *= pwHL; - } + for (int i = 1; i < int(octaves); i++) { + p *= lacunarity; + weight = clamp(signal * gain, 0.0, 1.0); + signal = offset - abs(snoise(p)); + signal *= signal; + signal *= weight; + result += signal * pwr; + pwr *= pwHL; + } - return result; + return result; } float svm_musgrave(int type, @@ -2753,17 +3005,19 @@ float svm_musgrave(int type, float gain, vec3 p) { - if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) - return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); - else if (type == 1 /* NODE_MUSGRAVE_FBM */) - return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); - else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) - return intensity * noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) - return intensity * noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); - else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) - return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); - return 0.0; + if (type == 0 /* NODE_MUSGRAVE_MULTIFRACTAL */) + return intensity * noise_musgrave_multi_fractal(p, dimension, lacunarity, octaves); + else if (type == 1 /* NODE_MUSGRAVE_FBM */) + return intensity * noise_musgrave_fBm(p, dimension, lacunarity, octaves); + else if (type == 2 /* NODE_MUSGRAVE_HYBRID_MULTIFRACTAL */) + return intensity * + noise_musgrave_hybrid_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + else if (type == 3 /* NODE_MUSGRAVE_RIDGED_MULTIFRACTAL */) + return intensity * + noise_musgrave_ridged_multi_fractal(p, dimension, lacunarity, octaves, offset, gain); + else if (type == 4 /* NODE_MUSGRAVE_HETERO_TERRAIN */) + return intensity * noise_musgrave_hetero_terrain(p, dimension, lacunarity, octaves, offset); + return 0.0; } void node_tex_musgrave(vec3 co, @@ -2777,308 +3031,337 @@ void node_tex_musgrave(vec3 co, out vec4 color, out float fac) { - fac = svm_musgrave(int(type), - dimension, - lacunarity, - detail, - offset, - 1.0, - gain, - co * scale); + fac = svm_musgrave(int(type), dimension, lacunarity, detail, offset, 1.0, gain, co *scale); - color = vec4(fac, fac, fac, 1.0); + color = vec4(fac, fac, fac, 1.0); } void node_tex_sky(vec3 co, out vec4 color) { - color = vec4(1.0); -} - -void node_tex_voronoi(vec3 co, float scale, float exponent, float coloring, float metric, float feature, out vec4 color, out float fac) -{ - vec3 p = co * scale; - int xx, yy, zz, xi, yi, zi; - vec4 da = vec4(1e10); - vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - - xi = floor_to_int(p[0]); - yi = floor_to_int(p[1]); - zi = floor_to_int(p[2]); - - for (xx = xi - 1; xx <= xi + 1; xx++) { - for (yy = yi - 1; yy <= yi + 1; yy++) { - for (zz = zi - 1; zz <= zi + 1; zz++) { - vec3 ip = vec3(xx, yy, zz); - vec3 vp = cellnoise_color(ip); - vec3 pd = p - (vp + ip); - - float d = 0.0; - if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ - d = dot(pd, pd); - } - else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ - d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); - } - else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ - d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); - } - else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ - d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + pow(abs(pd[2]), exponent), 1.0/exponent); - } - - vp += vec3(xx, yy, zz); - if (d < da[0]) { - da.yzw = da.xyz; - da[0] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = pa[0]; - pa[0] = vp; - } - else if (d < da[1]) { - da.zw = da.yz; - da[1] = d; - - pa[3] = pa[2]; - pa[2] = pa[1]; - pa[1] = vp; - } - else if (d < da[2]) { - da[3] = da[2]; - da[2] = d; - - pa[3] = pa[2]; - pa[2] = vp; - } - else if (d < da[3]) { - da[3] = d; - pa[3] = vp; - } - } - } - } - - if (coloring == 0.0) { - /* Intensity output */ - if (feature == 0.0) { /* F1 */ - fac = abs(da[0]); - } - else if (feature == 1.0) { /* F2 */ - fac = abs(da[1]); - } - else if (feature == 2.0) { /* F3 */ - fac = abs(da[2]); - } - else if (feature == 3.0) { /* F4 */ - fac = abs(da[3]); - } - else if (feature == 4.0) { /* F2F1 */ - fac = abs(da[1] - da[0]); - } - color = vec4(fac, fac, fac, 1.0); - } - else { - /* Color output */ - vec3 col = vec3(fac, fac, fac); - if (feature == 0.0) { /* F1 */ - col = pa[0]; - } - else if (feature == 1.0) { /* F2 */ - col = pa[1]; - } - else if (feature == 2.0) { /* F3 */ - col = pa[2]; - } - else if (feature == 3.0) { /* F4 */ - col = pa[3]; - } - else if (feature == 4.0) { /* F2F1 */ - col = abs(pa[1] - pa[0]); - } - - color = vec4(cellnoise_color(col), 1.0); - fac = (color.x + color.y + color.z) * (1.0 / 3.0); - } -} - -float calc_wave(vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) -{ - float n; - - if (wave_type == 0) /* type bands */ - n = (p.x + p.y + p.z) * 10.0; - else /* type rings */ - n = length(p) * 20.0; - - if (distortion != 0.0) - n += distortion * noise_turbulence(p * detail_scale, detail, 0); - - if (wave_profile == 0) { /* profile sin */ - return 0.5 + 0.5 * sin(n); - } - else { /* profile saw */ - n /= 2.0 * M_PI; - n -= int(n); - return (n < 0.0) ? n + 1.0 : n; - } -} - -void node_tex_wave( - vec3 co, float scale, float distortion, float detail, float detail_scale, float wave_type, float wave_profile, - out vec4 color, out float fac) -{ - float f; - f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); - - color = vec4(f, f, f, 1.0); - fac = f; + color = vec4(1.0); +} + +void node_tex_voronoi(vec3 co, + float scale, + float exponent, + float coloring, + float metric, + float feature, + out vec4 color, + out float fac) +{ + vec3 p = co * scale; + int xx, yy, zz, xi, yi, zi; + vec4 da = vec4(1e10); + vec3 pa[4] = vec3[4](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + + xi = floor_to_int(p[0]); + yi = floor_to_int(p[1]); + zi = floor_to_int(p[2]); + + for (xx = xi - 1; xx <= xi + 1; xx++) { + for (yy = yi - 1; yy <= yi + 1; yy++) { + for (zz = zi - 1; zz <= zi + 1; zz++) { + vec3 ip = vec3(xx, yy, zz); + vec3 vp = cellnoise_color(ip); + vec3 pd = p - (vp + ip); + + float d = 0.0; + if (metric == 0.0) { /* SHD_VORONOI_DISTANCE 0 */ + d = dot(pd, pd); + } + else if (metric == 1.0) { /* SHD_VORONOI_MANHATTAN 1 */ + d = abs(pd[0]) + abs(pd[1]) + abs(pd[2]); + } + else if (metric == 2.0) { /* SHD_VORONOI_CHEBYCHEV 2 */ + d = max(abs(pd[0]), max(abs(pd[1]), abs(pd[2]))); + } + else if (metric == 3.0) { /* SHD_VORONOI_MINKOWSKI 3 */ + d = pow(pow(abs(pd[0]), exponent) + pow(abs(pd[1]), exponent) + + pow(abs(pd[2]), exponent), + 1.0 / exponent); + } + + vp += vec3(xx, yy, zz); + if (d < da[0]) { + da.yzw = da.xyz; + da[0] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = pa[0]; + pa[0] = vp; + } + else if (d < da[1]) { + da.zw = da.yz; + da[1] = d; + + pa[3] = pa[2]; + pa[2] = pa[1]; + pa[1] = vp; + } + else if (d < da[2]) { + da[3] = da[2]; + da[2] = d; + + pa[3] = pa[2]; + pa[2] = vp; + } + else if (d < da[3]) { + da[3] = d; + pa[3] = vp; + } + } + } + } + + if (coloring == 0.0) { + /* Intensity output */ + if (feature == 0.0) { /* F1 */ + fac = abs(da[0]); + } + else if (feature == 1.0) { /* F2 */ + fac = abs(da[1]); + } + else if (feature == 2.0) { /* F3 */ + fac = abs(da[2]); + } + else if (feature == 3.0) { /* F4 */ + fac = abs(da[3]); + } + else if (feature == 4.0) { /* F2F1 */ + fac = abs(da[1] - da[0]); + } + color = vec4(fac, fac, fac, 1.0); + } + else { + /* Color output */ + vec3 col = vec3(fac, fac, fac); + if (feature == 0.0) { /* F1 */ + col = pa[0]; + } + else if (feature == 1.0) { /* F2 */ + col = pa[1]; + } + else if (feature == 2.0) { /* F3 */ + col = pa[2]; + } + else if (feature == 3.0) { /* F4 */ + col = pa[3]; + } + else if (feature == 4.0) { /* F2F1 */ + col = abs(pa[1] - pa[0]); + } + + color = vec4(cellnoise_color(col), 1.0); + fac = (color.x + color.y + color.z) * (1.0 / 3.0); + } +} + +float calc_wave( + vec3 p, float distortion, float detail, float detail_scale, int wave_type, int wave_profile) +{ + float n; + + if (wave_type == 0) /* type bands */ + n = (p.x + p.y + p.z) * 10.0; + else /* type rings */ + n = length(p) * 20.0; + + if (distortion != 0.0) + n += distortion * noise_turbulence(p * detail_scale, detail, 0); + + if (wave_profile == 0) { /* profile sin */ + return 0.5 + 0.5 * sin(n); + } + else { /* profile saw */ + n /= 2.0 * M_PI; + n -= int(n); + return (n < 0.0) ? n + 1.0 : n; + } +} + +void node_tex_wave(vec3 co, + float scale, + float distortion, + float detail, + float detail_scale, + float wave_type, + float wave_profile, + out vec4 color, + out float fac) +{ + float f; + f = calc_wave(co * scale, distortion, detail, detail_scale, int(wave_type), int(wave_profile)); + + color = vec4(f, f, f, 1.0); + fac = f; } /* light path */ -void node_light_path( - out float is_camera_ray, - out float is_shadow_ray, - out float is_diffuse_ray, - out float is_glossy_ray, - out float is_singular_ray, - out float is_reflection_ray, - out float is_transmission_ray, - out float ray_length, - out float ray_depth, - out float diffuse_depth, - out float glossy_depth, - out float transparent_depth, - out float transmission_depth) -{ - /* Supported. */ - is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; - is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; - is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; - is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; - /* Kind of supported. */ - is_singular_ray = is_glossy_ray; - is_reflection_ray = is_glossy_ray; - is_transmission_ray = is_glossy_ray; - ray_depth = rayDepth; - diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; - glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; - transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; - /* Not supported. */ - ray_length = 1.0; - transparent_depth = 0.0; -} - -void node_light_falloff(float strength, float tsmooth, out float quadratic, out float linear, out float constant) -{ - quadratic = strength; - linear = strength; - constant = strength; -} - -void node_object_info(mat4 obmat, vec4 info, out vec3 location, out float object_index, out float material_index, out float random) -{ - location = obmat[3].xyz; - object_index = info.x; - material_index = info.y; - random = info.z; +void node_light_path(out float is_camera_ray, + out float is_shadow_ray, + out float is_diffuse_ray, + out float is_glossy_ray, + out float is_singular_ray, + out float is_reflection_ray, + out float is_transmission_ray, + out float ray_length, + out float ray_depth, + out float diffuse_depth, + out float glossy_depth, + out float transparent_depth, + out float transmission_depth) +{ + /* Supported. */ + is_camera_ray = (rayType == EEVEE_RAY_CAMERA) ? 1.0 : 0.0; + is_shadow_ray = (rayType == EEVEE_RAY_SHADOW) ? 1.0 : 0.0; + is_diffuse_ray = (rayType == EEVEE_RAY_DIFFUSE) ? 1.0 : 0.0; + is_glossy_ray = (rayType == EEVEE_RAY_GLOSSY) ? 1.0 : 0.0; + /* Kind of supported. */ + is_singular_ray = is_glossy_ray; + is_reflection_ray = is_glossy_ray; + is_transmission_ray = is_glossy_ray; + ray_depth = rayDepth; + diffuse_depth = (is_diffuse_ray == 1.0) ? rayDepth : 0.0; + glossy_depth = (is_glossy_ray == 1.0) ? rayDepth : 0.0; + transmission_depth = (is_transmission_ray == 1.0) ? glossy_depth : 0.0; + /* Not supported. */ + ray_length = 1.0; + transparent_depth = 0.0; +} + +void node_light_falloff( + float strength, float tsmooth, out float quadratic, out float linear, out float constant) +{ + quadratic = strength; + linear = strength; + constant = strength; +} + +void node_object_info(mat4 obmat, + vec4 info, + out vec3 location, + out float object_index, + out float material_index, + out float random) +{ + location = obmat[3].xyz; + object_index = info.x; + material_index = info.y; + random = info.z; } void node_normal_map(vec4 info, vec4 tangent, vec3 normal, vec3 texnormal, out vec3 outnormal) { - if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { - outnormal = normal; - return; - } - tangent *= (gl_FrontFacing ? 1.0 : -1.0); - vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; + if (all(equal(tangent, vec4(0.0, 0.0, 0.0, 1.0)))) { + outnormal = normal; + return; + } + tangent *= (gl_FrontFacing ? 1.0 : -1.0); + vec3 B = tangent.w * cross(normal, tangent.xyz) * info.w; - outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; - outnormal = normalize(outnormal); + outnormal = texnormal.x * tangent.xyz + texnormal.y * B + texnormal.z * normal; + outnormal = normalize(outnormal); } -void node_bump(float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) +void node_bump( + float strength, float dist, float height, vec3 N, vec3 surf_pos, float invert, out vec3 result) { - N = mat3(ViewMatrix) * normalize(N); - dist *= invert; + N = mat3(ViewMatrix) * normalize(N); + dist *= invert; - vec3 dPdx = dFdx(surf_pos); - vec3 dPdy = dFdy(surf_pos); + vec3 dPdx = dFdx(surf_pos); + vec3 dPdy = dFdy(surf_pos); - /* Get surface tangents from normal. */ - vec3 Rx = cross(dPdy, N); - vec3 Ry = cross(N, dPdx); + /* Get surface tangents from normal. */ + vec3 Rx = cross(dPdy, N); + vec3 Ry = cross(N, dPdx); - /* Compute surface gradient and determinant. */ - float det = dot(dPdx, Rx); + /* Compute surface gradient and determinant. */ + float det = dot(dPdx, Rx); - float dHdx = dFdx(height); - float dHdy = dFdy(height); - vec3 surfgrad = dHdx * Rx + dHdy * Ry; + float dHdx = dFdx(height); + float dHdy = dFdy(height); + vec3 surfgrad = dHdx * Rx + dHdy * Ry; - strength = max(strength, 0.0); + strength = max(strength, 0.0); - result = normalize(abs(det) * N - dist * sign(det) * surfgrad); - result = normalize(mix(N, result, strength)); + result = normalize(abs(det) * N - dist * sign(det) * surfgrad); + result = normalize(mix(N, result, strength)); - result = mat3(ViewMatrixInverse) * result; + result = mat3(ViewMatrixInverse) * result; } void node_bevel(float radius, vec3 N, out vec3 result) { - result = N; + result = N; } -void node_hair_info(out float is_strand, out float intercept, out float thickness, out vec3 tangent, out float random) +void node_hair_info(out float is_strand, + out float intercept, + out float thickness, + out vec3 tangent, + out float random) { #ifdef HAIR_SHADER - is_strand = 1.0; - intercept = hairTime; - thickness = hairThickness; - tangent = normalize(hairTangent); - random = wang_hash_noise(uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ + is_strand = 1.0; + intercept = hairTime; + thickness = hairThickness; + tangent = normalize(hairTangent); + random = wang_hash_noise( + uint(hairStrandID)); /* TODO: could be precomputed per strand instead. */ #else - is_strand = 0.0; - intercept = 0.0; - thickness = 0.0; - tangent = vec3(1.0); - random = 0.0; + is_strand = 0.0; + intercept = 0.0; + thickness = 0.0; + tangent = vec3(1.0); + random = 0.0; #endif } -void node_displacement_object(float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) +void node_displacement_object( + float height, float midlevel, float scale, vec3 N, mat4 obmat, out vec3 result) { - N = (vec4(N, 0.0) * obmat).xyz; - result = (height - midlevel) * scale * normalize(N); - result = (obmat * vec4(result, 0.0)).xyz; + N = (vec4(N, 0.0) * obmat).xyz; + result = (height - midlevel) * scale * normalize(N); + result = (obmat * vec4(result, 0.0)).xyz; } void node_displacement_world(float height, float midlevel, float scale, vec3 N, out vec3 result) { - result = (height - midlevel) * scale * normalize(N); + result = (height - midlevel) * scale * normalize(N); } -void node_vector_displacement_tangent(vec4 vector, float midlevel, float scale, vec4 tangent, vec3 normal, mat4 obmat, mat4 viewmat, out vec3 result) +void node_vector_displacement_tangent(vec4 vector, + float midlevel, + float scale, + vec4 tangent, + vec3 normal, + mat4 obmat, + mat4 viewmat, + out vec3 result) { - vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); - vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); - vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); + vec3 N_object = normalize(((vec4(normal, 0.0) * viewmat) * obmat).xyz); + vec3 T_object = normalize(((vec4(tangent.xyz, 0.0) * viewmat) * obmat).xyz); + vec3 B_object = tangent.w * normalize(cross(N_object, T_object)); - vec3 offset = (vector.xyz - vec3(midlevel)) * scale; - result = offset.x * T_object + offset.y * N_object + offset.z * B_object; - result = (obmat * vec4(result, 0.0)).xyz; + vec3 offset = (vector.xyz - vec3(midlevel)) * scale; + result = offset.x * T_object + offset.y * N_object + offset.z * B_object; + result = (obmat * vec4(result, 0.0)).xyz; } -void node_vector_displacement_object(vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) +void node_vector_displacement_object( + vec4 vector, float midlevel, float scale, mat4 obmat, out vec3 result) { - result = (vector.xyz - vec3(midlevel)) * scale; - result = (obmat * vec4(result, 0.0)).xyz; + result = (vector.xyz - vec3(midlevel)) * scale; + result = (obmat * vec4(result, 0.0)).xyz; } void node_vector_displacement_world(vec4 vector, float midlevel, float scale, out vec3 result) { - result = (vector.xyz - vec3(midlevel)) * scale; + result = (vector.xyz - vec3(midlevel)) * scale; } /* output */ @@ -3086,9 +3369,9 @@ void node_vector_displacement_world(vec4 vector, float midlevel, float scale, ou void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result) { #ifdef VOLUMETRICS - result = volume; + result = volume; #else - result = surface; + result = surface; #endif } @@ -3097,10 +3380,10 @@ uniform float backgroundAlpha; void node_output_world(Closure surface, Closure volume, out Closure result) { #ifndef VOLUMETRICS - result.radiance = surface.radiance * backgroundAlpha; - result.opacity = backgroundAlpha; + result.radiance = surface.radiance * backgroundAlpha; + result.opacity = backgroundAlpha; #else - result = volume; + result = volume; #endif /* VOLUMETRICS */ } @@ -3109,65 +3392,80 @@ void node_output_world(Closure surface, Closure volume, out Closure result) /* EEVEE output */ void world_normals_get(out vec3 N) { -#ifdef HAIR_SHADER - vec3 B = normalize(cross(worldNormal, hairTangent)); - float cos_theta; - if (hairThicknessRes == 1) { - vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); - /* Random cosine normal distribution on the hair surface. */ - cos_theta = rand.x * 2.0 - 1.0; - } - else { - /* Shade as a cylinder. */ - cos_theta = hairThickTime / hairThickness; - } - float sin_theta = sqrt(max(0.0, 1.0f - cos_theta*cos_theta)); - N = normalize(worldNormal * sin_theta + B * cos_theta); -#else - N = gl_FrontFacing ? worldNormal : -worldNormal; -#endif +# ifdef HAIR_SHADER + vec3 B = normalize(cross(worldNormal, hairTangent)); + float cos_theta; + if (hairThicknessRes == 1) { + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); + /* Random cosine normal distribution on the hair surface. */ + cos_theta = rand.x * 2.0 - 1.0; + } + else { + /* Shade as a cylinder. */ + cos_theta = hairThickTime / hairThickness; + } + float sin_theta = sqrt(max(0.0, 1.0f - cos_theta * cos_theta)); + N = normalize(worldNormal * sin_theta + B * cos_theta); +# else + N = gl_FrontFacing ? worldNormal : -worldNormal; +# endif } -void node_eevee_specular( - vec4 diffuse, vec4 specular, float roughness, vec4 emissive, float transp, vec3 normal, - float clearcoat, float clearcoat_roughness, vec3 clearcoat_normal, - float occlusion, float ssr_id, out Closure result) -{ - vec3 out_diff, out_spec, ssr_spec; - eevee_closure_default(normal, diffuse.rgb, specular.rgb, int(ssr_id), roughness, occlusion, - out_diff, out_spec, ssr_spec); - - vec3 vN = normalize(mat3(ViewMatrix) * normal); - result = CLOSURE_DEFAULT; - result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; - result.opacity = 1.0 - transp; - result.ssr_data = vec4(ssr_spec, roughness); - result.ssr_normal = normal_encode(vN, viewCameraVec); - result.ssr_id = int(ssr_id); +void node_eevee_specular(vec4 diffuse, + vec4 specular, + float roughness, + vec4 emissive, + float transp, + vec3 normal, + float clearcoat, + float clearcoat_roughness, + vec3 clearcoat_normal, + float occlusion, + float ssr_id, + out Closure result) +{ + vec3 out_diff, out_spec, ssr_spec; + eevee_closure_default(normal, + diffuse.rgb, + specular.rgb, + int(ssr_id), + roughness, + occlusion, + out_diff, + out_spec, + ssr_spec); + + vec3 vN = normalize(mat3(ViewMatrix) * normal); + result = CLOSURE_DEFAULT; + result.radiance = out_diff * diffuse.rgb + out_spec + emissive.rgb; + result.opacity = 1.0 - transp; + result.ssr_data = vec4(ssr_spec, roughness); + result.ssr_normal = normal_encode(vN, viewCameraVec); + result.ssr_id = int(ssr_id); } void node_shader_to_rgba(Closure cl, out vec4 outcol, out float outalpha) { - vec4 spec_accum = vec4(0.0); - if (ssrToggle && cl.ssr_id == outputSsrId) { - vec3 V = cameraVec; - vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); - vec3 N = transform_direction(ViewMatrixInverse, vN); - float roughness = cl.ssr_data.a; - float roughnessSquared = max(1e-3, roughness * roughness); - fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); - } - - outalpha = cl.opacity; - outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); - -# ifdef USE_SSS -# ifdef USE_SSS_ALBEDO - outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; -# else - outcol.rgb += cl.sss_data.rgb; -# endif -# endif + vec4 spec_accum = vec4(0.0); + if (ssrToggle && cl.ssr_id == outputSsrId) { + vec3 V = cameraVec; + vec3 vN = normal_decode(cl.ssr_normal, viewCameraVec); + vec3 N = transform_direction(ViewMatrixInverse, vN); + float roughness = cl.ssr_data.a; + float roughnessSquared = max(1e-3, roughness * roughness); + fallback_cubemap(N, V, worldPosition, viewPosition, roughness, roughnessSquared, spec_accum); + } + + outalpha = cl.opacity; + outcol = vec4((spec_accum.rgb * cl.ssr_data.rgb) + cl.radiance, 1.0); + +# ifdef USE_SSS +# ifdef USE_SSS_ALBEDO + outcol.rgb += cl.sss_data.rgb * cl.sss_albedo; +# else + outcol.rgb += cl.sss_data.rgb; +# endif +# endif } #endif /* VOLUMETRICS */ diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl index fef81cf58fe..a8e9c620535 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl @@ -4,21 +4,22 @@ uniform vec4 color; in vec2 radii; out vec4 fragColor; -void main() { - float dist = length(gl_PointCoord - vec2(0.5)); +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); -// transparent outside of point -// --- 0 --- -// smooth transition -// --- 1 --- -// pure point color -// ... -// dist = 0 at center of point + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure point color + // ... + // dist = 0 at center of point - fragColor.rgb = color.rgb; - fragColor.a = mix(color.a, 0.0, smoothstep(radii[1], radii[0], dist)); + fragColor.rgb = color.rgb; + fragColor.a = mix(color.a, 0.0, smoothstep(radii[1], radii[0], dist)); - if (fragColor.a == 0.0) { - discard; - } + if (fragColor.a == 0.0) { + discard; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl index 852c76fcb26..c31cf852f6a 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_frag.glsl @@ -5,13 +5,13 @@ out vec4 fragColor; void main() { - vec2 centered = gl_PointCoord - vec2(0.5); - float dist_squared = dot(centered, centered); - const float rad_squared = 0.25; + vec2 centered = gl_PointCoord - vec2(0.5); + float dist_squared = dot(centered, centered); + const float rad_squared = 0.25; - // round point with jaggy edges - if (dist_squared > rad_squared) - discard; + // round point with jaggy edges + if (dist_squared > rad_squared) + discard; - fragColor = color; + fragColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl index eae5ee633ae..1c1301dd818 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl @@ -5,32 +5,33 @@ uniform vec4 outlineColor; in vec4 radii; out vec4 fragColor; -void main() { - float dist = length(gl_PointCoord - vec2(0.5)); +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); -// transparent outside of point -// --- 0 --- -// smooth transition -// --- 1 --- -// pure outline color -// --- 2 --- -// smooth transition -// --- 3 --- -// pure point color -// ... -// dist = 0 at center of point + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure point color + // ... + // dist = 0 at center of point - float midStroke = 0.5 * (radii[1] + radii[2]); + float midStroke = 0.5 * (radii[1] + radii[2]); - if (dist > midStroke) { - fragColor.rgb = outlineColor.rgb; - fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); - } - else { - fragColor = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist)); - } + if (dist > midStroke) { + fragColor.rgb = outlineColor.rgb; + fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else { + fragColor = mix(color, outlineColor, smoothstep(radii[3], radii[2], dist)); + } - if (fragColor.a == 0.0) { - discard; - } + if (fragColor.a == 0.0) { + discard; + } } diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl index 2d2724bb686..ba8321aa295 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_frag.glsl @@ -4,13 +4,13 @@ out vec4 fragColor; void main() { - vec2 centered = gl_PointCoord - vec2(0.5); - float dist_squared = dot(centered, centered); - const float rad_squared = 0.25; + vec2 centered = gl_PointCoord - vec2(0.5); + float dist_squared = dot(centered, centered); + const float rad_squared = 0.25; - // round point with jaggy edges - if (dist_squared > rad_squared) - discard; + // round point with jaggy edges + if (dist_squared > rad_squared) + discard; - fragColor = finalColor; + fragColor = finalColor; } diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl index 9b7d4bfc6d6..8ddf460a3ac 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl @@ -5,27 +5,28 @@ in vec4 radii; in vec4 fillColor; out vec4 fragColor; -void main() { - float dist = length(gl_PointCoord - vec2(0.5)); +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); -// transparent outside of point -// --- 0 --- -// smooth transition -// --- 1 --- -// pure outline color -// --- 2 --- -// smooth transition -// --- 3 --- -// pure fill color -// ... -// dist = 0 at center of point + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure fill color + // ... + // dist = 0 at center of point - float midStroke = 0.5 * (radii[1] + radii[2]); + float midStroke = 0.5 * (radii[1] + radii[2]); - if (dist > midStroke) { - fragColor.rgb = outlineColor.rgb; - fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); - } - else - fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); + if (dist > midStroke) { + fragColor.rgb = outlineColor.rgb; + fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else + fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); } diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl index e1f8203cb26..9c5690bf373 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_varying_outline_aa_frag.glsl @@ -4,27 +4,28 @@ in vec4 fillColor; in vec4 outlineColor; out vec4 fragColor; -void main() { - float dist = length(gl_PointCoord - vec2(0.5)); +void main() +{ + float dist = length(gl_PointCoord - vec2(0.5)); -// transparent outside of point -// --- 0 --- -// smooth transition -// --- 1 --- -// pure outline color -// --- 2 --- -// smooth transition -// --- 3 --- -// pure fill color -// ... -// dist = 0 at center of point + // transparent outside of point + // --- 0 --- + // smooth transition + // --- 1 --- + // pure outline color + // --- 2 --- + // smooth transition + // --- 3 --- + // pure fill color + // ... + // dist = 0 at center of point - float midStroke = 0.5 * (radii[1] + radii[2]); + float midStroke = 0.5 * (radii[1] + radii[2]); - if (dist > midStroke) { - fragColor.rgb = outlineColor.rgb; - fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); - } - else - fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); + if (dist > midStroke) { + fragColor.rgb = outlineColor.rgb; + fragColor.a = mix(outlineColor.a, 0.0, smoothstep(radii[1], radii[0], dist)); + } + else + fragColor = mix(fillColor, outlineColor, smoothstep(radii[3], radii[2], dist)); } diff --git a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl b/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl index 45ba6cf4d08..1f22b9cb0b4 100644 --- a/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_selection_id_frag.glsl @@ -9,5 +9,5 @@ out uint fragColor; void main() { - fragColor = id; + fragColor = id; } diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl index d65768eff4d..6bce517fee3 100644 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl @@ -13,6 +13,6 @@ out vec4 fragColor; void main() { - fragColor = color; - fragColor.xyz *= clamp(dot(normalize(normal), light), 0.0, 1.0); + fragColor = color; + fragColor.xyz *= clamp(dot(normalize(normal), light), 0.0, 1.0); } diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl index 6b13f408c84..2ed99be2bcf 100644 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_alpha_frag.glsl @@ -9,6 +9,6 @@ out vec4 fragColor; void main() { - fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light))); - fragColor.a = alpha; + fragColor = finalColor * (global + (1.0 - global) * max(0.0, dot(normalize(normal), light))); + fragColor.a = alpha; } diff --git a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl index 58c5f292647..738b0d84e51 100644 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl @@ -12,5 +12,5 @@ out vec4 fragColor; void main() { - fragColor = finalColor * max(0.0, dot(normalize(normal), light)); + fragColor = finalColor * max(0.0, dot(normalize(normal), light)); } diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl index fbfa4cfcc9d..4a6ce4fd3ac 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl @@ -7,68 +7,76 @@ out vec4 fragColor; uniform sampler2D glyph; const vec2 offsets4[4] = vec2[4]( - vec2(-0.5, 0.5), vec2( 0.5, 0.5), - vec2(-0.5, -0.5), vec2(-0.5, -0.5) -); + vec2(-0.5, 0.5), vec2(0.5, 0.5), vec2(-0.5, -0.5), vec2(-0.5, -0.5)); -const vec2 offsets16[16] = vec2[16]( - vec2(-1.5, 1.5), vec2(-0.5, 1.5), vec2( 0.5, 1.5), vec2( 1.5, 1.5), - vec2(-1.5, 0.5), vec2(-0.5, 0.5), vec2( 0.5, 0.5), vec2( 1.5, 0.5), - vec2(-1.5, -0.5), vec2(-0.5, -0.5), vec2( 0.5, -0.5), vec2( 1.5, -0.5), - vec2(-1.5, -1.5), vec2(-0.5, -1.5), vec2( 0.5, -1.5), vec2( 1.5, -1.5) -); +const vec2 offsets16[16] = vec2[16](vec2(-1.5, 1.5), + vec2(-0.5, 1.5), + vec2(0.5, 1.5), + vec2(1.5, 1.5), + vec2(-1.5, 0.5), + vec2(-0.5, 0.5), + vec2(0.5, 0.5), + vec2(1.5, 0.5), + vec2(-1.5, -0.5), + vec2(-0.5, -0.5), + vec2(0.5, -0.5), + vec2(1.5, -0.5), + vec2(-1.5, -1.5), + vec2(-0.5, -1.5), + vec2(0.5, -1.5), + vec2(1.5, -1.5)); #define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r void main() { - // input color replaces texture color - fragColor.rgb = color_flat.rgb; + // input color replaces texture color + fragColor.rgb = color_flat.rgb; - vec2 texel = 1.0 / vec2(textureSize(glyph, 0)); - vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp); + vec2 texel = 1.0 / vec2(textureSize(glyph, 0)); + vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp); - // modulate input alpha & texture alpha - if (texCoord_rect.x > 0) { - fragColor.a = texture(glyph, texco).r; - } - else { - fragColor.a = 0.0; + // modulate input alpha & texture alpha + if (texCoord_rect.x > 0) { + fragColor.a = texture(glyph, texco).r; + } + else { + fragColor.a = 0.0; - if (texCoord_rect.w > 0) { - /* 3x3 blur */ - /* Manual unroll for perf. (stupid glsl compiler) */ - fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]); - fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]); - fragColor.a *= (1.0 / 4.0); - } - else { - /* 5x5 blur */ - /* Manual unroll for perf. (stupid glsl compiler) */ - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 0]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 1]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 2]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 3]); + if (texCoord_rect.w > 0) { + /* 3x3 blur */ + /* Manual unroll for perf. (stupid glsl compiler) */ + fragColor.a += sample_glyph_offset(texco, texel, offsets4[0]); + fragColor.a += sample_glyph_offset(texco, texel, offsets4[1]); + fragColor.a += sample_glyph_offset(texco, texel, offsets4[2]); + fragColor.a += sample_glyph_offset(texco, texel, offsets4[3]); + fragColor.a *= (1.0 / 4.0); + } + else { + /* 5x5 blur */ + /* Manual unroll for perf. (stupid glsl compiler) */ + fragColor.a += sample_glyph_offset(texco, texel, offsets16[0]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[1]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[2]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[3]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 4]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 5]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 6]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 7]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[4]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[5]) * 2.0; + fragColor.a += sample_glyph_offset(texco, texel, offsets16[6]) * 2.0; + fragColor.a += sample_glyph_offset(texco, texel, offsets16[7]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 8]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[ 9]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0; - fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[8]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[9]) * 2.0; + fragColor.a += sample_glyph_offset(texco, texel, offsets16[10]) * 2.0; + fragColor.a += sample_glyph_offset(texco, texel, offsets16[11]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]); - fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]); - fragColor.a *= (1.0 / 20.0); - } - } + fragColor.a += sample_glyph_offset(texco, texel, offsets16[12]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[13]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[14]); + fragColor.a += sample_glyph_offset(texco, texel, offsets16[15]); + fragColor.a *= (1.0 / 20.0); + } + } - fragColor.a *= color_flat.a; + fragColor.a *= color_flat.a; } diff --git a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl index 0acd2106f7a..12ccbf00130 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl @@ -14,24 +14,24 @@ noperspective out vec2 texCoord_interp; void main() { - color_flat = color[0]; - texCoord_rect = tex_rect[0]; + color_flat = color[0]; + texCoord_rect = tex_rect[0]; - gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0)); - texCoord_interp = vec2(0.0, 0.0); - EmitVertex(); + gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0)); + texCoord_interp = vec2(0.0, 0.0); + EmitVertex(); - gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0)); - texCoord_interp = vec2(1.0, 0.0); - EmitVertex(); + gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0)); + texCoord_interp = vec2(1.0, 0.0); + EmitVertex(); - gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0)); - texCoord_interp = vec2(0.0, 1.0); - EmitVertex(); + gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0)); + texCoord_interp = vec2(0.0, 1.0); + EmitVertex(); - gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0)); - texCoord_interp = vec2(1.0, 1.0); - EmitVertex(); + gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0)); + texCoord_interp = vec2(1.0, 1.0); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl index 8903fd1df57..7a8a872f919 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl @@ -12,25 +12,25 @@ noperspective out vec2 texCoord_interp; void main() { - color_flat = color[0]; - texCoord_rect = tex_rect[0]; - gl_Position.zw = vec2(0.0, 1.0); + color_flat = color[0]; + texCoord_rect = tex_rect[0]; + gl_Position.zw = vec2(0.0, 1.0); - gl_Position.xy = pos_rect[0].xy; - texCoord_interp = vec2(0.0, 0.0); - EmitVertex(); + gl_Position.xy = pos_rect[0].xy; + texCoord_interp = vec2(0.0, 0.0); + EmitVertex(); - gl_Position.xy = pos_rect[0].zy; - texCoord_interp = vec2(1.0, 0.0); - EmitVertex(); + gl_Position.xy = pos_rect[0].zy; + texCoord_interp = vec2(1.0, 0.0); + EmitVertex(); - gl_Position.xy = pos_rect[0].xw; - texCoord_interp = vec2(0.0, 1.0); - EmitVertex(); + gl_Position.xy = pos_rect[0].xw; + texCoord_interp = vec2(0.0, 1.0); + EmitVertex(); - gl_Position.xy = pos_rect[0].zw; - texCoord_interp = vec2(1.0, 1.0); - EmitVertex(); + gl_Position.xy = pos_rect[0].zw; + texCoord_interp = vec2(1.0, 1.0); + EmitVertex(); - EndPrimitive(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl index 4a2cde71e07..a8a79ffe6c9 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_simple_vert.glsl @@ -13,10 +13,10 @@ out vec4 color; void main() { - /* Manual mat4*vec2 */ - pos_rect = ModelViewProjectionMatrix[0].xyxy * pos.xxzz; - pos_rect += ModelViewProjectionMatrix[1].xyxy * pos.yyww; - pos_rect += ModelViewProjectionMatrix[3].xyxy; - tex_rect = tex; - color = col; + /* Manual mat4*vec2 */ + pos_rect = ModelViewProjectionMatrix[0].xyxy * pos.xxzz; + pos_rect += ModelViewProjectionMatrix[1].xyxy * pos.yyww; + pos_rect += ModelViewProjectionMatrix[3].xyxy; + tex_rect = tex; + color = col; } diff --git a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl index 338156f5b68..d8e4b2bc986 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_vert.glsl @@ -11,7 +11,7 @@ out vec4 color; void main() { - pos_rect = pos; - tex_rect = tex; - color = col; + pos_rect = pos; + tex_rect = tex; + color = col; } diff --git a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl index f6f0f5b83ec..cfa82572e87 100644 --- a/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_uniform_color_frag.glsl @@ -10,16 +10,15 @@ out vec4 fragColor; void main() { #if defined(USE_COLOR_U32) - fragColor = vec4( - ((color ) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f), - ((color >> 24) ) * (1.0f / 255.0f)); + fragColor = vec4(((color)&uint(0xFF)) * (1.0f / 255.0f), + ((color >> 8) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 16) & uint(0xFF)) * (1.0f / 255.0f), + ((color >> 24)) * (1.0f / 255.0f)); #else - fragColor = color; + fragColor = color; #endif #if defined(USE_BACKGROUND) - gl_FragDepth = 1.0; + gl_FragDepth = 1.0; #endif } -- cgit v1.2.3