diff options
Diffstat (limited to 'source/blender/gpu')
99 files changed, 3542 insertions, 4553 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 7573985baa8..f0ef87c5f28 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -42,6 +42,7 @@ set(INC ../../../intern/glew-mx ../../../intern/guardedalloc ../../../intern/smoke/extern + ../../../intern/gawain ) set(INC_SYS @@ -60,32 +61,17 @@ set(SRC intern/gpu_framebuffer.c intern/gpu_immediate.c intern/gpu_init_exit.c + intern/gpu_lamp.c intern/gpu_material.c intern/gpu_matrix.c intern/gpu_select.c + intern/gpu_select_pick.c + intern/gpu_select_sample_query.c intern/gpu_shader.c intern/gpu_texture.c intern/gpu_uniformbuffer.c intern/gpu_viewport.c - gawain/attrib_binding.c - gawain/attrib_binding.h - gawain/batch.c - gawain/batch.h - gawain/buffer_id.h - gawain/buffer_id.cpp - gawain/common.h - gawain/element.c - gawain/element.h - gawain/immediate.c - gawain/immediate.h - gawain/imm_util.c - gawain/imm_util.h - gawain/vertex_buffer.c - gawain/vertex_buffer.h - gawain/vertex_format.c - gawain/vertex_format.h - shaders/gpu_shader_fx_lib.glsl shaders/gpu_shader_fx_ssao_frag.glsl shaders/gpu_shader_fx_dof_frag.glsl @@ -93,7 +79,7 @@ set(SRC shaders/gpu_shader_fx_dof_hq_frag.glsl shaders/gpu_shader_fx_dof_hq_vert.glsl shaders/gpu_shader_fx_dof_hq_geo.glsl - shaders/gpu_shader_fx_vert.glsl + shaders/gpu_shader_fullscreen_vert.glsl shaders/gpu_shader_material.glsl shaders/gpu_shader_sep_gaussian_blur_frag.glsl shaders/gpu_shader_sep_gaussian_blur_vert.glsl @@ -129,19 +115,27 @@ set(SRC intern/gpu_codegen.h intern/gpu_private.h + intern/gpu_lamp_private.h + intern/gpu_select_private.h + intern/gpu_shader_private.h ) data_to_c_simple(shaders/gpu_shader_depth_only_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_checker_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_diag_stripes_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_simple_lighting_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_line_dashed_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_line_dashed_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_smooth_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_smooth_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_image_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC) @@ -158,25 +152,31 @@ data_to_c_simple(shaders/gpu_shader_3D_clipped_uniform_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_instance_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_instance_variying_size_variying_color_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_instance_screenspace_variying_color_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_camera_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_distance_line_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_geom.glsl SRC) +data_to_c_simple(shaders/gpu_shader_instance_edges_variying_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_groundline_geom.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_groundpoint_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_uniform_color_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_point_uniform_color_smooth_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl SRC) -data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_point_uniform_color_aa_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_point_varying_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_point_fixed_size_varying_color_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_3D_point_varying_size_varying_color_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_point_varying_size_varying_color_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_edges_front_back_persp_geom.glsl SRC) @@ -205,7 +205,7 @@ data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_vertex_world.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC) -data_to_c_simple(shaders/gpu_shader_fx_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_fullscreen_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_ssao_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_fx_dof_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_basic_shader.h b/source/blender/gpu/GPU_basic_shader.h index bfdf4ab6bbd..dc378927e79 100644 --- a/source/blender/gpu/GPU_basic_shader.h +++ b/source/blender/gpu/GPU_basic_shader.h @@ -126,9 +126,6 @@ void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id); void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern); void GPU_basic_shader_line_width(float line_width); -bool GPU_basic_shader_use_glsl_get(void); -void GPU_basic_shader_use_glsl_set(bool enabled); - #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index 066bc9eeba7..2232e333bb6 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -30,7 +30,11 @@ #pragma once -#include "gawain/batch.h" +#include "../../../intern/gawain/gawain/batch.h" + +// TODO: CMake magic to do this: +// #include "gawain/batch.h" + #include "GPU_shader.h" /* Extend Batch_set_program to use Blender’s library of built-in shader programs. */ @@ -38,6 +42,7 @@ void Batch_set_builtin_program(Batch*, GPUBuiltinShader); /* Replacement for gluSphere */ Batch *Batch_get_sphere(int lod); +Batch *Batch_get_sphere_wire(int lod); void gpu_batch_init(void); void gpu_batch_exit(void); diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index b693d473bd8..958d5aed4a4 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -258,10 +258,8 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **gr void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial, bool wireframe, bool fast); -/* debug PBVH draw*/ -void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf); -void GPU_end_draw_pbvh_BB(void); -void GPU_init_draw_pbvh_BB(void); +/* debug PBVH draw */ +void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos); bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, struct GSet *bm_faces, bool show_diffuse_color); diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h index 921deaaa6d6..c7a99d33654 100644 --- a/source/blender/gpu/GPU_debug.h +++ b/source/blender/gpu/GPU_debug.h @@ -41,9 +41,6 @@ extern "C" { /* prints something if debug mode is active only */ void GPU_print_error_debug(const char *str); -/* prints current OpenGL state */ -void GPU_state_print(void); - /* inserts a debug marker message for the debug context messaging system */ void GPU_string_marker(const char *str); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index 91d436557f0..47ddabbed19 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -42,6 +42,7 @@ struct ImageUser; struct MTexPoly; struct Object; struct Scene; +struct SceneLayer; struct View3D; struct RegionView3D; struct SmokeModifierData; @@ -74,7 +75,8 @@ void GPU_disable_program_point_size(void); * - after drawing, the material must be disabled again */ void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d, - struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after); + struct Scene *scene, struct SceneLayer *sl, + struct Object *ob, bool glsl, bool *do_alpha_after); void GPU_end_object_materials(void); bool GPU_object_materials_check(void); diff --git a/source/blender/gpu/GPU_framebuffer.h b/source/blender/gpu/GPU_framebuffer.h index 9611a6f0577..15617832c9b 100644 --- a/source/blender/gpu/GPU_framebuffer.h +++ b/source/blender/gpu/GPU_framebuffer.h @@ -67,6 +67,10 @@ void GPU_framebuffer_blur( GPUFrameBuffer *fb, struct GPUTexture *tex, GPUFrameBuffer *blurfb, struct GPUTexture *blurtex); +void GPU_framebuffer_blit( + GPUFrameBuffer *fb_read, int read_slot, + GPUFrameBuffer *fb_write, int write_slot, bool use_depth); + /* GPU OffScreen * - wrapper around framebuffer and texture for simple offscreen drawing * - changes size if graphics card can't support it */ diff --git a/source/blender/gpu/GPU_immediate.h b/source/blender/gpu/GPU_immediate.h index 4a0840e22c0..35964a81030 100644 --- a/source/blender/gpu/GPU_immediate.h +++ b/source/blender/gpu/GPU_immediate.h @@ -30,8 +30,13 @@ #pragma once -#include "gawain/immediate.h" -#include "gawain/imm_util.h" +#include "../../../intern/gawain/gawain/immediate.h" +#include "../../../intern/gawain/gawain/imm_util.h" + +// TODO: CMake magic to do this: +// #include "gawain/immediate.h" +// #include "gawain/imm_util.h" + #include "GPU_shader.h" /* Extend immBindProgram to use Blender’s library of built-in shader programs. diff --git a/source/blender/gpu/GPU_lamp.h b/source/blender/gpu/GPU_lamp.h new file mode 100644 index 00000000000..32793830479 --- /dev/null +++ b/source/blender/gpu/GPU_lamp.h @@ -0,0 +1,75 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel, Clément Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file GPU_lamp.h + * \ingroup gpu + */ + +#ifndef __GPU_LAMP_H__ +#define __GPU_LAMP_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Scene; +struct Object; +struct RenderEngineType; + +typedef struct GPULamp GPULamp; + +typedef struct LampEngineData { + struct GPUFrameBuffer *framebuffers[4]; + struct GPUTexture *textures[4]; + void *storage[4]; +} LampEngineData; + +GPULamp *GPU_lamp_from_engine(struct Scene *scene, struct Object *ob, Object *par, struct RenderEngineType *re); +GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); +void GPU_lamp_free(struct Object *ob); + +bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma); +bool GPU_lamp_has_shadow_buffer(GPULamp *lamp); +void GPU_lamp_update_buffer_mats(GPULamp *lamp); +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]); +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); +int GPU_lamp_shadow_buffer_type(GPULamp *lamp); +int GPU_lamp_shadow_bind_code(GPULamp *lamp); +float *GPU_lamp_dynpersmat(GPULamp *lamp); + +void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]); +void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, + float coeff_const, float coeff_lin, float coeff_quad); +void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend); +int GPU_lamp_shadow_layer(GPULamp *lamp); + +#ifdef __cplusplus +} +#endif + +#endif /* __GPU_LAMP_H__ */ diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 0d92d22a173..cbcd6383a72 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -45,7 +45,6 @@ struct Image; struct ImageUser; struct Material; struct Object; -struct Image; struct Scene; struct SceneRenderLayer; struct GPUVertexAttribs; @@ -61,7 +60,7 @@ struct World; typedef struct GPUNode GPUNode; typedef struct GPUNodeLink GPUNodeLink; typedef struct GPUMaterial GPUMaterial; -typedef struct GPULamp GPULamp; + typedef struct GPUParticleInfo GPUParticleInfo; /* Functions to create GPU Materials nodes */ @@ -224,7 +223,6 @@ void GPU_material_free(struct ListBase *gpumaterial); void GPU_materials_free(void); -bool GPU_lamp_override_visible(GPULamp *lamp, struct SceneRenderLayer *srl, struct Material *ma); void GPU_material_bind( GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float cameraborder[4], bool scenelock); @@ -310,26 +308,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma); void GPU_free_shader_export(GPUShaderExport *shader); /* Lamps */ - -GPULamp *GPU_lamp_from_blender(struct Scene *scene, struct Object *ob, struct Object *par); -void GPU_lamp_free(struct Object *ob); - -bool GPU_lamp_has_shadow_buffer(GPULamp *lamp); -void GPU_lamp_update_buffer_mats(GPULamp *lamp); -void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]); -void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp); -int GPU_lamp_shadow_buffer_type(GPULamp *lamp); -int GPU_lamp_shadow_bind_code(GPULamp *lamp); -float *GPU_lamp_dynpersmat(GPULamp *lamp); - -void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]); -void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy); -void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, - float coeff_const, float coeff_lin, float coeff_quad); -void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend); -int GPU_lamp_shadow_layer(GPULamp *lamp); GPUNodeLink *GPU_lamp_get_data( - GPUMaterial *mat, GPULamp *lamp, + GPUMaterial *mat, struct GPULamp *lamp, GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy); /* World */ diff --git a/source/blender/gpu/GPU_matrix.h b/source/blender/gpu/GPU_matrix.h index 43a03f8e4b6..85b1b5c7acf 100644 --- a/source/blender/gpu/GPU_matrix.h +++ b/source/blender/gpu/GPU_matrix.h @@ -1,6 +1,3 @@ -#ifndef _GPU_MATRIX_H_ -#define _GPU_MATRIX_H_ - /* * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -32,8 +29,11 @@ * \ingroup gpu */ +#ifndef _GPU_MATRIX_H_ +#define _GPU_MATRIX_H_ + +#include "BLI_sys_types.h" #include "GPU_glew.h" -#include <stdbool.h> #ifdef __cplusplus extern "C" { @@ -84,6 +84,7 @@ void gpuTranslate3f(float x, float y, float z); void gpuTranslate3fv(const float vec[3]); void gpuScale3f(float x, float y, float z); void gpuScale3fv(const float vec[3]); +void gpuRotate3f(float deg, float x, float y, float z); /* axis of rotation should be a unit vector */ void gpuRotate3fv(float deg, const float axis[3]); /* axis of rotation should be a unit vector */ void gpuRotateAxis(float deg, char axis); /* TODO: enum for axis? */ @@ -105,16 +106,16 @@ void gpuRotate2D(float deg); /* 3D Projection Matrix */ +void gpuLoadProjectionMatrix3D(const float m[4][4]); + void gpuOrtho(float left, float right, float bottom, float top, float near, float far); void gpuFrustum(float left, float right, float bottom, float top, float near, float far); void gpuPerspective(float fovy, float aspect, float near, float far); -/* pass vector through current transform (world --> screen) */ -void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3]); - -/* pass vector through inverse transform (world <-- screen) */ -bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3]); +/* 3D Projection between Window and World Space */ +void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]); +bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]); /* 2D Projection Matrix */ @@ -130,15 +131,6 @@ const float *gpuGetNormalMatrix(float m[3][3]); const float *gpuGetNormalMatrixInverse(float m[3][3]); -#if SUPPORT_LEGACY_MATRIX -/* copy top matrix from each legacy stack into new fresh stack */ -void gpuMatrixBegin3D_legacy(void); - -/* call after using glScale, glTranslate, etc. between draw calls */ -void gpuMatrixUpdate_legacy(void); -#endif - - /* set uniform values for currently bound shader */ void gpuBindMatrices(GLuint program); bool gpuMatricesDirty(void); /* since last bind */ @@ -147,4 +139,47 @@ bool gpuMatricesDirty(void); /* since last bind */ } #endif + +#ifndef SUPPRESS_GENERIC_MATRIX_API +/* make matrix inputs generic, to avoid warnings */ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) +# define gpuMultMatrix3D(x) \ + gpuMultMatrix3D(_Generic((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 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 gpuLoadMatrix3D(x) \ + gpuLoadMatrix3D(_Generic((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 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)) \ +) +/* TODO: finish this in a simpler way --^ */ +#else +# define gpuMultMatrix3D(x) gpuMultMatrix3D((const float (*)[4])(x)) +# define gpuLoadMatrix3D(x) gpuLoadMatrix3D((const float (*)[4])(x)) + +# define gpuLoadProjectionMatrix3D(x) gpuLoadProjectionMatrix3D((const float (*)[4])(x)) + +# define gpuMultMatrix2D(x) gpuMultMatrix2D((const float (*)[3])(x)) +# define gpuLoadMatrix2D(x) gpuLoadMatrix2D((const float (*)[3])(x)) + +# define gpuGetModelViewMatrix3D(x) gpuGetModelViewMatrix3D((float (*)[4])(x)) +# define gpuGetProjectionMatrix3D(x) gpuGetProjectionMatrix3D((float (*)[4])(x)) +# define gpuGetModelViewProjectionMatrix3D(x) gpuGetModelViewProjectionMatrix3D((float (*)[4])(x)) +# define gpuGetNormalMatrix(x) gpuGetNormalMatrix((float (*)[3])(x)) +# define gpuGetNormalMatrixInverse(x) gpuGetNormalMatrixInverse((float (*)[3])(x)) +#endif /* C11 */ +#endif /* SUPPRESS_GENERIC_MATRIX_API */ #endif /* GPU_MATRIX_H */ diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h index 6a16b5b7456..cf5b8bf7d8f 100644 --- a/source/blender/gpu/GPU_select.h +++ b/source/blender/gpu/GPU_select.h @@ -30,19 +30,30 @@ #ifndef __GPU_SELECT_H__ #define __GPU_SELECT_H__ -#include "DNA_vec_types.h" /* rcft */ #include "BLI_sys_types.h" +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, }; -void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *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); unsigned int GPU_select_end(void); bool GPU_select_query_check_active(void); +/* cache selection region */ +bool GPU_select_is_cached(void); +void GPU_select_cache_begin(void); +void GPU_select_cache_load_id(void); +void GPU_select_cache_end(void); + #endif diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index fcf070890ea..71a1e3a6591 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -71,8 +71,12 @@ void GPU_shader_bind(GPUShader *shader); void GPU_shader_unbind(void); int GPU_shader_get_program(GPUShader *shader); + void *GPU_shader_get_interface(GPUShader *shader); -void GPU_shader_set_interface(GPUShader *shader, void *interface); + +void *GPU_fx_shader_get_interface(GPUShader *shader); +void GPU_fx_shader_set_interface(GPUShader *shader, void *interface); + int GPU_shader_get_uniform(GPUShader *shader, const char *name); int GPU_shader_get_uniform_block(GPUShader *shader, const char *name); void GPU_shader_uniform_vector(GPUShader *shader, int location, int length, @@ -103,12 +107,14 @@ typedef enum GPUBuiltinShader { GPU_SHADER_EDGES_OVERLAY, GPU_SHADER_KEYFRAME_DIAMOND, GPU_SHADER_SIMPLE_LIGHTING, + GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR, /* for simple 2D drawing */ GPU_SHADER_2D_UNIFORM_COLOR, GPU_SHADER_2D_FLAT_COLOR, GPU_SHADER_2D_SMOOTH_COLOR, GPU_SHADER_2D_IMAGE_COLOR, GPU_SHADER_2D_CHECKER, + GPU_SHADER_2D_DIAG_STRIPES, /* for simple 3D drawing */ GPU_SHADER_3D_UNIFORM_COLOR, GPU_SHADER_3D_UNIFORM_COLOR_INSTANCE, @@ -117,6 +123,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_3D_DEPTH_ONLY, GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR, /* basic image drawing */ + GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR, GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR, GPU_SHADER_3D_IMAGE_MODULATE_ALPHA, GPU_SHADER_3D_IMAGE_RECT_MODULATE_ALPHA, @@ -125,23 +132,35 @@ typedef enum GPUBuiltinShader { GPU_SHADER_2D_IMAGE_INTERLACE, /* points */ GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR, - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH, - GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH, - GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH, + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, + GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA, GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR, GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR, GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR, - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH, - GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH, + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA, + GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA, GPU_SHADER_3D_POINT_VARYING_SIZE_UNIFORM_COLOR, GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR, + /* lines */ + GPU_SHADER_2D_LINE_DASHED_COLOR, /* lamp 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, /* instance */ GPU_SHADER_INSTANCE_UNIFORM_COLOR, GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE, + GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, GPU_NUM_BUILTIN_SHADERS /* (not an actual shader) */ } GPUBuiltinShader; diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index a8df80cd626..93cc8443643 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -66,6 +66,7 @@ typedef enum GPUTextureFormat { GPU_RGBA8, GPU_RG32F, GPU_RG16F, + GPU_R16F, GPU_R8, #if 0 GPU_RGBA32F, @@ -87,7 +88,6 @@ typedef enum GPUTextureFormat { GPU_R32F, GPU_R32I, GPU_R32UI, - GPU_R16F, GPU_R16I, GPU_R16UI, GPU_R16, @@ -101,8 +101,8 @@ typedef enum GPUTextureFormat { GPU_RGB10_A2, GPU_RGB10_A2UI, GPU_DEPTH32F_STENCIL8, - GPU_DEPTH24_STENCIL8, #endif + GPU_DEPTH24_STENCIL8, /* Texture only format */ #if 0 @@ -155,6 +155,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int d, const float *pixels, char GPUTexture *GPU_texture_create_3D_custom( int w, int h, int d, int channels, GPUTextureFormat data_type, const float *pixels, char err_out[256]); GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]); +GPUTexture *GPU_texture_create_depth_with_stencil(int w, int h, char err_out[256]); GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]); GPUTexture *GPU_texture_from_blender( @@ -183,7 +184,8 @@ void GPU_texture_framebuffer_set(GPUTexture *tex, struct GPUFrameBuffer *fb, int int GPU_texture_target(const GPUTexture *tex); int GPU_texture_width(const GPUTexture *tex); int GPU_texture_height(const GPUTexture *tex); -int GPU_texture_depth(const GPUTexture *tex); +bool GPU_texture_depth(const GPUTexture *tex); +bool GPU_texture_stencil(const GPUTexture *tex); int GPU_texture_opengl_bindcode(const GPUTexture *tex); #ifdef __cplusplus diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 9de16f64ca1..2411fe755af 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -44,7 +44,7 @@ typedef struct GPUViewport GPUViewport; #define MAX_BUFFERS 8 #define MAX_TEXTURES 16 #define MAX_PASSES 16 -#define MAX_STORAGE 2 /* extend if needed */ +#define MAX_STORAGE 5 /* extend if needed */ /* All FramebufferLists are just the same pointers with different names */ typedef struct FramebufferList { @@ -56,34 +56,40 @@ typedef struct TextureList { } TextureList; typedef struct PassList { - struct DRWPass *passes[MAX_TEXTURES]; + struct DRWPass *passes[MAX_PASSES]; } PassList; typedef struct StorageList { void *storage[MAX_STORAGE]; /* custom structs from the engine */ } StorageList; -/* Buffer and textures used by the viewport by default */ -typedef struct DefaultFramebufferList { - struct GPUFrameBuffer *default_fb; -} DefaultFramebufferList; +typedef struct ViewportEngineData { + void *engine_type; -typedef struct DefaultTextureList { - struct GPUTexture *color; - struct GPUTexture *depth; -} DefaultTextureList; + FramebufferList *fbl; + TextureList *txl; + PassList *psl; + StorageList *stl; -typedef struct DefaultPassList { - struct DRWPass *non_meshes_pass; - struct DRWPass *ob_center_pass; -} DefaultPassList; + /* Profiling data */ + double init_time; + double cache_time; + double render_time; + double background_time; +} ViewportEngineData; GPUViewport *GPU_viewport_create(void); -void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine); +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect); void GPU_viewport_unbind(GPUViewport *viewport); void GPU_viewport_free(GPUViewport *viewport); -void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str); +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(GPUViewport *viewport, int *size); + +bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash); /* debug */ bool GPU_viewport_debug_depth_create(GPUViewport *viewport, int width, int height, char err_out[256]); diff --git a/source/blender/gpu/gawain/attrib_binding.c b/source/blender/gpu/gawain/attrib_binding.c deleted file mode 100644 index bb42aaf66eb..00000000000 --- a/source/blender/gpu/gawain/attrib_binding.c +++ /dev/null @@ -1,69 +0,0 @@ - -// Gawain vertex attribute binding -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "attrib_binding.h" - -#if MAX_VERTEX_ATTRIBS != 16 - #error "attrib binding code assumes MAX_VERTEX_ATTRIBS = 16" -#endif - -void clear_AttribBinding(AttribBinding* binding) - { - binding->loc_bits = 0; - binding->enabled_bits = 0; - } - -unsigned read_attrib_location(const AttribBinding* binding, unsigned a_idx) - { -#if TRUST_NO_ONE - assert(a_idx < MAX_VERTEX_ATTRIBS); - assert(binding->enabled_bits & (1 << a_idx)); -#endif - - return (binding->loc_bits >> (4 * a_idx)) & 0xF; - } - -static void write_attrib_location(AttribBinding* binding, unsigned a_idx, unsigned location) - { -#if TRUST_NO_ONE - assert(a_idx < MAX_VERTEX_ATTRIBS); - assert(location < MAX_VERTEX_ATTRIBS); -#endif - - const unsigned shift = 4 * a_idx; - const uint64_t mask = ((uint64_t)0xF) << shift; - // overwrite this attrib's previous location - binding->loc_bits = (binding->loc_bits & ~mask) | (location << shift); - // mark this attrib as enabled - binding->enabled_bits |= 1 << a_idx; - } - -void get_attrib_locations(const VertexFormat* format, AttribBinding* binding, GLuint program) - { -#if TRUST_NO_ONE - assert(glIsProgram(program)); -#endif - - clear_AttribBinding(binding); - - for (unsigned a_idx = 0; a_idx < format->attrib_ct; ++a_idx) - { - const Attrib* a = format->attribs + a_idx; - GLint loc = glGetAttribLocation(program, a->name); - -#if TRUST_NO_ONE - assert(loc != -1); - // TODO: make this a recoverable runtime error? indicates mismatch between vertex format and program -#endif - - write_attrib_location(binding, a_idx, loc); - } - } diff --git a/source/blender/gpu/gawain/attrib_binding.h b/source/blender/gpu/gawain/attrib_binding.h deleted file mode 100644 index 9e2431ca379..00000000000 --- a/source/blender/gpu/gawain/attrib_binding.h +++ /dev/null @@ -1,24 +0,0 @@ - -// Gawain vertex attribute binding -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "vertex_format.h" - -typedef struct { - uint64_t loc_bits; // store 4 bits for each of the 16 attribs - uint16_t enabled_bits; // 1 bit for each attrib -} AttribBinding; - -void clear_AttribBinding(AttribBinding*); - -void get_attrib_locations(const VertexFormat*, AttribBinding*, GLuint program); -unsigned read_attrib_location(const AttribBinding*, unsigned a_idx); diff --git a/source/blender/gpu/gawain/batch.c b/source/blender/gpu/gawain/batch.c deleted file mode 100644 index 55ccd94a555..00000000000 --- a/source/blender/gpu/gawain/batch.c +++ /dev/null @@ -1,340 +0,0 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "batch.h" -#include "buffer_id.h" -#include <stdlib.h> - -// necessary functions from matrix API -extern void gpuBindMatrices(GLuint program); -extern bool gpuMatricesDirty(void); // how best to use this here? - -Batch* Batch_create(PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem) - { - Batch* batch = calloc(1, sizeof(Batch)); - - Batch_init(batch, prim_type, verts, elem); - - return batch; - } - -void Batch_init(Batch* batch, PrimitiveType prim_type, VertexBuffer* verts, ElementList* elem) - { -#if TRUST_NO_ONE - assert(verts != NULL); - assert(prim_type == PRIM_POINTS || prim_type == PRIM_LINES || prim_type == PRIM_TRIANGLES); - // we will allow other primitive types in a future update -#endif - - batch->verts = verts; - batch->elem = elem; - batch->prim_type = prim_type; - batch->phase = READY_TO_DRAW; - } - -void Batch_discard(Batch* batch) - { - if (batch->vao_id) - vao_id_free(batch->vao_id); - - free(batch); - } - -void Batch_discard_all(Batch* batch) - { - VertexBuffer_discard(batch->verts); - if (batch->elem) - ElementList_discard(batch->elem); - Batch_discard(batch); - } - -void Batch_set_program(Batch* batch, GLuint program) - { -#if TRUST_NO_ONE - assert(glIsProgram(program)); -#endif - - batch->program = program; - batch->program_dirty = true; - - Batch_use_program(batch); // hack! to make Batch_Uniform* simpler - } - -static void Batch_update_program_bindings(Batch* batch) - { - const VertexFormat* format = &batch->verts->format; - - const unsigned attrib_ct = format->attrib_ct; - const unsigned stride = format->stride; - - // disable all as a precaution - // why are we not using prev_attrib_enabled_bits?? see immediate.c - for (unsigned a_idx = 0; a_idx < MAX_VERTEX_ATTRIBS; ++a_idx) - glDisableVertexAttribArray(a_idx); - - VertexBuffer_use(batch->verts); - - for (unsigned a_idx = 0; a_idx < attrib_ct; ++a_idx) - { - const Attrib* a = format->attribs + a_idx; - - const GLvoid* pointer = (const GLubyte*)0 + a->offset; - - const GLint loc = glGetAttribLocation(batch->program, a->name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glEnableVertexAttribArray(loc); - - switch (a->fetch_mode) - { - case KEEP_FLOAT: - case CONVERT_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer); - break; - case NORMALIZE_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer); - break; - case KEEP_INT: - glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer); - } - } - - batch->program_dirty = false; - } - -void Batch_use_program(Batch* 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) - - if (!batch->program_in_use) - { - glUseProgram(batch->program); - batch->program_in_use = true; - } - } - -void Batch_done_using_program(Batch* batch) - { - if (batch->program_in_use) - { - glUseProgram(0); - batch->program_in_use = false; - } - } - -void Batch_Uniform1b(Batch* batch, const char* name, bool value) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform1i(loc, value ? GL_TRUE : GL_FALSE); - } - -void Batch_Uniform2f(Batch* batch, const char* name, float x, float y) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform2f(loc, x, y); - } - -void Batch_Uniform4f(Batch* batch, const char* name, float x, float y, float z, float w) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform4f(loc, x, y, z, w); - } - -void Batch_Uniform1f(Batch* batch, const char* name, float x) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform1f(loc, x); - } - -void Batch_Uniform3fv(Batch* batch, const char* name, const float data[3]) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform3fv(loc, 1, data); - } - -void Batch_Uniform4fv(Batch* batch, const char* name, const float data[4]) - { - int loc = glGetUniformLocation(batch->program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform4fv(loc, 1, data); - } - -static void Batch_prime(Batch* batch) - { - batch->vao_id = vao_id_alloc(); - glBindVertexArray(batch->vao_id); - - VertexBuffer_use(batch->verts); - - if (batch->elem) - ElementList_use(batch->elem); - - // vertex attribs and element list remain bound to this VAO - } - -void Batch_draw(Batch* batch) - { -#if TRUST_NO_ONE - assert(batch->phase == READY_TO_DRAW); - assert(glIsProgram(batch->program)); -#endif - - if (batch->vao_id) - glBindVertexArray(batch->vao_id); - else - Batch_prime(batch); - - if (batch->program_dirty) - Batch_update_program_bindings(batch); - - Batch_use_program(batch); - - gpuBindMatrices(batch->program); - - if (batch->elem) - { - const ElementList* el = batch->elem; - -#if TRACK_INDEX_RANGE - if (el->base_index) - glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index); - else - glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0); -#else - glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0); -#endif - } - else - glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); - - Batch_done_using_program(batch); - glBindVertexArray(0); - } - - - -// clement : temp stuff -void Batch_draw_stupid(Batch* batch) -{ - if (batch->vao_id) - glBindVertexArray(batch->vao_id); - else - Batch_prime(batch); - - if (batch->program_dirty) - Batch_update_program_bindings(batch); - - // Batch_use_program(batch); - - //gpuBindMatrices(batch->program); - - if (batch->elem) - { - const ElementList* el = batch->elem; - -#if TRACK_INDEX_RANGE - if (el->base_index) - glDrawRangeElementsBaseVertex(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0, el->base_index); - else - glDrawRangeElements(batch->prim_type, el->min_index, el->max_index, el->index_ct, el->index_type, 0); -#else - glDrawElements(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0); -#endif - } - else - glDrawArrays(batch->prim_type, 0, batch->verts->vertex_ct); - - // Batch_done_using_program(batch); - glBindVertexArray(0); -} - -// clement : temp stuff -void Batch_draw_stupid_instanced(Batch* batch, unsigned int instance_vbo, int instance_count, - int attrib_nbr, int attrib_stride, int attrib_size[16], int attrib_loc[16]) -{ - if (batch->vao_id) - glBindVertexArray(batch->vao_id); - else - Batch_prime(batch); - - if (batch->program_dirty) - Batch_update_program_bindings(batch); - - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo); - int ptr_ofs = 0; - for (int i = 0; i < attrib_nbr; ++i) { - int size = attrib_size[i]; - int loc = attrib_loc[i]; - int atr_ofs = 0; - - while (size > 0) { - glEnableVertexAttribArray(loc + atr_ofs); - glVertexAttribPointer(loc + atr_ofs, (size > 4) ? 4 : size, GL_FLOAT, GL_FALSE, - sizeof(float) * attrib_stride, (GLvoid*)(sizeof(float) * ptr_ofs)); - glVertexAttribDivisor(loc + atr_ofs, 1); - atr_ofs++; - ptr_ofs += (size > 4) ? 4 : size; - size -= 4; - } - } - glBindBuffer(GL_ARRAY_BUFFER, 0); - - // Batch_use_program(batch); - - //gpuBindMatrices(batch->program); - - if (batch->elem) - { - const ElementList* el = batch->elem; - - glDrawElementsInstanced(batch->prim_type, el->index_ct, GL_UNSIGNED_INT, 0, instance_count); - } - else - glDrawArraysInstanced(batch->prim_type, 0, batch->verts->vertex_ct, instance_count); - - // Batch_done_using_program(batch); - glBindVertexArray(0); -} - diff --git a/source/blender/gpu/gawain/batch.h b/source/blender/gpu/gawain/batch.h deleted file mode 100644 index 660ed9eb762..00000000000 --- a/source/blender/gpu/gawain/batch.h +++ /dev/null @@ -1,104 +0,0 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "vertex_buffer.h" -#include "element.h" - -typedef enum { - READY_TO_FORMAT, - READY_TO_BUILD, - BUILDING, - READY_TO_DRAW -} BatchPhase; - -typedef struct Batch{ - // geometry - VertexBuffer* verts; - ElementList* elem; // NULL if element list not needed - PrimitiveType prim_type; - - // book-keeping - GLuint vao_id; // remembers all geometry state (vertex attrib bindings & element buffer) - BatchPhase phase; - bool program_dirty; - bool program_in_use; - - // state - GLuint program; -} Batch; - -Batch* Batch_create(PrimitiveType, VertexBuffer*, ElementList*); -void Batch_init(Batch*, PrimitiveType, VertexBuffer*, ElementList*); - -void Batch_discard(Batch*); // verts & elem are not discarded -void Batch_discard_all(Batch*); // including verts & elem - -void Batch_set_program(Batch*, GLuint program); -// 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. - -void Batch_use_program(Batch*); // call before Batch_Uniform (temp hack?) -void Batch_done_using_program(Batch*); - -void Batch_Uniform1b(Batch*, const char* name, bool value); -void Batch_Uniform1f(Batch*, const char* name, float value); -void Batch_Uniform2f(Batch*, const char* name, float x, float y); -void Batch_Uniform4f(Batch*, const char* name, float x, float y, float z, float w); -void Batch_Uniform3fv(Batch*, const char* name, const float data[3]); -void Batch_Uniform4fv(Batch*, const char* name, const float data[4]); - -void Batch_draw(Batch*); - - -// clement : temp stuff -void Batch_draw_stupid(Batch*); -void Batch_draw_stupid_instanced(Batch*, unsigned int instance_vbo, int instance_count, - int attrib_nbr, int attrib_stride, int attrib_loc[16], int attrib_size[16]); - - - - - - -#if 0 // future plans - -// Can multiple batches share a VertexBuffer? Use ref count? - - -// We often need a batch with its own data, to be created and discarded together. -// WithOwn variants reduce number of system allocations. - -typedef struct { - Batch batch; - VertexBuffer verts; // link batch.verts to this -} BatchWithOwnVertexBuffer; - -typedef struct { - Batch batch; - ElementList elem; // link batch.elem to this -} BatchWithOwnElementList; - -typedef struct { - Batch batch; - ElementList elem; // link batch.elem to this - VertexBuffer verts; // link batch.verts to this -} BatchWithOwnVertexBufferAndElementList; - -Batch* create_BatchWithOwnVertexBuffer(PrimitiveType, VertexFormat*, unsigned v_ct, ElementList*); -Batch* create_BatchWithOwnElementList(PrimitiveType, VertexBuffer*, unsigned prim_ct); -Batch* create_BatchWithOwnVertexBufferAndElementList(PrimitiveType, VertexFormat*, unsigned v_ct, unsigned prim_ct); -// verts: shared, own -// elem: none, shared, own -Batch* create_BatchInGeneral(PrimitiveType, VertexBufferStuff, ElementListStuff); - -#endif // future plans diff --git a/source/blender/gpu/gawain/buffer_id.cpp b/source/blender/gpu/gawain/buffer_id.cpp deleted file mode 100644 index 450656c4ebf..00000000000 --- a/source/blender/gpu/gawain/buffer_id.cpp +++ /dev/null @@ -1,115 +0,0 @@ - -// Gawain buffer IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.#include "buffer_id.h" - -#include "buffer_id.h" -#include <mutex> -#include <vector> - -#define ORPHAN_DEBUG 0 - -#if ORPHAN_DEBUG - #include <cstdio> -#endif - -static std::vector<GLuint> orphaned_buffer_ids; -static std::vector<GLuint> orphaned_vao_ids; - -static std::mutex orphan_mutex; - -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(); - } - -GLuint buffer_id_alloc() - { -#if TRUST_NO_ONE - assert(thread_is_main()); -#endif - - // delete orphaned IDs - orphan_mutex.lock(); - if (!orphaned_buffer_ids.empty()) - { - const auto orphaned_buffer_ct = (unsigned)orphaned_buffer_ids.size(); -#if ORPHAN_DEBUG - printf("deleting %u orphaned VBO%s\n", orphaned_buffer_ct, orphaned_buffer_ct == 1 ? "" : "s"); -#endif - glDeleteBuffers(orphaned_buffer_ct, orphaned_buffer_ids.data()); - orphaned_buffer_ids.clear(); - } - orphan_mutex.unlock(); - - GLuint new_buffer_id = 0; - glGenBuffers(1, &new_buffer_id); - return new_buffer_id; - } - -void buffer_id_free(GLuint buffer_id) - { - if (thread_is_main()) - glDeleteBuffers(1, &buffer_id); - else - { - // add this ID to the orphaned list - orphan_mutex.lock(); -#if ORPHAN_DEBUG - printf("orphaning VBO %u\n", buffer_id); -#endif - orphaned_buffer_ids.emplace_back(buffer_id); - orphan_mutex.unlock(); - } - } - -GLuint vao_id_alloc() - { -#if TRUST_NO_ONE - assert(thread_is_main()); -#endif - - // delete orphaned IDs - orphan_mutex.lock(); - if (!orphaned_vao_ids.empty()) - { - const auto orphaned_vao_ct = (unsigned)orphaned_vao_ids.size(); -#if ORPHAN_DEBUG - printf("deleting %u orphaned VAO%s\n", orphaned_vao_ct, orphaned_vao_ct == 1 ? "" : "s"); -#endif - glDeleteVertexArrays(orphaned_vao_ct, orphaned_vao_ids.data()); - orphaned_vao_ids.clear(); - } - orphan_mutex.unlock(); - - GLuint new_vao_id = 0; - glGenVertexArrays(1, &new_vao_id); - return new_vao_id; - } - -void vao_id_free(GLuint vao_id) - { - if (thread_is_main()) - glDeleteVertexArrays(1, &vao_id); - else - { - // add this ID to the orphaned list - orphan_mutex.lock(); -#if ORPHAN_DEBUG - printf("orphaning VAO %u\n", vao_id); -#endif - orphaned_vao_ids.emplace_back(vao_id); - orphan_mutex.unlock(); - } - } diff --git a/source/blender/gpu/gawain/buffer_id.h b/source/blender/gpu/gawain/buffer_id.h deleted file mode 100644 index 3f67458d060..00000000000 --- a/source/blender/gpu/gawain/buffer_id.h +++ /dev/null @@ -1,34 +0,0 @@ - -// Gawain buffer IDs -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -// Manage GL buffer IDs in a thread-safe way -// Use these instead of glGenBuffers & its friends -// - alloc must be called from main thread -// - free can be called from any thread - -#ifdef __cplusplus -extern "C" { -#endif - -#include "common.h" - -GLuint buffer_id_alloc(void); -void buffer_id_free(GLuint buffer_id); - -GLuint vao_id_alloc(void); -void vao_id_free(GLuint vao_id); - - -#ifdef __cplusplus -} -#endif diff --git a/source/blender/gpu/gawain/common.h b/source/blender/gpu/gawain/common.h deleted file mode 100644 index 90340b94e4d..00000000000 --- a/source/blender/gpu/gawain/common.h +++ /dev/null @@ -1,58 +0,0 @@ - -// Gawain common #defines and #includes -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -// #define TRUST_NO_ONE !defined(NDEBUG) -#define TRUST_NO_ONE 1 -// strict error checking, always enabled during early development - -#include <GL/glew.h> -#include <stdbool.h> -#include <stdint.h> - -#if TRUST_NO_ONE - #include <assert.h> -#endif - -#define PER_THREAD -// #define PER_THREAD __thread -// MSVC uses __declspec(thread) for C code - -#define APPLE_LEGACY (defined(__APPLE__) && defined(WITH_GL_PROFILE_COMPAT)) - -#if APPLE_LEGACY - #undef glGenVertexArrays - #define glGenVertexArrays glGenVertexArraysAPPLE - - #undef glDeleteVertexArrays - #define glDeleteVertexArrays glDeleteVertexArraysAPPLE - - #undef glBindVertexArray - #define glBindVertexArray glBindVertexArrayAPPLE -#endif - -typedef enum { - PRIM_POINTS = GL_POINTS, - PRIM_LINES = GL_LINES, - PRIM_TRIANGLES = GL_TRIANGLES, - -#ifdef WITH_GL_PROFILE_COMPAT - PRIM_QUADS = GL_QUADS, // legacy GL has this, modern GL & Vulkan do not -#endif - - PRIM_LINE_STRIP = GL_LINE_STRIP, - PRIM_LINE_LOOP = GL_LINE_LOOP, // GL has this, Vulkan does not - PRIM_TRIANGLE_STRIP = GL_TRIANGLE_STRIP, - PRIM_TRIANGLE_FAN = GL_TRIANGLE_FAN, - - PRIM_NONE = 0xF -} PrimitiveType; diff --git a/source/blender/gpu/gawain/element.c b/source/blender/gpu/gawain/element.c deleted file mode 100644 index 3c3ca1c7626..00000000000 --- a/source/blender/gpu/gawain/element.c +++ /dev/null @@ -1,283 +0,0 @@ - -// Gawain element list (AKA index buffer) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "element.h" -#include "buffer_id.h" -#include <stdlib.h> - -#define KEEP_SINGLE_COPY 1 - -unsigned ElementList_size(const ElementList* elem) - { -#if TRACK_INDEX_RANGE - switch (elem->index_type) - { - case INDEX_U8: return elem->index_ct * sizeof(GLubyte); - case INDEX_U16: return elem->index_ct * sizeof(GLushort); - case INDEX_U32: return elem->index_ct * sizeof(GLuint); - default: - #if TRUST_NO_ONE - assert(false); - #endif - return 0; - } - -#else - return elem->index_ct * sizeof(GLuint); -#endif - } - -static void ElementList_prime(ElementList* elem) - { - elem->vbo_id = buffer_id_alloc(); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); - // fill with delicious data & send to GPU the first time only - glBufferData(GL_ELEMENT_ARRAY_BUFFER, ElementList_size(elem), elem->data, GL_STATIC_DRAW); - -#if KEEP_SINGLE_COPY - // now that GL has a copy, discard original - free(elem->data); - elem->data = NULL; -#endif - } - -void ElementList_use(ElementList* elem) - { - if (elem->vbo_id) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem->vbo_id); - else - ElementList_prime(elem); - } - -void ElementListBuilder_init(ElementListBuilder* builder, PrimitiveType prim_type, unsigned prim_ct, unsigned vertex_ct) - { - unsigned verts_per_prim = 0; - switch (prim_type) - { - case PRIM_POINTS: - verts_per_prim = 1; - break; - case PRIM_LINES: - verts_per_prim = 2; - break; - case PRIM_TRIANGLES: - verts_per_prim = 3; - break; - default: -#if TRUST_NO_ONE - assert(false); -#endif - return; - } - - builder->max_allowed_index = vertex_ct - 1; - builder->max_index_ct = prim_ct * verts_per_prim; - builder->index_ct = 0; // start empty - builder->prim_type = prim_type; - builder->data = calloc(builder->max_index_ct, sizeof(unsigned)); - } - -void add_generic_vertex(ElementListBuilder* builder, unsigned v) - { -#if TRUST_NO_ONE - assert(builder->data != NULL); - assert(builder->index_ct < builder->max_index_ct); - assert(v <= builder->max_allowed_index); -#endif - - builder->data[builder->index_ct++] = v; - } - -void add_point_vertex(ElementListBuilder* builder, unsigned v) - { -#if TRUST_NO_ONE - assert(builder->prim_type == PRIM_POINTS); -#endif - - add_generic_vertex(builder, v); - } - -void add_line_vertices(ElementListBuilder* builder, unsigned v1, unsigned v2) - { -#if TRUST_NO_ONE - assert(builder->prim_type == PRIM_LINES); - assert(v1 != v2); -#endif - - add_generic_vertex(builder, v1); - add_generic_vertex(builder, v2); - } - -void add_triangle_vertices(ElementListBuilder* builder, unsigned v1, unsigned v2, unsigned v3) - { -#if TRUST_NO_ONE - assert(builder->prim_type == PRIM_TRIANGLES); - assert(v1 != v2 && v2 != v3 && v3 != v1); -#endif - - add_generic_vertex(builder, v1); - add_generic_vertex(builder, v2); - add_generic_vertex(builder, v3); - } - -#if TRACK_INDEX_RANGE -// Everything remains 32 bit while building to keep things simple. -// Find min/max after, then convert to smallest index type possible. - -static unsigned index_range(const unsigned values[], unsigned value_ct, unsigned* min_out, unsigned* max_out) - { - unsigned min_value = values[0]; - unsigned max_value = values[0]; - for (unsigned i = 1; i < value_ct; ++i) - { - const unsigned value = values[i]; - 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(const unsigned values[], ElementList* elem) - { - const unsigned index_ct = elem->index_ct; - GLubyte* data = malloc(index_ct * sizeof(GLubyte)); - - if (elem->max_index > 0xFF) - { - const unsigned base = elem->min_index; - - elem->base_index = base; - elem->min_index = 0; - elem->max_index -= base; - - for (unsigned i = 0; i < index_ct; ++i) - data[i] = (GLubyte)(values[i] - base); - } - else - { - elem->base_index = 0; - - for (unsigned i = 0; i < index_ct; ++i) - data[i] = (GLubyte)(values[i]); - } - - elem->data = data; - } - -static void squeeze_indices_short(const unsigned values[], ElementList* elem) - { - const unsigned index_ct = elem->index_ct; - GLushort* data = malloc(index_ct * sizeof(GLushort)); - - if (elem->max_index > 0xFFFF) - { - const unsigned base = elem->min_index; - - elem->base_index = base; - elem->min_index = 0; - elem->max_index -= base; - - for (unsigned i = 0; i < index_ct; ++i) - data[i] = (GLushort)(values[i] - base); - } - else - { - elem->base_index = 0; - - for (unsigned i = 0; i < index_ct; ++i) - data[i] = (GLushort)(values[i]); - } - - elem->data = data; - } - -#endif // TRACK_INDEX_RANGE - -ElementList* ElementList_build(ElementListBuilder* builder) - { - ElementList* elem = calloc(1, sizeof(ElementList)); - ElementList_build_in_place(builder, elem); - return elem; - } - -void ElementList_build_in_place(ElementListBuilder* builder, ElementList* elem) - { -#if TRUST_NO_ONE - assert(builder->data != NULL); -#endif - - elem->index_ct = builder->index_ct; - -#if TRACK_INDEX_RANGE - const unsigned range = index_range(builder->data, builder->index_ct, &elem->min_index, &elem->max_index); - - if (range <= 0xFF) - { - elem->index_type = INDEX_U8; - squeeze_indices_byte(builder->data, elem); - } - else if (range <= 0xFFFF) - { - elem->index_type = INDEX_U16; - squeeze_indices_short(builder->data, elem); - } - else - { - elem->index_type = INDEX_U32; - elem->base_index = 0; - - if (builder->index_ct < builder->max_index_ct) - { - builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned)); - // TODO: realloc only if index_ct is much smaller than max_index_ct - } - - elem->data = builder->data; - } -#else - if (builder->index_ct < builder->max_index_ct) - { - builder->data = realloc(builder->data, builder->index_ct * sizeof(unsigned)); - // TODO: realloc only if index_ct is much smaller than max_index_ct - } - - elem->data = builder->data; -#endif - - // elem->data will never be *larger* than builder->data... how about converting - // in place to avoid extra allocation? - - elem->vbo_id = 0; - // TODO: create GL buffer object directly, based on an input flag - - // discard builder (one-time use) - if (builder->data != elem->data) - free(builder->data); - builder->data = NULL; - // other fields are safe to leave - } - -void ElementList_discard(ElementList* elem) - { - if (elem->vbo_id) - buffer_id_free(elem->vbo_id); -#if KEEP_SINGLE_COPY - else -#endif - if (elem->data) - free(elem->data); - - free(elem); - } diff --git a/source/blender/gpu/gawain/element.h b/source/blender/gpu/gawain/element.h deleted file mode 100644 index 4e0d5fb0649..00000000000 --- a/source/blender/gpu/gawain/element.h +++ /dev/null @@ -1,64 +0,0 @@ - -// Gawain element list (AKA index buffer) -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "common.h" - -#define TRACK_INDEX_RANGE 1 - -typedef enum { - INDEX_U8 = GL_UNSIGNED_BYTE, // GL has this, Vulkan does not - INDEX_U16 = GL_UNSIGNED_SHORT, - INDEX_U32 = GL_UNSIGNED_INT -} IndexType; - -typedef struct { - unsigned index_ct; -#if TRACK_INDEX_RANGE - IndexType index_type; - unsigned min_index; - unsigned max_index; - unsigned base_index; -#endif - void* data; // NULL indicates data in VRAM (unmapped) or not yet allocated - GLuint vbo_id; // 0 indicates not yet sent to VRAM -} ElementList; - -void ElementList_use(ElementList*); -unsigned ElementList_size(const ElementList*); - -typedef struct { - unsigned max_allowed_index; - unsigned max_index_ct; - unsigned index_ct; - PrimitiveType prim_type; - unsigned* data; -} ElementListBuilder; - -// supported primitives: -// PRIM_POINTS -// PRIM_LINES -// PRIM_TRIANGLES - -void ElementListBuilder_init(ElementListBuilder*, PrimitiveType, unsigned prim_ct, unsigned vertex_ct); -//void ElementListBuilder_init_custom(ElementListBuilder*, PrimitiveType, unsigned index_ct, unsigned vertex_ct); - -void add_generic_vertex(ElementListBuilder*, unsigned v); - -void add_point_vertex(ElementListBuilder*, unsigned v); -void add_line_vertices(ElementListBuilder*, unsigned v1, unsigned v2); -void add_triangle_vertices(ElementListBuilder*, unsigned v1, unsigned v2, unsigned v3); - -ElementList* ElementList_build(ElementListBuilder*); -void ElementList_build_in_place(ElementListBuilder*, ElementList*); - -void ElementList_discard(ElementList*); diff --git a/source/blender/gpu/gawain/imm_util.c b/source/blender/gpu/gawain/imm_util.c deleted file mode 100644 index 74caeb6fd3a..00000000000 --- a/source/blender/gpu/gawain/imm_util.c +++ /dev/null @@ -1,46 +0,0 @@ - -// Gawain immediate mode drawing utilities -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "imm_util.h" -#include "immediate.h" - - -void immRectf(unsigned pos, float x1, float y1, float x2, float y2) -{ - immBegin(PRIM_TRIANGLE_FAN, 4); - immVertex2f(pos, x1, y1); - immVertex2f(pos, x2, y1); - immVertex2f(pos, x2, y2); - immVertex2f(pos, x1, y2); - immEnd(); -} - -void immRecti(unsigned pos, int x1, int y1, int x2, int y2) -{ - immBegin(PRIM_TRIANGLE_FAN, 4); - immVertex2i(pos, x1, y1); - immVertex2i(pos, x2, y1); - immVertex2i(pos, x2, y2); - immVertex2i(pos, x1, y2); - immEnd(); -} - -#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]) -{ - VertexFormat *format = immVertexFormat(); - unsigned pos = add_attrib(format, "pos", COMP_I32, 2, CONVERT_INT_TO_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); - immUniformColor4fv(color); - immRecti(pos, x1, y1, x2, y2); - immUnbindProgram(); -} -#endif diff --git a/source/blender/gpu/gawain/imm_util.h b/source/blender/gpu/gawain/imm_util.h deleted file mode 100644 index 730bd7c1a3c..00000000000 --- a/source/blender/gpu/gawain/imm_util.h +++ /dev/null @@ -1,18 +0,0 @@ - -// Gawain immediate mode drawing utilities -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - - -// Draw 2D rectangles (replaces glRect functions) -// caller is reponsible for vertex format & shader -void immRectf(unsigned pos, float x1, float y1, float x2, float y2); -void immRecti(unsigned pos, int x1, int y1, int x2, int y2); diff --git a/source/blender/gpu/gawain/immediate.c b/source/blender/gpu/gawain/immediate.c deleted file mode 100644 index b7aad530620..00000000000 --- a/source/blender/gpu/gawain/immediate.c +++ /dev/null @@ -1,868 +0,0 @@ - -// Gawain immediate mode work-alike -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "immediate.h" -#include "attrib_binding.h" -#include "buffer_id.h" -#include <string.h> - -// necessary functions from matrix API -extern void gpuBindMatrices(GLuint program); -extern bool gpuMatricesDirty(void); - -typedef struct { - // TODO: organize this struct by frequency of change (run-time) - -#if IMM_BATCH_COMBO - Batch* batch; -#endif - - // current draw call - GLubyte* buffer_data; - unsigned buffer_offset; - unsigned buffer_bytes_mapped; - unsigned vertex_ct; - bool strict_vertex_ct; - PrimitiveType prim_type; - - VertexFormat vertex_format; - - // current vertex - unsigned vertex_idx; - GLubyte* vertex_data; - uint16_t unassigned_attrib_bits; // which attributes of current vertex have not been given values? - - GLuint vbo_id; - GLuint vao_id; - - GLuint bound_program; - AttribBinding attrib_binding; - uint16_t prev_enabled_attrib_bits; // <-- only affects this VAO, so we're ok -} Immediate; - -// size of internal buffer -- make this adjustable? -#define IMM_BUFFER_SIZE (4 * 1024 * 1024) - -static PER_THREAD bool initialized = false; -static PER_THREAD Immediate imm; - -void immInit(void) - { -#if TRUST_NO_ONE - assert(!initialized); -#endif - - memset(&imm, 0, sizeof(Immediate)); - - imm.vbo_id = buffer_id_alloc(); - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); - -#if APPLE_LEGACY - glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_SERIALIZED_MODIFY_APPLE, GL_FALSE); - glBufferParameteriAPPLE(GL_ARRAY_BUFFER, GL_BUFFER_FLUSHING_UNMAP_APPLE, GL_FALSE); -#endif - - imm.prim_type = PRIM_NONE; - imm.strict_vertex_ct = true; - - glBindBuffer(GL_ARRAY_BUFFER, 0); - initialized = true; - - immActivate(); - } - -void immActivate(void) - { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == PRIM_NONE); // make sure we're not between a Begin/End pair - assert(imm.vao_id == 0); -#endif - - imm.vao_id = vao_id_alloc(); - } - -void immDeactivate(void) - { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == PRIM_NONE); // make sure we're not between a Begin/End pair - assert(imm.vao_id != 0); -#endif - - vao_id_free(imm.vao_id); - imm.vao_id = 0; - imm.prev_enabled_attrib_bits = 0; - } - -void immDestroy(void) - { - immDeactivate(); - buffer_id_free(imm.vbo_id); - initialized = false; - } - -VertexFormat* immVertexFormat(void) - { - VertexFormat_clear(&imm.vertex_format); - return &imm.vertex_format; - } - -void immBindProgram(GLuint program) - { -#if TRUST_NO_ONE - assert(imm.bound_program == 0); - assert(glIsProgram(program)); -#endif - - if (!imm.vertex_format.packed) - VertexFormat_pack(&imm.vertex_format); - - glUseProgram(program); - get_attrib_locations(&imm.vertex_format, &imm.attrib_binding, program); - imm.bound_program = program; - - gpuBindMatrices(program); - } - -void immUnbindProgram(void) - { -#if TRUST_NO_ONE - assert(imm.bound_program != 0); -#endif - - glUseProgram(0); - imm.bound_program = 0; - } - -static bool vertex_count_makes_sense_for_primitive(unsigned vertex_ct, PrimitiveType prim_type) - { - // does vertex_ct make sense for this primitive type? - if (vertex_ct == 0) - return false; - - switch (prim_type) - { - case PRIM_POINTS: - return true; - case PRIM_LINES: - return vertex_ct % 2 == 0; - case PRIM_LINE_STRIP: - case PRIM_LINE_LOOP: - return vertex_ct >= 2; - case PRIM_TRIANGLES: - return vertex_ct % 3 == 0; - case PRIM_TRIANGLE_STRIP: - case PRIM_TRIANGLE_FAN: - return vertex_ct >= 3; - #ifdef WITH_GL_PROFILE_COMPAT - case PRIM_QUADS: - return vertex_ct % 4 == 0; - #endif - default: - return false; - } - } - -void immBegin(PrimitiveType prim_type, unsigned vertex_ct) - { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == PRIM_NONE); // make sure we haven't already begun - assert(vertex_count_makes_sense_for_primitive(vertex_ct, prim_type)); -#endif - - imm.prim_type = prim_type; - imm.vertex_ct = vertex_ct; - imm.vertex_idx = 0; - imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits; - - // how many bytes do we need for this draw call? - const unsigned bytes_needed = vertex_buffer_size(&imm.vertex_format, vertex_ct); - -#if TRUST_NO_ONE - assert(bytes_needed <= IMM_BUFFER_SIZE); -#endif - - glBindBuffer(GL_ARRAY_BUFFER, imm.vbo_id); - - // does the current buffer have enough room? - const unsigned available_bytes = IMM_BUFFER_SIZE - imm.buffer_offset; - // ensure vertex data is aligned - const unsigned 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 -#if APPLE_LEGACY - glBufferData(GL_ARRAY_BUFFER, IMM_BUFFER_SIZE, NULL, GL_DYNAMIC_DRAW); -#else - if (GLEW_VERSION_4_3 || GLEW_ARB_invalidate_subdata) - glInvalidateBufferData(imm.vbo_id); - else - glMapBufferRange(GL_ARRAY_BUFFER, 0, IMM_BUFFER_SIZE, GL_MAP_INVALIDATE_BUFFER_BIT); -#endif - - imm.buffer_offset = 0; - } - -// printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); - -#if APPLE_LEGACY - imm.buffer_data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY) + imm.buffer_offset; -#else - imm.buffer_data = glMapBufferRange(GL_ARRAY_BUFFER, imm.buffer_offset, bytes_needed, - GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT | (imm.strict_vertex_ct ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT)); -#endif - -#if TRUST_NO_ONE - assert(imm.buffer_data != NULL); -#endif - - imm.buffer_bytes_mapped = bytes_needed; - imm.vertex_data = imm.buffer_data; - } - -void immBeginAtMost(PrimitiveType prim_type, unsigned vertex_ct) - { -#if TRUST_NO_ONE - assert(vertex_ct > 0); -#endif - - imm.strict_vertex_ct = false; - immBegin(prim_type, vertex_ct); - } - -#if IMM_BATCH_COMBO - -Batch* immBeginBatch(PrimitiveType prim_type, unsigned vertex_ct) - { -#if TRUST_NO_ONE - assert(initialized); - assert(imm.prim_type == PRIM_NONE); // make sure we haven't already begun - assert(vertex_count_makes_sense_for_primitive(vertex_ct, prim_type)); -#endif - - imm.prim_type = prim_type; - imm.vertex_ct = vertex_ct; - imm.vertex_idx = 0; - imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits; - - VertexBuffer* verts = VertexBuffer_create_with_format(&imm.vertex_format); - VertexBuffer_allocate_data(verts, vertex_ct); - - imm.buffer_bytes_mapped = VertexBuffer_size(verts); - imm.vertex_data = verts->data; - - imm.batch = Batch_create(prim_type, verts, NULL); - imm.batch->phase = BUILDING; - - Batch_set_program(imm.batch, imm.bound_program); - - return imm.batch; - } - -Batch* immBeginBatchAtMost(PrimitiveType prim_type, unsigned vertex_ct) - { - imm.strict_vertex_ct = false; - return immBeginBatch(prim_type, vertex_ct); - } - -#endif // IMM_BATCH_COMBO - -static void immDrawSetup(void) - { - // set up VAO -- can be done during Begin or End really - glBindVertexArray(imm.vao_id); - - // enable/disable vertex attribs as needed - if (imm.attrib_binding.enabled_bits != imm.prev_enabled_attrib_bits) - { - for (unsigned loc = 0; loc < MAX_VERTEX_ATTRIBS; ++loc) - { - bool is_enabled = imm.attrib_binding.enabled_bits & (1 << loc); - bool was_enabled = imm.prev_enabled_attrib_bits & (1 << loc); - - if (is_enabled && !was_enabled) - { -// printf("enabling attrib %u\n", loc); - glEnableVertexAttribArray(loc); - } - else if (was_enabled && !is_enabled) - { -// printf("disabling attrib %u\n", loc); - glDisableVertexAttribArray(loc); - } - } - - imm.prev_enabled_attrib_bits = imm.attrib_binding.enabled_bits; - } - - const unsigned stride = imm.vertex_format.stride; - - for (unsigned a_idx = 0; a_idx < imm.vertex_format.attrib_ct; ++a_idx) - { - const Attrib* a = imm.vertex_format.attribs + a_idx; - - const unsigned offset = imm.buffer_offset + a->offset; - const GLvoid* pointer = (const GLubyte*)0 + offset; - - const unsigned loc = read_attrib_location(&imm.attrib_binding, a_idx); - -// printf("specifying attrib %u '%s' with offset %u, stride %u\n", loc, a->name, offset, stride); - - switch (a->fetch_mode) - { - case KEEP_FLOAT: - case CONVERT_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_FALSE, stride, pointer); - break; - case NORMALIZE_INT_TO_FLOAT: - glVertexAttribPointer(loc, a->comp_ct, a->comp_type, GL_TRUE, stride, pointer); - break; - case KEEP_INT: - glVertexAttribIPointer(loc, a->comp_ct, a->comp_type, stride, pointer); - } - } - - if (gpuMatricesDirty()) - gpuBindMatrices(imm.bound_program); - } - -void immEnd(void) - { -#if TRUST_NO_ONE - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - unsigned buffer_bytes_used; - if (imm.strict_vertex_ct) - { -#if TRUST_NO_ONE - assert(imm.vertex_idx == imm.vertex_ct); // with all vertices defined -#endif - buffer_bytes_used = imm.buffer_bytes_mapped; - } - else - { -#if TRUST_NO_ONE - assert(imm.vertex_idx <= imm.vertex_ct); -#endif - // printf("used %u of %u verts,", imm.vertex_idx, imm.vertex_ct); - if (imm.vertex_idx == imm.vertex_ct) - { - 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_ct = imm.vertex_idx; - buffer_bytes_used = vertex_buffer_size(&imm.vertex_format, imm.vertex_ct); - // unused buffer bytes are available to the next immBegin - // printf(" %u of %u bytes\n", buffer_bytes_used, imm.buffer_bytes_mapped); - } -#if !APPLE_LEGACY - // tell OpenGL what range was modified so it doesn't copy the whole mapped range - // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1); - glFlushMappedBufferRange(GL_ARRAY_BUFFER, 0, buffer_bytes_used); -#endif - } - -#if IMM_BATCH_COMBO - if (imm.batch) - { - if (buffer_bytes_used != imm.buffer_bytes_mapped) - { - VertexBuffer_resize_data(imm.batch->verts, imm.vertex_ct); - // TODO: resize only if vertex count is much smaller - } - - imm.batch->phase = READY_TO_DRAW; - imm.batch = NULL; // don't free, batch belongs to caller - } - else -#endif - { -#if APPLE_LEGACY - // tell OpenGL what range was modified so it doesn't copy the whole buffer - // printf("flushing %u to %u\n", imm.buffer_offset, imm.buffer_offset + buffer_bytes_used - 1); - glFlushMappedBufferRangeAPPLE(GL_ARRAY_BUFFER, imm.buffer_offset, buffer_bytes_used); -#endif - glUnmapBuffer(GL_ARRAY_BUFFER); - - if (imm.vertex_ct > 0) - { - immDrawSetup(); - glDrawArrays(imm.prim_type, 0, imm.vertex_ct); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindVertexArray(0); - - // prep for next immBegin - imm.buffer_offset += buffer_bytes_used; - } - - // prep for next immBegin - imm.prim_type = PRIM_NONE; - imm.strict_vertex_ct = true; - } - -static void setAttribValueBit(unsigned attrib_id) - { - uint16_t mask = 1 << attrib_id; - -#if TRUST_NO_ONE - assert(imm.unassigned_attrib_bits & mask); // not already set -#endif - - imm.unassigned_attrib_bits &= ~mask; - } - - -// --- generic attribute functions --- - -void immAttrib1f(unsigned attrib_id, float x) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_F32); - assert(attrib->comp_ct == 1); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); - - data[0] = x; - } - -void immAttrib2f(unsigned attrib_id, float x, float y) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_F32); - assert(attrib->comp_ct == 2); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); - - data[0] = x; - data[1] = y; - } - -void immAttrib3f(unsigned attrib_id, float x, float y, float z) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_F32); - assert(attrib->comp_ct == 3); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - float* data = (float*)(imm.vertex_data + attrib->offset); -// printf("%s %td %p\n", __FUNCTION__, (GLubyte*)data - imm.buffer_data, data); - - data[0] = x; - data[1] = y; - data[2] = z; - } - -void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_F32); - assert(attrib->comp_ct == 4); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - float* data = (float*)(imm.vertex_data + attrib->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; - } - -void immAttrib2i(unsigned attrib_id, int x, int y) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_I32); - assert(attrib->comp_ct == 2); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - int* data = (int*)(imm.vertex_data + attrib->offset); - - data[0] = x; - data[1] = y; - } - -void immAttrib2s(unsigned attrib_id, short x, short y) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_I16); - assert(attrib->comp_ct == 2); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - short* data = (short*)(imm.vertex_data + attrib->offset); - - data[0] = x; - data[1] = y; - } - -void immAttrib3fv(unsigned attrib_id, const float data[3]) - { - immAttrib3f(attrib_id, data[0], data[1], data[2]); - } - -void immAttrib4fv(unsigned attrib_id, const float data[4]) - { - immAttrib4f(attrib_id, data[0], data[1], data[2], data[3]); - } - -void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_U8); - assert(attrib->comp_ct == 3); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - GLubyte* data = imm.vertex_data + attrib->offset; -// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); - - data[0] = r; - data[1] = g; - data[2] = b; - } - -void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a) - { - Attrib* attrib = imm.vertex_format.attribs + attrib_id; - -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(attrib->comp_type == COMP_U8); - assert(attrib->comp_ct == 4); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - - GLubyte* data = imm.vertex_data + attrib->offset; -// printf("%s %td %p\n", __FUNCTION__, data - imm.buffer_data, data); - - data[0] = r; - data[1] = g; - data[2] = b; - data[3] = a; - } - -void immAttrib3ubv(unsigned attrib_id, const unsigned char data[3]) - { - immAttrib3ub(attrib_id, data[0], data[1], data[2]); - } - -void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]) - { - immAttrib4ub(attrib_id, data[0], data[1], data[2], data[3]); - } - -void immSkipAttrib(unsigned attrib_id) - { -#if TRUST_NO_ONE - assert(attrib_id < imm.vertex_format.attrib_ct); - assert(imm.vertex_idx < imm.vertex_ct); - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair -#endif - - setAttribValueBit(attrib_id); - } - -static void immEndVertex(void) // and move on to the next vertex - { -#if TRUST_NO_ONE - assert(imm.prim_type != PRIM_NONE); // make sure we're between a Begin/End pair - assert(imm.vertex_idx < imm.vertex_ct); -#endif - - // have all attribs been assigned values? - // if not, copy value from previous vertex - if (imm.unassigned_attrib_bits) - { -#if TRUST_NO_ONE - assert(imm.vertex_idx > 0); // first vertex must have all attribs specified -#endif - - for (unsigned a_idx = 0; a_idx < imm.vertex_format.attrib_ct; ++a_idx) - { - if ((imm.unassigned_attrib_bits >> a_idx) & 1) - { - const Attrib* a = imm.vertex_format.attribs + a_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 - } - } - } - - imm.vertex_idx++; - imm.vertex_data += imm.vertex_format.stride; - imm.unassigned_attrib_bits = imm.attrib_binding.enabled_bits; - } - -void immVertex2f(unsigned attrib_id, float x, float y) - { - immAttrib2f(attrib_id, x, y); - immEndVertex(); - } - -void immVertex3f(unsigned attrib_id, float x, float y, float z) - { - immAttrib3f(attrib_id, x, y, z); - immEndVertex(); - } - -void immVertex2i(unsigned attrib_id, int x, int y) - { - immAttrib2i(attrib_id, x, y); - immEndVertex(); - } - -void immVertex2s(unsigned attrib_id, short x, short y) - { - immAttrib2s(attrib_id, x, y); - immEndVertex(); - } - -void immVertex2fv(unsigned attrib_id, const float data[2]) - { - immAttrib2f(attrib_id, data[0], data[1]); - immEndVertex(); - } - -void immVertex3fv(unsigned attrib_id, const float data[3]) - { - immAttrib3f(attrib_id, data[0], data[1], data[2]); - immEndVertex(); - } - -void immVertex2iv(unsigned attrib_id, const int data[2]) - { - immAttrib2i(attrib_id, data[0], data[1]); - immEndVertex(); - } - - -// --- generic uniform functions --- - -void immUniform1f(const char* name, float x) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform1f(loc, x); - } - -void immUniform2f(const char* name, float x, float y) -{ - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform2f(loc, x, y); -} - -void immUniform2fv(const char* name, const float data[2]) -{ - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform2fv(loc, 1, data); -} - -void immUniform3f(const char* name, float x, float y, float z) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform3f(loc, x, y, z); - } - -void immUniform3fv(const char* name, const float data[3]) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform3fv(loc, 1, data); - } - -void immUniform4f(const char* name, float x, float y, float z, float w) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform4f(loc, x, y, z, w); - } - -void immUniform4fv(const char* name, const float data[4]) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform4fv(loc, 1, data); - } - -void immUniformMat4(const char* name, const float data[4][4]) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniformMatrix4fv(loc, 1, GL_FALSE, (float *)data); - } - -void immUniform1i(const char* name, int x) - { - int loc = glGetUniformLocation(imm.bound_program, name); - -#if TRUST_NO_ONE - assert(loc != -1); -#endif - - glUniform1i(loc, x); - } - - -// --- convenience functions for setting "uniform vec4 color" --- - -void immUniformColor4f(float r, float g, float b, float a) - { - immUniform4f("color", r, g, b, a); - } - -void immUniformColor4fv(const float rgba[4]) - { - immUniform4fv("color", rgba); - } - -void immUniformColor3f(float r, float g, float b) - { - immUniform4f("color", r, g, b, 1.0f); - } - -void immUniformColor3fv(const float rgb[3]) - { - immUniform4f("color", rgb[0], rgb[1], rgb[2], 1.0f); - } - -void immUniformColor3fvAlpha(const float rgb[3], float a) - { - immUniform4f("color", rgb[0], rgb[1], rgb[2], a); - } - -// TODO: v-- treat as sRGB? --v - -void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b) - { - const float scale = 1.0f / 255.0f; - immUniform4f("color", scale * r, scale * g, scale * b, 1.0f); - } - -void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a) - { - const float scale = 1.0f / 255.0f; - immUniform4f("color", scale * r, scale * g, scale * b, scale * a); - } - -void immUniformColor3ubv(const unsigned char rgb[3]) - { - immUniformColor3ub(rgb[0], rgb[1], rgb[2]); - } - -void immUniformColor4ubv(const unsigned char rgba[4]) - { - immUniformColor4ub(rgba[0], rgba[1], rgba[2], rgba[3]); - } diff --git a/source/blender/gpu/gawain/immediate.h b/source/blender/gpu/gawain/immediate.h deleted file mode 100644 index 53f9e6c46e1..00000000000 --- a/source/blender/gpu/gawain/immediate.h +++ /dev/null @@ -1,110 +0,0 @@ - -// Gawain immediate mode work-alike -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "vertex_format.h" - -#define IMM_BATCH_COMBO 1 - - -VertexFormat* immVertexFormat(void); // returns a cleared vertex format, ready for add_attrib - -void immBindProgram(GLuint program); // every immBegin must have a program bound first -void immUnbindProgram(void); // call after your last immEnd, or before binding another program - -void immBegin(PrimitiveType, unsigned vertex_ct); // must supply exactly vertex_ct vertices -void immBeginAtMost(PrimitiveType, unsigned max_vertex_ct); // can supply fewer vertices -void immEnd(void); // finishes and draws - -#if IMM_BATCH_COMBO -#include "batch.h" -// immBegin a batch, then use standard immFunctions as usual. -// immEnd will finalize the batch instead of drawing. -// Then you can draw it as many times as you like! Partially replaces the need for display lists. -Batch* immBeginBatch(PrimitiveType, unsigned vertex_ct); -Batch* immBeginBatchAtMost(PrimitiveType, unsigned vertex_ct); -#endif - - -// provide attribute values that can change per vertex -// first vertex after immBegin must have all its attributes specified -// skipped attributes will continue using the previous value for that attrib_id -void immAttrib1f(unsigned attrib_id, float x); -void immAttrib2f(unsigned attrib_id, float x, float y); -void immAttrib3f(unsigned attrib_id, float x, float y, float z); -void immAttrib4f(unsigned attrib_id, float x, float y, float z, float w); - -void immAttrib2i(unsigned attrib_id, int x, int y); - -void immAttrib2s(unsigned attrib_id, short x, short y); - -void immAttrib3fv(unsigned attrib_id, const float data[3]); -void immAttrib4fv(unsigned attrib_id, const float data[4]); - -void immAttrib3ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b); -void immAttrib4ub(unsigned attrib_id, unsigned char r, unsigned char g, unsigned char b, unsigned char a); - -void immAttrib3ubv(unsigned attrib_id, const unsigned char data[4]); -void immAttrib4ubv(unsigned attrib_id, const unsigned char data[4]); - -// explicitly skip an attribute -// this advanced option kills automatic value copying for this attrib_id -void immSkipAttrib(unsigned attrib_id); - - -// provide one last attribute value & end the current vertex -// this is most often used for 2D or 3D position (similar to glVertex) -void immVertex2f(unsigned attrib_id, float x, float y); -void immVertex3f(unsigned attrib_id, float x, float y, float z); - -void immVertex2i(unsigned attrib_id, int x, int y); - -void immVertex2s(unsigned attrib_id, short x, short y); - -void immVertex2fv(unsigned attrib_id, const float data[2]); -void immVertex3fv(unsigned attrib_id, const float data[3]); - -void immVertex2iv(unsigned attrib_id, const int data[2]); - - -// provide uniform values that don't change for the entire draw call -void immUniform1i(const char* name, int x); -void immUniform1f(const char* name, float x); -void immUniform2f(const char* name, float x, float y); -void immUniform2fv(const char* name, const float data[2]); -void immUniform3f(const char* name, float x, float y, float z); -void immUniform3fv(const char* name, const float data[3]); -void immUniform4f(const char* name, float x, float y, float z, float w); -void immUniform4fv(const char* name, const float data[4]); -void immUniformMat4(const char* name, const float data[4][4]); - - -// convenience functions for setting "uniform vec4 color" -// the rgb functions have implicit alpha = 1.0 -void immUniformColor4f(float r, float g, float b, float a); -void immUniformColor4fv(const float rgba[4]); -void immUniformColor3f(float r, float g, float b); -void immUniformColor3fv(const float rgb[3]); -void immUniformColor3fvAlpha(const float rgb[3], float a); - -void immUniformColor3ub(unsigned char r, unsigned char g, unsigned char b); -void immUniformColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a); -void immUniformColor3ubv(const unsigned char rgb[3]); -void immUniformColor4ubv(const unsigned char rgba[4]); - - -// these are called by the system -- not part of drawing API - -void immInit(void); -void immActivate(void); -void immDeactivate(void); -void immDestroy(void); diff --git a/source/blender/gpu/gawain/vertex_buffer.c b/source/blender/gpu/gawain/vertex_buffer.c deleted file mode 100644 index 827703403e3..00000000000 --- a/source/blender/gpu/gawain/vertex_buffer.c +++ /dev/null @@ -1,170 +0,0 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "vertex_buffer.h" -#include "buffer_id.h" -#include <stdlib.h> -#include <string.h> - -#define KEEP_SINGLE_COPY 1 - -VertexBuffer* VertexBuffer_create(void) - { - VertexBuffer* verts = malloc(sizeof(VertexBuffer)); - VertexBuffer_init(verts); - return verts; - } - -VertexBuffer* VertexBuffer_create_with_format(const VertexFormat* format) - { - VertexBuffer* verts = VertexBuffer_create(); - VertexFormat_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 VertexBuffer_init(VertexBuffer* verts) - { - memset(verts, 0, sizeof(VertexBuffer)); - } - -void VertexBuffer_init_with_format(VertexBuffer* verts, const VertexFormat* format) - { - VertexBuffer_init(verts); - VertexFormat_copy(&verts->format, format); - if (!format->packed) - VertexFormat_pack(&verts->format); - } - -void VertexBuffer_discard(VertexBuffer* verts) - { - if (verts->vbo_id) - buffer_id_free(verts->vbo_id); -#if KEEP_SINGLE_COPY - else -#endif - if (verts->data) - free(verts->data); - - free(verts); - } - -unsigned VertexBuffer_size(const VertexBuffer* verts) - { - return vertex_buffer_size(&verts->format, verts->vertex_ct); - } - -void VertexBuffer_allocate_data(VertexBuffer* verts, unsigned v_ct) - { - VertexFormat* format = &verts->format; - if (!format->packed) - VertexFormat_pack(format); - - verts->vertex_ct = v_ct; - - // Data initially lives in main memory. Will be transferred to VRAM when we "prime" it. - verts->data = malloc(VertexBuffer_size(verts)); - } - -void VertexBuffer_resize_data(VertexBuffer* verts, unsigned v_ct) - { -#if TRUST_NO_ONE - assert(verts->vertex_ct != v_ct); // allow this? - assert(verts->data != NULL); // has already been allocated - assert(verts->vbo_id == 0); // has not been sent to VRAM -#endif - - verts->vertex_ct = v_ct; - verts->data = realloc(verts->data, VertexBuffer_size(verts)); - // TODO: skip realloc if v_ct < existing vertex count - // extra space will be reclaimed, and never sent to VRAM (see VertexBuffer_prime) - } - -void setAttrib(VertexBuffer* verts, unsigned a_idx, unsigned v_idx, const void* data) - { - const VertexFormat* format = &verts->format; - const Attrib* a = format->attribs + a_idx; - -#if TRUST_NO_ONE - assert(a_idx < format->attrib_ct); - assert(v_idx < verts->vertex_ct); - assert(verts->data != NULL); // data must be in main mem -#endif - - memcpy((GLubyte*)verts->data + a->offset + v_idx * format->stride, data, a->sz); - } - -void fillAttrib(VertexBuffer* verts, unsigned a_idx, const void* data) - { - const VertexFormat* format = &verts->format; - const Attrib* a = format->attribs + a_idx; - -#if TRUST_NO_ONE - assert(a_idx < format->attrib_ct); -#endif - - const unsigned stride = a->sz; // tightly packed input data - - fillAttribStride(verts, a_idx, stride, data); - } - -void fillAttribStride(VertexBuffer* verts, unsigned a_idx, unsigned stride, const void* data) - { - const VertexFormat* format = &verts->format; - const Attrib* a = format->attribs + a_idx; - -#if TRUST_NO_ONE - assert(a_idx < format->attrib_ct); - assert(verts->data != NULL); // data must be in main mem -#endif - - const unsigned vertex_ct = verts->vertex_ct; - - if (format->attrib_ct == 1 && stride == format->stride) - { - // we can copy it all at once - memcpy(verts->data, data, vertex_ct * a->sz); - } - else - { - // we must copy it per vertex - for (unsigned v = 0; v < vertex_ct; ++v) - memcpy((GLubyte*)verts->data + a->offset + v * format->stride, (const GLubyte*)data + v * stride, a->sz); - } - } - -static void VertexBuffer_prime(VertexBuffer* verts) - { - const VertexFormat* format = &verts->format; - - verts->vbo_id = buffer_id_alloc(); - glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); - // fill with delicious data & send to GPU the first time only - glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size(format, verts->vertex_ct), verts->data, GL_STATIC_DRAW); - -#if KEEP_SINGLE_COPY - // now that GL has a copy, discard original - free(verts->data); - verts->data = NULL; -#endif - } - -void VertexBuffer_use(VertexBuffer* verts) - { - if (verts->vbo_id) - glBindBuffer(GL_ARRAY_BUFFER, verts->vbo_id); - else - VertexBuffer_prime(verts); - } diff --git a/source/blender/gpu/gawain/vertex_buffer.h b/source/blender/gpu/gawain/vertex_buffer.h deleted file mode 100644 index 6a72cfe6ff3..00000000000 --- a/source/blender/gpu/gawain/vertex_buffer.h +++ /dev/null @@ -1,64 +0,0 @@ - -// Gawain geometry batch -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "vertex_format.h" - -// How to create a VertexBuffer: -// 1) verts = create_VertexBuffer() or init_VertexBuffer(verts) -// 2) add_attrib(verts->format, ...) -// 3) allocate_vertex_data(verts, vertex_ct) <-- finalizes/packs vertex format -// 4) fillAttrib(verts, pos, application_pos_buffer) -// 5) prime_VertexBuffer(verts); - -// Is VertexBuffer always used as part of a Batch? - -typedef struct { - VertexFormat format; - unsigned vertex_ct; - GLubyte* data; // NULL indicates data in VRAM (unmapped) or not yet allocated - GLuint vbo_id; // 0 indicates not yet sent to VRAM -} VertexBuffer; - -VertexBuffer* VertexBuffer_create(void); -VertexBuffer* VertexBuffer_create_with_format(const VertexFormat*); - -void VertexBuffer_discard(VertexBuffer*); - -void VertexBuffer_init(VertexBuffer*); -void VertexBuffer_init_with_format(VertexBuffer*, const VertexFormat*); - -unsigned VertexBuffer_size(const VertexBuffer*); -void VertexBuffer_allocate_data(VertexBuffer*, unsigned v_ct); -void VertexBuffer_resize_data(VertexBuffer*, unsigned v_ct); - -// The most important setAttrib variant is the untyped one. Get it right first. -// It takes a void* so the app developer is responsible for matching their app data types -// to the vertex attribute's type and component count. They're in control of both, so this -// should not be a problem. - -void setAttrib(VertexBuffer*, unsigned a_idx, unsigned v_idx, const void* data); -void fillAttrib(VertexBuffer*, unsigned a_idx, const void* data); // tightly packed, non interleaved input data -void fillAttribStride(VertexBuffer*, unsigned a_idx, unsigned stride, const void* data); - -// TODO: decide whether to keep the functions below -// doesn't immediate mode satisfy these needs? - -// void setAttrib1f(unsigned a_idx, unsigned v_idx, float x); -// void setAttrib2f(unsigned a_idx, unsigned v_idx, float x, float y); -// void setAttrib3f(unsigned a_idx, unsigned v_idx, float x, float y, float z); -// void setAttrib4f(unsigned a_idx, unsigned v_idx, float x, float y, float z, float w); -// -// void setAttrib3ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b); -// void setAttrib4ub(unsigned a_idx, unsigned v_idx, unsigned char r, unsigned char g, unsigned char b, unsigned char a); - -void VertexBuffer_use(VertexBuffer*); diff --git a/source/blender/gpu/gawain/vertex_format.c b/source/blender/gpu/gawain/vertex_format.c deleted file mode 100644 index 671b979a810..00000000000 --- a/source/blender/gpu/gawain/vertex_format.c +++ /dev/null @@ -1,246 +0,0 @@ - -// Gawain vertex format -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#include "vertex_format.h" -#include <stdlib.h> -#include <string.h> - -#define PACK_DEBUG 0 - -#if PACK_DEBUG - #include <stdio.h> -#endif - -void VertexFormat_clear(VertexFormat* format) - { -#if TRUST_NO_ONE - memset(format, 0, sizeof(VertexFormat)); -#else - format->attrib_ct = 0; - format->packed = false; - format->name_offset = 0; -#endif - } - -void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src) - { - // copy regular struct fields - memcpy(dest, src, sizeof(VertexFormat)); - } - -static unsigned comp_sz(VertexCompType type) - { -#if TRUST_NO_ONE - assert(type >= GL_BYTE && type <= GL_FLOAT); -#endif - - const GLubyte sizes[] = {1,1,2,2,4,4,4}; - return sizes[type - GL_BYTE]; - } - -static unsigned attrib_sz(const Attrib *a) - { -#if USE_10_10_10 - if (a->comp_type == COMP_I10) - return 4; // always packed as 10_10_10_2 -#endif - - return a->comp_ct * comp_sz(a->comp_type); - } - -static unsigned attrib_align(const Attrib *a) - { -#if USE_10_10_10 - if (a->comp_type == COMP_I10) - return 4; // always packed as 10_10_10_2 -#endif - - unsigned c = comp_sz(a->comp_type); - if (a->comp_ct == 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 - } - -unsigned vertex_buffer_size(const VertexFormat* format, unsigned vertex_ct) - { -#if TRUST_NO_ONE - assert(format->packed && format->stride > 0); -#endif - - return format->stride * vertex_ct; - } - -static const char* copy_attrib_name(VertexFormat* format, const char* name) - { - // strncpy does 110% of what we need; let's do exactly 100% - char* name_copy = format->names + format->name_offset; - unsigned available = VERTEX_ATTRIB_NAMES_BUFFER_LEN - format->name_offset; - bool terminated = false; - - for (unsigned i = 0; i < available; ++i) - { - const char c = name[i]; - name_copy[i] = c; - if (c == '\0') - { - terminated = true; - format->name_offset += (i + 1); - break; - } - } - -#if TRUST_NO_ONE - assert(terminated); - assert(format->name_offset <= VERTEX_ATTRIB_NAMES_BUFFER_LEN); -#endif - - return name_copy; - } - -unsigned add_attrib(VertexFormat* format, const char* name, VertexCompType comp_type, unsigned comp_ct, VertexFetchMode fetch_mode) - { -#if TRUST_NO_ONE - assert(format->attrib_ct < MAX_VERTEX_ATTRIBS); // there's room for more - assert(!format->packed); // packed means frozen/locked - assert(comp_ct >= 1 && comp_ct <= 4); - switch (comp_type) - { - case COMP_F32: - // float type can only kept as float - assert(fetch_mode == KEEP_FLOAT); - break; - #if USE_10_10_10 - case COMP_I10: - assert(comp_ct == 3); // 10_10_10 format intended for normals (xyz) or colors (rgb) - assert(fetch_mode == NORMALIZE_INT_TO_FLOAT); - break; - #endif - default: - // integer types can be kept as int or converted/normalized to float - assert(fetch_mode != KEEP_FLOAT); - } -#endif - - const unsigned attrib_id = format->attrib_ct++; - Attrib* attrib = format->attribs + attrib_id; - - attrib->name = copy_attrib_name(format, name); - attrib->comp_type = comp_type; -#if USE_10_10_10 - attrib->comp_ct = (comp_type == COMP_I10) ? 4 : comp_ct; // system needs 10_10_10_2 to be 4 or BGRA -#else - attrib->comp_ct = comp_ct; -#endif - attrib->sz = attrib_sz(attrib); - attrib->offset = 0; // offsets & stride are calculated later (during pack) - attrib->fetch_mode = fetch_mode; - - return attrib_id; - } - -unsigned padding(unsigned offset, unsigned alignment) - { - const unsigned mod = offset % alignment; - return (mod == 0) ? 0 : (alignment - mod); - } - -#if PACK_DEBUG -static void show_pack(unsigned a_idx, unsigned sz, unsigned pad) - { - const char c = 'A' + a_idx; - for (unsigned i = 0; i < pad; ++i) - putchar('-'); - for (unsigned i = 0; i < sz; ++i) - putchar(c); - } -#endif - -void VertexFormat_pack(VertexFormat* format) - { - // for now, attributes are packed in the order they were added, - // making sure each attrib is naturally aligned (add padding where necessary) - - // later we can implement more efficient packing w/ reordering - // (keep attrib 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 attribs, not all 16. - - Attrib* a0 = format->attribs + 0; - a0->offset = 0; - unsigned offset = a0->sz; - -#if PACK_DEBUG - show_pack(0, a0->sz, 0); -#endif - - for (unsigned a_idx = 1; a_idx < format->attrib_ct; ++a_idx) - { - Attrib* a = format->attribs + a_idx; - unsigned mid_padding = padding(offset, attrib_align(a)); - offset += mid_padding; - a->offset = offset; - offset += a->sz; - -#if PACK_DEBUG - show_pack(a_idx, a->sz, mid_padding); -#endif - } - - unsigned end_padding = padding(offset, attrib_align(a0)); - -#if PACK_DEBUG - show_pack(0, 0, end_padding); - putchar('\n'); -#endif - - format->stride = offset + end_padding; - format->packed = true; - } - - -#if USE_10_10_10 - -// OpenGL ES packs in a different order as desktop GL but component conversion is the same. -// Of the code here, only struct PackedNormal needs to change. - -#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); -#endif - - 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); - } - -PackedNormal convert_i10_v3(const float data[3]) - { - PackedNormal n = { .x = quantize(data[0]), .y = quantize(data[1]), .z = quantize(data[2]) }; - return n; - } - -#endif // USE_10_10_10 diff --git a/source/blender/gpu/gawain/vertex_format.h b/source/blender/gpu/gawain/vertex_format.h deleted file mode 100644 index 66477b0cfc7..00000000000 --- a/source/blender/gpu/gawain/vertex_format.h +++ /dev/null @@ -1,87 +0,0 @@ - -// Gawain vertex format -// -// This code is part of the Gawain library, with modifications -// specific to integration with Blender. -// -// Copyright 2016 Mike Erwin -// -// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of -// the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/. - -#pragma once - -#include "common.h" - -#define MAX_VERTEX_ATTRIBS 16 -#define AVG_VERTEX_ATTRIB_NAME_LEN 5 -#define VERTEX_ATTRIB_NAMES_BUFFER_LEN ((AVG_VERTEX_ATTRIB_NAME_LEN + 1) * MAX_VERTEX_ATTRIBS) - -#define USE_10_10_10 defined(_WIN32) -// (GLEW_VERSION_3_3 || GLEW_ARB_vertex_type_2_10_10_10_rev) -// ^-- this is only guaranteed on Windows right now, will be true on all platforms soon - -typedef enum { - COMP_I8 = GL_BYTE, - COMP_U8 = GL_UNSIGNED_BYTE, - COMP_I16 = GL_SHORT, - COMP_U16 = GL_UNSIGNED_SHORT, - COMP_I32 = GL_INT, - COMP_U32 = GL_UNSIGNED_INT, - - COMP_F32 = GL_FLOAT, // TODO: drop the GL_ equivalence here, use a private lookup table - -#if USE_10_10_10 - COMP_I10 = GL_INT_2_10_10_10_REV -#endif -} VertexCompType; - -typedef enum { - KEEP_FLOAT, - KEEP_INT, - NORMALIZE_INT_TO_FLOAT, // 127 (ubyte) -> 0.5 (and so on for other int types) - CONVERT_INT_TO_FLOAT // 127 (any int type) -> 127.0 -} VertexFetchMode; - -typedef struct { - VertexCompType comp_type; - unsigned comp_ct; // 1 to 4 - unsigned sz; // size in bytes, 1 to 16 - unsigned offset; // from beginning of vertex, in bytes - VertexFetchMode fetch_mode; - const char* name; -} Attrib; - -typedef struct { - unsigned attrib_ct; // 0 to 16 (MAX_VERTEX_ATTRIBS) - unsigned stride; // stride in bytes, 1 to 256 - bool packed; - Attrib attribs[MAX_VERTEX_ATTRIBS]; // TODO: variable-size attribs array - char names[VERTEX_ATTRIB_NAMES_BUFFER_LEN]; - unsigned name_offset; -} VertexFormat; - -void VertexFormat_clear(VertexFormat*); -void VertexFormat_copy(VertexFormat* dest, const VertexFormat* src); - -unsigned add_attrib(VertexFormat*, const char* name, VertexCompType, unsigned comp_ct, VertexFetchMode); - -// format conversion - -#if USE_10_10_10 - -typedef struct { - int x : 10; - int y : 10; - int z : 10; - int w : 2; // ignored for our purposes -} PackedNormal; - -PackedNormal convert_i10_v3(const float data[3]); - -#endif // USE_10_10_10 - -// for internal use -void VertexFormat_pack(VertexFormat*); -unsigned padding(unsigned offset, unsigned alignment); -unsigned vertex_buffer_size(const VertexFormat*, unsigned vertex_ct); diff --git a/source/blender/gpu/intern/gpu_basic_shader.c b/source/blender/gpu/intern/gpu_basic_shader.c index 757982d1b30..960181df545 100644 --- a/source/blender/gpu/intern/gpu_basic_shader.c +++ b/source/blender/gpu/intern/gpu_basic_shader.c @@ -159,24 +159,6 @@ const GLubyte stipple_hexagon[128] = { 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22}; /* ********************************************* */ -/* GLSL State */ - -static bool USE_GLSL = true; - -/** - * \note this isn't part of the basic shader API, - * only set from the command line once on startup. - */ -void GPU_basic_shader_use_glsl_set(bool enabled) -{ - USE_GLSL = enabled; -} - -bool GPU_basic_shader_use_glsl_get(void) -{ - return USE_GLSL; -} - /* Init / exit */ void GPU_basic_shaders_init(void) @@ -312,85 +294,16 @@ static void GPU_basic_shader_uniform_autoset(GPUShader *shader, int options) void GPU_basic_shader_bind(int options) { - if (USE_GLSL) { - if (options) { - GPUShader *shader = gpu_basic_shader(options); + if (options) { + GPUShader *shader = gpu_basic_shader(options); - if (shader) { - GPU_shader_bind(shader); - GPU_basic_shader_uniform_autoset(shader, options); - } - } - else { - GPU_shader_unbind(); + if (shader) { + GPU_shader_bind(shader); + GPU_basic_shader_uniform_autoset(shader, options); } } else { - const int bound_options = GPU_MATERIAL_STATE.bound_options; - - if (options & GPU_SHADER_LIGHTING) { - glEnable(GL_LIGHTING); - - if (options & GPU_SHADER_USE_COLOR) - glEnable(GL_COLOR_MATERIAL); - else - glDisable(GL_COLOR_MATERIAL); - - if (options & GPU_SHADER_TWO_SIDED) - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - else - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - } - else if (bound_options & GPU_SHADER_LIGHTING) { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - } - - if (options & GPU_SHADER_TEXTURE_2D) { - GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE; - glEnable(GL_TEXTURE_2D); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode); - } - else if (bound_options & GPU_SHADER_TEXTURE_2D) { - if ((options & GPU_SHADER_TEXTURE_RECT) == 0) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - glDisable(GL_TEXTURE_2D); - } - - if (options & GPU_SHADER_TEXTURE_RECT) { - GLint env_mode = (options & (GPU_SHADER_USE_COLOR | GPU_SHADER_LIGHTING)) ? GL_MODULATE : GL_REPLACE; - glEnable(GL_TEXTURE_RECTANGLE); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode); - } - else if (bound_options & GPU_SHADER_TEXTURE_RECT) { - if ((options & GPU_SHADER_TEXTURE_2D) == 0) { - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } - glDisable(GL_TEXTURE_RECTANGLE); - } - - if ((options & GPU_SHADER_LINE) && (options & GPU_SHADER_STIPPLE)) { - glEnable(GL_LINE_STIPPLE); - } - else if ((bound_options & GPU_SHADER_LINE) && (bound_options & GPU_SHADER_STIPPLE)) { - glDisable(GL_LINE_STIPPLE); - } - - if (((options & GPU_SHADER_LINE) == 0) && (options & GPU_SHADER_STIPPLE)) { - glEnable(GL_POLYGON_STIPPLE); - } - else if (((bound_options & GPU_SHADER_LINE) == 0) && (bound_options & GPU_SHADER_STIPPLE)) { - glDisable(GL_POLYGON_STIPPLE); - } - - if (options & GPU_SHADER_FLAT_NORMAL) { - glShadeModel(GL_FLAT); - } - else if (bound_options & GPU_SHADER_FLAT_NORMAL) { - glShadeModel(GL_SMOOTH); - } + GPU_shader_unbind(); } GPU_MATERIAL_STATE.bound_options = options; @@ -500,14 +413,12 @@ void GPU_basic_shader_light_set(int light_num, GPULightData *light) } else { /* TODO(sergey): Needs revisit. */ - if (USE_GLSL || true) { - /* glsl shader needs these zero to skip them */ - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + /* glsl shader needs these zero to skip them */ + const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero); - glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero); - glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero); - } + glLightfv(GL_LIGHT0 + light_num, GL_POSITION, zero); + glLightfv(GL_LIGHT0 + light_num, GL_DIFFUSE, zero); + glLightfv(GL_LIGHT0 + light_num, GL_SPECULAR, zero); glDisable(GL_LIGHT0 + light_num); } @@ -520,56 +431,19 @@ void GPU_basic_shader_light_set_viewer(bool local) void GPU_basic_shader_stipple(GPUBasicShaderStipple stipple_id) { - if (USE_GLSL) { - glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id); - } - else { - switch (stipple_id) { - case GPU_SHADER_STIPPLE_HALFTONE: - glPolygonStipple(stipple_halftone); - return; - case GPU_SHADER_STIPPLE_QUARTTONE: - glPolygonStipple(stipple_quarttone); - return; - case GPU_SHADER_STIPPLE_CHECKER_8PX: - glPolygonStipple(stipple_checker_8px); - return; - case GPU_SHADER_STIPPLE_HEXAGON: - glPolygonStipple(stipple_hexagon); - return; - case GPU_SHADER_STIPPLE_DIAG_STRIPES_SWAP: - glPolygonStipple(stipple_diag_stripes_neg); - return; - case GPU_SHADER_STIPPLE_DIAG_STRIPES: - glPolygonStipple(stipple_diag_stripes_pos); - return; - default: - glPolygonStipple(stipple_hexagon); - return; - } - } + glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_id"), stipple_id); } void GPU_basic_shader_line_width(float line_width) { - if (USE_GLSL) { - GPU_MATERIAL_STATE.line_width = line_width; - if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) { - glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width); - } - } - else { - glLineWidth(line_width); + GPU_MATERIAL_STATE.line_width = line_width; + if (GPU_MATERIAL_STATE.bound_options & GPU_SHADER_LINE) { + glUniform1f(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "line_width"), line_width); } } void GPU_basic_shader_line_stipple(GLint stipple_factor, GLushort stipple_pattern) { - if (USE_GLSL) { - glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor); - glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern); - } - else { - glLineStipple(stipple_factor, stipple_pattern); - } + glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_factor"), stipple_factor); + glUniform1i(GPU_shader_get_uniform(gpu_basic_shader(GPU_MATERIAL_STATE.bound_options), "stipple_pattern"), stipple_pattern); } diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c index 716c5e55b3c..65a827febde 100644 --- a/source/blender/gpu/intern/gpu_batch.c +++ b/source/blender/gpu/intern/gpu_batch.c @@ -31,7 +31,7 @@ #include "GPU_batch.h" #include "gpu_shader_private.h" -void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id) +void Batch_set_builtin_program(Batch *batch, GPUBuiltinShader shader_id) { GPUShader *shader = GPU_shader_get_builtin_shader(shader_id); Batch_set_program(batch, shader->program); @@ -40,6 +40,8 @@ void Batch_set_builtin_program(Batch* batch, GPUBuiltinShader shader_id) static Batch *sphere_high = NULL; static Batch *sphere_med = NULL; static Batch *sphere_low = NULL; +static Batch *sphere_wire_low = NULL; +static Batch *sphere_wire_med = NULL; static VertexBuffer *vbo; static VertexFormat format = {0}; @@ -70,23 +72,23 @@ static Batch *batch_sphere(int lat_res, int lon_res) } vbo = VertexBuffer_create_with_format(&format); - VertexBuffer_allocate_data(vbo, (lat_res-1) * lon_res * 6); + VertexBuffer_allocate_data(vbo, (lat_res - 1) * lon_res * 6); vert = 0; lon = 0.0f; - for(int i = 0; i < lon_res; i++, lon += lon_inc) { + 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) { + for (int j = 0; j < lat_res; j++, lat += lat_inc) { if (j != lat_res - 1) { /* Pole */ - batch_sphere_lat_lon_vert(lat, lon); - batch_sphere_lat_lon_vert(lat+lat_inc, lon); - batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc); + batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(lat + lat_inc, lon); + batch_sphere_lat_lon_vert(lat, lon); } if (j != 0) { /* Pole */ - batch_sphere_lat_lon_vert(lat, lon); - batch_sphere_lat_lon_vert(lat+lat_inc, lon+lon_inc); - batch_sphere_lat_lon_vert(lat, lon+lon_inc); + batch_sphere_lat_lon_vert(lat, lon + lon_inc); + batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(lat, lon); } } } @@ -94,6 +96,38 @@ static Batch *batch_sphere(int lat_res, int lon_res) return Batch_create(GL_TRIANGLES, vbo, NULL); } +static Batch *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; + + if (format.attrib_ct == 0) { + pos_id = add_attrib(&format, "pos", GL_FLOAT, 3, KEEP_FLOAT); + nor_id = add_attrib(&format, "nor", GL_FLOAT, 3, KEEP_FLOAT); + } + + vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, (lat_res * lon_res * 2) + ((lat_res - 1) * lon_res * 2)); + vert = 0; + + 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(lat + lat_inc, lon); + batch_sphere_lat_lon_vert(lat, lon); + + if (j != lat_res - 1) { /* Pole */ + batch_sphere_lat_lon_vert(lat + lat_inc, lon + lon_inc); + batch_sphere_lat_lon_vert(lat + lat_inc, lon); + } + } + } + + return Batch_create(GL_LINES, vbo, NULL); +} + Batch *Batch_get_sphere(int lod) { BLI_assert(lod >= 0 && lod <= 2); @@ -106,12 +140,25 @@ Batch *Batch_get_sphere(int lod) return sphere_high; } +Batch *Batch_get_sphere_wire(int lod) +{ + BLI_assert(lod >= 0 && lod <= 1); + + if (lod == 0) + return sphere_wire_low; + else + return sphere_wire_med; +} + void gpu_batch_init(void) { /* Hard coded resolution */ - sphere_low = batch_sphere(8, 8); + sphere_low = batch_sphere(8, 16); sphere_med = batch_sphere(16, 10); sphere_high = batch_sphere(32, 24); + + sphere_wire_low = batch_sphere_wire(6, 8); + sphere_wire_med = batch_sphere_wire(8, 16); } void gpu_batch_exit(void) @@ -119,4 +166,6 @@ void gpu_batch_exit(void) Batch_discard_all(sphere_low); Batch_discard_all(sphere_med); Batch_discard_all(sphere_high); + Batch_discard_all(sphere_wire_low); + Batch_discard_all(sphere_wire_med); } diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index 370841327aa..6492cf90929 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -56,6 +56,7 @@ #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_basic_shader.h" +#include "GPU_immediate.h" #include "bmesh.h" @@ -2033,59 +2034,57 @@ void GPU_free_pbvh_buffer_multires(GridCommonGPUBuffer **grid_common_gpu_buffer) } /* debug function, draws the pbvh BB */ -void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf) +void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf, unsigned int pos) { - const float quads[4][4][3] = { - { - {min[0], min[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {min[0], min[1], max[2]} - }, - - { - {min[0], min[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {min[0], min[1], max[2]} - }, - - { - {max[0], max[1], min[2]}, - {max[0], min[1], min[2]}, - {max[0], min[1], max[2]}, - {max[0], max[1], max[2]} - }, - - { - {max[0], max[1], min[2]}, - {min[0], max[1], min[2]}, - {min[0], max[1], max[2]}, - {max[0], max[1], max[2]} - }, - }; - if (leaf) - glColor4f(0.0, 1.0, 0.0, 0.5); + immUniformColor4f(0.0, 1.0, 0.0, 0.5); else - glColor4f(1.0, 0.0, 0.0, 0.5); + immUniformColor4f(1.0, 0.0, 0.0, 0.5); - glVertexPointer(3, GL_FLOAT, 0, &quads[0][0][0]); - glDrawArrays(GL_QUADS, 0, 16); -} + /* TODO(merwin): revisit this after we have mutable VertexBuffers + * could keep a static batch & index buffer, change the VBO contents per draw + */ -void GPU_init_draw_pbvh_BB(void) -{ - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_CULL_FACE); - glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - glEnable(GL_BLEND); -} + immBegin(PRIM_LINES, 24); -void GPU_end_draw_pbvh_BB(void) -{ - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - glPopAttrib(); + /* 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, 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]); + + /* 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, 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]); + + /* 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, 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]); + + immEnd(); } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 4223ec54f74..df3b6f962e5 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -360,7 +360,7 @@ static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data) BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]); for (i = 0; i < type; i++) { - BLI_dynstr_appendf(ds, "%f", data[i]); + BLI_dynstr_appendf(ds, "%.12f", data[i]); if (i == type - 1) BLI_dynstr_append(ds, ")"); else @@ -653,7 +653,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final BLI_dynstr_append(ds, ");\n"); } - BLI_dynstr_append(ds, "\n\tgl_FragColor = "); + BLI_dynstr_append(ds, "\n\tfragColor = "); codegen_convert_datatype(ds, finaloutput->type, GPU_VEC4, "tmp", finaloutput->id); BLI_dynstr_append(ds, ";\n"); } @@ -788,7 +788,7 @@ static char *code_generate_vertex(ListBase *nodes, const GPUMatType type) BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n"); #endif BLI_dynstr_appendf( - ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", + ds, "\tvar%d.xyz = normalize(NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid); BLI_dynstr_appendf( ds, "\tvar%d.w = att%d.w;\n", diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c index 528bdefc209..5214b6b1ab7 100644 --- a/source/blender/gpu/intern/gpu_compositing.c +++ b/source/blender/gpu/intern/gpu_compositing.c @@ -47,6 +47,7 @@ #include "GPU_glew.h" #include "GPU_shader.h" #include "GPU_texture.h" +#include "GPU_batch.h" #include "MEM_guardedalloc.h" @@ -193,7 +194,8 @@ struct GPUFX { /* we have a stencil, restore the previous state */ bool restore_stencil; - unsigned int vbuffer; + Batch *quad_batch; + Batch *point_batch; }; #if 0 @@ -269,12 +271,32 @@ GPUFX *GPU_fx_compositor_create(void) { GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor"); - glGenBuffers(1, &fx->vbuffer); - glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer); - glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), NULL, GL_STATIC_DRAW); - glBufferSubData(GL_ARRAY_BUFFER, 0, 8 * sizeof(float), fullscreencos); - glBufferSubData(GL_ARRAY_BUFFER, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs); - glBindBuffer(GL_ARRAY_BUFFER, 0); + /* Quad buffer */ + static VertexFormat format = {0}; + static unsigned int pos, uvs; + if (format.attrib_ct == 0) { + pos = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + uvs = add_attrib(&format, "uvs", GL_FLOAT, 2, KEEP_FLOAT); + } + VertexBuffer *vbo = VertexBuffer_create_with_format(&format); + VertexBuffer_allocate_data(vbo, 4); + for (int i = 0; i < 4; ++i) { + setAttrib(vbo, pos, i, fullscreencos[i]); + setAttrib(vbo, uvs, i, fullscreenuvs[i]); + } + fx->quad_batch = Batch_create(GL_TRIANGLE_STRIP, vbo, NULL); + + /* Point Buffer */ + static VertexFormat format_point = {0}; + static unsigned int dummy_attrib; + if (format_point.attrib_ct == 0) { + dummy_attrib = add_attrib(&format_point, "pos", GL_FLOAT, 2, KEEP_FLOAT); + } + float dummy[2] = {0.0f, 0.0f}; + VertexBuffer *vbo_point = VertexBuffer_create_with_format(&format_point); + VertexBuffer_allocate_data(vbo_point, 1); + setAttrib(vbo_point, dummy_attrib, 0, &dummy); + fx->point_batch = Batch_create(GL_POINTS, vbo_point, NULL); return fx; } @@ -364,7 +386,8 @@ static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo) void GPU_fx_compositor_destroy(GPUFX *fx) { cleanup_fx_gl_data(fx, true); - glDeleteBuffers(1, &fx->vbuffer); + Batch_discard_all(fx->quad_batch); + Batch_discard_all(fx->point_batch); MEM_freeN(fx); } @@ -702,19 +725,13 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) /* disable writing to color buffer, it's depth only pass */ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - /* set up quad buffer */ - glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer); - glVertexPointer(2, GL_FLOAT, 0, NULL); - glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float))); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - depth_resolve_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_RESOLVE, false); if (depth_resolve_shader) { - GPUDepthResolveInterface *interface = GPU_shader_get_interface(depth_resolve_shader); + GPUDepthResolveInterface *interface = GPU_fx_shader_get_interface(depth_resolve_shader); - GPU_shader_bind(depth_resolve_shader); + /* set up quad buffer */ + Batch_set_program(fx->quad_batch, GPU_shader_get_program(depth_resolve_shader)); GPU_texture_bind(fx->depth_buffer_xray, 0); GPU_texture_compare_mode(fx->depth_buffer_xray, false); @@ -722,7 +739,7 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) GPU_shader_uniform_texture(depth_resolve_shader, interface->depth_uniform, fx->depth_buffer_xray); /* draw */ - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_compare_mode(fx->depth_buffer_xray, true); @@ -734,10 +751,6 @@ void GPU_fx_compositor_XRay_resolve(GPUFX *fx) glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glPopAttrib(); } @@ -774,13 +787,6 @@ bool GPU_fx_do_composite_pass( src = fx->color_buffer; target = fx->color_buffer_sec; - /* set up quad buffer */ - glBindBuffer(GL_ARRAY_BUFFER, fx->vbuffer); - glVertexPointer(2, GL_FLOAT, 0, NULL); - glTexCoordPointer(2, GL_FLOAT, 0, ((GLubyte *)NULL + 8 * sizeof(float))); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - /* full screen FX pass */ /* invert the view matrix */ @@ -808,8 +814,6 @@ bool GPU_fx_do_composite_pass( viewvecs[1][2] = vec_far[2] - viewvecs[0][2]; } - /* set invalid color in case shader fails */ - glColor3f(1.0, 0.0, 1.0); glDisable(GL_DEPTH_TEST); /* ssao pass */ @@ -828,9 +832,9 @@ bool GPU_fx_do_composite_pass( ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1]; - GPUSSAOShaderInterface *interface = GPU_shader_get_interface(ssao_shader); + GPUSSAOShaderInterface *interface = GPU_fx_shader_get_interface(ssao_shader); - GPU_shader_bind(ssao_shader); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(ssao_shader)); GPU_shader_uniform_vector(ssao_shader, interface->ssao_uniform, 4, 1, ssao_params); GPU_shader_uniform_vector(ssao_shader, interface->ssao_color_uniform, 4, 1, fx_ssao->color); @@ -854,7 +858,7 @@ bool GPU_fx_do_composite_pass( /* draw */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(src); @@ -912,11 +916,8 @@ bool GPU_fx_do_composite_pass( if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3)) { GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); GPU_framebuffer_restore(); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); - glBindBuffer(GL_ARRAY_BUFFER, 0); return false; } @@ -924,9 +925,9 @@ bool GPU_fx_do_composite_pass( { float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; - GPUDOFHQPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1); + GPUDOFHQPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1); - GPU_shader_bind(dof_shader_pass1); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1)); GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim); @@ -953,7 +954,8 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_check_valid(fx->gbuffer, NULL); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); + /* disable bindings */ GPU_texture_filter_mode(src, true); GPU_texture_unbind(src); @@ -975,19 +977,18 @@ bool GPU_fx_do_composite_pass( int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h}; float selection[2] = {0.0f, 1.0f}; - GPUDOFHQPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2); + GPUDOFHQPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2); - GPU_shader_bind(dof_shader_pass2); + Batch_set_program(fx->point_batch, GPU_shader_get_program(dof_shader_pass2)); + + GPU_texture_bind(fx->dof_nearfar_coc, numslots++); + GPU_texture_bind(fx->dof_half_downsampled_far, numslots++); + GPU_texture_bind(fx->dof_half_downsampled_near, numslots++); GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector_int(dof_shader_pass2, interface->rendertargetdim_uniform, 2, 1, rendertargetdim); GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection); - - GPU_texture_bind(fx->dof_nearfar_coc, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, interface->coc_uniform, fx->dof_nearfar_coc); - - GPU_texture_bind(fx->dof_half_downsampled_far, numslots++); - GPU_texture_bind(fx->dof_half_downsampled_near, numslots++); GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_far); GPU_texture_filter_mode(fx->dof_half_downsampled_far, false); @@ -1003,24 +1004,24 @@ bool GPU_fx_do_composite_pass( glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ - glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + Batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL); GPU_texture_unbind(fx->dof_half_downsampled_far); GPU_framebuffer_texture_detach(fx->dof_far_blur); - GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near); - GPU_texture_filter_mode(fx->dof_half_downsampled_near, false); - selection[0] = 1.0f; selection[1] = 0.0f; GPU_shader_uniform_vector(dof_shader_pass2, interface->select_uniform, 2, 1, selection); + GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_half_downsampled_near); + GPU_texture_filter_mode(fx->dof_half_downsampled_near, false); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0); /* have to clear the buffer unfortunately */ glClear(GL_COLOR_BUFFER_BIT); /* the draw call we all waited for, draw a point per pixel, scaled per circle of confusion */ - glDrawArraysInstancedARB(GL_POINTS, 0, 1, fx->dof_downsampled_w * fx->dof_downsampled_h); + Batch_draw_stupid_instanced(fx->point_batch, 0, fx->dof_downsampled_w * fx->dof_downsampled_h, 0, 0, NULL, NULL); + Batch_done_using_program(fx->point_batch); /* disable bindings */ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1032,15 +1033,16 @@ bool GPU_fx_do_composite_pass( GPU_texture_unbind(fx->dof_nearfar_coc); GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur); + numslots = 0; } /* third pass, accumulate the near/far blur fields */ { float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h}; - GPUDOFHQPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3); + GPUDOFHQPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3); - GPU_shader_bind(dof_shader_pass3); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3)); GPU_shader_uniform_vector(dof_shader_pass3, interface->dof_uniform, 4, 1, dof_params); @@ -1066,7 +1068,7 @@ bool GPU_fx_do_composite_pass( /* if this is the last pass, prepare for rendering on the frambuffer */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(fx->dof_near_blur); @@ -1108,11 +1110,8 @@ bool GPU_fx_do_composite_pass( if (!(dof_shader_pass1 && dof_shader_pass2 && dof_shader_pass3 && dof_shader_pass4 && dof_shader_pass5)) { GPU_framebuffer_texture_unbind(fx->gbuffer, NULL); GPU_framebuffer_restore(); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); GPU_shader_unbind(); - glBindBuffer(GL_ARRAY_BUFFER, 0); return false; } @@ -1120,9 +1119,9 @@ bool GPU_fx_do_composite_pass( { float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; - GPUDOFPassOneInterface *interface = GPU_shader_get_interface(dof_shader_pass1); + GPUDOFPassOneInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass1); - GPU_shader_bind(dof_shader_pass1); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass1)); GPU_shader_uniform_vector(dof_shader_pass1, interface->dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass1, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim); @@ -1141,7 +1140,7 @@ bool GPU_fx_do_composite_pass( /* binding takes care of setting the viewport to the downsampled size */ GPU_texture_bind_as_framebuffer(fx->dof_near_coc_buffer); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(src); GPU_texture_compare_mode(fx->depth_buffer, true); @@ -1159,12 +1158,12 @@ bool GPU_fx_do_composite_pass( float tmp = invrendertargetdim[0]; invrendertargetdim[0] = 0.0f; - GPUDOFPassTwoInterface *interface = GPU_shader_get_interface(dof_shader_pass2); + GPUDOFPassTwoInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass2); dof_params[2] = GPU_texture_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor); /* Blurring vertically */ - GPU_shader_bind(dof_shader_pass2); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2)); GPU_shader_uniform_vector(dof_shader_pass2, interface->dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass2, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim); @@ -1182,10 +1181,14 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0); /* Drawing quad */ - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); + + /* Rebind Shader */ + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass2)); /* *unbind/detach */ GPU_texture_unbind(fx->dof_near_coc_buffer); + GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer); /* Blurring horizontally */ @@ -1197,7 +1200,8 @@ bool GPU_fx_do_composite_pass( GPU_shader_uniform_texture(dof_shader_pass2, interface->color_uniform, fx->dof_near_coc_final_buffer); GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + Batch_draw(fx->quad_batch); /* *unbind/detach */ GPU_texture_compare_mode(fx->depth_buffer, true); @@ -1214,9 +1218,9 @@ bool GPU_fx_do_composite_pass( /* third pass, calculate near coc */ { - GPUDOFPassThreeInterface *interface = GPU_shader_get_interface(dof_shader_pass3); + GPUDOFPassThreeInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass3); - GPU_shader_bind(dof_shader_pass3); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass3)); GPU_texture_bind(fx->dof_near_coc_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass3, interface->near_coc_downsampled, fx->dof_near_coc_buffer); @@ -1226,7 +1230,7 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); @@ -1242,9 +1246,9 @@ bool GPU_fx_do_composite_pass( float invrendertargetdim[2] = {1.0f / GPU_texture_width(fx->dof_near_coc_blurred_buffer), 1.0f / GPU_texture_height(fx->dof_near_coc_blurred_buffer)}; - GPUDOFPassFourInterface *interface = GPU_shader_get_interface(dof_shader_pass4); + GPUDOFPassFourInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass4); - GPU_shader_bind(dof_shader_pass4); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass4)); GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++); GPU_shader_uniform_texture(dof_shader_pass4, interface->near_coc_downsampled, fx->dof_near_coc_final_buffer); @@ -1252,7 +1256,7 @@ bool GPU_fx_do_composite_pass( GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_final_buffer); @@ -1267,9 +1271,9 @@ bool GPU_fx_do_composite_pass( { float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]}; - GPUDOFPassFiveInterface *interface = GPU_shader_get_interface(dof_shader_pass5); + GPUDOFPassFiveInterface *interface = GPU_fx_shader_get_interface(dof_shader_pass5); - GPU_shader_bind(dof_shader_pass5); + Batch_set_program(fx->quad_batch, GPU_shader_get_program(dof_shader_pass5)); GPU_shader_uniform_vector(dof_shader_pass5, interface->dof_uniform, 4, 1, dof_params); GPU_shader_uniform_vector(dof_shader_pass5, interface->invrendertargetdim_uniform, 2, 1, invrendertargetdim); @@ -1292,7 +1296,7 @@ bool GPU_fx_do_composite_pass( /* if this is the last pass, prepare for rendering on the frambuffer */ gpu_fx_bind_render_target(&passes_left, fx, ofs, target); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + Batch_draw(fx->quad_batch); /* disable bindings */ GPU_texture_unbind(fx->dof_near_coc_buffer); GPU_texture_unbind(fx->dof_near_coc_blurred_buffer); @@ -1318,10 +1322,6 @@ bool GPU_fx_do_composite_pass( } } - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glBindBuffer(GL_ARRAY_BUFFER, 0); - GPU_shader_unbind(); return true; @@ -1363,7 +1363,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->ssao_concentric_tex = GPU_shader_get_uniform(shader, "ssao_concentric_tex"); interface->ssao_jitter_uniform = GPU_shader_get_uniform(shader, "jitter_tex"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } @@ -1377,7 +1377,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } @@ -1391,7 +1391,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->select_uniform = GPU_shader_get_uniform(shader, "layerselection"); interface->dof_uniform = GPU_shader_get_uniform(shader, "dof_params"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } @@ -1407,7 +1407,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs"); interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } @@ -1421,7 +1421,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO: @@ -1434,7 +1434,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE: @@ -1444,7 +1444,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer"); interface->near_coc_blurred = GPU_shader_get_uniform(shader, "blurredcolorbuffer"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR: @@ -1454,7 +1454,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->near_coc_downsampled = GPU_shader_get_uniform(shader, "colorbuffer"); interface->invrendertargetdim_uniform = GPU_shader_get_uniform(shader, "invrendertargetdim"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE: @@ -1469,7 +1469,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); interface->viewvecs_uniform = GPU_shader_get_uniform(shader, "viewvecs"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } @@ -1479,7 +1479,7 @@ void GPU_fx_shader_init_interface(struct GPUShader *shader, GPUFXShaderEffect ef interface->depth_uniform = GPU_shader_get_uniform(shader, "depthbuffer"); - GPU_shader_set_interface(shader, interface); + GPU_fx_shader_set_interface(shader, interface); break; } diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c index e306394c4c3..eeeb6e0ab33 100644 --- a/source/blender/gpu/intern/gpu_debug.c +++ b/source/blender/gpu/intern/gpu_debug.c @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): Brecht Van Lommel, Jason Wilkins. + * Contributor(s): Brecht Van Lommel, Jason Wilkins, Mike Erwin. * * ***** END GPL LICENSE BLOCK ***** */ @@ -43,19 +43,21 @@ #include <stdlib.h> #include <string.h> -/* control whether we use older AMD_debug_output extension, or just the newer extensions - * TODO(merwin): determine whether all supported GPU + OS combos have newer extensions */ -#define LEGACY_DEBUG 0 +#ifndef __APPLE__ /* only non-Apple systems implement OpenGL debug callbacks */ + +/* control whether we use older AMD_debug_output extension + * some supported GPU + OS combos do not have the newer extensions */ +# define LEGACY_DEBUG 1 /* Debug callbacks need the same calling convention as OpenGL functions. */ -#if defined(_WIN32) -# define APIENTRY __stdcall -#else -# define APIENTRY -#endif +# if defined(_WIN32) +# define APIENTRY __stdcall +# else +# define APIENTRY +# endif -static const char* source_name(GLenum source) +static const char *source_name(GLenum source) { switch (source) { case GL_DEBUG_SOURCE_API: return "API"; @@ -68,7 +70,7 @@ static const char* source_name(GLenum source) } } -static const char* message_type_name(GLenum message) +static const char *message_type_name(GLenum message) { switch (message) { case GL_DEBUG_TYPE_ERROR: return "error"; @@ -105,9 +107,9 @@ static void APIENTRY gpu_debug_proc( } } -#if LEGACY_DEBUG +# if LEGACY_DEBUG -static const char* category_name_amd(GLenum category) +static const char *category_name_amd(GLenum category) { switch (category) { case GL_DEBUG_CATEGORY_API_ERROR_AMD: return "API error"; @@ -143,12 +145,16 @@ static void APIENTRY gpu_debug_proc_amd( fflush(stderr); } } -#endif /* LEGACY_DEBUG */ +# endif /* LEGACY_DEBUG */ -#undef APIENTRY +# undef APIENTRY +#endif /* not Apple */ void gpu_debug_init(void) { +#ifdef __APPLE__ + 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) { @@ -166,37 +172,43 @@ void gpu_debug_init(void) glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); GPU_string_marker(success); } -#if LEGACY_DEBUG +# if LEGACY_DEBUG else if (GLEW_AMD_debug_output) { fprintf(stderr, "Using AMD_debug_output extension\n"); glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext()); glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE); GPU_string_marker(success); } -#endif +# endif 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 LEGACY_DEBUG +# if LEGACY_DEBUG else if (GLEW_AMD_debug_output) { glDebugMessageCallbackAMD(NULL, NULL); } +# endif #endif } void GPU_string_marker(const char *buf) { +#ifdef __APPLE__ + UNUSED_VARS(buf); +#else /* not Apple */ if (GLEW_VERSION_4_3 || GLEW_KHR_debug) { glDebugMessageInsert( GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, @@ -207,13 +219,14 @@ void GPU_string_marker(const char *buf) GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, -1, buf); } -#if LEGACY_DEBUG +# if LEGACY_DEBUG else if (GLEW_AMD_debug_output) { glDebugMessageInsertAMD( GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, 0, buf); } -#endif +# endif +#endif /* not Apple */ } void GPU_print_error_debug(const char *str) @@ -221,390 +234,3 @@ void GPU_print_error_debug(const char *str) if (G.debug & G_DEBUG) fprintf(stderr, "GPU: %s\n", str); } - -static void gpu_state_print_fl_ex(const char *name, GLenum type) -{ - const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff}; - - float value[32]; - int a; - - memset(value, 0xff, sizeof(value)); - glGetFloatv(type, value); - - if (glGetError() == GL_NO_ERROR) { - printf("%s: ", name); - for (a = 0; a < 32; a++) { - if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) { - break; - } - printf("%.2f ", value[a]); - } - printf("\n"); - } -} - -#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val) - -void GPU_state_print(void) -{ - /* clear any errors */ - while (glGetError() != GL_NO_ERROR) {} - - gpu_state_print_fl(GL_ACCUM_ALPHA_BITS); - gpu_state_print_fl(GL_ACCUM_BLUE_BITS); - gpu_state_print_fl(GL_ACCUM_CLEAR_VALUE); - gpu_state_print_fl(GL_ACCUM_GREEN_BITS); - gpu_state_print_fl(GL_ACCUM_RED_BITS); - gpu_state_print_fl(GL_ACTIVE_TEXTURE); - gpu_state_print_fl(GL_ALIASED_LINE_WIDTH_RANGE); - gpu_state_print_fl(GL_ALIASED_POINT_SIZE_RANGE); - gpu_state_print_fl(GL_ALPHA_BIAS); - gpu_state_print_fl(GL_ALPHA_BITS); - gpu_state_print_fl(GL_ALPHA_SCALE); - gpu_state_print_fl(GL_ALPHA_TEST); - gpu_state_print_fl(GL_ALPHA_TEST_FUNC); - gpu_state_print_fl(GL_ALPHA_TEST_REF); - gpu_state_print_fl(GL_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_ATTRIB_STACK_DEPTH); - gpu_state_print_fl(GL_AUTO_NORMAL); - gpu_state_print_fl(GL_AUX_BUFFERS); - gpu_state_print_fl(GL_BLEND); - gpu_state_print_fl(GL_BLEND_COLOR); - gpu_state_print_fl(GL_BLEND_DST_ALPHA); - gpu_state_print_fl(GL_BLEND_DST_RGB); - gpu_state_print_fl(GL_BLEND_EQUATION_ALPHA); - gpu_state_print_fl(GL_BLEND_EQUATION_RGB); - gpu_state_print_fl(GL_BLEND_SRC_ALPHA); - gpu_state_print_fl(GL_BLEND_SRC_RGB); - gpu_state_print_fl(GL_BLUE_BIAS); - gpu_state_print_fl(GL_BLUE_BITS); - gpu_state_print_fl(GL_BLUE_SCALE); - gpu_state_print_fl(GL_CLIENT_ACTIVE_TEXTURE); - gpu_state_print_fl(GL_CLIENT_ATTRIB_STACK_DEPTH); - gpu_state_print_fl(GL_CLIP_PLANE0); - gpu_state_print_fl(GL_COLOR_ARRAY); - gpu_state_print_fl(GL_COLOR_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_COLOR_ARRAY_SIZE); - gpu_state_print_fl(GL_COLOR_ARRAY_STRIDE); - gpu_state_print_fl(GL_COLOR_ARRAY_TYPE); - gpu_state_print_fl(GL_COLOR_CLEAR_VALUE); - gpu_state_print_fl(GL_COLOR_LOGIC_OP); - gpu_state_print_fl(GL_COLOR_MATERIAL); - gpu_state_print_fl(GL_COLOR_MATERIAL_FACE); - gpu_state_print_fl(GL_COLOR_MATERIAL_PARAMETER); - gpu_state_print_fl(GL_COLOR_MATRIX); - gpu_state_print_fl(GL_COLOR_MATRIX_STACK_DEPTH); - gpu_state_print_fl(GL_COLOR_SUM); - gpu_state_print_fl(GL_COLOR_TABLE); - gpu_state_print_fl(GL_COLOR_WRITEMASK); - gpu_state_print_fl(GL_COMPRESSED_TEXTURE_FORMATS); - gpu_state_print_fl(GL_CONVOLUTION_1D); - gpu_state_print_fl(GL_CONVOLUTION_2D); - gpu_state_print_fl(GL_CULL_FACE); - gpu_state_print_fl(GL_CULL_FACE_MODE); - gpu_state_print_fl(GL_CURRENT_COLOR); - gpu_state_print_fl(GL_CURRENT_FOG_COORD); - gpu_state_print_fl(GL_CURRENT_INDEX); - gpu_state_print_fl(GL_CURRENT_NORMAL); - gpu_state_print_fl(GL_CURRENT_PROGRAM); - gpu_state_print_fl(GL_CURRENT_RASTER_COLOR); - gpu_state_print_fl(GL_CURRENT_RASTER_DISTANCE); - gpu_state_print_fl(GL_CURRENT_RASTER_INDEX); - gpu_state_print_fl(GL_CURRENT_RASTER_POSITION); - gpu_state_print_fl(GL_CURRENT_RASTER_POSITION_VALID); - gpu_state_print_fl(GL_CURRENT_RASTER_SECONDARY_COLOR); - gpu_state_print_fl(GL_CURRENT_RASTER_TEXTURE_COORDS); - gpu_state_print_fl(GL_CURRENT_SECONDARY_COLOR); - gpu_state_print_fl(GL_CURRENT_TEXTURE_COORDS); - gpu_state_print_fl(GL_DEPTH_BIAS); - gpu_state_print_fl(GL_DEPTH_BITS); - gpu_state_print_fl(GL_DEPTH_CLEAR_VALUE); - gpu_state_print_fl(GL_DEPTH_FUNC); - gpu_state_print_fl(GL_DEPTH_RANGE); - gpu_state_print_fl(GL_DEPTH_SCALE); - gpu_state_print_fl(GL_DEPTH_TEST); - gpu_state_print_fl(GL_DEPTH_WRITEMASK); - gpu_state_print_fl(GL_DITHER); - gpu_state_print_fl(GL_DOUBLEBUFFER); - gpu_state_print_fl(GL_DRAW_BUFFER); - gpu_state_print_fl(GL_DRAW_BUFFER0); - gpu_state_print_fl(GL_EDGE_FLAG); - gpu_state_print_fl(GL_EDGE_FLAG_ARRAY); - gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_EDGE_FLAG_ARRAY_STRIDE); - gpu_state_print_fl(GL_ELEMENT_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_FEEDBACK_BUFFER_SIZE); - gpu_state_print_fl(GL_FEEDBACK_BUFFER_TYPE); - gpu_state_print_fl(GL_FOG); - gpu_state_print_fl(GL_FOG_COLOR); - gpu_state_print_fl(GL_FOG_COORD_ARRAY); - gpu_state_print_fl(GL_FOG_COORD_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_FOG_COORD_ARRAY_STRIDE); - gpu_state_print_fl(GL_FOG_COORD_ARRAY_TYPE); - gpu_state_print_fl(GL_FOG_COORD_SRC); - gpu_state_print_fl(GL_FOG_DENSITY); - gpu_state_print_fl(GL_FOG_END); - gpu_state_print_fl(GL_FOG_HINT); - gpu_state_print_fl(GL_FOG_INDEX); - gpu_state_print_fl(GL_FOG_MODE); - gpu_state_print_fl(GL_FOG_START); - gpu_state_print_fl(GL_FRAGMENT_PROGRAM_ARB); /* TODO: remove ARB program support */ - gpu_state_print_fl(GL_FRAGMENT_SHADER_DERIVATIVE_HINT); - gpu_state_print_fl(GL_FRONT_FACE); - gpu_state_print_fl(GL_GENERATE_MIPMAP_HINT); - gpu_state_print_fl(GL_GREEN_BIAS); - gpu_state_print_fl(GL_GREEN_BITS); - gpu_state_print_fl(GL_GREEN_SCALE); - gpu_state_print_fl(GL_HISTOGRAM); - gpu_state_print_fl(GL_INDEX_ARRAY); - gpu_state_print_fl(GL_INDEX_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_INDEX_ARRAY_STRIDE); - gpu_state_print_fl(GL_INDEX_ARRAY_TYPE); - gpu_state_print_fl(GL_INDEX_BITS); - gpu_state_print_fl(GL_INDEX_CLEAR_VALUE); - gpu_state_print_fl(GL_INDEX_LOGIC_OP); - gpu_state_print_fl(GL_INDEX_MODE); - gpu_state_print_fl(GL_INDEX_OFFSET); - gpu_state_print_fl(GL_INDEX_SHIFT); - gpu_state_print_fl(GL_INDEX_WRITEMASK); - gpu_state_print_fl(GL_LIGHT0); - gpu_state_print_fl(GL_LIGHT1); - gpu_state_print_fl(GL_LIGHT2); - gpu_state_print_fl(GL_LIGHT3); - gpu_state_print_fl(GL_LIGHT4); - gpu_state_print_fl(GL_LIGHT5); - gpu_state_print_fl(GL_LIGHT6); - gpu_state_print_fl(GL_LIGHT7); - gpu_state_print_fl(GL_LIGHTING); - gpu_state_print_fl(GL_LIGHT_MODEL_AMBIENT); - gpu_state_print_fl(GL_LIGHT_MODEL_COLOR_CONTROL); - gpu_state_print_fl(GL_LIGHT_MODEL_LOCAL_VIEWER); - gpu_state_print_fl(GL_LIGHT_MODEL_TWO_SIDE); - gpu_state_print_fl(GL_LINE_SMOOTH); - gpu_state_print_fl(GL_LINE_SMOOTH_HINT); - gpu_state_print_fl(GL_LINE_STIPPLE); - gpu_state_print_fl(GL_LINE_STIPPLE_PATTERN); - gpu_state_print_fl(GL_LINE_STIPPLE_REPEAT); - gpu_state_print_fl(GL_LINE_WIDTH); - gpu_state_print_fl(GL_LINE_WIDTH_GRANULARITY); - gpu_state_print_fl(GL_LINE_WIDTH_RANGE); - gpu_state_print_fl(GL_LIST_BASE); - gpu_state_print_fl(GL_LIST_INDEX); - gpu_state_print_fl(GL_LIST_MODE); - gpu_state_print_fl(GL_LOGIC_OP); - gpu_state_print_fl(GL_LOGIC_OP_MODE); - gpu_state_print_fl(GL_MAP1_COLOR_4); - gpu_state_print_fl(GL_MAP1_GRID_DOMAIN); - gpu_state_print_fl(GL_MAP1_GRID_SEGMENTS); - gpu_state_print_fl(GL_MAP1_INDEX); - gpu_state_print_fl(GL_MAP1_NORMAL); - gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_1); - gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_2); - gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_3); - gpu_state_print_fl(GL_MAP1_TEXTURE_COORD_4); - gpu_state_print_fl(GL_MAP1_VERTEX_3); - gpu_state_print_fl(GL_MAP1_VERTEX_4); - gpu_state_print_fl(GL_MAP2_COLOR_4); - gpu_state_print_fl(GL_MAP2_GRID_DOMAIN); - gpu_state_print_fl(GL_MAP2_GRID_SEGMENTS); - gpu_state_print_fl(GL_MAP2_INDEX); - gpu_state_print_fl(GL_MAP2_NORMAL); - gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_1); - gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_2); - gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_3); - gpu_state_print_fl(GL_MAP2_TEXTURE_COORD_4); - gpu_state_print_fl(GL_MAP2_VERTEX_3); - gpu_state_print_fl(GL_MAP2_VERTEX_4); - gpu_state_print_fl(GL_MAP_COLOR); - gpu_state_print_fl(GL_MAP_STENCIL); - gpu_state_print_fl(GL_MATRIX_MODE); - gpu_state_print_fl(GL_MAX_3D_TEXTURE_SIZE); - gpu_state_print_fl(GL_MAX_ATTRIB_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_CLIENT_ATTRIB_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_CLIP_PLANES); - gpu_state_print_fl(GL_MAX_COLOR_MATRIX_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS); - gpu_state_print_fl(GL_MAX_CUBE_MAP_TEXTURE_SIZE); - gpu_state_print_fl(GL_MAX_DRAW_BUFFERS); - gpu_state_print_fl(GL_MAX_ELEMENTS_INDICES); - gpu_state_print_fl(GL_MAX_ELEMENTS_VERTICES); - gpu_state_print_fl(GL_MAX_EVAL_ORDER); - gpu_state_print_fl(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS); - gpu_state_print_fl(GL_MAX_LIGHTS); - gpu_state_print_fl(GL_MAX_LIST_NESTING); - gpu_state_print_fl(GL_MAX_MODELVIEW_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_NAME_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_PIXEL_MAP_TABLE); - gpu_state_print_fl(GL_MAX_PROJECTION_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_TEXTURE_COORDS); - gpu_state_print_fl(GL_MAX_TEXTURE_IMAGE_UNITS); - gpu_state_print_fl(GL_MAX_TEXTURE_LOD_BIAS); - gpu_state_print_fl(GL_MAX_TEXTURE_SIZE); - gpu_state_print_fl(GL_MAX_TEXTURE_STACK_DEPTH); - gpu_state_print_fl(GL_MAX_TEXTURE_UNITS); - gpu_state_print_fl(GL_MAX_VARYING_FLOATS); - gpu_state_print_fl(GL_MAX_VERTEX_ATTRIBS); - gpu_state_print_fl(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - gpu_state_print_fl(GL_MAX_VERTEX_UNIFORM_COMPONENTS); - gpu_state_print_fl(GL_MAX_VIEWPORT_DIMS); - gpu_state_print_fl(GL_MINMAX); - gpu_state_print_fl(GL_MODELVIEW_MATRIX); - gpu_state_print_fl(GL_MODELVIEW_STACK_DEPTH); - gpu_state_print_fl(GL_MULTISAMPLE); - gpu_state_print_fl(GL_NAME_STACK_DEPTH); - gpu_state_print_fl(GL_NORMALIZE); - gpu_state_print_fl(GL_NORMAL_ARRAY); - gpu_state_print_fl(GL_NORMAL_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_NORMAL_ARRAY_STRIDE); - gpu_state_print_fl(GL_NORMAL_ARRAY_TYPE); - gpu_state_print_fl(GL_NUM_COMPRESSED_TEXTURE_FORMATS); - gpu_state_print_fl(GL_PACK_ALIGNMENT); - gpu_state_print_fl(GL_PACK_IMAGE_HEIGHT); - gpu_state_print_fl(GL_PACK_LSB_FIRST); - gpu_state_print_fl(GL_PACK_ROW_LENGTH); - gpu_state_print_fl(GL_PACK_SKIP_IMAGES); - gpu_state_print_fl(GL_PACK_SKIP_PIXELS); - gpu_state_print_fl(GL_PACK_SKIP_ROWS); - gpu_state_print_fl(GL_PACK_SWAP_BYTES); - gpu_state_print_fl(GL_PERSPECTIVE_CORRECTION_HINT); - gpu_state_print_fl(GL_PIXEL_MAP_A_TO_A_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_B_TO_B_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_G_TO_G_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_I_TO_A_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_I_TO_B_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_I_TO_G_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_I_TO_I_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_I_TO_R_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_R_TO_R_SIZE); - gpu_state_print_fl(GL_PIXEL_MAP_S_TO_S_SIZE); - gpu_state_print_fl(GL_PIXEL_PACK_BUFFER_BINDING); - gpu_state_print_fl(GL_PIXEL_UNPACK_BUFFER_BINDING); - gpu_state_print_fl(GL_POINT_DISTANCE_ATTENUATION); - gpu_state_print_fl(GL_POINT_FADE_THRESHOLD_SIZE); - gpu_state_print_fl(GL_POINT_SIZE); - gpu_state_print_fl(GL_POINT_SIZE_GRANULARITY); - gpu_state_print_fl(GL_POINT_SIZE_MAX); - gpu_state_print_fl(GL_POINT_SIZE_MIN); - gpu_state_print_fl(GL_POINT_SIZE_RANGE); - gpu_state_print_fl(GL_POINT_SMOOTH); - gpu_state_print_fl(GL_POINT_SMOOTH_HINT); - gpu_state_print_fl(GL_POINT_SPRITE); - gpu_state_print_fl(GL_POLYGON_MODE); - gpu_state_print_fl(GL_POLYGON_OFFSET_FACTOR); - gpu_state_print_fl(GL_POLYGON_OFFSET_FILL); - gpu_state_print_fl(GL_POLYGON_OFFSET_LINE); - gpu_state_print_fl(GL_POLYGON_OFFSET_POINT); - gpu_state_print_fl(GL_POLYGON_OFFSET_UNITS); - gpu_state_print_fl(GL_POLYGON_SMOOTH); - gpu_state_print_fl(GL_POLYGON_SMOOTH_HINT); - gpu_state_print_fl(GL_POLYGON_STIPPLE); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_BIAS); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_ALPHA_SCALE); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_BIAS); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_BLUE_SCALE); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_COLOR_TABLE); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_BIAS); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_GREEN_SCALE); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_BIAS); - gpu_state_print_fl(GL_POST_COLOR_MATRIX_RED_SCALE); - gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_BIAS); - gpu_state_print_fl(GL_POST_CONVOLUTION_ALPHA_SCALE); - gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_BIAS); - gpu_state_print_fl(GL_POST_CONVOLUTION_BLUE_SCALE); - gpu_state_print_fl(GL_POST_CONVOLUTION_COLOR_TABLE); - gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_BIAS); - gpu_state_print_fl(GL_POST_CONVOLUTION_GREEN_SCALE); - gpu_state_print_fl(GL_POST_CONVOLUTION_RED_BIAS); - gpu_state_print_fl(GL_POST_CONVOLUTION_RED_SCALE); - gpu_state_print_fl(GL_PROJECTION_MATRIX); - gpu_state_print_fl(GL_PROJECTION_STACK_DEPTH); - gpu_state_print_fl(GL_READ_BUFFER); - gpu_state_print_fl(GL_RED_BIAS); - gpu_state_print_fl(GL_RED_BITS); - gpu_state_print_fl(GL_RED_SCALE); - gpu_state_print_fl(GL_RENDER_MODE); - gpu_state_print_fl(GL_RESCALE_NORMAL); - gpu_state_print_fl(GL_RGBA_MODE); - gpu_state_print_fl(GL_SAMPLES); - gpu_state_print_fl(GL_SAMPLE_BUFFERS); - gpu_state_print_fl(GL_SAMPLE_COVERAGE_INVERT); - gpu_state_print_fl(GL_SAMPLE_COVERAGE_VALUE); - gpu_state_print_fl(GL_SCISSOR_BOX); - gpu_state_print_fl(GL_SCISSOR_TEST); - gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY); - gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_SIZE); - gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_STRIDE); - gpu_state_print_fl(GL_SECONDARY_COLOR_ARRAY_TYPE); - gpu_state_print_fl(GL_SELECTION_BUFFER_SIZE); - gpu_state_print_fl(GL_SEPARABLE_2D); - gpu_state_print_fl(GL_SHADE_MODEL); - gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_GRANULARITY); - gpu_state_print_fl(GL_SMOOTH_LINE_WIDTH_RANGE); - gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_GRANULARITY); - gpu_state_print_fl(GL_SMOOTH_POINT_SIZE_RANGE); - gpu_state_print_fl(GL_STENCIL_BACK_FAIL); - gpu_state_print_fl(GL_STENCIL_BACK_FUNC); - gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_FAIL); - gpu_state_print_fl(GL_STENCIL_BACK_PASS_DEPTH_PASS); - gpu_state_print_fl(GL_STENCIL_BACK_REF); - gpu_state_print_fl(GL_STENCIL_BACK_VALUE_MASK); - gpu_state_print_fl(GL_STENCIL_BACK_WRITEMASK); - gpu_state_print_fl(GL_STENCIL_BITS); - gpu_state_print_fl(GL_STENCIL_CLEAR_VALUE); - gpu_state_print_fl(GL_STENCIL_FAIL); - gpu_state_print_fl(GL_STENCIL_FUNC); - gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_FAIL); - gpu_state_print_fl(GL_STENCIL_PASS_DEPTH_PASS); - gpu_state_print_fl(GL_STENCIL_REF); - gpu_state_print_fl(GL_STENCIL_TEST); - gpu_state_print_fl(GL_STENCIL_VALUE_MASK); - gpu_state_print_fl(GL_STENCIL_WRITEMASK); - gpu_state_print_fl(GL_STEREO); - gpu_state_print_fl(GL_SUBPIXEL_BITS); - gpu_state_print_fl(GL_TEXTURE_1D); - gpu_state_print_fl(GL_TEXTURE_2D); - gpu_state_print_fl(GL_TEXTURE_3D); - gpu_state_print_fl(GL_TEXTURE_BINDING_1D); - gpu_state_print_fl(GL_TEXTURE_BINDING_2D); - gpu_state_print_fl(GL_TEXTURE_BINDING_3D); - gpu_state_print_fl(GL_TEXTURE_BINDING_CUBE_MAP); - gpu_state_print_fl(GL_TEXTURE_COMPRESSION_HINT); - gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY); - gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_SIZE); - gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_STRIDE); - gpu_state_print_fl(GL_TEXTURE_COORD_ARRAY_TYPE); - gpu_state_print_fl(GL_TEXTURE_CUBE_MAP); - gpu_state_print_fl(GL_TEXTURE_GEN_Q); - gpu_state_print_fl(GL_TEXTURE_GEN_R); - gpu_state_print_fl(GL_TEXTURE_GEN_S); - gpu_state_print_fl(GL_TEXTURE_GEN_T); - gpu_state_print_fl(GL_TEXTURE_MATRIX); - gpu_state_print_fl(GL_TEXTURE_STACK_DEPTH); - gpu_state_print_fl(GL_TRANSPOSE_COLOR_MATRIX); - gpu_state_print_fl(GL_TRANSPOSE_MODELVIEW_MATRIX); - gpu_state_print_fl(GL_TRANSPOSE_PROJECTION_MATRIX); - gpu_state_print_fl(GL_TRANSPOSE_TEXTURE_MATRIX); - gpu_state_print_fl(GL_UNPACK_ALIGNMENT); - gpu_state_print_fl(GL_UNPACK_IMAGE_HEIGHT); - gpu_state_print_fl(GL_UNPACK_LSB_FIRST); - gpu_state_print_fl(GL_UNPACK_ROW_LENGTH); - gpu_state_print_fl(GL_UNPACK_SKIP_IMAGES); - gpu_state_print_fl(GL_UNPACK_SKIP_PIXELS); - gpu_state_print_fl(GL_UNPACK_SKIP_ROWS); - gpu_state_print_fl(GL_UNPACK_SWAP_BYTES); - gpu_state_print_fl(GL_VERTEX_ARRAY); - gpu_state_print_fl(GL_VERTEX_ARRAY_BUFFER_BINDING); - gpu_state_print_fl(GL_VERTEX_ARRAY_SIZE); - gpu_state_print_fl(GL_VERTEX_ARRAY_STRIDE); - gpu_state_print_fl(GL_VERTEX_ARRAY_TYPE); - gpu_state_print_fl(GL_VERTEX_PROGRAM_POINT_SIZE); - gpu_state_print_fl(GL_VERTEX_PROGRAM_TWO_SIDE); - gpu_state_print_fl(GL_VIEWPORT); - gpu_state_print_fl(GL_ZOOM_X); - gpu_state_print_fl(GL_ZOOM_Y); -} - -#undef gpu_state_print_fl diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 1fb1e239310..fb246aa802e 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -78,6 +78,7 @@ #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_material.h" +#include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -137,7 +138,7 @@ void GPU_render_text( else if (!col) glColor3f(1.0f, 1.0f, 1.0f); - glPushMatrix(); + gpuPushMatrix(); /* get the tab width */ ImBuf *first_ibuf = BKE_image_get_first_ibuf(ima); @@ -155,12 +156,12 @@ void GPU_render_text( character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index); if (character == '\n') { - glTranslatef(line_start, -line_height, 0.0f); + gpuTranslate2f(line_start, -line_height); line_start = 0.0f; continue; } else if (character == '\t') { - glTranslatef(advance_tab, 0.0f, 0.0f); + gpuTranslate2f(advance_tab, 0.0f); line_start -= advance_tab; /* so we can go back to the start of the line */ continue; @@ -209,21 +210,22 @@ void GPU_render_text( } glEnd(); - glTranslatef(advance, 0.0f, 0.0f); + gpuTranslate2f(advance, 0.0f); line_start -= advance; /* so we can go back to the start of the line */ } - glPopMatrix(); + gpuPopMatrix(); BKE_image_release_ibuf(ima, first_ibuf, NULL); } } /* Checking powers of two for images since OpenGL ES requires it */ - +#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); } +#endif static bool is_over_resolution_limit(GLenum textarget, int w, int h) { @@ -418,7 +420,7 @@ void GPU_clear_tpage(bool force) GTS.curima = NULL; if (GTS.curtilemode != 0) { glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + glLoadIdentity(); /* TEXTURE */ glMatrixMode(GL_MODELVIEW); } GTS.curtilemode = 0; @@ -602,10 +604,10 @@ int GPU_verify_image( GTS.curtileYRep != GTS.tileYRep) { glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + glLoadIdentity(); /* TEXTURE */ if (ima && (ima->tpageflag & IMA_TILES)) - glScalef(ima->xrep, ima->yrep, 1.0f); + glScalef(ima->xrep, ima->yrep, 0); /* TEXTURE */ glMatrixMode(GL_MODELVIEW); } @@ -1686,7 +1688,7 @@ void GPU_end_dupli_object(void) } void GPU_begin_object_materials( - View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, + View3D *v3d, RegionView3D *rv3d, Scene *scene, SceneLayer *sl, Object *ob, bool glsl, bool *do_alpha_after) { Material *ma; @@ -1725,8 +1727,10 @@ void GPU_begin_object_materials( #ifdef WITH_GAMEENGINE if (rv3d->rflag & RV3D_IS_GAME_ENGINE) { - ob = BKE_object_lod_matob_get(ob, scene); + ob = BKE_object_lod_matob_get(ob, sl); } +#else + UNUSED_VARS(sl); #endif /* initialize state */ @@ -2092,7 +2096,7 @@ void GPU_end_object_materials(void) /* resetting the texture matrix after the scaling needed for tiled textures */ if (GTS.tilemode) { glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + glLoadIdentity(); /* TEXTURE */ glMatrixMode(GL_MODELVIEW); } } @@ -2169,8 +2173,8 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ Lamp *la = base->object->data; /* setup lamp transform */ - glPushMatrix(); - glLoadMatrixf((float *)viewmat); + gpuPushMatrix(); + gpuLoadMatrix3D(viewmat); /* setup light */ GPULightData light = {0}; @@ -2204,7 +2208,7 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][ GPU_basic_shader_light_set(count, &light); - glPopMatrix(); + gpuPopMatrix(); count++; if (count == 8) @@ -2252,15 +2256,6 @@ static void gpu_multisample(bool enable) void GPU_state_init(void) { - float mat_ambient[] = { 0.0, 0.0, 0.0, 0.0 }; - float mat_specular[] = { 0.5, 0.5, 0.5, 1.0 }; - - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient); - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, mat_specular); - glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, 35); - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - GPU_default_lights(); GPU_disable_program_point_size(); @@ -2276,37 +2271,16 @@ void GPU_state_init(void) glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); - glDisable(GL_FOG); - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); glDisable(GL_LOGIC_OP); glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_1D); glDisable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - /* default disabled, enable should be local per function */ - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glPixelTransferi(GL_MAP_COLOR, GL_FALSE); - glPixelTransferi(GL_RED_SCALE, 1); - glPixelTransferi(GL_RED_BIAS, 0); - glPixelTransferi(GL_GREEN_SCALE, 1); - glPixelTransferi(GL_GREEN_BIAS, 0); - glPixelTransferi(GL_BLUE_SCALE, 1); - glPixelTransferi(GL_BLUE_BIAS, 0); - glPixelTransferi(GL_ALPHA_SCALE, 1); - glPixelTransferi(GL_ALPHA_BIAS, 0); - - glPixelTransferi(GL_DEPTH_BIAS, 0); - glPixelTransferi(GL_DEPTH_SCALE, 1); glDepthRange(0.0, 1.0); glMatrixMode(GL_TEXTURE); - glLoadIdentity(); + glLoadIdentity(); /* TEXTURE */ glMatrixMode(GL_MODELVIEW); glFrontFace(GL_CCW); @@ -2314,8 +2288,6 @@ void GPU_state_init(void) glDisable(GL_CULL_FACE); gpu_multisample(false); - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); } void GPU_enable_program_point_size(void) diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c index 1efc451f4a8..ce35c43bcec 100644 --- a/source/blender/gpu/intern/gpu_framebuffer.c +++ b/source/blender/gpu/intern/gpu_framebuffer.c @@ -32,9 +32,9 @@ #include "BKE_global.h" -#include "GPU_debug.h" -#include "GPU_glew.h" +#include "GPU_batch.h" #include "GPU_framebuffer.h" +#include "GPU_matrix.h" #include "GPU_shader.h" #include "GPU_texture.h" @@ -131,14 +131,16 @@ bool GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slo } } - if (GPU_texture_depth(tex)) + glBindFramebuffer(GL_FRAMEBUFFER, fb->object); + GG.currentfb = fb->object; + + if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + else if (GPU_texture_depth(tex)) attachment = GL_DEPTH_ATTACHMENT; else attachment = GL_COLOR_ATTACHMENT0 + slot; - glBindFramebuffer(GL_FRAMEBUFFER, fb->object); - GG.currentfb = fb->object; - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GPU_texture_target(tex), GPU_texture_opengl_bindcode(tex), 0); @@ -166,7 +168,11 @@ void GPU_framebuffer_texture_detach(GPUTexture *tex) GG.currentfb = fb->object; } - if (GPU_texture_depth(tex)) { + if (GPU_texture_stencil(tex) && GPU_texture_depth(tex)) { + fb->depthtex = NULL; + attachment = GL_DEPTH_STENCIL_ATTACHMENT; + } + else if (GPU_texture_depth(tex)) { fb->depthtex = NULL; attachment = GL_DEPTH_ATTACHMENT; } @@ -212,14 +218,9 @@ void GPU_texture_bind_as_framebuffer(GPUTexture *tex) glEnable(GL_MULTISAMPLE); } - /* push matrices and set default viewport and matrix */ + /* set default viewport */ glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex)); GG.currentfb = fb->object; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); } void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) @@ -250,14 +251,9 @@ void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot) glDrawBuffers(numslots, attachments); glReadBuffer(GL_COLOR_ATTACHMENT0 + slot); - /* push matrices and set default viewport and matrix */ + /* set default viewport */ glViewport(0, 0, GPU_texture_width(fb->colortex[slot]), GPU_texture_height(fb->colortex[slot])); GG.currentfb = fb->object; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); } void GPU_framebuffer_bind(GPUFrameBuffer *fb) @@ -300,12 +296,6 @@ void GPU_framebuffer_bind(GPUFrameBuffer *fb) void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex)) { - /* restore matrix */ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - /* restore attributes */ glPopAttrib(); } @@ -379,20 +369,48 @@ void GPU_framebuffer_blur( GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex) { + const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}}; + const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}}; + + static VertexFormat format = {0}; + static VertexBuffer vbo = {{0}}; + static Batch batch = {{0}}; + const float scaleh[2] = {1.0f / GPU_texture_width(blurtex), 0.0f}; const float scalev[2] = {0.0f, 1.0f / GPU_texture_height(tex)}; GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR); - int scale_uniform, texture_source_uniform; if (!blur_shader) return; - scale_uniform = GPU_shader_get_uniform(blur_shader, "ScaleU"); - texture_source_uniform = GPU_shader_get_uniform(blur_shader, "textureSource"); + /* Preparing to draw quad */ + if (format.attrib_ct == 0) { + unsigned int i = 0; + /* Vertex format */ + unsigned int pos = add_attrib(&format, "pos", GL_FLOAT, 2, KEEP_FLOAT); + unsigned int uvs = add_attrib(&format, "uvs", GL_FLOAT, 2, KEEP_FLOAT); + + /* Vertices */ + VertexBuffer_init_with_format(&vbo, &format); + VertexBuffer_allocate_data(&vbo, 36); + + for (int j = 0; j < 3; ++j) { + setAttrib(&vbo, uvs, i, fullscreenuvs[j]); setAttrib(&vbo, pos, i++, fullscreencos[j]); + } + for (int j = 1; j < 4; ++j) { + setAttrib(&vbo, uvs, i, fullscreenuvs[j]); setAttrib(&vbo, pos, i++, fullscreencos[j]); + } + + Batch_init(&batch, GL_TRIANGLES, &vbo, NULL); + } - /* Blurring horizontally */ + glDisable(GL_DEPTH_TEST); + + /* Load fresh matrices */ + gpuMatrixBegin3D(); /* TODO: finish 2D API */ + /* Blurring horizontally */ /* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid * pushing unnecessary matrices onto the OpenGL stack. */ glBindFramebuffer(GL_FRAMEBUFFER, blurfb->object); @@ -401,51 +419,66 @@ void GPU_framebuffer_blur( /* avoid warnings from texture binding */ GG.currentfb = blurfb->object; - GPU_shader_bind(blur_shader); - GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scaleh); - GPU_shader_uniform_texture(blur_shader, texture_source_uniform, tex); glViewport(0, 0, GPU_texture_width(blurtex), GPU_texture_height(blurtex)); - /* Preparing to draw quad */ - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - glDisable(GL_DEPTH_TEST); - GPU_texture_bind(tex, 0); - /* Drawing quad */ - glBegin(GL_QUADS); - glTexCoord2d(0, 0); glVertex2f(1, 1); - glTexCoord2d(1, 0); glVertex2f(-1, 1); - glTexCoord2d(1, 1); glVertex2f(-1, -1); - glTexCoord2d(0, 1); glVertex2f(1, -1); - glEnd(); + Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR); + Batch_Uniform2f(&batch, "ScaleU", scaleh[0], scaleh[1]); + Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0); + Batch_draw(&batch); /* Blurring vertically */ - glBindFramebuffer(GL_FRAMEBUFFER, fb->object); glDrawBuffer(GL_COLOR_ATTACHMENT0); GG.currentfb = fb->object; glViewport(0, 0, GPU_texture_width(tex), GPU_texture_height(tex)); - GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, scalev); - GPU_shader_uniform_texture(blur_shader, texture_source_uniform, blurtex); + GPU_texture_bind(blurtex, 0); - glBegin(GL_QUADS); - glTexCoord2d(0, 0); glVertex2f(1, 1); - glTexCoord2d(1, 0); glVertex2f(-1, 1); - glTexCoord2d(1, 1); glVertex2f(-1, -1); - glTexCoord2d(0, 1); glVertex2f(1, -1); - glEnd(); + /* Hack to make the following uniform stick */ + Batch_set_builtin_program(&batch, GPU_SHADER_SEP_GAUSSIAN_BLUR); + Batch_Uniform2f(&batch, "ScaleU", scalev[0], scalev[1]); + Batch_Uniform1i(&batch, "textureSource", GL_TEXTURE0); + Batch_draw(&batch); - GPU_shader_unbind(); + gpuMatrixEnd(); +} + +void GPU_framebuffer_blit(GPUFrameBuffer *fb_read, int read_slot, GPUFrameBuffer *fb_write, int write_slot, bool use_depth) +{ + GPUTexture *read_tex = (use_depth) ? fb_read->depthtex : fb_read->colortex[read_slot]; + GPUTexture *write_tex = (use_depth) ? fb_write->depthtex : fb_write->colortex[write_slot]; + int read_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(read_tex); + int write_attach = (use_depth) ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0 + GPU_texture_framebuffer_attachment(write_tex); + int read_bind = GPU_texture_opengl_bindcode(read_tex); + int write_bind = GPU_texture_opengl_bindcode(write_tex); + const int read_w = GPU_texture_width(read_tex); + const int read_h = GPU_texture_height(read_tex); + const int write_w = GPU_texture_width(write_tex); + const int write_h = GPU_texture_height(write_tex); + + /* read from multi-sample buffer */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, fb_read->object); + glFramebufferTexture2D( + GL_READ_FRAMEBUFFER, read_attach, + GL_TEXTURE_2D, read_bind, 0); + BLI_assert(glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + + /* write into new single-sample buffer */ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_write->object); + glFramebufferTexture2D( + GL_DRAW_FRAMEBUFFER, write_attach, + GL_TEXTURE_2D, write_bind, 0); + BLI_assert(glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE); + + glBlitFramebuffer(0, 0, read_w, read_h, 0, 0, write_w, write_h, (use_depth) ? GL_DEPTH_BUFFER_BIT : GL_COLOR_BUFFER_BIT, GL_NEAREST); + + /* Restore previous framebuffer */ + glBindFramebuffer(GL_FRAMEBUFFER, GG.currentfb); + glDrawBuffer(GL_COLOR_ATTACHMENT0); } /* GPUOffScreen */ diff --git a/source/blender/gpu/intern/gpu_lamp.c b/source/blender/gpu/intern/gpu_lamp.c new file mode 100644 index 00000000000..ee0bcb83a6a --- /dev/null +++ b/source/blender/gpu/intern/gpu_lamp.c @@ -0,0 +1,475 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2006 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel, Clément Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_lamp.c + * \ingroup gpu + * + * Manages Opengl lights. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_group.h" + +#include "GPU_framebuffer.h" +#include "GPU_glew.h" +#include "GPU_lamp.h" +#include "GPU_material.h" +#include "GPU_shader.h" +#include "GPU_texture.h" + +#include "gpu_lamp_private.h" + +bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma) +{ + if (srl && srl->light_override) + return BKE_group_object_exists(srl->light_override, lamp->ob); + else if (ma && ma->group) + return BKE_group_object_exists(ma->group, lamp->ob); + else + return true; +} + +static void gpu_lamp_calc_winmat(GPULamp *lamp) +{ + float temp, angle, pixsize, wsize; + + if (lamp->type == LA_SUN) { + wsize = lamp->la->shadow_frustum_size; + orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend); + } + else if (lamp->type == LA_SPOT) { + angle = saacos(lamp->spotsi); + temp = 0.5f * lamp->size * cosf(angle) / sinf(angle); + pixsize = lamp->d / temp; + wsize = pixsize * 0.5f * lamp->size; + /* compute shadows according to X and Y scaling factors */ + perspective_m4( + lamp->winmat, + -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0], + -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1], + lamp->d, lamp->clipend); + } +} + +void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]) +{ + float mat[4][4]; + float obmat_scale[3]; + + lamp->lay = lay; + lamp->hide = hide; + + normalize_m4_m4_ex(mat, obmat, obmat_scale); + + copy_v3_v3(lamp->vec, mat[2]); + copy_v3_v3(lamp->co, mat[3]); + copy_m4_m4(lamp->obmat, mat); + invert_m4_m4(lamp->imat, mat); + + if (lamp->type == LA_SPOT) { + /* update spotlamp scale on X and Y axis */ + lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2]; + lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2]; + } + + if (GPU_lamp_has_shadow_buffer(lamp)) { + /* makeshadowbuf */ + gpu_lamp_calc_winmat(lamp); + } +} + +void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) +{ + lamp->energy = energy; + if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; + + lamp->col[0] = r; + lamp->col[1] = g; + lamp->col[2] = b; +} + +void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, + float coeff_const, float coeff_lin, float coeff_quad) +{ + lamp->dist = distance; + lamp->att1 = att1; + lamp->att2 = att2; + lamp->coeff_const = coeff_const; + lamp->coeff_lin = coeff_lin; + lamp->coeff_quad = coeff_quad; +} + +void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) +{ + lamp->spotsi = cosf(spotsize * 0.5f); + lamp->spotbl = (1.0f - lamp->spotsi) * spotblend; +} + +static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) +{ + lamp->scene = scene; + lamp->ob = ob; + lamp->par = par; + lamp->la = la; + + /* add_render_lamp */ + lamp->mode = la->mode; + lamp->type = la->type; + + lamp->energy = la->energy; + if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; + + lamp->col[0] = la->r; + lamp->col[1] = la->g; + lamp->col[2] = la->b; + + GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); + + lamp->spotsi = la->spotsize; + if (lamp->mode & LA_HALO) + if (lamp->spotsi > DEG2RADF(170.0f)) + lamp->spotsi = DEG2RADF(170.0f); + lamp->spotsi = cosf(lamp->spotsi * 0.5f); + lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend; + lamp->k = la->k; + + lamp->dist = la->dist; + lamp->falloff_type = la->falloff_type; + lamp->att1 = la->att1; + lamp->att2 = la->att2; + lamp->coeff_const = la->coeff_const; + lamp->coeff_lin = la->coeff_lin; + lamp->coeff_quad = la->coeff_quad; + lamp->curfalloff = la->curfalloff; + + /* initshadowbuf */ + lamp->bias = 0.02f * la->bias; + lamp->size = la->bufsize; + lamp->d = la->clipsta; + lamp->clipend = la->clipend; + + /* arbitrary correction for the fact we do no soft transition */ + lamp->bias *= 0.25f; +} + +static void gpu_lamp_shadow_free(GPULamp *lamp) +{ + if (lamp->tex) { + GPU_texture_free(lamp->tex); + lamp->tex = NULL; + } + if (lamp->depthtex) { + GPU_texture_free(lamp->depthtex); + lamp->depthtex = NULL; + } + if (lamp->fb) { + GPU_framebuffer_free(lamp->fb); + lamp->fb = NULL; + } + if (lamp->blurtex) { + GPU_texture_free(lamp->blurtex); + lamp->blurtex = NULL; + } + if (lamp->blurfb) { + GPU_framebuffer_free(lamp->blurfb); + lamp->blurfb = NULL; + } +} + +static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size) +{ + return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL); +} + +GPULamp *GPU_lamp_from_engine(Scene *scene, Object *ob, Object *par, struct RenderEngineType *re) +{ + GPULamp *lamp; + LinkData *link; + + for (link = ob->gpulamp.first; link; link = link->next) { + lamp = (GPULamp *)link->data; + + if ((lamp->par == par) && (lamp->scene == scene) && (lamp->re == re)) + return link->data; + } + + lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); + + link = MEM_callocN(sizeof(LinkData), "GPULampLink"); + link->data = lamp; + BLI_addtail(&ob->gpulamp, link); + + lamp->scene = scene; + lamp->ob = ob; + lamp->par = par; + lamp->la = ob->data; + lamp->re = re; + + return lamp; +} + +GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) +{ + Lamp *la; + GPULamp *lamp; + LinkData *link; + + for (link = ob->gpulamp.first; link; link = link->next) { + lamp = (GPULamp *)link->data; + + if (lamp->par == par && lamp->scene == scene) + return link->data; + } + + lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); + + link = MEM_callocN(sizeof(LinkData), "GPULampLink"); + link->data = lamp; + BLI_addtail(&ob->gpulamp, link); + + la = ob->data; + gpu_lamp_from_blender(scene, ob, par, la, lamp); + + if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || + (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) + { + /* opengl */ + lamp->fb = GPU_framebuffer_create(); + if (!lamp->fb) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { + /* Shadow depth map */ + lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); + if (!lamp->depthtex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + /* Shadow color map */ + lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size); + if (!lamp->tex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + /* FBO and texture for blurring */ + lamp->blurfb = GPU_framebuffer_create(); + if (!lamp->blurfb) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5); + if (!lamp->blurtex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + /* we need to properly bind to test for completeness */ + GPU_texture_bind_as_framebuffer(lamp->blurtex); + + if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex); + } + else { + lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); + if (!lamp->tex) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + + if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { + gpu_lamp_shadow_free(lamp); + return lamp; + } + } + + GPU_framebuffer_restore(); + + lamp->shadow_color[0] = la->shdwr; + lamp->shadow_color[1] = la->shdwg; + lamp->shadow_color[2] = la->shdwb; + } + else { + lamp->shadow_color[0] = 1.0; + lamp->shadow_color[1] = 1.0; + lamp->shadow_color[2] = 1.0; + } + + return lamp; +} + +void GPU_lamp_free(Object *ob) +{ + GPULamp *lamp; + LinkData *link; + LinkData *nlink; + Material *ma; + + for (link = ob->gpulamp.first; link; link = link->next) { + lamp = link->data; + + while (lamp->materials.first) { + nlink = lamp->materials.first; + ma = nlink->data; + BLI_freelinkN(&lamp->materials, nlink); + + if (ma->gpumaterial.first) + GPU_material_free(&ma->gpumaterial); + } + + gpu_lamp_shadow_free(lamp); + + MEM_freeN(lamp); + } + + BLI_freelistN(&ob->gpulamp); +} + +bool GPU_lamp_has_shadow_buffer(GPULamp *lamp) +{ + return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && + !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) && + lamp->tex && lamp->fb); +} + +void GPU_lamp_update_buffer_mats(GPULamp *lamp) +{ + float rangemat[4][4], persmat[4][4]; + + /* initshadowbuf */ + invert_m4_m4(lamp->viewmat, lamp->obmat); + normalize_v3(lamp->viewmat[0]); + normalize_v3(lamp->viewmat[1]); + normalize_v3(lamp->viewmat[2]); + + /* makeshadowbuf */ + mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat); + + /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ + unit_m4(rangemat); + rangemat[0][0] = 0.5f; + rangemat[1][1] = 0.5f; + rangemat[2][2] = 0.5f; + rangemat[3][0] = 0.5f; + rangemat[3][1] = 0.5f; + rangemat[3][2] = 0.5f; + + mul_m4_m4m4(lamp->persmat, rangemat, persmat); +} + +void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]) +{ + GPU_lamp_update_buffer_mats(lamp); + + /* opengl */ + glDisable(GL_SCISSOR_TEST); + GPU_texture_bind_as_framebuffer(lamp->tex); + if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) + GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE)); + + /* set matrices */ + copy_m4_m4(viewmat, lamp->viewmat); + copy_m4_m4(winmat, lamp->winmat); + *winsize = lamp->size; +} + +void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) +{ + if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { + GPU_shader_unbind(); + GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); + } + + GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); + GPU_framebuffer_restore(); + glEnable(GL_SCISSOR_TEST); +} + +int GPU_lamp_shadow_buffer_type(GPULamp *lamp) +{ + return lamp->la->shadowmap_type; +} + +int GPU_lamp_shadow_bind_code(GPULamp *lamp) +{ + return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1; +} + +float *GPU_lamp_dynpersmat(GPULamp *lamp) +{ + return &lamp->dynpersmat[0][0]; +} + +int GPU_lamp_shadow_layer(GPULamp *lamp) +{ + if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW))) + return lamp->lay; + else + return -1; +} diff --git a/source/blender/gpu/intern/gpu_lamp_private.h b/source/blender/gpu/intern/gpu_lamp_private.h new file mode 100644 index 00000000000..ef71385e66d --- /dev/null +++ b/source/blender/gpu/intern/gpu_lamp_private.h @@ -0,0 +1,86 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel, Clément Foucault. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gpu_lamp_private.h + * \ingroup gpu + */ + +#ifndef __GPU_LAMP_PRIVATE_H__ +#define __GPU_LAMP_PRIVATE_H__ + +#include "BLI_sys_types.h" /* for bool */ + +struct GPULamp { + Scene *scene; + Object *ob; + Object *par; + Lamp *la; + struct RenderEngineType *re; + + /* Old Viewport (pre-2.8) */ + int type, mode, lay, hide; + + float dynenergy, dyncol[3]; + float energy, col[3]; + + float co[3], vec[3]; + float dynco[3], dynvec[3]; + float obmat[4][4]; + float imat[4][4]; + float dynimat[4][4]; + + float spotsi, spotbl, k; + float spotvec[2]; + float dyndist, dynatt1, dynatt2; + float dist, att1, att2; + float coeff_const, coeff_lin, coeff_quad; + float shadow_color[3]; + + float bias, d, clipend; + int size; + + int falloff_type; + struct CurveMapping *curfalloff; + + float winmat[4][4]; + float viewmat[4][4]; + float persmat[4][4]; + float dynpersmat[4][4]; + + GPUFrameBuffer *fb; + GPUFrameBuffer *blurfb; + GPUTexture *tex; + GPUTexture *depthtex; + GPUTexture *blurtex; + + ListBase materials; + + /* New viewport */ + struct LampEngineData data; +}; + +#endif /* __GPU_LAMP_PRIVATE_H__ */ diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 9e08f629bcb..153ae8ec8dc 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -60,11 +60,13 @@ #include "GPU_extensions.h" #include "GPU_framebuffer.h" +#include "GPU_lamp.h" #include "GPU_material.h" #include "GPU_shader.h" #include "GPU_texture.h" #include "gpu_codegen.h" +#include "gpu_lamp_private.h" #ifdef WITH_OPENSUBDIV # include "BKE_DerivedMesh.h" @@ -128,50 +130,6 @@ struct GPUMaterial { bool is_opensubdiv; }; -struct GPULamp { - Scene *scene; - Object *ob; - Object *par; - Lamp *la; - - int type, mode, lay, hide; - - float dynenergy, dyncol[3]; - float energy, col[3]; - - float co[3], vec[3]; - float dynco[3], dynvec[3]; - float obmat[4][4]; - float imat[4][4]; - float dynimat[4][4]; - - float spotsi, spotbl, k; - float spotvec[2]; - float dyndist, dynatt1, dynatt2; - float dist, att1, att2; - float coeff_const, coeff_lin, coeff_quad; - float shadow_color[3]; - - float bias, d, clipend; - int size; - - int falloff_type; - struct CurveMapping *curfalloff; - - float winmat[4][4]; - float viewmat[4][4]; - float persmat[4][4]; - float dynpersmat[4][4]; - - GPUFrameBuffer *fb; - GPUFrameBuffer *blurfb; - GPUTexture *tex; - GPUTexture *depthtex; - GPUTexture *blurtex; - - ListBase materials; -}; - /* Forward declaration so shade_light_textures() can use this, while still keeping the code somewhat organized */ static void texture_rgb_blend( GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink *out, GPUNodeLink *fact, GPUNodeLink *facg, @@ -308,16 +266,6 @@ void GPU_material_free(ListBase *gpumaterial) BLI_freelistN(gpumaterial); } -bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma) -{ - if (srl && srl->light_override) - return BKE_group_object_exists(srl->light_override, lamp->ob); - else if (ma && ma->group) - return BKE_group_object_exists(ma->group, lamp->ob); - else - return true; -} - void GPU_material_bind( GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], float camerafactors[4], bool scenelock) @@ -1016,7 +964,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr) { - BaseLegacy *base; + Base *base; Scene *sce_iter; for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) { @@ -2222,391 +2170,6 @@ void GPU_materials_free(void) /* Lamps and shadow buffers */ -static void gpu_lamp_calc_winmat(GPULamp *lamp) -{ - float temp, angle, pixsize, wsize; - - if (lamp->type == LA_SUN) { - wsize = lamp->la->shadow_frustum_size; - orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend); - } - else if (lamp->type == LA_SPOT) { - angle = saacos(lamp->spotsi); - temp = 0.5f * lamp->size * cosf(angle) / sinf(angle); - pixsize = lamp->d / temp; - wsize = pixsize * 0.5f * lamp->size; - /* compute shadows according to X and Y scaling factors */ - perspective_m4( - lamp->winmat, - -wsize * lamp->spotvec[0], wsize * lamp->spotvec[0], - -wsize * lamp->spotvec[1], wsize * lamp->spotvec[1], - lamp->d, lamp->clipend); - } -} - -void GPU_lamp_update(GPULamp *lamp, int lay, int hide, float obmat[4][4]) -{ - float mat[4][4]; - float obmat_scale[3]; - - lamp->lay = lay; - lamp->hide = hide; - - normalize_m4_m4_ex(mat, obmat, obmat_scale); - - copy_v3_v3(lamp->vec, mat[2]); - copy_v3_v3(lamp->co, mat[3]); - copy_m4_m4(lamp->obmat, mat); - invert_m4_m4(lamp->imat, mat); - - if (lamp->type == LA_SPOT) { - /* update spotlamp scale on X and Y axis */ - lamp->spotvec[0] = obmat_scale[0] / obmat_scale[2]; - lamp->spotvec[1] = obmat_scale[1] / obmat_scale[2]; - } - - if (GPU_lamp_has_shadow_buffer(lamp)) { - /* makeshadowbuf */ - gpu_lamp_calc_winmat(lamp); - } -} - -void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float energy) -{ - lamp->energy = energy; - if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; - - lamp->col[0] = r; - lamp->col[1] = g; - lamp->col[2] = b; -} - -void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2, - float coeff_const, float coeff_lin, float coeff_quad) -{ - lamp->dist = distance; - lamp->att1 = att1; - lamp->att2 = att2; - lamp->coeff_const = coeff_const; - lamp->coeff_lin = coeff_lin; - lamp->coeff_quad = coeff_quad; -} - -void GPU_lamp_update_spot(GPULamp *lamp, float spotsize, float spotblend) -{ - lamp->spotsi = cosf(spotsize * 0.5f); - lamp->spotbl = (1.0f - lamp->spotsi) * spotblend; -} - -static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *la, GPULamp *lamp) -{ - lamp->scene = scene; - lamp->ob = ob; - lamp->par = par; - lamp->la = la; - - /* add_render_lamp */ - lamp->mode = la->mode; - lamp->type = la->type; - - lamp->energy = la->energy; - if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy; - - lamp->col[0] = la->r; - lamp->col[1] = la->g; - lamp->col[2] = la->b; - - GPU_lamp_update(lamp, ob->lay, (ob->restrictflag & OB_RESTRICT_RENDER), ob->obmat); - - lamp->spotsi = la->spotsize; - if (lamp->mode & LA_HALO) - if (lamp->spotsi > DEG2RADF(170.0f)) - lamp->spotsi = DEG2RADF(170.0f); - lamp->spotsi = cosf(lamp->spotsi * 0.5f); - lamp->spotbl = (1.0f - lamp->spotsi) * la->spotblend; - lamp->k = la->k; - - lamp->dist = la->dist; - lamp->falloff_type = la->falloff_type; - lamp->att1 = la->att1; - lamp->att2 = la->att2; - lamp->coeff_const = la->coeff_const; - lamp->coeff_lin = la->coeff_lin; - lamp->coeff_quad = la->coeff_quad; - lamp->curfalloff = la->curfalloff; - - /* initshadowbuf */ - lamp->bias = 0.02f * la->bias; - lamp->size = la->bufsize; - lamp->d = la->clipsta; - lamp->clipend = la->clipend; - - /* arbitrary correction for the fact we do no soft transition */ - lamp->bias *= 0.25f; -} - -static void gpu_lamp_shadow_free(GPULamp *lamp) -{ - if (lamp->tex) { - GPU_texture_free(lamp->tex); - lamp->tex = NULL; - } - if (lamp->depthtex) { - GPU_texture_free(lamp->depthtex); - lamp->depthtex = NULL; - } - if (lamp->fb) { - GPU_framebuffer_free(lamp->fb); - lamp->fb = NULL; - } - if (lamp->blurtex) { - GPU_texture_free(lamp->blurtex); - lamp->blurtex = NULL; - } - if (lamp->blurfb) { - GPU_framebuffer_free(lamp->blurfb); - lamp->blurfb = NULL; - } -} - -static GPUTexture *gpu_lamp_create_vsm_shadow_map(int size) -{ - return GPU_texture_create_2D_custom(size, size, 2, GPU_RG32F, NULL, NULL); -} - -GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par) -{ - Lamp *la; - GPULamp *lamp; - LinkData *link; - - for (link = ob->gpulamp.first; link; link = link->next) { - lamp = (GPULamp *)link->data; - - if (lamp->par == par && lamp->scene == scene) - return link->data; - } - - lamp = MEM_callocN(sizeof(GPULamp), "GPULamp"); - - link = MEM_callocN(sizeof(LinkData), "GPULampLink"); - link->data = lamp; - BLI_addtail(&ob->gpulamp, link); - - la = ob->data; - gpu_lamp_from_blender(scene, ob, par, la, lamp); - - if ((la->type == LA_SPOT && (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY))) || - (la->type == LA_SUN && (la->mode & LA_SHAD_RAY))) - { - /* opengl */ - lamp->fb = GPU_framebuffer_create(); - if (!lamp->fb) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { - /* Shadow depth map */ - lamp->depthtex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); - if (!lamp->depthtex) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - /* Shadow color map */ - lamp->tex = gpu_lamp_create_vsm_shadow_map(lamp->size); - if (!lamp->tex) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - /* FBO and texture for blurring */ - lamp->blurfb = GPU_framebuffer_create(); - if (!lamp->blurfb) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - lamp->blurtex = gpu_lamp_create_vsm_shadow_map(lamp->size * 0.5); - if (!lamp->blurtex) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - /* we need to properly bind to test for completeness */ - GPU_texture_bind_as_framebuffer(lamp->blurtex); - - if (!GPU_framebuffer_check_valid(lamp->blurfb, NULL)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - GPU_framebuffer_texture_unbind(lamp->blurfb, lamp->blurtex); - } - else { - lamp->tex = GPU_texture_create_depth(lamp->size, lamp->size, NULL); - if (!lamp->tex) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - - if (!GPU_framebuffer_check_valid(lamp->fb, NULL)) { - gpu_lamp_shadow_free(lamp); - return lamp; - } - } - - GPU_framebuffer_restore(); - - lamp->shadow_color[0] = la->shdwr; - lamp->shadow_color[1] = la->shdwg; - lamp->shadow_color[2] = la->shdwb; - } - else { - lamp->shadow_color[0] = 1.0; - lamp->shadow_color[1] = 1.0; - lamp->shadow_color[2] = 1.0; - } - - return lamp; -} - -void GPU_lamp_free(Object *ob) -{ - GPULamp *lamp; - LinkData *link; - LinkData *nlink; - Material *ma; - - for (link = ob->gpulamp.first; link; link = link->next) { - lamp = link->data; - - while (lamp->materials.first) { - nlink = lamp->materials.first; - ma = nlink->data; - BLI_freelinkN(&lamp->materials, nlink); - - if (ma->gpumaterial.first) - GPU_material_free(&ma->gpumaterial); - } - - gpu_lamp_shadow_free(lamp); - - MEM_freeN(lamp); - } - - BLI_freelistN(&ob->gpulamp); -} - -bool GPU_lamp_has_shadow_buffer(GPULamp *lamp) -{ - return (!(lamp->scene->gm.flag & GAME_GLSL_NO_SHADOWS) && - !(lamp->scene->gm.flag & GAME_GLSL_NO_LIGHTS) && - lamp->tex && lamp->fb); -} - -void GPU_lamp_update_buffer_mats(GPULamp *lamp) -{ - float rangemat[4][4], persmat[4][4]; - - /* initshadowbuf */ - invert_m4_m4(lamp->viewmat, lamp->obmat); - normalize_v3(lamp->viewmat[0]); - normalize_v3(lamp->viewmat[1]); - normalize_v3(lamp->viewmat[2]); - - /* makeshadowbuf */ - mul_m4_m4m4(persmat, lamp->winmat, lamp->viewmat); - - /* opengl depth buffer is range 0.0..1.0 instead of -1.0..1.0 in blender */ - unit_m4(rangemat); - rangemat[0][0] = 0.5f; - rangemat[1][1] = 0.5f; - rangemat[2][2] = 0.5f; - rangemat[3][0] = 0.5f; - rangemat[3][1] = 0.5f; - rangemat[3][2] = 0.5f; - - mul_m4_m4m4(lamp->persmat, rangemat, persmat); -} - -void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsize, float winmat[4][4]) -{ - GPU_lamp_update_buffer_mats(lamp); - - /* opengl */ - glDisable(GL_SCISSOR_TEST); - GPU_texture_bind_as_framebuffer(lamp->tex); - if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) - GPU_shader_bind(GPU_shader_get_builtin_shader(GPU_SHADER_VSM_STORE)); - - /* set matrices */ - copy_m4_m4(viewmat, lamp->viewmat); - copy_m4_m4(winmat, lamp->winmat); - *winsize = lamp->size; -} - -void GPU_lamp_shadow_buffer_unbind(GPULamp *lamp) -{ - if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) { - GPU_shader_unbind(); - GPU_framebuffer_blur(lamp->fb, lamp->tex, lamp->blurfb, lamp->blurtex); - } - - GPU_framebuffer_texture_unbind(lamp->fb, lamp->tex); - GPU_framebuffer_restore(); - glEnable(GL_SCISSOR_TEST); -} - -int GPU_lamp_shadow_buffer_type(GPULamp *lamp) -{ - return lamp->la->shadowmap_type; -} - -int GPU_lamp_shadow_bind_code(GPULamp *lamp) -{ - return lamp->tex ? GPU_texture_opengl_bindcode(lamp->tex) : -1; -} - -float *GPU_lamp_dynpersmat(GPULamp *lamp) -{ - return &lamp->dynpersmat[0][0]; -} - -int GPU_lamp_shadow_layer(GPULamp *lamp) -{ - if (lamp->fb && lamp->tex && (lamp->mode & (LA_LAYER | LA_LAYER_SHADOW))) - return lamp->lay; - else - return -1; -} - GPUNodeLink *GPU_lamp_get_data( GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **r_col, GPUNodeLink **r_lv, GPUNodeLink **r_dist, GPUNodeLink **r_shadow, GPUNodeLink **r_energy) diff --git a/source/blender/gpu/intern/gpu_matrix.c b/source/blender/gpu/intern/gpu_matrix.c index 855ccaa4999..8f8754f612d 100644 --- a/source/blender/gpu/intern/gpu_matrix.c +++ b/source/blender/gpu/intern/gpu_matrix.c @@ -29,6 +29,7 @@ * \ingroup gpu */ +#define SUPPRESS_GENERIC_MATRIX_API #include "GPU_matrix.h" #include "BLI_math_matrix.h" @@ -80,7 +81,7 @@ void gpuMatrixBegin2D(void) state.mode = MATRIX_MODE_2D; state.top = 0; unit_m3(ModelView2D); - gpuOrtho2D(-1.0f, +1.0f, -1.0f, +1.0f); // or identity? + unit_m3(Projection2D); } void gpuMatrixBegin3D(void) @@ -88,21 +89,9 @@ void gpuMatrixBegin3D(void) state.mode = MATRIX_MODE_3D; state.top = 0; unit_m4(ModelView3D); - gpuOrtho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f); // or identity? + unit_m4(Projection3D); } -#if SUPPORT_LEGACY_MATRIX -void gpuMatrixBegin3D_legacy(void) -{ - /* copy top matrix from each legacy stack into new fresh stack */ - state.mode = MATRIX_MODE_3D; - state.top = 0; - state.dirty = true; - glGetFloatv(GL_MODELVIEW_MATRIX, (float*)ModelView3D); - glGetFloatv(GL_PROJECTION_MATRIX, (float*)Projection3D); -} -#endif - void gpuMatrixEnd(void) { state.mode = MATRIX_MODE_INACTIVE; @@ -135,6 +124,14 @@ static void checkmat(cosnt float *m) void gpuPushMatrix(void) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glPushMatrix(); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode != MATRIX_MODE_INACTIVE); BLI_assert(state.top < MATRIX_STACK_DEPTH); state.top++; @@ -146,6 +143,14 @@ void gpuPushMatrix(void) void gpuPopMatrix(void) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glPopMatrix(); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode != MATRIX_MODE_INACTIVE); BLI_assert(state.top > 0); state.top--; @@ -154,12 +159,47 @@ void gpuPopMatrix(void) void gpuLoadMatrix3D(const float m[4][4]) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glLoadMatrixf((const float*) m); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); copy_m4_m4(ModelView3D, m); CHECKMAT(ModelView3D); state.dirty = true; } +void gpuLoadProjectionMatrix3D(const float m[4][4]) +{ +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + GLenum mode; + glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); + if (mode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + } + + glLoadMatrixf((const float*) m); + + if (mode != GL_PROJECTION_MATRIX) { + glMatrixMode(mode); /* restore */ + } + + state.dirty = true; + return; + } +#endif + + BLI_assert(state.mode == MATRIX_MODE_3D); + copy_m4_m4(Projection3D, m); + CHECKMAT(Projection3D); + state.dirty = true; +} + void gpuLoadMatrix2D(const float m[3][3]) { BLI_assert(state.mode == MATRIX_MODE_2D); @@ -177,6 +217,11 @@ void gpuLoadIdentity(void) case MATRIX_MODE_2D: unit_m3(ModelView2D); break; +#if SUPPORT_LEGACY_MATRIX + case MATRIX_MODE_INACTIVE: + glLoadIdentity(); + break; +#endif default: BLI_assert(false); } @@ -185,6 +230,14 @@ void gpuLoadIdentity(void) void gpuTranslate2f(float x, float y) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glTranslatef(x, y, 0.0f); + state.dirty = true; + return; + } +#endif + Mat3 m; unit_m3(m); m[2][0] = x; @@ -199,6 +252,14 @@ void gpuTranslate2fv(const float vec[2]) void gpuTranslate3f(float x, float y, float z) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glTranslatef(x, y, z); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); #if 1 translate_m4(ModelView3D, x, y, z); @@ -244,6 +305,12 @@ void gpuScaleUniform(float factor) gpuMultMatrix2D(m); break; } +#if SUPPORT_LEGACY_MATRIX + case MATRIX_MODE_INACTIVE: + glScalef(factor, factor, factor); /* always scale Z since we can't distinguish 2D from 3D */ + state.dirty = true; + break; +#endif default: BLI_assert(false); } @@ -251,6 +318,14 @@ void gpuScaleUniform(float factor) void gpuScale2f(float x, float y) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glScalef(x, y, 1.0f); + state.dirty = true; + return; + } +#endif + Mat3 m = {{0.0f}}; m[0][0] = x; m[1][1] = y; @@ -265,6 +340,14 @@ void gpuScale2fv(const float vec[2]) void gpuScale3f(float x, float y, float z) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glScalef(x, y, z); + state.dirty = true; + return; + } +#endif + Mat4 m = {{0.0f}}; m[0][0] = x; m[1][1] = y; @@ -280,6 +363,14 @@ void gpuScale3fv(const float vec[3]) void gpuMultMatrix3D(const float m[4][4]) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glMultMatrixf((const float*) m); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); mul_m4_m4_post(ModelView3D, m); CHECKMAT(ModelView3D); @@ -294,8 +385,35 @@ void gpuMultMatrix2D(const float m[3][3]) state.dirty = true; } +void gpuRotate2D(float deg) +{ +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glRotatef(deg, 0.0f, 0.0f, 1.0f); + state.dirty = true; + return; + } +#endif + + BLI_assert(false); /* TODO: finish for MATRIX_MODE_2D */ +} + +void gpuRotate3f(float deg, float x, float y, float z) +{ + const float axis[3] = {x, y, z}; + gpuRotate3fv(deg, axis); +} + void gpuRotate3fv(float deg, const float axis[3]) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + glRotatef(deg, axis[0], axis[1], axis[2]); + state.dirty = true; + return; + } +#endif + Mat4 m; axis_angle_to_mat4(m, axis, DEG2RADF(deg)); gpuMultMatrix3D(m); @@ -303,6 +421,21 @@ void gpuRotate3fv(float deg, const float axis[3]) void gpuRotateAxis(float deg, char axis) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + float a[3] = { 0.0f }; + switch (axis) { + case 'X': a[0] = 1.0f; break; + case 'Y': a[1] = 1.0f; break; + case 'Z': a[2] = 1.0f; break; + default: BLI_assert(false); /* bad axis */ + } + glRotatef(deg, a[0], a[1], a[2]); + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); #if 1 /* rotate_m4 works in place, right? */ rotate_m4(ModelView3D, axis, DEG2RADF(deg)); @@ -340,7 +473,7 @@ static void mat4_ortho_set(float m[4][4], float left, float right, float bottom, state.dirty = true; } -static void mat4_frustum_set(float m[][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; @@ -433,6 +566,26 @@ static void mat4_look_from_origin(float m[4][4], float lookdir[3], float camup[3 void gpuOrtho(float left, float right, float bottom, float top, float near, float far) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + GLenum mode; + glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); + if (mode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + } + + glLoadIdentity(); + glOrtho(left, right, bottom, top, near, far); + + if (mode != GL_PROJECTION_MATRIX) { + glMatrixMode(mode); /* restore */ + } + + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); mat4_ortho_set(Projection3D, left, right, bottom, top, near, far); CHECKMAT(Projection3D); @@ -441,6 +594,26 @@ void gpuOrtho(float left, float right, float bottom, float top, float near, floa void gpuOrtho2D(float left, float right, float bottom, float top) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + GLenum mode; + glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); + if (mode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + } + + glLoadIdentity(); + glOrtho(left, right, bottom, top, -1.0f, 1.0f); + + if (mode != GL_PROJECTION_MATRIX) { + glMatrixMode(mode); /* restore */ + } + + state.dirty = true; + return; + } +#endif + /* TODO: this function, but correct */ BLI_assert(state.mode == MATRIX_MODE_2D); Mat4 m; @@ -452,6 +625,26 @@ void gpuOrtho2D(float left, float right, float bottom, float top) void gpuFrustum(float left, float right, float bottom, float top, float near, float far) { +#if SUPPORT_LEGACY_MATRIX + if (state.mode == MATRIX_MODE_INACTIVE) { + GLenum mode; + glGetIntegerv(GL_MATRIX_MODE, (GLint*)&mode); + if (mode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + } + + glLoadIdentity(); + glFrustum(left, right, bottom, top, near, far); + + if (mode != GL_PROJECTION_MATRIX) { + glMatrixMode(mode); /* restore */ + } + + state.dirty = true; + return; + } +#endif + BLI_assert(state.mode == MATRIX_MODE_3D); mat4_frustum_set(Projection3D, left, right, bottom, top, near, far); CHECKMAT(Projection3D); @@ -481,19 +674,23 @@ void gpuLookAt(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, gpuTranslate3f(-eyeX, -eyeY, -eyeZ); } -void gpuProject(const float obj[3], const float model[4][4], const float proj[4][4], const GLint view[4], float win[3]) +void gpuProject(const float world[3], const float model[4][4], const float proj[4][4], const int view[4], float win[3]) { float v[4]; - mul_v4_m4v3(v, model, obj); + mul_v4_m4v3(v, model, world); mul_m4_v4(proj, v); + 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; } -bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const GLint view[4], float obj[3]) +bool gpuUnProject(const float win[3], const float model[4][4], const float proj[4][4], const int view[4], float world[3]) { float pm[4][4]; float in[4]; @@ -502,6 +699,7 @@ bool gpuUnProject(const float win[3], const float model[4][4], const float proj[ mul_m4_m4m4(pm, proj, model); if (!invert_m4(pm)) { + zero_v3(world); return false; } @@ -522,19 +720,12 @@ bool gpuUnProject(const float win[3], const float model[4][4], const float proj[ mul_v4_m4v3(out, pm, in); if (out[3] == 0.0f) { + copy_v3_v3(world, out); return false; } - else { - out[0] /= out[3]; - out[1] /= out[3]; - out[2] /= out[3]; - - obj[0] = out[0]; - obj[1] = out[1]; - obj[2] = out[2]; - return true; - } + mul_v3_v3fl(world, out, 1.0f / out[3]); + return true; } const float *gpuGetModelViewMatrix3D(float m[4][4]) @@ -579,38 +770,33 @@ const float *gpuGetProjectionMatrix3D(float m[4][4]) BLI_assert(state.mode == MATRIX_MODE_3D); if (m) { - copy_m4_m4(m, ModelView3D); + copy_m4_m4(m, Projection3D); return (const float*)m; } else { - return (const float*)ModelView3D; + return (const float*)Projection3D; } } const float *gpuGetModelViewProjectionMatrix3D(float m[4][4]) { + if (m == NULL) { + static Mat4 temp; + m = temp; + } + #if SUPPORT_LEGACY_MATRIX if (state.mode == MATRIX_MODE_INACTIVE) { - if (m == NULL) { - static Mat4 temp; - m = temp; - } - Mat4 proj; - glGetFloatv(GL_MODELVIEW_MATRIX, (float*)proj); - glGetFloatv(GL_PROJECTION_MATRIX, (float*)m); - mul_m4_m4_post(m, proj); + glGetFloatv(GL_MODELVIEW_MATRIX, (float*)m); + glGetFloatv(GL_PROJECTION_MATRIX, (float*)proj); + mul_m4_m4_pre(m, proj); return (const float*)m; } #endif BLI_assert(state.mode == MATRIX_MODE_3D); - if (m == NULL) { - static Mat4 temp; - m = temp; - } - mul_m4_m4m4(m, Projection3D, ModelView3D); return (const float*)m; } @@ -692,6 +878,27 @@ void gpuBindMatrices(GLuint program) glUniformMatrix3fv(loc_N, 1, GL_FALSE, gpuGetNormalMatrix(NULL)); } + /* also needed by material.glsl + * - ProjectionMatrixInverse + * - ModelViewMatrixInverse + */ + GLint loc_MV_inv = glGetUniformLocation(program, "ModelViewInverseMatrix"); + GLint loc_P_inv = glGetUniformLocation(program, "ProjectionInverseMatrix"); + + if (loc_MV_inv != -1) { + Mat4 m; + gpuGetModelViewMatrix3D(m); + invert_m4(m); + glUniformMatrix4fv(loc_MV_inv, 1, GL_FALSE, (const float*) m); + } + + if (loc_P_inv != -1) { + Mat4 m; + gpuGetProjectionMatrix3D(m); + invert_m4(m); + glUniformMatrix4fv(loc_P_inv, 1, GL_FALSE, (const float*) m); + } + state.dirty = false; } @@ -699,11 +906,3 @@ bool gpuMatricesDirty(void) { return state.dirty; } - -#if SUPPORT_LEGACY_MATRIX -void gpuMatrixUpdate_legacy(void) -{ - BLI_assert(state.mode == MATRIX_MODE_INACTIVE); - state.dirty = true; -} -#endif diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c index 58582232cd5..c384fa01fc6 100644 --- a/source/blender/gpu/intern/gpu_select.c +++ b/source/blender/gpu/intern/gpu_select.c @@ -29,109 +29,86 @@ * Interface for accessing gpu-related methods for selection. The semantics will be * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility. */ +#include <stdlib.h> + #include "GPU_select.h" #include "GPU_extensions.h" #include "GPU_glew.h" - + #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "BLI_utildefines.h" -/* Ad hoc number of queries to allocate to skip doing many glGenQueries */ -#define ALLOC_QUERIES 200 - -typedef struct GPUQueryState { +#include "gpu_select_private.h" + +/* Internal algorithm used */ +enum { + /** GL_SELECT, legacy OpenGL selection */ + ALGO_GL_LEGACY = 1, + /** glBegin/EndQuery(GL_SAMPLES_PASSED... ), `gpu_select_query.c` + * Only sets 4th component (ID) correctly. */ + ALGO_GL_QUERY = 2, + /** Read depth buffer for every drawing pass and extract depths, `gpu_select_pick.c` + * Only sets 4th component (ID) correctly. */ + ALGO_GL_PICK = 3, +}; + +typedef struct GPUSelectState { /* To ignore selection id calls when not initialized */ bool select_is_active; - /* 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 */ - unsigned int *queries; - /* array holding the id corresponding to each query */ - unsigned int *id; - /* number of queries in *queries and *id */ - unsigned int num_of_queries; - /* index to the next query to start */ - unsigned int active_query; /* flag to cache user preference for occlusion based selection */ bool use_gpu_select; - /* cache on initialization */ - unsigned int *buffer; - /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ - unsigned int bufsize; /* mode of operation */ char mode; - unsigned int index; - int oldhits; -} GPUQueryState; + /* internal algorithm for selection */ + char algorithm; + /* allow GPU_select_begin/end without drawing */ + bool use_cache; +} GPUSelectState; -static GPUQueryState g_query_state = {0}; +static GPUSelectState g_select_state = {0}; /** * initialize and provide buffer for results */ -void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, char mode, int oldhits) +void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, const rcti *input, char mode, int oldhits) { - g_query_state.select_is_active = true; - g_query_state.query_issued = false; - g_query_state.active_query = 0; - g_query_state.use_gpu_select = GPU_select_query_check_active(); - 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_select_state.select_is_active = true; + g_select_state.use_gpu_select = GPU_select_query_check_active(); + g_select_state.mode = mode; - if (!g_query_state.use_gpu_select) { - glSelectBuffer(bufsize, (GLuint *)buffer); - glRenderMode(GL_SELECT); - glInitNames(); - glPushName(-1); + if (ELEM(g_select_state.mode, GPU_SELECT_PICK_ALL, GPU_SELECT_PICK_NEAREST)) { + g_select_state.algorithm = ALGO_GL_PICK; + } + else if (!g_select_state.use_gpu_select) { + g_select_state.algorithm = ALGO_GL_LEGACY; } else { - float viewport[4]; - - 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); - - glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_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 scissor so that our geometry doesn't - * get rejected before the depth test. Should probably cull rect against - * scissor for viewport but this is a rare case I think */ - glGetFloatv(GL_SCISSOR_BOX, viewport); - if (!input || input->xmin == input->xmax) { - glViewport(viewport[0], viewport[1], 24, 24); - } - else { - glViewport(viewport[0], viewport[1], (int)(input->xmax - input->xmin), (int)(input->ymax - input->ymin)); - } + g_select_state.algorithm = ALGO_GL_QUERY; + } - /* 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); + switch (g_select_state.algorithm) { + case ALGO_GL_LEGACY: + { + g_select_state.use_cache = false; + glSelectBuffer(bufsize, (GLuint *)buffer); + glRenderMode(GL_SELECT); + glInitNames(); + glPushName(-1); + break; } - else if (mode == GPU_SELECT_NEAREST_FIRST_PASS) { - glClear(GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_TRUE); - glDepthFunc(GL_LEQUAL); + case ALGO_GL_QUERY: + { + g_select_state.use_cache = false; + gpu_select_query_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode, oldhits); + break; } - else if (mode == GPU_SELECT_NEAREST_SECOND_PASS) { - glEnable(GL_DEPTH_TEST); - glDepthMask(GL_FALSE); - glDepthFunc(GL_EQUAL); + default: /* ALGO_GL_PICK */ + { + gpu_select_pick_begin((unsigned int (*)[4])buffer, bufsize / 4, input, mode); + break; } } } @@ -146,41 +123,24 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c bool GPU_select_load_id(unsigned int id) { /* if no selection mode active, ignore */ - if (!g_query_state.select_is_active) + if (!g_select_state.select_is_active) return true; - if (!g_query_state.use_gpu_select) { - glLoadName(id); - } - else { - if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); + switch (g_select_state.algorithm) { + case ALGO_GL_LEGACY: + { + glLoadName(id); + return true; } - /* 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]); + case ALGO_GL_QUERY: + { + return gpu_select_query_load_id(id); } - - 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 && g_query_state.index < g_query_state.oldhits) { - if (g_query_state.buffer[g_query_state.index * 4 + 3] == id) { - g_query_state.index++; - return true; - } - else { - return false; - } + default: /* ALGO_GL_PICK */ + { + return gpu_select_pick_load_id(id); } } - - return true; } /** @@ -191,59 +151,27 @@ bool GPU_select_load_id(unsigned int id) unsigned int GPU_select_end(void) { unsigned int hits = 0; - if (!g_query_state.use_gpu_select) { - glPopName(); - hits = glRenderMode(GL_RENDER); - } - else { - int i; - if (g_query_state.query_issued) { - glEndQuery(GL_SAMPLES_PASSED); + switch (g_select_state.algorithm) { + case ALGO_GL_LEGACY: + { + glPopName(); + hits = glRenderMode(GL_RENDER); + break; } - - for (i = 0; i < g_query_state.active_query; i++) { - unsigned int result; - glGetQueryObjectuiv(g_query_state.queries[i], GL_QUERY_RESULT, &result); - if (result > 0) { - if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) { - int maxhits = g_query_state.bufsize / 4; - - if (hits < maxhits) { - g_query_state.buffer[hits * 4] = 1; - g_query_state.buffer[hits * 4 + 1] = 0xFFFF; - g_query_state.buffer[hits * 4 + 2] = 0xFFFF; - g_query_state.buffer[hits * 4 + 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 * 4 + 3] == g_query_state.id[i]) { - g_query_state.buffer[j * 4 + 1] = 0; - g_query_state.buffer[j * 4 + 2] = 0; - } - } - break; - } - } + case ALGO_GL_QUERY: + { + hits = gpu_select_query_end(); + break; + } + default: /* ALGO_GL_PICK */ + { + hits = gpu_select_pick_end(); + break; } - - glDeleteQueries(g_query_state.num_of_queries, g_query_state.queries); - MEM_freeN(g_query_state.queries); - MEM_freeN(g_query_state.id); - glPopAttrib(); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } - g_query_state.select_is_active = false; + g_select_state.select_is_active = false; return hits; } @@ -253,10 +181,43 @@ unsigned int GPU_select_end(void) */ bool GPU_select_query_check_active(void) { - return ((U.gpu_select_method == USER_SELECT_USE_OCCLUSION_QUERY) || - ((U.gpu_select_method == USER_SELECT_AUTO) && - (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY) || - /* unsupported by nouveau, gallium 0.4, see: T47940 */ - GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)))); + return ELEM(U.gpu_select_method, USER_SELECT_USE_OCCLUSION_QUERY, USER_SELECT_AUTO); +} + +/* ---------------------------------------------------------------------------- + * Caching + * + * Support multiple begin/end's as long as they are within the initial region. + * Currently only used by ALGO_GL_PICK. + */ + +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(); + } +} + +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(); + } +} + +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; +} +bool GPU_select_is_cached(void) +{ + return g_select_state.use_cache && gpu_select_pick_is_cached(); } diff --git a/source/blender/gpu/intern/gpu_select_pick.c b/source/blender/gpu/intern/gpu_select_pick.c new file mode 100644 index 00000000000..780ffd82671 --- /dev/null +++ b/source/blender/gpu/intern/gpu_select_pick.c @@ -0,0 +1,740 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2017 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_select_pick.c + * \ingroup gpu + * + * Custom select code for picking small regions (not efficient for large regions). + * `gpu_select_pick_*` API. + */ +#include <string.h> +#include <stdlib.h> +#include <float.h> + +#include "GPU_select.h" +#include "GPU_extensions.h" +#include "GPU_glew.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_rect.h" +#include "BLI_listbase.h" +#include "BLI_math_vector.h" +#include "BLI_utildefines.h" + +#include "gpu_select_private.h" + +#include "BLI_strict_flags.h" + +/* #define DEBUG_PRINT */ + +/* Alloc number for depths */ +#define ALLOC_DEPTHS 200 + +/* Z-depth of cleared depth buffer */ +#define DEPTH_MAX 0xffffffff + +/* ---------------------------------------------------------------------------- + * SubRectStride + */ + +/* For looping over a sub-region of a rect, could be moved into 'rct.c'*/ +typedef struct SubRectStride { + unsigned int start; /* start here */ + unsigned int span; /* read these */ + unsigned int span_len; /* len times (read span 'len' times). */ + unsigned int skip; /* skip those */ +} SubRectStride; + +/* we may want to change back to float if uint isn't well supported */ +typedef unsigned int depth_t; + +/** + * Calculate values needed for looping over a sub-region (smaller buffer within a larger buffer). + * + * 'src' must be bigger than 'dst'. + */ +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->ymax >= dst->ymax && src->ymax >= dst->ymax); + BLI_assert(x >= 0 && y >= 0); + + r_sub->start = (unsigned int)((src_x * y) + x); + r_sub->span = (unsigned int)dst_x; + r_sub->span_len = (unsigned int)dst_y; + r_sub->skip = (unsigned int)(src_x - dst_x); +} + +/** + * Ignore depth clearing as a change, + * only check if its been changed _and_ filled in (ignore clearing since XRAY does this). + */ +BLI_INLINE bool depth_is_filled(const depth_t *prev, const depth_t *curr) +{ + return (*prev != *curr) && (*curr != DEPTH_MAX); +} + +/* ---------------------------------------------------------------------------- + * DepthBufCache + * + * Result of reading glReadPixels, + * use for both cache and non-cached storage. + */ + +/* store result of glReadPixels */ +typedef struct DepthBufCache { + struct DepthBufCache *next, *prev; + unsigned int id; + depth_t buf[0]; +} DepthBufCache; + +static DepthBufCache *depth_buf_malloc(unsigned int rect_len) +{ + 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, + unsigned int rect_len) +{ + const depth_t *curr = rect_depth->buf; + for (unsigned int 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) +{ + const depth_t *curr = rect_depth->buf + sub_rect->start; + for (unsigned int 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, + unsigned int rect_len) +{ +#if 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 (unsigned int 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) +{ + /* 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 (unsigned int 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; +} + +/* ---------------------------------------------------------------------------- + * DepthID + * + * Internal structure for storing hits. + */ + +typedef struct DepthID { + unsigned int 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; + } +} + +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; + } +} + +/* depth sorting */ +typedef struct GPUPickState { + /* cache on initialization */ + unsigned int (*buffer)[4]; + + /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ + unsigned int 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; + unsigned int 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; + unsigned int 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; + unsigned int hits_len; + unsigned int hits_len_alloc; + } all; + + /* GPU_SELECT_PICK_NEAREST */ + struct { + unsigned int *rect_id; + } nearest; + }; +} GPUPickState; + + +static GPUPickState g_pick_state = {0}; + +void gpu_select_pick_begin( + unsigned int (*buffer)[4], unsigned int bufsize, + const rcti *input, char mode) +{ + 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); +#endif + + ps->bufsize = bufsize; + ps->buffer = buffer; + ps->mode = mode; + + const unsigned int rect_len = (unsigned int)(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) { + + glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT); + /* disable writing to the framebuffer */ + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + + if (mode == GPU_SELECT_PICK_ALL) { + glDepthFunc(GL_ALWAYS); + } + else { + glDepthFunc(GL_LEQUAL); + } + + float viewport[4]; + glGetFloatv(GL_SCISSOR_BOX, viewport); + + 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); + + 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); + + /* 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 */ +#if 0 + glReadPixels(UNPACK4(ps->gl.clip_readpixels), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, ps->gl.rect_depth->buf); +#else + for (unsigned int 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(unsigned int) * ps->dst.rect_len, __func__); + memset(ps->nearest.rect_id, 0xff, sizeof(unsigned int) * ps->dst.rect_len); + } +} + +/** + * Given 2x depths, we know are different - update the depth information + * use for both cached/uncached depth buffers. + */ +static void gpu_select_load_id_pass_all(const DepthBufCache *rect_curr) +{ + GPUPickState *ps = &g_pick_state; + const unsigned int 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 unsigned int rect_len = ps->src.rect_len; + for (unsigned int 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 (unsigned int 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; +} + +static void gpu_select_load_id_pass_nearest(const DepthBufCache *rect_prev, const DepthBufCache *rect_curr) +{ + GPUPickState *ps = &g_pick_state; + const unsigned int id = rect_curr->id; + /* keep track each pixels ID in 'nearest.rect_id' */ + if (id != SELECT_ID_NONE) { + unsigned int *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 unsigned int rect_len = ps->src.rect_len; + for (unsigned int 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 (unsigned int 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(unsigned int id) +{ + GPUPickState *ps = &g_pick_state; + if (ps->gl.is_init) { + const unsigned int 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; +} + +unsigned int gpu_select_pick_end(void) +{ + GPUPickState *ps = &g_pick_state; + +#ifdef DEBUG_PRINT + 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); + } + + glPopAttrib(); + 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; + } + + unsigned int maxhits = g_pick_state.bufsize; + DepthID *depth_data; + unsigned int 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) */ + unsigned int 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 unsigned int 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 (unsigned int i = 0; i < ps->src.rect_len; i++) { + EVAL_TEST(i, i); + } + } + else { + /* same as above but different rect sizes */ + unsigned int i_src = ps->cache.sub_rect.start, i_dst = 0; + for (unsigned int j = 0; j < ps->cache.sub_rect.span_len; j++) { + const unsigned int 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 (unsigned int 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) */ + unsigned int hits = 0; + + if (depth_data_len > maxhits) { + hits = (unsigned int)-1; + } + else { + /* leave sorting up to the caller */ + qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp); + + for (unsigned int i = 0; i < depth_data_len; i++) { +#ifdef DEBUG_PRINT + 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; +} + +/* ---------------------------------------------------------------------------- + * Caching + * + * Support multiple begin/end's reusing depth buffers. + */ + +void gpu_select_pick_cache_begin(void) +{ + BLI_assert(g_pick_state.use_cache == false); +#ifdef DEBUG_PRINT + printf("%s\n", __func__); +#endif + 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)); +#endif + g_pick_state.use_cache = false; + g_pick_state.is_cached = false; + + BLI_freelistN(&g_pick_state.cache.bufs); +} + +/* is drawing needed? */ +bool gpu_select_pick_is_cached(void) +{ + 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; +#ifdef DEBUG_PRINT + 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); + } + } + } + } +} diff --git a/source/blender/gpu/intern/gpu_select_private.h b/source/blender/gpu/intern/gpu_select_private.h new file mode 100644 index 00000000000..8935bd7b253 --- /dev/null +++ b/source/blender/gpu/intern/gpu_select_private.h @@ -0,0 +1,53 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Antony Riakiotakis. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_select_private.h + * \ingroup gpu + * + * Selection implementations. + */ + +#ifndef __GPU_SELECT_PRIVATE_H__ +#define __GPU_SELECT_PRIVATE_H__ + +/* gpu_select_pick */ +void gpu_select_pick_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode); +bool gpu_select_pick_load_id(unsigned int id); +unsigned int gpu_select_pick_end(void); + +void gpu_select_pick_cache_begin(void); +void gpu_select_pick_cache_end(void); +bool gpu_select_pick_is_cached(void); +void gpu_select_pick_cache_load_id(void); + +/* gpu_select_sample_query */ +void gpu_select_query_begin(unsigned int (*buffer)[4], unsigned int bufsize, const rcti *input, char mode, int oldhits); +bool gpu_select_query_load_id(unsigned int id); +unsigned int gpu_select_query_end(void); + + +#define SELECT_ID_NONE ((unsigned int)0xffffffff) + +#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 new file mode 100644 index 00000000000..ba5fefc5227 --- /dev/null +++ b/source/blender/gpu/intern/gpu_select_sample_query.c @@ -0,0 +1,209 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2014 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Antony Riakiotakis. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_select_sample_query.c + * \ingroup gpu + * + * Interface for accessing gpu-related methods for selection. The semantics will be + * similar to glRenderMode(GL_SELECT) since the goal is to maintain compatibility. + */ + +#include <stdlib.h> + +#include "GPU_select.h" +#include "GPU_extensions.h" +#include "GPU_glew.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_rect.h" + +#include "BLI_utildefines.h" + +#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 */ + unsigned int *queries; + /* array holding the id corresponding to each query */ + unsigned int *id; + /* number of queries in *queries and *id */ + unsigned int num_of_queries; + /* index to the next query to start */ + unsigned int active_query; + /* cache on initialization */ + unsigned int (*buffer)[4]; + /* buffer size (stores number of integers, for actual size multiply by sizeof integer)*/ + unsigned int bufsize; + /* mode of operation */ + char mode; + unsigned int index; + int oldhits; +} GPUQueryState; + +static GPUQueryState g_query_state = {0}; + + +void gpu_select_query_begin( + unsigned int (*buffer)[4], unsigned int 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); + + glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_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 scissor so that our geometry doesn't + * get rejected before the depth test. Should probably cull rect against + * scissor for viewport but this is a rare case I think */ + glGetFloatv(GL_SCISSOR_BOX, 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(unsigned int 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 && 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; +} + +unsigned int gpu_select_query_end(void) +{ + int i; + + unsigned int hits = 0; + const unsigned int 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++) { + unsigned int result; + 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); + glPopAttrib(); + 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 295182b3153..40653622d12 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -34,11 +34,11 @@ #include "BKE_global.h" #include "GPU_compositing.h" -#include "GPU_debug.h" #include "GPU_extensions.h" #include "GPU_shader.h" #include "GPU_uniformbuffer.h" #include "GPU_texture.h" +#include "GPU_matrix.h" #include "gpu_shader_private.h" @@ -50,7 +50,9 @@ extern char datatoc_gpu_shader_depth_only_frag_glsl[]; extern char datatoc_gpu_shader_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_checker_frag_glsl[]; +extern char datatoc_gpu_shader_diag_stripes_frag_glsl[]; extern char datatoc_gpu_shader_simple_lighting_frag_glsl[]; +extern char datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_frag_glsl[]; extern char datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl[]; extern char datatoc_gpu_shader_2D_vert_glsl[]; @@ -61,6 +63,7 @@ extern char datatoc_gpu_shader_2D_image_vert_glsl[]; extern char datatoc_gpu_shader_3D_image_vert_glsl[]; extern char datatoc_gpu_shader_image_color_frag_glsl[]; +extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[]; extern char datatoc_gpu_shader_image_interlace_frag_glsl[]; extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[]; extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[]; @@ -75,25 +78,34 @@ extern char datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl[]; extern char datatoc_gpu_shader_instance_vert_glsl[]; extern char datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl[]; extern char datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl[]; +extern char datatoc_gpu_shader_instance_screen_aligned_axis_name_vert_glsl[]; +extern char datatoc_gpu_shader_instance_camera_vert_glsl[]; +extern char datatoc_gpu_shader_instance_distance_line_vert_glsl[]; +extern char datatoc_gpu_shader_instance_edges_variying_color_geom_glsl[]; +extern char datatoc_gpu_shader_instance_edges_variying_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_groundpoint_vert_glsl[]; extern char datatoc_gpu_shader_3D_groundline_geom_glsl[]; extern char datatoc_gpu_shader_point_uniform_color_frag_glsl[]; -extern char datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl[]; -extern char datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl[]; -extern char datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_aa_frag_glsl[]; +extern char datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl[]; +extern char datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl[]; extern char datatoc_gpu_shader_point_varying_color_frag_glsl[]; extern char datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl[]; extern char datatoc_gpu_shader_3D_point_varying_size_vert_glsl[]; extern char datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl[]; -extern char datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl[]; -extern char datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl[]; +extern char datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl[]; extern char datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl[]; -extern char datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl[]; -extern char datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl[]; -extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl[]; +extern char datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl[]; + +extern char datatoc_gpu_shader_2D_line_dashed_vert_glsl[]; +extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[]; extern char datatoc_gpu_shader_edges_front_back_persp_vert_glsl[]; extern char datatoc_gpu_shader_edges_front_back_persp_geom_glsl[]; @@ -115,7 +127,7 @@ extern char datatoc_gpu_shader_vsm_store_vert_glsl[]; extern char datatoc_gpu_shader_vsm_store_frag_glsl[]; extern char datatoc_gpu_shader_sep_gaussian_blur_vert_glsl[]; extern char datatoc_gpu_shader_sep_gaussian_blur_frag_glsl[]; -extern char datatoc_gpu_shader_fx_vert_glsl[]; +extern char datatoc_gpu_shader_fullscreen_vert_glsl[]; extern char datatoc_gpu_shader_fx_ssao_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_frag_glsl[]; extern char datatoc_gpu_shader_fx_dof_vert_glsl[]; @@ -484,6 +496,8 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, } #endif + shader->interface = ShaderInterface_create(shader->program); + return shader; } @@ -492,6 +506,7 @@ void GPU_shader_bind(GPUShader *shader) BLI_assert(shader && shader->program); glUseProgram(shader->program); + gpuBindMatrices(shader->program); } void GPU_shader_unbind(void) @@ -515,6 +530,9 @@ void GPU_shader_free(GPUShader *shader) if (shader->uniform_interface) MEM_freeN(shader->uniform_interface); + if (shader->interface) + ShaderInterface_discard(shader->interface); + MEM_freeN(shader); } @@ -532,18 +550,23 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name) return glGetUniformBlockIndex(shader->program, name); } -void *GPU_shader_get_interface(GPUShader *shader) +void *GPU_fx_shader_get_interface(GPUShader *shader) { return shader->uniform_interface; } +void *GPU_shader_get_interface(GPUShader *shader) +{ + return shader->interface; +} + /* Clement : Temp */ int GPU_shader_get_program(GPUShader *shader) { return (int)shader->program; } -void GPU_shader_set_interface(GPUShader *shader, void *interface) +void GPU_fx_shader_set_interface(GPUShader *shader, void *interface) { shader->uniform_interface = interface; } @@ -665,6 +688,7 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_edges_overlay_frag_glsl, datatoc_gpu_shader_edges_overlay_geom_glsl }, [GPU_SHADER_SIMPLE_LIGHTING] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_simple_lighting_frag_glsl }, + [GPU_SHADER_SIMPLE_LIGHTING_SMOOTH_COLOR] = { datatoc_gpu_shader_3D_smooth_color_vert_glsl, datatoc_gpu_shader_simple_lighting_smooth_color_frag_glsl }, [GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_image_vert_glsl, datatoc_gpu_shader_image_mask_uniform_color_frag_glsl }, @@ -679,6 +703,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_image_interlace_frag_glsl }, [GPU_SHADER_2D_CHECKER] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_checker_frag_glsl }, + [GPU_SHADER_2D_DIAG_STRIPES] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_diag_stripes_frag_glsl }, + [GPU_SHADER_2D_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_2D_FLAT_COLOR] = { datatoc_gpu_shader_2D_flat_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, @@ -686,6 +712,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) datatoc_gpu_shader_2D_smooth_color_frag_glsl }, [GPU_SHADER_2D_IMAGE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, datatoc_gpu_shader_image_color_frag_glsl }, + [GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR] = { datatoc_gpu_shader_2D_image_vert_glsl, + datatoc_gpu_shader_image_shuffle_color_frag_glsl }, [GPU_SHADER_3D_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_3D_FLAT_COLOR] = { datatoc_gpu_shader_3D_flat_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, @@ -700,23 +728,38 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_clipped_uniform_color_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, + [GPU_SHADER_2D_LINE_DASHED_COLOR] = { datatoc_gpu_shader_2D_line_dashed_vert_glsl, + datatoc_gpu_shader_2D_line_dashed_frag_glsl }, + + [GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR] = + { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_simple_lighting_frag_glsl}, + [GPU_SHADER_3D_OBJECTSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_objectspace_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, [GPU_SHADER_3D_SCREENSPACE_VARIYING_COLOR] = { datatoc_gpu_shader_instance_screenspace_variying_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_3D_INSTANCE_SCREEN_ALIGNED_AXIS] = { datatoc_gpu_shader_instance_screen_aligned_axis_name_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + + [GPU_SHADER_CAMERA] = { datatoc_gpu_shader_instance_camera_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, + [GPU_SHADER_DISTANCE_LINES] = { datatoc_gpu_shader_instance_distance_line_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl}, [GPU_SHADER_2D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_2D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, [GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_2D_point_varying_size_varying_color_vert_glsl, datatoc_gpu_shader_point_varying_color_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] = - { datatoc_gpu_shader_2D_point_uniform_size_smooth_vert_glsl, - datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] = - { datatoc_gpu_shader_2D_point_uniform_size_outline_smooth_vert_glsl, - datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl }, - [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_SMOOTH] = - { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert_glsl, - datatoc_gpu_shader_point_varying_color_outline_smooth_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, + [GPU_SHADER_2D_POINT_UNIFORM_SIZE_VARYING_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert_glsl, + datatoc_gpu_shader_point_varying_color_outline_aa_frag_glsl }, [GPU_SHADER_3D_POINT_FIXED_SIZE_UNIFORM_COLOR] = { datatoc_gpu_shader_3D_vert_glsl, datatoc_gpu_shader_point_uniform_color_frag_glsl }, [GPU_SHADER_3D_POINT_FIXED_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_fixed_size_varying_color_vert_glsl, @@ -726,23 +769,27 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR] = { datatoc_gpu_shader_3D_point_varying_size_varying_color_vert_glsl, datatoc_gpu_shader_point_varying_color_frag_glsl }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_SMOOTH] = - { datatoc_gpu_shader_3D_point_uniform_size_smooth_vert_glsl, - datatoc_gpu_shader_point_uniform_color_smooth_frag_glsl }, - [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_SMOOTH] = - { datatoc_gpu_shader_3D_point_uniform_size_outline_smooth_vert_glsl, - datatoc_gpu_shader_point_uniform_color_outline_smooth_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_aa_frag_glsl }, + [GPU_SHADER_3D_POINT_UNIFORM_SIZE_UNIFORM_COLOR_OUTLINE_AA] = + { datatoc_gpu_shader_3D_point_uniform_size_outline_aa_vert_glsl, + datatoc_gpu_shader_point_uniform_color_outline_aa_frag_glsl }, [GPU_SHADER_INSTANCE_UNIFORM_COLOR] = { datatoc_gpu_shader_instance_vert_glsl, datatoc_gpu_shader_uniform_color_frag_glsl }, [GPU_SHADER_INSTANCE_VARIYING_COLOR_VARIYING_SIZE] = { datatoc_gpu_shader_instance_variying_size_variying_color_vert_glsl, datatoc_gpu_shader_flat_color_frag_glsl }, + [GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR] = { datatoc_gpu_shader_instance_edges_variying_color_vert_glsl, + datatoc_gpu_shader_flat_color_frag_glsl, + datatoc_gpu_shader_instance_edges_variying_color_geom_glsl}, }; if (builtin_shaders[shader] == NULL) { /* just a few special cases */ const char *defines = (shader == GPU_SHADER_SMOKE_COBA) ? "#define USE_COBA;\n" : - (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" : NULL; + (shader == GPU_SHADER_SIMPLE_LIGHTING) ? "#define USE_NORMALS;\n" : + (shader == GPU_SHADER_3D_OBJECTSPACE_SIMPLE_LIGHTING_VARIYING_COLOR) ? "#define USE_INSTANCE_COLOR;\n" : NULL; const GPUShaderStages *stages = builtin_shader_stages + shader; @@ -754,14 +801,6 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) stages = &legacy_fancy_edges; } - if (shader == GPU_SHADER_EDGES_FRONT_BACK_PERSP && !GLEW_VERSION_3_2) { - /* TODO: remove after switch to core profile (maybe) */ - static const GPUShaderStages legacy_fancy_edges = - { datatoc_gpu_shader_edges_front_back_persp_legacy_vert_glsl, - datatoc_gpu_shader_flat_color_alpha_test_0_frag_glsl }; - stages = &legacy_fancy_edges; - } - /* common case */ builtin_shaders[shader] = GPU_shader_create(stages->vert, stages->frag, stages->geom, NULL, defines, 0, 0, 0); @@ -792,7 +831,7 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp) switch (effect) { case GPU_SHADER_FX_SSAO: - shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); + shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_ssao_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0); break; case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE: @@ -837,7 +876,7 @@ GPUShader *GPU_shader_get_builtin_fx_shader(int effect, bool persp) break; case GPU_SHADER_FX_DEPTH_RESOLVE: - shader = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0); + shader = GPU_shader_create(datatoc_gpu_shader_fullscreen_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0); break; } diff --git a/source/blender/gpu/intern/gpu_shader_private.h b/source/blender/gpu/intern/gpu_shader_private.h index d5193e09aa4..10ffc17f0d5 100644 --- a/source/blender/gpu/intern/gpu_shader_private.h +++ b/source/blender/gpu/intern/gpu_shader_private.h @@ -25,6 +25,7 @@ #pragma once #include "GPU_glew.h" +#include "gawain/shader_interface.h" struct GPUShader { GLuint program; /* handle for full program (links shader stages below) */ @@ -33,8 +34,8 @@ struct GPUShader { GLuint geometry; /* handle for geometry shader */ GLuint fragment; /* handle for fragment shader */ - int totattrib; /* total number of attributes */ - int uniforms; /* required uniforms */ - void *uniform_interface; /* cached uniform interface for shader. Data depends on shader */ + /* NOTE: ^-- only FX compositing shaders use this */ + + ShaderInterface *interface; /* cached uniform & attrib interface for shader */ }; diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c index 3513250993e..88dbe0c2ed9 100644 --- a/source/blender/gpu/intern/gpu_texture.c +++ b/source/blender/gpu/intern/gpu_texture.c @@ -62,19 +62,30 @@ struct GPUTexture { GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */ int fb_attachment; /* slot the texture is attached to */ bool depth; /* is a depth texture? */ + bool stencil; /* is a stencil texture? */ }; -static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, bool *is_depth) +static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, GLenum *format, GLenum *data_format, bool *is_depth, bool *is_stencil) { if (data_type == GPU_DEPTH_COMPONENT24 || data_type == GPU_DEPTH_COMPONENT16 || data_type == GPU_DEPTH_COMPONENT32F) { *is_depth = true; + *is_stencil = false; + *data_format = GL_FLOAT; *format = GL_DEPTH_COMPONENT; } + else if (data_type == GPU_DEPTH24_STENCIL8) { + *is_depth = true; + *is_stencil = true; + *data_format = GL_UNSIGNED_INT_24_8; + *format = GL_DEPTH_STENCIL; + } else { *is_depth = false; + *is_stencil = false; + *data_format = GL_FLOAT; switch (components) { case 1: *format = GL_RED; break; @@ -93,9 +104,10 @@ static GLenum GPU_texture_get_format(int components, GPUTextureFormat data_type, case GPU_RG32F: return GL_RG32F; case GPU_RG16F: return GL_RG16F; case GPU_RGBA8: return GL_RGBA8; + case GPU_R16F: return GL_R16F; case GPU_R8: return GL_R8; /* Special formats texture & renderbuffer */ - /* ** Add Format here **/ + case GPU_DEPTH24_STENCIL8: return GL_DEPTH24_STENCIL8; /* Texture only format */ /* ** Add Format here **/ /* Special formats texture only */ @@ -148,20 +160,20 @@ static float *GPU_texture_3D_rescale(GPUTexture *tex, int w, int h, int d, int c /* 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 format, int channels, - bool try_rescale, const float *fpixels, float **rescaled_fpixels) + GPUTexture *tex, GLenum proxy, GLenum internalformat, GLenum format, GLenum data_format, + int channels, bool try_rescale, const float *fpixels, float **rescaled_fpixels) { int r_width; switch (proxy) { case GL_PROXY_TEXTURE_1D: - glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL); + glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL); break; case GL_PROXY_TEXTURE_2D: - glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL); + glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL); break; case GL_PROXY_TEXTURE_3D: - glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL); + glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL); break; } @@ -182,11 +194,11 @@ static bool GPU_texture_try_alloc( if (tex->d == 0 && proxy == GL_PROXY_TEXTURE_3D) break; if (proxy == GL_PROXY_TEXTURE_1D) - glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, GL_FLOAT, NULL); + glTexImage1D(proxy, 0, internalformat, tex->w, 0, format, data_format, NULL); else if (proxy == GL_PROXY_TEXTURE_2D) - glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, NULL); + glTexImage2D(proxy, 0, internalformat, tex->w, tex->h, 0, format, data_format, NULL); else if (proxy == GL_PROXY_TEXTURE_3D) - glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, NULL); + glTexImage3D(proxy, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, NULL); glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width); } @@ -213,7 +225,7 @@ static GPUTexture *GPU_texture_create_nD( GPUTextureFormat data_type, int components, int samples, const bool can_rescale, char err_out[256]) { - GLenum format, internalformat, proxy; + GLenum format, internalformat, proxy, data_format; float *rescaled_fpixels = NULL; const float *pix; bool valid; @@ -228,6 +240,7 @@ static GPUTexture *GPU_texture_create_nD( tex->d = d; tex->number = -1; tex->refcount = 1; + tex->fb_attachment = -1; if (n == 1) { if (h == 0) @@ -245,12 +258,10 @@ static GPUTexture *GPU_texture_create_nD( tex->target_base = tex->target = GL_TEXTURE_3D; } - tex->fb_attachment = -1; - if (samples && n == 2 && d == 0) tex->target = GL_TEXTURE_2D_MULTISAMPLE; - internalformat = GPU_texture_get_format(components, data_type, &format, &tex->depth); + internalformat = GPU_texture_get_format(components, data_type, &format, &data_format, &tex->depth, &tex->stencil); /* Generate Texture object */ glGenTextures(1, &tex->bindcode); @@ -278,7 +289,7 @@ static GPUTexture *GPU_texture_create_nD( proxy = GL_PROXY_TEXTURE_1D; } - valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, components, can_rescale, fpixels, + valid = GPU_texture_try_alloc(tex, proxy, internalformat, format, data_format, components, can_rescale, fpixels, &rescaled_fpixels); if (!valid) { @@ -294,7 +305,7 @@ static GPUTexture *GPU_texture_create_nD( pix = (rescaled_fpixels) ? rescaled_fpixels : fpixels; if (tex->target == GL_TEXTURE_1D) { - glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, GL_FLOAT, pix); + glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, data_format, pix); } else if (tex->target == GL_TEXTURE_1D_ARRAY || tex->target == GL_TEXTURE_2D || @@ -303,14 +314,14 @@ static GPUTexture *GPU_texture_create_nD( if (samples) { glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); if (pix) - glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, GL_FLOAT, pix); + glTexSubImage2D(tex->target, 0, 0, 0, tex->w, tex->h, format, data_format, pix); } else { - glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, GL_FLOAT, pix); + glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, data_format, pix); } } else { - glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, GL_FLOAT, pix); + glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->d, 0, format, data_format, pix); } if (rescaled_fpixels) @@ -494,6 +505,11 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]) return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, 0, false, err_out); } +GPUTexture *GPU_texture_create_depth_with_stencil(int w, int h, char err_out[256]) +{ + return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH24_STENCIL8, 1, 0, false, err_out); +} + GPUTexture *GPU_texture_create_depth_multisample(int w, int h, int samples, char err_out[256]) { return GPU_texture_create_nD(w, h, 0, 2, NULL, GPU_DEPTH_COMPONENT24, 1, samples, false, err_out); @@ -708,11 +724,16 @@ int GPU_texture_height(const GPUTexture *tex) return tex->h; } -int GPU_texture_depth(const GPUTexture *tex) +bool GPU_texture_depth(const GPUTexture *tex) { return tex->depth; } +bool GPU_texture_stencil(const GPUTexture *tex) +{ + return tex->stencil; +} + int GPU_texture_opengl_bindcode(const GPUTexture *tex) { return tex->bindcode; diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 62ba06b7a0a..7c2cb8cd4bb 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -33,11 +33,14 @@ #include <string.h> +#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_string.h" #include "DNA_vec_types.h" +#include "BKE_global.h" + #include "GPU_framebuffer.h" #include "GPU_glew.h" #include "GPU_immediate.h" @@ -55,98 +58,172 @@ struct GPUViewport { GPUTexture *debug_depth; int size[2]; - /* Viewport Buffer Storage */ - /* TODO indentify to what engine conf are theses buffers */ - DefaultFramebufferList *fbl; - DefaultTextureList *txl; - DefaultPassList *psl; - StorageList *stl; + ListBase data; /* ViewportEngineData wrapped in LinkData */ + unsigned int data_hash; /* If hash mismatch we free all ViewportEngineData in this viewport */ - char engine_name[32]; + FramebufferList *fbl; + TextureList *txl; }; -static void GPU_viewport_buffers_free(GPUViewport *viewport); -static void GPU_viewport_passes_free(GPUViewport *viewport); -static void GPU_viewport_storage_free(GPUViewport *viewport); +static void GPU_viewport_buffers_free(FramebufferList *fbl, TextureList *txl); +static void GPU_viewport_storage_free(StorageList *stl); +static void GPU_viewport_passes_free(PassList *psl); GPUViewport *GPU_viewport_create(void) { GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); viewport->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); viewport->txl = MEM_callocN(sizeof(TextureList), "TextureList"); - viewport->psl = MEM_callocN(sizeof(PassList), "PassList"); - viewport->stl = MEM_callocN(sizeof(StorageList), "StorageList"); viewport->size[0] = viewport->size[1] = -1; return viewport; } -void GPU_viewport_get_engine_data(GPUViewport *viewport, void **fbs, void **txs, void **pss, void **str) +void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) { - *fbs = viewport->fbl; - *txs = viewport->txl; - *pss = viewport->psl; - *str = viewport->stl; + LinkData *ld = MEM_callocN(sizeof(LinkData), "LinkData"); + ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); + data->engine_type = engine_type; + + data->fbl = MEM_callocN(sizeof(FramebufferList), "FramebufferList"); + data->txl = MEM_callocN(sizeof(TextureList), "TextureList"); + data->psl = MEM_callocN(sizeof(PassList), "PassList"); + data->stl = MEM_callocN(sizeof(StorageList), "StorageList"); + + ld->data = data; + BLI_addtail(&viewport->data, ld); + + return data; } -void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect, const char *engine) +static void GPU_viewport_engines_data_free(GPUViewport *viewport) { - /* add one pixel because of scissor test */ - int rect_w = BLI_rcti_size_x(rect) + 1, rect_h = BLI_rcti_size_y(rect) + 1; + LinkData *next; + for (LinkData *link = viewport->data.first; link; link = next) { + next = link->next; + ViewportEngineData *data = link->data; -#ifndef WITH_VIEWPORT_CACHE_TEST - /* TODO for testing only, we need proper cache invalidation */ - GPU_viewport_passes_free(viewport); -#endif + GPU_viewport_buffers_free(data->fbl, data->txl); + GPU_viewport_passes_free(data->psl); + GPU_viewport_storage_free(data->stl); + + MEM_freeN(data->fbl); + MEM_freeN(data->txl); + MEM_freeN(data->psl); + MEM_freeN(data->stl); + + MEM_freeN(data); + + BLI_remlink(&viewport->data, link); + MEM_freeN(link); + } +} + +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; +} + +void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport) +{ + return viewport->fbl; +} - if (!STREQ(engine, viewport->engine_name)) { - GPU_viewport_storage_free(viewport); - GPU_viewport_buffers_free(viewport); +void *GPU_viewport_texture_list_get(GPUViewport *viewport) +{ + return viewport->txl; +} + +void GPU_viewport_size_get(GPUViewport *viewport, int *size) +{ + size[0] = viewport->size[0]; + size[1] = viewport->size[1]; +} + +bool GPU_viewport_cache_validate(GPUViewport *viewport, unsigned int hash) +{ + bool dirty = false; + + /* TODO for testing only, we need proper cache invalidation */ + if (G.debug_value != 666 && G.debug_value != 667) { + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + GPU_viewport_passes_free(data->psl); + } + dirty = true; + } - BLI_strncpy(viewport->engine_name, engine, 32); + if (viewport->data_hash != hash) { + GPU_viewport_engines_data_free(viewport); + dirty = true; } - if (viewport->fbl->default_fb) { + viewport->data_hash = hash; + + return dirty; +} + +void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect) +{ + DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; + DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl; + + /* 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; + + if (dfbl->default_fb) { if (rect_w != viewport->size[0] || rect_h != viewport->size[1]) { - GPU_viewport_buffers_free(viewport); + GPU_viewport_buffers_free(viewport->fbl, viewport->txl); + + for (LinkData *link = viewport->data.first; link; link = link->next) { + ViewportEngineData *data = link->data; + GPU_viewport_buffers_free(data->fbl, data->txl); + } } } - if (!viewport->fbl->default_fb) { + if (!dfbl->default_fb) { bool ok = true; viewport->size[0] = rect_w; viewport->size[1] = rect_h; - viewport->fbl->default_fb = GPU_framebuffer_create(); - if (!viewport->fbl->default_fb) { + dfbl->default_fb = GPU_framebuffer_create(); + if (!dfbl->default_fb) { ok = false; goto cleanup; } /* Color */ /* No multi samples for now */ - viewport->txl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL); - if (!viewport->txl->color) { + dtxl->color = GPU_texture_create_2D(rect_w, rect_h, NULL, NULL); + if (!dtxl->color) { ok = false; goto cleanup; } - if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->color, 0)) { + if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->color, 0)) { ok = false; goto cleanup; } /* Depth */ - viewport->txl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL); - if (!viewport->txl->depth) { + dtxl->depth = GPU_texture_create_depth(rect_w, rect_h, NULL); + if (!dtxl->depth) { ok = false; goto cleanup; } - else if (!GPU_framebuffer_texture_attach(viewport->fbl->default_fb, viewport->txl->depth, 0)) { + else if (!GPU_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0)) { ok = false; goto cleanup; } - else if (!GPU_framebuffer_check_valid(viewport->fbl->default_fb, NULL)) { + else if (!GPU_framebuffer_check_valid(dfbl->default_fb, NULL)) { ok = false; goto cleanup; } @@ -161,12 +238,14 @@ cleanup: GPU_framebuffer_restore(); } - GPU_framebuffer_slots_bind(viewport->fbl->default_fb, 0); + GPU_framebuffer_slots_bind(dfbl->default_fb, 0); } static void draw_ofs_to_screen(GPUViewport *viewport) { - GPUTexture *color = viewport->txl->color; + DefaultTextureList *dtxl = (DefaultTextureList *)viewport->txl; + + GPUTexture *color = dtxl->color; const float w = (float)GPU_texture_width(color); const float h = (float)GPU_texture_height(color); @@ -176,12 +255,11 @@ static void draw_ofs_to_screen(GPUViewport *viewport) unsigned pos = add_attrib(format, "pos", GL_FLOAT, 2, KEEP_FLOAT); immBindBuiltinProgram(GPU_SHADER_3D_IMAGE_MODULATE_ALPHA); - GPU_texture_bind(color, 0); immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - immBegin(GL_QUADS, 4); + immBegin(GL_TRIANGLE_STRIP, 4); immAttrib2f(texcoord, 0.0f, 0.0f); immVertex2f(pos, 0.0f, 0.0f); @@ -189,12 +267,12 @@ static void draw_ofs_to_screen(GPUViewport *viewport) immAttrib2f(texcoord, 1.0f, 0.0f); immVertex2f(pos, w, 0.0f); - immAttrib2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); - immAttrib2f(texcoord, 0.0f, 1.0f); immVertex2f(pos, 0.0f, h); + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + immEnd(); GPU_texture_unbind(color); @@ -204,21 +282,22 @@ static void draw_ofs_to_screen(GPUViewport *viewport) void GPU_viewport_unbind(GPUViewport *viewport) { - if (viewport->fbl->default_fb) { + DefaultFramebufferList *dfbl = (DefaultFramebufferList *)viewport->fbl; + + if (dfbl->default_fb) { GPU_framebuffer_texture_unbind(NULL, NULL); GPU_framebuffer_restore(); glEnable(GL_SCISSOR_TEST); + glDisable(GL_DEPTH_TEST); /* This might be bandwidth limiting */ draw_ofs_to_screen(viewport); } } -static void GPU_viewport_buffers_free(GPUViewport *viewport) +static void GPU_viewport_buffers_free(FramebufferList *fbl, TextureList *txl) { - FramebufferList *fbl = (FramebufferList *)viewport->fbl; - TextureList *txl = (TextureList *)viewport->txl; int i; for (i = MAX_BUFFERS - 1; i > -1; --i) { GPUFrameBuffer *fb = fbl->framebuffers[i]; @@ -236,10 +315,8 @@ static void GPU_viewport_buffers_free(GPUViewport *viewport) } } -static void GPU_viewport_storage_free(GPUViewport *viewport) +static void GPU_viewport_storage_free(StorageList *stl) { - StorageList *stl = (StorageList *)viewport->stl; - for (int i = MAX_STORAGE - 1; i > -1; --i) { void *storage = stl->storage[i]; if (storage) { @@ -249,12 +326,9 @@ static void GPU_viewport_storage_free(GPUViewport *viewport) } } -static void GPU_viewport_passes_free(GPUViewport *viewport) +static void GPU_viewport_passes_free(PassList *psl) { - PassList *psl = (PassList *)viewport->psl; - int i; - - for (i = MAX_PASSES - 1; i > -1; --i) { + for (int i = MAX_PASSES - 1; i > -1; --i) { struct DRWPass *pass = psl->passes[i]; if (pass) { DRW_pass_free(pass); @@ -266,15 +340,13 @@ static void GPU_viewport_passes_free(GPUViewport *viewport) void GPU_viewport_free(GPUViewport *viewport) { - GPU_viewport_debug_depth_free(viewport); - GPU_viewport_buffers_free(viewport); - GPU_viewport_passes_free(viewport); - GPU_viewport_storage_free(viewport); + GPU_viewport_engines_data_free(viewport); + GPU_viewport_buffers_free(viewport->fbl, viewport->txl); MEM_freeN(viewport->fbl); MEM_freeN(viewport->txl); - MEM_freeN(viewport->psl); - MEM_freeN(viewport->stl); + + GPU_viewport_debug_depth_free(viewport); } /****************** debug ********************/ @@ -320,7 +392,7 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con immUniform1f("zfar", zfar); immUniform1i("image", 0); /* default GL_TEXTURE0 unit */ - immBegin(GL_QUADS, 4); + immBegin(GL_TRIANGLE_STRIP, 4); immAttrib2f(texcoord, 0.0f, 0.0f); immVertex2f(pos, 0.0f, 0.0f); @@ -328,12 +400,12 @@ void GPU_viewport_debug_depth_draw(GPUViewport *viewport, const float znear, con immAttrib2f(texcoord, 1.0f, 0.0f); immVertex2f(pos, w, 0.0f); - immAttrib2f(texcoord, 1.0f, 1.0f); - immVertex2f(pos, w, h); - immAttrib2f(texcoord, 0.0f, 1.0f); immVertex2f(pos, 0.0f, h); + immAttrib2f(texcoord, 1.0f, 1.0f); + immVertex2f(pos, w, h); + immEnd(); GPU_texture_unbind(viewport->debug_depth); 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 a6c00b080b2..f5217a9d238 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_image_vert.glsl @@ -1,6 +1,7 @@ uniform mat4 ModelViewProjectionMatrix; +/* Keep in sync with intern/opencolorio/gpu_shader_display_transform_vertex.glsl */ #if __VERSION__ == 120 attribute vec2 texCoord; attribute vec2 pos; 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 new file mode 100644 index 00000000000..85aab7e06ef --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_frag.glsl @@ -0,0 +1,25 @@ + +// Draw dashed lines, perforated in screen space. +// Based on a (3D) version by Mike Erwin. + +#if __VERSION__ == 120 + noperspective varying float distance_along_line; + #define fragColor gl_FragColor +#else + noperspective in float distance_along_line; + out vec4 fragColor; +#endif + +uniform float dash_width; +uniform float dash_width_on; +uniform vec4 color1; +uniform vec4 color2; + +void main() +{ + if (mod(distance_along_line, dash_width) <= dash_width_on) { + fragColor = color1; + } else { + fragColor = color2; + } +} diff --git a/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl new file mode 100644 index 00000000000..7b4207142e6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_line_dashed_vert.glsl @@ -0,0 +1,22 @@ + +// Draw dashed lines, perforated in screen space. +// Based on a (3D) version by Mike Erwin. + +uniform mat4 ModelViewProjectionMatrix; + +#if __VERSION__ == 120 + attribute vec2 pos; + attribute vec2 line_origin; // = pos for one vertex of the line + noperspective varying float distance_along_line; +#else + in vec2 pos; + in vec2 line_origin; + noperspective out float distance_along_line; +#endif + +void main() +{ + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + + distance_along_line = distance(line_origin, pos); +} diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl index 201e5e90ecc..201e5e90ecc 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_smooth_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_aa_vert.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl index a37ae16f837..a37ae16f837 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_smooth_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_outline_aa_vert.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl index d3a142cc7bd..d3a142cc7bd 100644 --- a/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_smooth_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_2D_point_uniform_size_varying_color_outline_aa_vert.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl index 287f95b48ab..287f95b48ab 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_smooth_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_aa_vert.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl index d05920002ed..d05920002ed 100644 --- a/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_smooth_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_3D_point_uniform_size_outline_aa_vert.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl index a0141f1ab2c..5f7455582cd 100644 --- a/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_basic_frag.glsl @@ -21,6 +21,10 @@ #define STIPPLE_DIAG_STRIPES 4 #define STIPPLE_DIAG_STRIPES_SWAP 5 +#ifndef NO_SPECULAR +uniform mat4 ProjectionMatrix; +#endif + #if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) #if defined(USE_FLAT_NORMAL) varying vec3 eyespace_vert_pos; @@ -163,7 +167,7 @@ void main() #ifndef NO_SPECULAR /* view vector computation, depends on orthographics or perspective */ - vec3 V = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0); + vec3 V = (ProjectionMatrix[3][3] == 0.0) ? normalize(varying_position) : vec3(0.0, 0.0, -1.0); #endif for (int i = 0; i < NUM_SCENE_LIGHTS; i++) { diff --git a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl index 42fbdadf1d1..dbf6c267f14 100644 --- a/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_basic_vert.glsl @@ -1,4 +1,8 @@ +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform mat3 NormalMatrix; + #if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) #if defined(USE_FLAT_NORMAL) varying vec3 eyespace_vert_pos; @@ -29,15 +33,15 @@ varying float gl_ClipDistance[6]; void main() { - vec4 co = gl_ModelViewMatrix * gl_Vertex; + vec4 co = ModelViewMatrix * gl_Vertex; #if defined(USE_SOLID_LIGHTING) || defined(USE_SCENE_LIGHTING) #if !defined(USE_FLAT_NORMAL) - varying_normal = normalize(gl_NormalMatrix * gl_Normal); + varying_normal = normalize(NormalMatrix * gl_Normal); #endif #if defined(USE_FLAT_NORMAL) /* transform vertex into eyespace */ - eyespace_vert_pos = (gl_ModelViewMatrix * gl_Vertex).xyz; + eyespace_vert_pos = (ModelViewMatrix * gl_Vertex).xyz; #endif #ifndef USE_SOLID_LIGHTING @@ -45,7 +49,7 @@ void main() #endif #endif - gl_Position = gl_ProjectionMatrix * co; + gl_Position = ProjectionMatrix * co; #ifdef CLIP_WORKAROUND int i; diff --git a/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl new file mode 100644 index 00000000000..74cf1c5a3dc --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_diag_stripes_frag.glsl @@ -0,0 +1,24 @@ + +uniform vec4 color1; +uniform vec4 color2; +uniform int size1; +uniform int size2; + +#if __VERSION__ == 120 + #define fragColor gl_FragColor +#else + out vec4 fragColor; +#endif + +void main() +{ + float phase = mod((gl_FragCoord.x + gl_FragCoord.y), (size1 + size2)); + + if (phase < size1) + { + fragColor = color1; + } + else { + fragColor = color2; + } +} 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 71a43d1b7ae..fb1d0aafe05 100644 --- a/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_edges_overlay_vert.glsl @@ -1,5 +1,5 @@ -//mat4 ModelViewProjectionMatrix; +uniform mat4 ModelViewProjectionMatrix; in vec3 pos; in float edgeWidthModulator; @@ -8,6 +8,6 @@ out vec4 pos_xformed; out float widthModulator; void main() { - pos_xformed = gl_ModelViewProjectionMatrix * vec4(pos, 1.0); + pos_xformed = ModelViewProjectionMatrix * vec4(pos, 1.0); widthModulator = edgeWidthModulator; } diff --git a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl index 3819203bcd9..45f86e036a1 100644 --- a/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fire_frag.glsl @@ -1,5 +1,13 @@ -varying vec3 coords; +#if __VERSION__ == 120 + varying vec3 coords; + #define fragColor gl_FragColor +#else + in vec3 coords; + out vec4 fragColor; + #define texture1D texture + #define texture3D texture +#endif uniform sampler3D flame_texture; uniform sampler1D spectrum_texture; @@ -13,5 +21,5 @@ void main() color.rgb = emission.a * emission.rgb; color.a = emission.a; - gl_FragColor = color; + fragColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl new file mode 100644 index 00000000000..cf2d28343cc --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_fullscreen_vert.glsl @@ -0,0 +1,16 @@ + +#if __VERSION__ == 120 + attribute vec2 pos; + attribute vec2 uvs; + varying vec4 uvcoordsvar; +#else + in vec2 pos; + in vec2 uvs; + out vec4 uvcoordsvar; +#endif + +void main() +{ + uvcoordsvar = vec4(uvs, 0.0, 0.0); + gl_Position = vec4(pos, 0.0, 1.0); +} diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl index e04cd7d3306..3ba455d34e7 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl @@ -1,5 +1,10 @@ uniform sampler2D depthbuffer; -varying vec4 uvcoordsvar; + +#if __VERSION__ == 120 + varying vec4 uvcoordsvar; +#else + in vec4 uvcoordsvar; +#endif void main(void) { diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl index 338ef6d51a7..6b3f1b99594 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl @@ -16,17 +16,35 @@ uniform vec4 dof_params; // viewvectors for reconstruction of world space uniform vec4 viewvecs[3]; -// coordinates on framebuffer in normalized (0.0-1.0) uv space -varying vec4 uvcoordsvar; - -/* color texture coordinates, offset by a small amount */ -varying vec2 color_uv1; -varying vec2 color_uv2; - -varying vec2 depth_uv1; -varying vec2 depth_uv2; -varying vec2 depth_uv3; -varying vec2 depth_uv4; +#if __VERSION__ == 120 + // coordinates on framebuffer in normalized (0.0-1.0) uv space + varying vec4 uvcoordsvar; + + /* color texture coordinates, offset by a small amount */ + varying vec2 color_uv1; + varying vec2 color_uv2; + + varying vec2 depth_uv1; + varying vec2 depth_uv2; + varying vec2 depth_uv3; + varying vec2 depth_uv4; + + #define FragColor gl_FragColor +#else + // coordinates on framebuffer in normalized (0.0-1.0) uv space + in vec4 uvcoordsvar; + + /* color texture coordinates, offset by a small amount */ + in vec2 color_uv1; + in vec2 color_uv2; + + in vec2 depth_uv1; + in vec2 depth_uv2; + in vec2 depth_uv3; + in vec2 depth_uv4; + + out vec4 FragColor; +#endif float calculate_far_coc(in float zdepth) @@ -102,7 +120,7 @@ void first_pass() coc = max(calculate_near_coc(zdepth), coc); final_coc = max(max(coc.x, coc.y), max(coc.z, coc.w)); - gl_FragColor = vec4(color.rgb, final_coc); + FragColor = vec4(color.rgb, final_coc); } /* second pass, gaussian blur the downsampled image */ @@ -119,7 +137,7 @@ void second_pass() color += texture2D(colorbuffer, uvcoordsvar.xy - 2.5 * invrendertargetdim) * 0.09375; color += texture2D(colorbuffer, uvcoordsvar.xy - 4.5 * invrendertargetdim) * 0.015625; - gl_FragColor = color; + FragColor = color; } @@ -129,7 +147,7 @@ void third_pass() vec4 color = texture2D(colorbuffer, uvcoordsvar.xy); vec4 color_blurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy); float coc = 2.0 * max(color_blurred.a, color.a); -color.a; - gl_FragColor = vec4(color.rgb, coc); + FragColor = vec4(color.rgb, coc); } @@ -141,7 +159,7 @@ void fourth_pass() color += texture2D(colorbuffer, uvcoordsvar.xw); color += texture2D(colorbuffer, uvcoordsvar.yw); - gl_FragColor = color / 4.0; + FragColor = color / 4.0; } vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color) @@ -188,7 +206,7 @@ void fifth_pass() color /= dot(factors, vec4(1.0)); /* using original color is not correct, but use that for now because alpha of * blurred buffers uses CoC instead */ - gl_FragColor = vec4(color.rgb, color_orig.a); + FragColor = vec4(color.rgb, color_orig.a); } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl index 182113367d3..46feb91de6e 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl @@ -20,18 +20,42 @@ uniform vec4 dof_params; /* viewvectors for reconstruction of world space */ uniform vec4 viewvecs[3]; -/* initial uv coordinate */ -varying vec2 uvcoord; - -/* coordinate used for calculating radius et al set in geometry shader */ -varying vec2 particlecoord; -varying vec4 color; +#if __VERSION__ == 120 + /* initial uv coordinate */ + varying vec2 uvcoord; + + /* coordinate used for calculating radius et al set in geometry shader */ + varying vec2 particlecoord; + varying vec4 color; + + /* downsampling coordinates */ + varying vec2 downsample1; + varying vec2 downsample2; + varying vec2 downsample3; + varying vec2 downsample4; + + #define fragData0 gl_FragData[0] + #define fragData1 gl_FragData[1] + #define fragData2 gl_FragData[2] +#else + /* initial uv coordinate */ + in vec2 uvcoord; + + /* coordinate used for calculating radius et al set in geometry shader */ + in vec2 particlecoord; + flat in vec4 color; + + /* downsampling coordinates */ + in vec2 downsample1; + in vec2 downsample2; + in vec2 downsample3; + in vec2 downsample4; + + layout(location = 0) out vec4 fragData0; + layout(location = 1) out vec4 fragData1; + layout(location = 2) out vec4 fragData2; +#endif -/* downsampling coordinates */ -varying vec2 downsample1; -varying vec2 downsample2; -varying vec2 downsample3; -varying vec2 downsample4; #define M_PI 3.1415926535897932384626433832795 @@ -82,16 +106,16 @@ void downsample_pass() float norm_far = dot(far_weights, vec4(1.0)); /* now write output to weighted buffers. */ - gl_FragData[0] = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z + + fragData0 = color1 * near_weights.x + color2 * near_weights.y + color3 * near_weights.z + color4 * near_weights.w; - gl_FragData[1] = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z + + fragData1 = color1 * far_weights.x + color2 * far_weights.y + color3 * far_weights.z + color4 * far_weights.w; if (norm_near > 0.0) - gl_FragData[0] /= norm_near; + fragData0 /= norm_near; if (norm_far > 0.0) - gl_FragData[1] /= norm_far; - gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0); + fragData1 /= norm_far; + fragData2 = vec4(near_coc, far_coc, 0.0, 1.0); } /* accumulate color in the near/far blur buffers */ @@ -102,16 +126,16 @@ void accumulate_pass(void) { if (dof_params.w == 0.0) r = 1.0; else - r = cos(M_PI / dof_params.w) / - (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI)))); + r = cos(M_PI / dof_params.w) / + (cos(theta - (2.0 * M_PI / dof_params.w) * floor((dof_params.w * theta + M_PI) / (2.0 * M_PI)))); if (dot(particlecoord, particlecoord) > r * r) discard; - gl_FragData[0] = color; + fragData0 = color; } -#define MERGE_THRESHOLD 4.0 +#define MERGE_THRESHOLD 4.0 /* combine the passes, */ void final_pass(void) { vec4 finalcolor; @@ -152,7 +176,9 @@ void final_pass(void) { finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight); } - gl_FragData[0] = finalcolor; + fragData0 = finalcolor; + // fragData0 = vec4(nearweight, farweight, 0.0, 1.0); + // fragData0 = vec4(nearcolor.rgb, 1.0); } void main() diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl index 4c650e7695f..c9a726a007e 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl @@ -24,7 +24,7 @@ uniform sampler2D cocbuffer; #else in vec2 uvcoord[]; out vec2 particlecoord; - out vec4 color; + flat out vec4 color; #endif #define M_PI 3.1415926535897932384626433832795 @@ -46,21 +46,23 @@ void main() vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y); - gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0); color = colortex; + + gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0); particlecoord = vec2(-1.0, -1.0); EmitVertex(); + gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0); particlecoord = vec2(-1.0, 1.0); - color = colortex; EmitVertex(); + gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0); particlecoord = vec2(1.0, -1.0); - color = colortex; EmitVertex(); + gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0); particlecoord = vec2(1.0, 1.0); - color = colortex; EmitVertex(); + EndPrimitive(); } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl index 09a0c75facc..78fe0e563f2 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl @@ -1,27 +1,47 @@ -uniform vec2 invrendertargetdim; -uniform ivec2 rendertargetdim; -/* initial uv coordinate */ -varying vec2 uvcoord; -/* coordinate used for calculating radius et al set in geometry shader */ -varying vec2 particlecoord; +#if __VERSION__ == 120 + attribute vec2 pos; + attribute vec2 uvs; + /* initial uv coordinate */ + varying vec2 uvcoord; + + /* coordinate used for calculating radius et al set in geometry shader */ + varying vec2 particlecoord; + + /* downsampling coordinates */ + varying vec2 downsample1; + varying vec2 downsample2; + varying vec2 downsample3; + varying vec2 downsample4; +#else + in vec2 pos; + in vec2 uvs; + /* initial uv coordinate */ + out vec2 uvcoord; + + /* coordinate used for calculating radius et al set in geometry shader */ + out vec2 particlecoord; + + /* downsampling coordinates */ + out vec2 downsample1; + out vec2 downsample2; + out vec2 downsample3; + out vec2 downsample4; +#endif -/* downsampling coordinates */ -varying vec2 downsample1; -varying vec2 downsample2; -varying vec2 downsample3; -varying vec2 downsample4; +uniform vec2 invrendertargetdim; +uniform ivec2 rendertargetdim; void vert_dof_downsample() { /* gather pixels from neighbors. half dimensions means we offset half a pixel to * get this right though it's possible we may lose a pixel at some point */ - downsample1 = gl_MultiTexCoord0.xy + vec2(-0.5, -0.5) * invrendertargetdim; - downsample2 = gl_MultiTexCoord0.xy + vec2(-0.5, 0.5) * invrendertargetdim; - downsample3 = gl_MultiTexCoord0.xy + vec2(0.5, 0.5) * invrendertargetdim; - downsample4 = gl_MultiTexCoord0.xy + vec2(0.5, -0.5) * invrendertargetdim; + downsample1 = uvs.xy + vec2(-0.5, -0.5) * invrendertargetdim; + downsample2 = uvs.xy + vec2(-0.5, 0.5) * invrendertargetdim; + downsample3 = uvs.xy + vec2(0.5, 0.5) * invrendertargetdim; + downsample4 = uvs.xy + vec2(0.5, -0.5) * invrendertargetdim; - gl_Position = gl_Vertex; + gl_Position = vec4(pos, 0.0, 1.0); } /* geometry shading pass, calculate a texture coordinate based on the indexed id */ @@ -42,8 +62,8 @@ void vert_dof_coc_scatter_pass() void vert_dof_final() { - uvcoord = gl_MultiTexCoord0.xy; - gl_Position = gl_Vertex; + uvcoord = uvs; + gl_Position = vec4(pos, 0.0, 1.0); } void main() diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl index 63b57d5775c..eb2b6b04da8 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl @@ -1,51 +1,72 @@ uniform vec2 invrendertargetdim; -//texture coordinates for framebuffer read -varying vec4 uvcoordsvar; -/* color texture coordinates, offset by a small amount */ -varying vec2 color_uv1; -varying vec2 color_uv2; +#if __VERSION__ == 120 + attribute vec2 pos; + attribute vec2 uvs; -varying vec2 depth_uv1; -varying vec2 depth_uv2; -varying vec2 depth_uv3; -varying vec2 depth_uv4; + //texture coordinates for framebuffer read + varying vec4 uvcoordsvar; + + /* color texture coordinates, offset by a small amount */ + varying vec2 color_uv1; + varying vec2 color_uv2; + + varying vec2 depth_uv1; + varying vec2 depth_uv2; + varying vec2 depth_uv3; + varying vec2 depth_uv4; +#else + in vec2 pos; + in vec2 uvs; + + //texture coordinates for framebuffer read + out vec4 uvcoordsvar; + + /* color texture coordinates, offset by a small amount */ + out vec2 color_uv1; + out vec2 color_uv2; + + out vec2 depth_uv1; + out vec2 depth_uv2; + out vec2 depth_uv3; + out vec2 depth_uv4; +#endif //very simple shader for gull screen FX, just pass values on void vert_generic() { - uvcoordsvar = gl_MultiTexCoord0; - gl_Position = gl_Vertex; + uvcoordsvar = vec4(uvs, 0.0, 0.0); + gl_Position = vec4(pos, 0.0, 1.0); } void vert_dof_first_pass() { /* we offset the texture coordinates by 1.5 pixel, * then we reuse that to sample the surrounding pixels */ - color_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim; - color_uv2 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim; + color_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim; + color_uv2 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim; - depth_uv1 = gl_MultiTexCoord0.xy + vec2(-1.5, -1.5) * invrendertargetdim; - depth_uv2 = gl_MultiTexCoord0.xy + vec2(-0.5, -1.5) * invrendertargetdim; - depth_uv3 = gl_MultiTexCoord0.xy + vec2(0.5, -1.5) * invrendertargetdim; - depth_uv4 = gl_MultiTexCoord0.xy + vec2(1.5, -1.5) * invrendertargetdim; + depth_uv1 = uvs.xy + vec2(-1.5, -1.5) * invrendertargetdim; + depth_uv2 = uvs.xy + vec2(-0.5, -1.5) * invrendertargetdim; + depth_uv3 = uvs.xy + vec2(0.5, -1.5) * invrendertargetdim; + depth_uv4 = uvs.xy + vec2(1.5, -1.5) * invrendertargetdim; - gl_Position = gl_Vertex; + gl_Position = vec4(pos, 0.0, 1.0); } void vert_dof_fourth_pass() { vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5); - uvcoordsvar = gl_MultiTexCoord0.xxyy + + uvcoordsvar = uvs.xxyy + halfpixel * vec4(invrendertargetdim.x, invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y); - gl_Position = gl_Vertex; + gl_Position = vec4(pos, 0.0, 1.0); } void vert_dof_fifth_pass() @@ -53,8 +74,8 @@ void vert_dof_fifth_pass() vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5); color_uv1 = vec2(0.5, 1.5) * invrendertargetdim; - uvcoordsvar = gl_MultiTexCoord0; - gl_Position = gl_Vertex; + uvcoordsvar = vec4(uvs, 0.0, 0.0); + gl_Position = vec4(pos, 0.0, 1.0); } void main() diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl index 1dc49b52be1..7aa6786d292 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl @@ -1,14 +1,17 @@ +uniform mat4 ProjectionMatrix; + /* simple depth reconstruction, see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer * we change the factors from the article to fit the OpennGL model. */ #ifdef PERSP_MATRIX + /* perspective camera code */ vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth) { float d = 2.0 * depth - 1.0; - float zview = -gl_ProjectionMatrix[3][2] / (d + gl_ProjectionMatrix[2][2]); + float zview = -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff); } @@ -18,7 +21,7 @@ vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth) vec4 d = 2.0 * depth - vec4(1.0); /* return positive value, so sign differs! */ - return vec4(gl_ProjectionMatrix[3][2]) / (d + vec4(gl_ProjectionMatrix[2][2])); + return vec4(ProjectionMatrix[3][2]) / (d + vec4(ProjectionMatrix[2][2])); } #else diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl index 50c8e255162..4a6cc09f5ea 100644 --- a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl @@ -1,3 +1,4 @@ + // color buffer uniform sampler2D colorbuffer; @@ -9,8 +10,15 @@ uniform sampler1D ssao_concentric_tex; // depth buffer uniform sampler2D depthbuffer; -// coordinates on framebuffer in normalized (0.0-1.0) uv space -varying vec4 uvcoordsvar; + +#if __VERSION__ == 120 + // coordinates on framebuffer in normalized (0.0-1.0) uv space + varying vec4 uvcoordsvar; + #define FragColor gl_FragColor +#else + in vec4 uvcoordsvar; + out vec4 FragColor; +#endif /* ssao_params.x : pixel scale for the ssao radious */ /* ssao_params.y : factor for the ssao darkening */ @@ -46,9 +54,9 @@ float calculate_ssao_factor(float depth) /* find the offset in screen space by multiplying a point * in camera space at the depth of the point by the projection matrix. */ vec2 offset; - float homcoord = gl_ProjectionMatrix[2][3] * position.z + gl_ProjectionMatrix[3][3]; - offset.x = gl_ProjectionMatrix[0][0] * ssao_params.x / homcoord; - offset.y = gl_ProjectionMatrix[1][1] * ssao_params.x / homcoord; + float homcoord = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3]; + offset.x = ProjectionMatrix[0][0] * ssao_params.x / homcoord; + offset.y = ProjectionMatrix[1][1] * ssao_params.x / homcoord; /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */ offset *= 0.5; @@ -90,5 +98,5 @@ void main() float depth = texture2D(depthbuffer, uvcoordsvar.xy).r; vec4 scene_col = texture2D(colorbuffer, uvcoordsvar.xy); vec3 final_color = mix(scene_col.rgb, ssao_color.rgb, calculate_ssao_factor(depth)); - gl_FragColor = vec4(final_color.rgb, scene_col.a); + FragColor = vec4(final_color.rgb, scene_col.a); } diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl deleted file mode 100644 index 5194e414520..00000000000 --- a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl +++ /dev/null @@ -1,9 +0,0 @@ -varying vec4 uvcoordsvar; - -//very simple shader for full screen FX, just pass values on - -void main() -{ - uvcoordsvar = gl_MultiTexCoord0; - gl_Position = gl_Vertex; -} diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl index fe630dbeddb..545910d39ca 100644 --- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl +++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl @@ -1,3 +1,6 @@ + +uniform mat4 ProjectionMatrix; + uniform int PrimitiveIdBase; uniform int osd_active_uv_offset; @@ -69,7 +72,7 @@ void emit_flat(int index, vec3 normal) set_mtface_vertex_attrs(st); - gl_Position = gl_ProjectionMatrix * inpt[index].v.position; + gl_Position = ProjectionMatrix * inpt[index].v.position; EmitVertex(); } @@ -90,7 +93,7 @@ void emit_smooth(int index) set_mtface_vertex_attrs(st); - gl_Position = gl_ProjectionMatrix * inpt[index].v.position; + gl_Position = ProjectionMatrix * inpt[index].v.position; EmitVertex(); } 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 new file mode 100644 index 00000000000..fa4f41b79fb --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_image_shuffle_color_frag.glsl @@ -0,0 +1,22 @@ + +#if __VERSION__ == 120 + varying vec2 texCoord_interp; + #define fragColor gl_FragColor +#else + in vec2 texCoord_interp; + out vec4 fragColor; + #define texture2D texture +#endif + +uniform sampler2D image; +uniform vec4 color; +uniform vec4 shuffle; + +void main() +{ + vec4 sample = texture2D(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_instance_camera_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl new file mode 100644 index 00000000000..aec8fd9b0a1 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_camera_vert.glsl @@ -0,0 +1,50 @@ + +uniform mat4 ViewProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in float pos; + +/* ---- Per instance Attribs ---- */ +in vec3 color; +in vec4 corners[2]; /* trouble fetching vec2 */ +in float depth; +in vec4 tria; +in mat4 InstanceModelMatrix; + +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); +} 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 new file mode 100644 index 00000000000..142df70e68a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_distance_line_vert.glsl @@ -0,0 +1,25 @@ + +uniform mat4 ViewProjectionMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; + +/* ---- Per instance Attribs ---- */ +in vec3 color; +in float start; +in float end; +in mat4 InstanceModelMatrix; + +uniform float size; + +flat out vec4 finalColor; + +void main() +{ + float len = end - start; + vec3 sta = vec3(0.0, 0.0, -start); + + gl_Position = ViewProjectionMatrix * InstanceModelMatrix * vec4(pos * -len + sta, 1.0); + gl_PointSize = size; + finalColor = vec4(color, 1.0); +}
\ No newline at end of file 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 new file mode 100644 index 00000000000..6f580ef3ff6 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_geom.glsl @@ -0,0 +1,57 @@ + +// Draw "fancy" wireframe, displaying front-facing, back-facing and +// silhouette lines differently. +// Mike Erwin, April 2015 + +// After working with this shader a while, convinced we should make +// separate shaders for perpective & ortho. (Oct 2016) + +// Due to perspective, the line segment's endpoints might disagree on +// whether the adjacent faces are front facing. This geometry shader +// decides which edge type to use if endpoints disagree. + +uniform mat4 ProjectionMatrix; + +uniform bool drawFront = true; +uniform bool drawBack = true; +uniform bool drawSilhouette = true; + +layout(lines) in; +layout(line_strip, max_vertices = 2) out; + +in vec4 MV_pos[]; +in float edgeClass[]; +in vec3 fCol[]; + +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(); +} + +void main() +{ + 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)); + } +} 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 new file mode 100644 index 00000000000..5d1e949c1d4 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_edges_variying_color_vert.glsl @@ -0,0 +1,64 @@ + +// Draw "fancy" wireframe, displaying front-facing, back-facing and +// silhouette lines differently. +// Mike Erwin, April 2015 + +// After working with this shader a while, convinced we should make +// separate shaders for perpective & ortho. (Oct 2016) + +// Due to perspective, the line segment's endpoints might disagree on +// whether the adjacent faces are front facing. We use a geometry +// shader to resolve this properly. + +uniform mat4 ViewMatrix; + +in vec3 pos; +in vec3 N1, N2; // normals of faces this edge joins (object coords) + +/* instance attrib */ +in vec3 color; +in mat4 InstanceModelMatrix; + +out vec4 MV_pos; +out float edgeClass; +out vec3 fCol; + +// TODO: in float angle; // [-pi .. +pi], + peak, 0 flat, - valley + +mat3 NormalMatrix; + +bool front(vec3 N, vec3 eye) +{ + return dot(NormalMatrix * N, eye) > 0.0; +} + +void main() +{ + vec3 eye; + + mat4 ModelViewMatrix = ViewMatrix * InstanceModelMatrix; + + MV_pos = ModelViewMatrix * vec4(pos, 1.0); + + NormalMatrix = transpose(inverse(mat3(ModelViewMatrix))); + + /* if persp */ + if (ViewMatrix[3][3] == 0.0) { + eye = normalize(-MV_pos.xyz); + } + else { + eye = vec3(0.0, 0.0, 1.0); + } + + 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 + + fCol = color; +} 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 new file mode 100644 index 00000000000..ce82dc6af2a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_objectspace_variying_color_vert.glsl @@ -0,0 +1,29 @@ + +uniform mat4 ViewMatrix; +uniform mat4 ViewProjectionMatrix; +uniform mat4 ModelMatrix; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; +in vec3 nor; + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec4 color; + +out vec3 normal; +flat out vec4 finalColor; + +void main() +{ + mat4 FinalModelMatrix = ModelMatrix * InstanceModelMatrix; + mat4 ModelViewProjectionMatrix = ViewProjectionMatrix * FinalModelMatrix; + /* 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 attrib */ + mat3 NormalMatrix = transpose(inverse(mat3(ViewMatrix * FinalModelMatrix))); + + gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0); + normal = NormalMatrix * nor; + + finalColor = color; +} diff --git a/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl new file mode 100644 index 00000000000..a39bfde41ee --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_instance_screen_aligned_axis_name_vert.glsl @@ -0,0 +1,29 @@ + +uniform mat4 ViewProjectionMatrix; +uniform vec3 screen_vecs[2]; + +/* ---- Instanciated Attribs ---- */ +in vec3 pos; /* using Z as axis id */ + +/* ---- Per instance Attribs ---- */ +in mat4 InstanceModelMatrix; +in vec3 color; +in float size; + +flat out vec4 finalColor; + +void main() +{ + vec3 offset; + + 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); + + vec3 screen_pos = screen_vecs[0].xyz * pos.x + screen_vecs[1].xyz * pos.y; + gl_Position = ViewProjectionMatrix * (InstanceModelMatrix * vec4(offset * size, 1.0) + vec4(screen_pos * size, 0.0)); + finalColor = vec4(color, 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 43a7e42153a..ebda79558c7 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_frag.glsl @@ -29,7 +29,7 @@ void main() { float mid_stroke = 0.5 * (radii[1] + radii[2]); - vec4 backgroundColor = vec4(finalColor.rgb, 0.0); + vec4 backgroundColor = vec4(finalOutlineColor.rgb, 0.0); if (dist > mid_stroke) fragColor = mix(finalOutlineColor, backgroundColor, smoothstep(radii[1], radii[0], dist)); 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 69afefa685f..6f33491af55 100644 --- a/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_keyframe_diamond_vert.glsl @@ -26,7 +26,7 @@ void main() { gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); // pass through unchanged - gl_PointSize = size; + gl_PointSize = size + pixel_fudge; // 0.5 pixel_fudge on either side finalColor = color; finalOutlineColor = outlineColor; diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 0f3ffa8244b..ef30f8ae6c5 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1,3 +1,18 @@ + +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform mat4 ModelViewMatrixInverse; +uniform mat4 ProjectionMatrixInverse; +uniform mat3 NormalMatrix; + +#if __VERSION__ == 120 + #define fragColor gl_FragColor +#else + out vec4 fragColor; + #define texture2D texture + #define textureCube texture +#endif + /* Converters */ float convert_rgba_to_float(vec4 color) @@ -177,7 +192,7 @@ void geom( out vec3 normal, out vec4 vcol, out float vcol_alpha, out float frontback) { local = co; - view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0); + view = (ProjectionMatrix[3][3] == 0.0) ? normalize(local) : vec3(0.0, 0.0, -1.0); global = (viewinvmat * vec4(local, 1.0)).xyz; orco = attorco; uv_attribute(attuv, uv); @@ -1413,8 +1428,8 @@ void mtex_bump_init_objspace( out float fPrevMagnitude_out, out vec3 vNacc_out, out vec3 vR1, out vec3 vR2, out float fDet) { - mat3 obj2view = to_mat3(gl_ModelViewMatrix); - mat3 view2obj = to_mat3(gl_ModelViewMatrixInverse); + mat3 obj2view = to_mat3(ModelViewMatrix); + mat3 view2obj = to_mat3(ModelViewMatrixInverse); vec3 vSigmaS = view2obj * dFdx(surf_pos); vec3 vSigmaT = view2obj * dFdy(surf_pos); @@ -1670,7 +1685,7 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal) void mtex_nspace_object(vec3 texnormal, out vec3 outnormal) { - outnormal = normalize(gl_NormalMatrix * texnormal); + outnormal = normalize(NormalMatrix * texnormal); } void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal) @@ -1794,7 +1809,7 @@ void lamp_visibility_clamp(float visifac, out float outvisifac) void world_paper_view(vec3 vec, out vec3 outvec) { vec3 nvec = normalize(vec); - outvec = (gl_ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0); + outvec = (ProjectionMatrix[3][3] == 0.0) ? vec3(nvec.x, 0.0, nvec.y) : vec3(0.0, 0.0, -1.0); } void world_zen_mapping(vec3 view, float zenup, float zendown, out float zenfac) @@ -1828,7 +1843,7 @@ void world_blend(vec3 vec, out float blend) void shade_view(vec3 co, out vec3 view) { /* handle perspective/orthographic */ - view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0); + view = (ProjectionMatrix[3][3] == 0.0) ? normalize(co) : vec3(0.0, 0.0, -1.0); } void shade_tangent_v(vec3 lv, vec3 tang, out vec3 vn) @@ -2346,7 +2361,7 @@ void shade_mist_factor( if (enable == 1.0) { float fac, zcor; - zcor = (gl_ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2]; + zcor = (ProjectionMatrix[3][3] == 0.0) ? length(co) : -co[2]; fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0); if (misttype == 0.0) fac *= fac; @@ -2605,11 +2620,11 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result) void background_transform_to_world(vec3 viewvec, out vec3 worldvec) { - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(viewvec, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_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); - worldvec = (gl_ModelViewMatrixInverse * co).xyz; + worldvec = (ModelViewMatrixInverse * co).xyz; } void node_background(vec4 color, float strength, vec3 N, out vec4 result) @@ -2634,7 +2649,7 @@ void node_add_shader(vec4 shader1, vec4 shader2, out vec4 shader) void node_fresnel(float ior, vec3 N, vec3 I, out float result) { /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + 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); @@ -2646,7 +2661,7 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float { /* fresnel */ float eta = max(1.0 - blend, 0.00001); - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + 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); @@ -2700,7 +2715,7 @@ void node_geometry( true_normal = normal; /* handle perspective/orthographic */ - vec3 I_view = (gl_ProjectionMatrix[3][3] == 0.0) ? normalize(I) : vec3(0.0, 0.0, -1.0); + 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; parametric = vec3(0.0); @@ -2719,7 +2734,7 @@ void node_tex_coord( uv = attr_uv; object = (obinvmat * (viewinvmat * vec4(I, 1.0))).xyz; camera = vec3(I.xy, -I.z); - vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0); + 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; @@ -2734,13 +2749,13 @@ void node_tex_coord_background( out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object, out vec3 camera, out vec3 window, out vec3 reflection) { - vec4 v = (gl_ProjectionMatrix[3][3] == 0.0) ? vec4(I, 1.0) : vec4(0.0, 0.0, 1.0, 1.0); - vec4 co_homogenous = (gl_ProjectionMatrixInverse * v); + 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); - vec3 coords = (gl_ModelViewMatrixInverse * co).xyz; + vec3 coords = (ModelViewMatrixInverse * co).xyz; generated = coords; normal = -coords; @@ -2748,7 +2763,7 @@ void node_tex_coord_background( object = coords; camera = vec3(co.xy, -co.z); - window = (gl_ProjectionMatrix[3][3] == 0.0) ? + window = (ProjectionMatrix[3][3] == 0.0) ? vec3(mtex_2d_mapping(I).xy * camerafac.xy + camerafac.zw, 0.0) : vec3(vec2(0.5) * camerafac.xy + camerafac.zw, 0.0); diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl index 8c8d81f6997..8c8d81f6997 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_smooth_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_aa_frag.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl index f83785de95e..f83785de95e 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_smooth_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_uniform_color_outline_aa_frag.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl index d6cbe2d9a22..d6cbe2d9a22 100644 --- a/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_smooth_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_point_varying_color_outline_aa_frag.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl index b485d2cce86..d7cdec9441d 100644 --- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl @@ -1,16 +1,25 @@ uniform vec2 ScaleU; uniform sampler2D textureSource; +#if __VERSION__ == 120 + varying vec2 texCoord_interp; + #define fragColor gl_FragColor +#else + in vec2 texCoord_interp; + out vec4 fragColor; + #define texture2D texture +#endif + void main() { vec4 color = vec4(0.0); - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(0.0, 0.0)) * 0.3125; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375; - color += texture2D(textureSource, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625; + color += texture2D(textureSource, texCoord_interp.st + vec2(-3.0 * ScaleU.x, -3.0 * ScaleU.y)) * 0.015625; + color += texture2D(textureSource, texCoord_interp.st + vec2(-2.0 * ScaleU.x, -2.0 * ScaleU.y)) * 0.09375; + color += texture2D(textureSource, texCoord_interp.st + vec2(-1.0 * ScaleU.x, -1.0 * ScaleU.y)) * 0.234375; + color += texture2D(textureSource, texCoord_interp.st + vec2(0.0, 0.0)) * 0.3125; + color += texture2D(textureSource, texCoord_interp.st + vec2(1.0 * ScaleU.x, 1.0 * ScaleU.y)) * 0.234375; + color += texture2D(textureSource, texCoord_interp.st + vec2(2.0 * ScaleU.x, 2.0 * ScaleU.y)) * 0.09375; + color += texture2D(textureSource, texCoord_interp.st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y)) * 0.015625; - gl_FragColor = color; + fragColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl index 5d00108b052..a0e5b022e67 100644 --- a/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_vert.glsl @@ -1,6 +1,18 @@ +uniform mat4 ModelViewProjectionMatrix; + +#if __VERSION__ == 120 + attribute vec2 pos; + attribute vec2 uvs; + varying vec2 texCoord_interp; +#else + in vec2 pos; + in vec2 uvs; + out vec2 texCoord_interp; +#endif + void main() { - gl_Position = ftransform(); - gl_TexCoord[0] = gl_MultiTexCoord0; + gl_Position = ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0); + texCoord_interp = uvs; } 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 9828787fb04..4eacd08d5af 100644 --- a/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_frag.glsl @@ -1,12 +1,21 @@ +#ifndef USE_INSTANCE_COLOR uniform vec4 color; +#endif uniform vec3 light; #if __VERSION__ == 120 varying vec3 normal; +#ifdef USE_INSTANCE_COLOR + varying vec4 finalColor; +#endif #define fragColor gl_FragColor #else in vec3 normal; +#ifdef USE_INSTANCE_COLOR + flat in vec4 finalColor; + #define color finalColor +#endif out vec4 fragColor; #endif 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 new file mode 100644 index 00000000000..260539f76d7 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_simple_lighting_smooth_color_frag.glsl @@ -0,0 +1,17 @@ + +uniform vec3 light; + +#if __VERSION__ == 120 + varying vec3 normal; + varying vec4 finalColor; + #define fragColor gl_FragColor +#else + in vec3 normal; + in vec4 finalColor; + out vec4 fragColor; +#endif + +void main() +{ + fragColor = finalColor * max(0.0, dot(normalize(normal), light)); +} diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl index 6ded453225e..fcb385ed30a 100644 --- a/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_smoke_frag.glsl @@ -1,5 +1,13 @@ -varying vec3 coords; +#if __VERSION__ == 120 + varying vec3 coords; + #define fragColor gl_FragColor +#else + in vec3 coords; + out vec4 fragColor; + #define texture1D texture + #define texture3D texture +#endif uniform vec3 active_color; uniform float step_size; @@ -44,5 +52,5 @@ void main() vec4 color = transfer_function * density_scale; #endif - gl_FragColor = color; + fragColor = color; } diff --git a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl index 297486ae26a..f49272d0913 100644 --- a/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_smoke_vert.glsl @@ -1,5 +1,11 @@ -varying vec3 coords; +uniform mat4 ModelViewProjectionMatrix; + +#if __VERSION__ == 120 + varying vec3 coords; +#else + out vec3 coords; +#endif uniform vec3 min_location; uniform vec3 invsize; @@ -7,6 +13,6 @@ uniform vec3 ob_sizei; void main() { - gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0); + gl_Position = ModelViewProjectionMatrix * vec4(gl_Vertex.xyz * ob_sizei, 1.0); coords = (gl_Vertex.xyz - min_location) * invsize; } diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index db0068d2f3d..5a6b237b3be 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -1,3 +1,8 @@ + +uniform mat4 ModelViewMatrix; +uniform mat4 ProjectionMatrix; +uniform mat3 NormalMatrix; + #ifdef USE_OPENSUBDIV in vec3 normal; in vec4 position; @@ -7,8 +12,13 @@ out block { } outpt; #endif -varying vec3 varposition; -varying vec3 varnormal; +#if __VERSION__ == 120 + varying vec3 varposition; + varying vec3 varnormal; +#else + out vec3 varposition; + out vec3 varnormal; +#endif #ifdef CLIP_WORKAROUND varying float gl_ClipDistance[6]; @@ -89,11 +99,11 @@ void main() vec3 normal = gl_Normal; #endif - vec4 co = gl_ModelViewMatrix * position; + vec4 co = ModelViewMatrix * position; varposition = co.xyz; - varnormal = normalize(gl_NormalMatrix * normal); - gl_Position = gl_ProjectionMatrix * co; + varnormal = normalize(NormalMatrix * normal); + gl_Position = ProjectionMatrix * co; #ifdef CLIP_WORKAROUND int i; diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl index d45a4b316a8..7a39c3fc674 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl @@ -1,7 +1,11 @@ -varying vec3 varposition; -varying vec3 varnormal; - +#if __VERSION__ == 120 + varying vec3 varposition; + varying vec3 varnormal; +#else + out vec3 varposition; + out vec3 varnormal; +#endif /* Color, keep in sync with: gpu_shader_vertex.glsl */ diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl index 3761bf350eb..9035a311ecb 100644 --- a/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_frag.glsl @@ -2,7 +2,13 @@ * This fragment shader was initially found at http://fabiensanglard.net/shadowmappingVSM/index.php */ -varying vec4 v_position; +#if __VERSION__ == 120 + varying vec4 v_position; + #define fragColor gl_FragColor +#else + in vec4 v_position; + out vec4 fragColor; +#endif void main() { @@ -17,5 +23,6 @@ void main() float dy = dFdy(depth); moment2 += 0.25 * (dx * dx + dy * dy); - gl_FragColor = vec4(moment1, moment2, 0.0, 0.0); + fragColor = vec4(moment1, moment2, 0.0, 0.0); + // TODO: write to a 2-component target --^ } diff --git a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl index 224c3e78adc..96ea22b3483 100644 --- a/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vsm_store_vert.glsl @@ -1,7 +1,14 @@ -varying vec4 v_position; + +uniform mat4 ModelViewProjectionMatrix; + +#if __VERSION__ == 120 + varying vec4 v_position; +#else + out vec4 v_position; +#endif void main() { - gl_Position = ftransform(); + gl_Position = ModelViewProjectionMatrix * gl_Vertex; v_position = gl_Position; } |