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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDalai Felinto <dfelinto@gmail.com>2015-09-24 18:24:20 +0300
committerDalai Felinto <dfelinto@gmail.com>2015-09-24 18:24:20 +0300
commit27b3ea622f8bd313a8e2827dfec752bf2125566c (patch)
treef212e49d224ce8e1cfc3b17a64ae524711494391 /source/blender/gpu
parent372dff8d1dc7e24d4b2cd37de245588ecfce8bfa (diff)
parentde80e687689032cb85179a1f7e89750573631d5d (diff)
Merge remote-tracking branch 'origin/master' into cycles_camera_nodescycles_camera_nodes
Note: the branch currently crashes in blender_camera_nodes.cpp: BL::NodeTree b_ntree = b_data.node_groups[nodes_tree_name]; The crash was introduced in: cb7cf523e5c000609f32a382e2c0fcc57f635a42 Conflicts: intern/cycles/SConscript intern/cycles/blender/addon/__init__.py intern/cycles/blender/addon/properties.py intern/cycles/blender/blender_camera.cpp intern/cycles/kernel/kernel_types.h intern/cycles/kernel/svm/svm.h intern/cycles/kernel/svm/svm_types.h intern/cycles/render/camera.cpp intern/cycles/render/camera.h
Diffstat (limited to 'source/blender/gpu')
-rw-r--r--source/blender/gpu/CMakeLists.txt48
-rw-r--r--source/blender/gpu/GPU_buffers.h125
-rw-r--r--source/blender/gpu/GPU_compositing.h99
-rw-r--r--source/blender/gpu/GPU_debug.h71
-rw-r--r--source/blender/gpu/GPU_draw.h42
-rw-r--r--source/blender/gpu/GPU_extensions.h144
-rw-r--r--source/blender/gpu/GPU_glew.h37
-rw-r--r--source/blender/gpu/GPU_init_exit.h46
-rw-r--r--source/blender/gpu/GPU_material.h197
-rw-r--r--source/blender/gpu/GPU_select.h4
-rw-r--r--source/blender/gpu/GPU_simple_shader.h8
-rw-r--r--source/blender/gpu/SConscript23
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c1886
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c670
-rw-r--r--source/blender/gpu/intern/gpu_codegen.h118
-rw-r--r--source/blender/gpu/intern/gpu_compositing.c1289
-rw-r--r--source/blender/gpu/intern/gpu_debug.c724
-rw-r--r--source/blender/gpu/intern/gpu_draw.c1225
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c1240
-rw-r--r--source/blender/gpu/intern/gpu_init_exit.c79
-rw-r--r--source/blender/gpu/intern/gpu_material.c884
-rw-r--r--source/blender/gpu/intern/gpu_private.h36
-rw-r--r--source/blender/gpu/intern/gpu_select.c22
-rw-r--r--source/blender/gpu/intern/gpu_simple_shader.c9
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl32
-rw-r--r--source/blender/gpu/shaders/gpu_program_smoke_frag.glsl27
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl14
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl208
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl166
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl50
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl58
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl68
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_lib.glsl39
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl94
-rw-r--r--source/blender/gpu/shaders/gpu_shader_fx_vert.glsl9
-rw-r--r--source/blender/gpu/shaders/gpu_shader_geometry.glsl100
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl202
-rw-r--r--source/blender/gpu/shaders/gpu_shader_sep_gaussian_blur_frag.glsl2
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex.glsl21
-rw-r--r--source/blender/gpu/shaders/gpu_shader_vertex_world.glsl13
40 files changed, 7107 insertions, 3022 deletions
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 13e46bc7de8..328623f884f 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -36,6 +36,7 @@ set(INC
../nodes
../nodes/intern
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/smoke/extern
)
@@ -49,27 +50,69 @@ set(SRC
intern/gpu_codegen.c
intern/gpu_draw.c
intern/gpu_extensions.c
+ intern/gpu_init_exit.c
intern/gpu_material.c
intern/gpu_simple_shader.c
intern/gpu_select.c
+ intern/gpu_compositing.c
+ intern/gpu_debug.c
+
+ shaders/gpu_program_smoke_frag.glsl
+ shaders/gpu_program_smoke_color_frag.glsl
+
+ shaders/gpu_shader_fx_lib.glsl
+ shaders/gpu_shader_fx_ssao_frag.glsl
+ shaders/gpu_shader_fx_dof_frag.glsl
+ shaders/gpu_shader_fx_dof_vert.glsl
+ 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_material.glsl
+ shaders/gpu_shader_sep_gaussian_blur_frag.glsl
+ shaders/gpu_shader_sep_gaussian_blur_vert.glsl
+ shaders/gpu_shader_simple_frag.glsl
+ shaders/gpu_shader_simple_vert.glsl
+ shaders/gpu_shader_vertex.glsl
+ shaders/gpu_shader_vsm_store_frag.glsl
+ shaders/gpu_shader_vsm_store_vert.glsl
+ shaders/gpu_shader_fx_depth_resolve.glsl
GPU_buffers.h
GPU_draw.h
+ GPU_debug.h
GPU_extensions.h
+ GPU_glew.h
+ GPU_init_exit.h
GPU_material.h
GPU_simple_shader.h
GPU_select.h
+ GPU_compositing.h
intern/gpu_codegen.h
+ intern/gpu_private.h
)
+data_to_c_simple(shaders/gpu_shader_geometry.glsl SRC)
+data_to_c_simple(shaders/gpu_program_smoke_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_program_smoke_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_material.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC)
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_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)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_vert.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_dof_hq_geo.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_depth_resolve.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_fx_lib.glsl SRC)
if(WITH_GAMEENGINE)
add_definitions(-DWITH_GAMEENGINE)
@@ -79,12 +122,15 @@ if(WITH_MOD_SMOKE)
add_definitions(-DWITH_SMOKE)
endif()
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
endif()
+if(WITH_OPENSUBDIV)
+ add_definitions(-DWITH_OPENSUBDIV)
+endif()
blender_add_lib(bf_gpu "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h
index ba461d5f8a2..e653af0c7ec 100644
--- a/source/blender/gpu/GPU_buffers.h
+++ b/source/blender/gpu/GPU_buffers.h
@@ -39,32 +39,41 @@
# define DEBUG_VBO(X)
#endif
+#include <stddef.h>
+
struct BMesh;
struct CCGElem;
struct CCGKey;
-struct CustomData;
struct DMFlagMat;
struct DerivedMesh;
-struct GHash;
struct GSet;
struct GPUVertPointLink;
+struct GPUDrawObject;
struct PBVH;
+struct MVert;
typedef struct GPUBuffer {
- int size; /* in bytes */
- void *pointer; /* used with vertex arrays */
- unsigned int id; /* used with vertex buffer objects */
+ size_t size; /* in bytes */
+ void *pointer; /* used with vertex arrays */
+ unsigned int id; /* used with vertex buffer objects */
+ bool use_vbo; /* true for VBOs, false for vertex arrays */
} GPUBuffer;
typedef struct GPUBufferMaterial {
/* range of points used for this material */
- int start;
- int totpoint;
+ unsigned int start;
+ unsigned int totelements;
+ unsigned int totloops;
+ unsigned int *polys; /* array of polygons for this material */
+ unsigned int totpolys; /* total polygons in polys */
+ unsigned int totvisiblepolys; /* total visible polygons */
/* original material index */
short mat_nr;
} GPUBufferMaterial;
+void GPU_buffer_material_finalize(struct GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat);
+
/* meshes are split up by material since changing materials requires
* GL state changes that can't occur in the middle of drawing an
* array.
@@ -85,12 +94,11 @@ typedef struct GPUDrawObject {
GPUBuffer *points;
GPUBuffer *normals;
GPUBuffer *uv;
+ GPUBuffer *uv_tex;
GPUBuffer *colors;
GPUBuffer *edges;
GPUBuffer *uvedges;
-
- /* for each triangle, the original MFace index */
- int *triangle_to_mface;
+ GPUBuffer *triangles; /* triangle index buffer */
/* for each original vertex, the list of related points */
struct GPUVertPointLink *vert_points;
@@ -107,18 +115,37 @@ typedef struct GPUDrawObject {
GPUBufferMaterial *materials;
int totmaterial;
- int tot_triangle_point;
- int tot_loose_point;
+ unsigned int tot_triangle_point;
+ unsigned int tot_loose_point;
+ /* different than total loops since ngons get tesselated still */
+ unsigned int tot_loop_verts;
/* caches of the original DerivedMesh values */
- int totvert;
- int totedge;
+ unsigned int totvert;
+ unsigned int totedge;
+
+ unsigned int loose_edge_offset;
+ unsigned int tot_loose_edge_drawn;
+ unsigned int tot_edge_drawn;
- /* if there was a failure allocating some buffer, use old
- * rendering code */
- bool legacy;
+ /* for subsurf, offset where drawing of interior edges starts */
+ unsigned int interior_offset;
+ unsigned int totinterior;
} GPUDrawObject;
+/* currently unused */
+// #define USE_GPU_POINT_LINK
+
+typedef struct GPUVertPointLink {
+#ifdef USE_GPU_POINT_LINK
+ struct GPUVertPointLink *next;
+#endif
+ /* -1 means uninitialized */
+ int point_index;
+} GPUVertPointLink;
+
+
+
/* used for GLSL materials */
typedef struct GPUAttrib {
int index;
@@ -129,12 +156,31 @@ typedef struct GPUAttrib {
void GPU_global_buffer_pool_free(void);
void GPU_global_buffer_pool_free_unused(void);
-GPUBuffer *GPU_buffer_alloc(int size);
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays);
void GPU_buffer_free(GPUBuffer *buffer);
-GPUDrawObject *GPU_drawobject_new(struct DerivedMesh *dm);
void GPU_drawobject_free(struct DerivedMesh *dm);
+/* free special global multires grid buffer */
+void GPU_buffer_multires_free(bool force);
+
+/* flag that controls data type to fill buffer with, a modifier will prepare. */
+typedef enum {
+ GPU_BUFFER_VERTEX = 0,
+ GPU_BUFFER_NORMAL,
+ GPU_BUFFER_COLOR,
+ GPU_BUFFER_UV,
+ GPU_BUFFER_UV_TEXPAINT,
+ GPU_BUFFER_EDGE,
+ GPU_BUFFER_UVEDGE,
+ GPU_BUFFER_TRIANGLES
+} GPUBufferType;
+
+typedef enum {
+ GPU_BINDING_ARRAY = 0,
+ GPU_BINDING_INDEX = 1,
+} GPUBindingType;
+
/* called before drawing */
void GPU_vertex_setup(struct DerivedMesh *dm);
void GPU_normal_setup(struct DerivedMesh *dm);
@@ -142,15 +188,22 @@ void GPU_uv_setup(struct DerivedMesh *dm);
void GPU_texpaint_uv_setup(struct DerivedMesh *dm);
/* colType is the cddata MCol type to use! */
void GPU_color_setup(struct DerivedMesh *dm, int colType);
+void GPU_buffer_bind_as_color(GPUBuffer *buffer);
void GPU_edge_setup(struct DerivedMesh *dm); /* does not mix with other data */
void GPU_uvedge_setup(struct DerivedMesh *dm);
+
+void GPU_triangle_setup(struct DerivedMesh *dm);
+
int GPU_attrib_element_size(GPUAttrib data[], int numdata);
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata);
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size);
+
+void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding);
+void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding);
/* can't lock more than one buffer at once */
-void *GPU_buffer_lock(GPUBuffer *buffer);
-void *GPU_buffer_lock_stream(GPUBuffer *buffer);
-void GPU_buffer_unlock(GPUBuffer *buffer);
+void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding);
+void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding);
+void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding);
/* switch color rendering on=1/off=0 */
void GPU_color_switch(int mode);
@@ -159,29 +212,33 @@ void GPU_color_switch(int mode);
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count);
/* called after drawing */
-void GPU_buffer_unbind(void);
+void GPU_buffers_unbind(void);
-/* used to check whether to use the old (without buffers) code */
-bool GPU_buffer_legacy(struct DerivedMesh *dm);
+/* only unbind interleaved data */
+void GPU_interleaved_attrib_unbind(void);
/* Buffers for non-DerivedMesh drawing */
typedef struct GPU_PBVH_Buffers GPU_PBVH_Buffers;
/* build */
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
- struct MFace *mface, struct MVert *mvert,
- int *face_indices, int totface);
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+ const int (*face_vert_indices)[4],
+ const struct MPoly *mpoly, const struct MLoop *mloop, const struct MLoopTri *looptri,
+ const struct MVert *verts,
+ const int *face_indices,
+ const int face_indices_len);
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
- unsigned int **grid_hidden, int gridsize);
+ unsigned int **grid_hidden, int gridsize, const struct CCGKey *key);
GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading);
/* update */
-void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
- int *vert_indices, int totvert, const float *vmask,
- int (*face_vert_indices)[4], bool show_diffuse_color);
+void GPU_update_mesh_pbvh_buffers(
+ GPU_PBVH_Buffers *buffers, const struct MVert *mvert,
+ const int *vert_indices, int totvert, const float *vmask,
+ const int (*face_vert_indices)[4], bool show_diffuse_color);
void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
struct BMesh *bm,
@@ -197,7 +254,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, struct CCGElem **gr
/* draw */
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe);
+ bool wireframe, bool fast);
/* debug PBVH draw*/
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf);
diff --git a/source/blender/gpu/GPU_compositing.h b/source/blender/gpu/GPU_compositing.h
new file mode 100644
index 00000000000..04e89da00a7
--- /dev/null
+++ b/source/blender/gpu/GPU_compositing.h
@@ -0,0 +1,99 @@
+/*
+ * ***** 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): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file GPU_compositing.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_COMPOSITING_H__
+#define __GPU_COMPOSITING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* opaque handle for framebuffer compositing effects (defined in gpu_compositing.c )*/
+typedef struct GPUFX GPUFX;
+struct GPUDOFSettings;
+struct GPUSSAOSettings;
+struct GPUOffScreen;
+struct GPUFXSettings;
+struct rcti;
+struct Scene;
+enum eGPUFXFlags;
+
+/**** Public API *****/
+
+typedef enum GPUFXShaderEffect {
+ /* Screen space ambient occlusion shader */
+ GPU_SHADER_FX_SSAO = 1,
+
+ /* depth of field passes. Yep, quite a complex effect */
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE = 2,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO = 3,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE = 4,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR = 5,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE = 6,
+
+ /* high quality */
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE = 7,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO = 8,
+ GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE = 9,
+
+ GPU_SHADER_FX_DEPTH_RESOLVE = 10,
+} GPUFXShaderEffect;
+
+/* keep in synch with enum above! */
+#define MAX_FX_SHADERS 11
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void);
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx);
+
+/* initialize a framebuffer with size taken from the viewport */
+bool GPU_fx_compositor_initialize_passes(
+ GPUFX *fx, const struct rcti *rect, const struct rcti *scissor_rect,
+ const struct GPUFXSettings *fx_settings);
+
+/* do compositing on the fx passes that have been initialized */
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs);
+
+/* bind new depth buffer for XRay pass */
+void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray);
+
+/* resolve a final depth buffer by compositing the XRay and normal depth buffers */
+void GPU_fx_compositor_XRay_resolve(GPUFX *fx);
+
+void GPU_fx_compositor_init_dof_settings(struct GPUDOFSettings *dof);
+void GPU_fx_compositor_init_ssao_settings(struct GPUSSAOSettings *ssao);
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __GPU_COMPOSITING_H__
diff --git a/source/blender/gpu/GPU_debug.h b/source/blender/gpu/GPU_debug.h
new file mode 100644
index 00000000000..2c1728bfff1
--- /dev/null
+++ b/source/blender/gpu/GPU_debug.h
@@ -0,0 +1,71 @@
+/*
+ * ***** 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): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_debug.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_DEBUG_H__
+#define __GPU_DEBUG_H__
+
+#include "GPU_glew.h"
+
+#include "BLI_utildefines.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* prints something if debug mode is active only */
+void GPU_print_error_debug(const char *str);
+
+/* replacement for gluErrorString */
+const char *gpuErrorString(GLenum err);
+
+/* prints current OpenGL state */
+void GPU_state_print(void);
+
+void GPU_assert_no_gl_errors(const char *file, int line, const char *str);
+
+# define GPU_ASSERT_NO_GL_ERRORS(str) GPU_assert_no_gl_errors(__FILE__, __LINE__, (str))
+
+# define GPU_CHECK_ERRORS_AROUND(glProcCall) \
+ ( \
+ GPU_ASSERT_NO_GL_ERRORS("Pre: " #glProcCall), \
+ (glProcCall), \
+ GPU_ASSERT_NO_GL_ERRORS("Post: " #glProcCall) \
+ )
+
+
+/* inserts a debug marker message for the debug context messaging system */
+void GPU_string_marker(size_t size, const char *str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_DEBUG_H__ */
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 3ddec157c49..0992f8e9d21 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -36,14 +36,16 @@
extern "C" {
#endif
+struct ImBuf;
struct Image;
struct ImageUser;
-struct MTFace;
+struct MTexPoly;
struct Object;
struct Scene;
struct View3D;
struct RegionView3D;
struct SmokeModifierData;
+struct DupliObject;
/* OpenGL drawing functions related to shading. These are also
* shared with the game engine, where there were previously
@@ -57,10 +59,6 @@ struct SmokeModifierData;
void GPU_state_init(void);
-/* Debugging */
-
-void GPU_state_print(void);
-
/* Material drawing
* - first the state is initialized by a particular object and
* it's materials
@@ -71,10 +69,14 @@ void GPU_state_print(void);
void GPU_begin_object_materials(struct View3D *v3d, struct RegionView3D *rv3d,
struct Scene *scene, struct Object *ob, bool glsl, bool *do_alpha_after);
void GPU_end_object_materials(void);
+bool GPU_object_materials_check(void);
int GPU_enable_material(int nr, void *attribs);
void GPU_disable_material(void);
+void GPU_begin_dupli_object(struct DupliObject *dob);
+void GPU_end_dupli_object(void);
+
void GPU_material_diffuse_get(int nr, float diff[4]);
bool GPU_material_use_matcaps_get(void);
@@ -86,8 +88,9 @@ int GPU_get_material_alpha_blend(void);
* be drawn using one or the other
* - passing NULL clears the state again */
-int GPU_set_tpage(struct MTFace *tface, int mipmap, int transp);
+int GPU_set_tpage(struct MTexPoly *mtexpoly, int mipmap, int transp);
void GPU_clear_tpage(bool force);
+
/* Lights
* - returns how many lights were enabled
* - this affects fixed functions materials and texface, not glsl */
@@ -99,18 +102,20 @@ int GPU_scene_object_lights(struct Scene *scene, struct Object *ob,
/* Text render
* - based on moving uv coordinates */
-void GPU_render_text(struct MTFace *tface, int mode,
- const char *textstr, int textlen, unsigned int *col,
- float *v1, float *v2, float *v3, float *v4, int glattrib);
+void GPU_render_text(
+ struct MTexPoly *mtexpoly, int mode,
+ const char *textstr, int textlen, unsigned int *col,
+ const float *v_quad[4], const float *uv_quad[4],
+ int glattrib);
/* Mipmap settings
* - these will free textures on changes */
-void GPU_set_mipmap(int mipmap);
-int GPU_get_mipmap(void);
-void GPU_set_linear_mipmap(int linear);
-int GPU_get_linear_mipmap(void);
-void GPU_paint_set_mipmap(int mipmap);
+void GPU_set_mipmap(bool mipmap);
+bool GPU_get_mipmap(void);
+void GPU_set_linear_mipmap(bool linear);
+bool GPU_get_linear_mipmap(void);
+void GPU_paint_set_mipmap(bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
@@ -123,11 +128,11 @@ void GPU_set_gpu_mipmapping(int gpu_mipmap);
/* Image updates and free
* - these deal with images bound as opengl textures */
-void GPU_paint_update_image(struct Image *ima, int x, int y, int w, int h);
+void GPU_paint_update_image(struct Image *ima, ImageUser *iuser, int x, int y, int w, int h);
void GPU_update_images_framechange(void);
int GPU_update_image_time(struct Image *ima, double time);
int GPU_verify_image(struct Image *ima, struct ImageUser *iuser, int tftile, bool compare, bool mipmap, bool is_data);
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth,
+void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
bool mipmap, bool use_hight_bit_depth, struct Image *ima);
void GPU_create_gl_tex_compressed(unsigned int *bind, unsigned int *pix, int x, int y, int mipmap, struct Image *ima, struct ImBuf *ibuf);
bool GPU_upload_dxt_texture(struct ImBuf *ibuf);
@@ -143,6 +148,11 @@ void GPU_create_smoke(struct SmokeModifierData *smd, int highres);
/* Delayed free of OpenGL buffers by main thread */
void GPU_free_unused_buffers(void);
+#ifdef WITH_OPENSUBDIV
+struct DerivedMesh;
+void GPU_draw_update_fvar_offset(struct DerivedMesh *dm);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h
index 04c4119df6e..0e8d204d224 100644
--- a/source/blender/gpu/GPU_extensions.h
+++ b/source/blender/gpu/GPU_extensions.h
@@ -52,48 +52,56 @@ typedef struct GPUOffScreen GPUOffScreen;
struct GPUShader;
typedef struct GPUShader GPUShader;
+struct GPUProgram;
+typedef struct GPUProgram GPUProgram;
+
/* GPU extensions support */
void GPU_extensions_disable(void);
-void GPU_extensions_init(void); /* call this before running any of the functions below */
-void GPU_extensions_exit(void);
-int GPU_print_error(const char *str);
-int GPU_glsl_support(void);
-int GPU_non_power_of_two_support(void);
-int GPU_display_list_support(void);
+bool GPU_glsl_support(void);
+bool GPU_non_power_of_two_support(void);
+bool GPU_vertex_buffer_support(void);
+bool GPU_display_list_support(void);
+bool GPU_bicubic_bump_support(void);
+bool GPU_geometry_shader_support(void);
+bool GPU_instanced_drawing_support(void);
+
+int GPU_max_texture_size(void);
int GPU_color_depth(void);
-void GPU_code_generate_glsl_lib(void);
-int GPU_bicubic_bump_support(void);
-int GPU_max_texture_size (void);
+void GPU_get_dfdy_factors(float fac[2]);
+
+bool GPU_mem_stats_supported(void);
+void GPU_mem_stats_get(int *totalmem, int *freemem);
+void GPU_code_generate_glsl_lib(void);
/* GPU Types */
typedef enum GPUDeviceType {
- GPU_DEVICE_NVIDIA = (1<<0),
- GPU_DEVICE_ATI = (1<<1),
- GPU_DEVICE_INTEL = (1<<2),
- GPU_DEVICE_SOFTWARE = (1<<3),
- GPU_DEVICE_UNKNOWN = (1<<4),
- GPU_DEVICE_ANY = (0xff)
+ GPU_DEVICE_NVIDIA = (1<<0),
+ GPU_DEVICE_ATI = (1<<1),
+ GPU_DEVICE_INTEL = (1<<2),
+ GPU_DEVICE_SOFTWARE = (1<<3),
+ GPU_DEVICE_UNKNOWN = (1<<4),
+ GPU_DEVICE_ANY = (0xff)
} GPUDeviceType;
typedef enum GPUOSType {
- GPU_OS_WIN = (1<<8),
- GPU_OS_MAC = (1<<9),
- GPU_OS_UNIX = (1<<10),
- GPU_OS_ANY = (0xff00)
+ GPU_OS_WIN = (1<<8),
+ GPU_OS_MAC = (1<<9),
+ GPU_OS_UNIX = (1<<10),
+ GPU_OS_ANY = (0xff00)
} GPUOSType;
typedef enum GPUDriverType {
- GPU_DRIVER_OFFICIAL = (1<<16),
+ GPU_DRIVER_OFFICIAL = (1<<16),
GPU_DRIVER_OPENSOURCE = (1<<17),
- GPU_DRIVER_SOFTWARE = (1<<18),
- GPU_DRIVER_ANY = (0xff0000)
+ GPU_DRIVER_SOFTWARE = (1<<18),
+ GPU_DRIVER_ANY = (0xff0000)
} GPUDriverType;
-int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
+bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
/* GPU Texture
* - always returns unsigned char RGBA textures
@@ -109,11 +117,19 @@ int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver);
* - if created with from_blender, will not free the texture
*/
-GPUTexture *GPU_texture_create_1D(int w, float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_2D(int w, int h, float *pixels, char err_out[256]);
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels);
+typedef enum GPUHDRType {
+ GPU_HDR_NONE = 0,
+ GPU_HDR_HALF_FLOAT = 1,
+ GPU_HDR_FULL_FLOAT = (1 << 1),
+} GPUHDRType;
+
+GPUTexture *GPU_texture_create_1D(int w, const float *pixels, char err_out[256]);
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *pixels, GPUHDRType hdr, char err_out[256]);
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels);
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256]);
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256]);
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256]);
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256]);
GPUTexture *GPU_texture_from_blender(struct Image *ima,
struct ImageUser *iuser, bool is_data, double time, int mipmap);
GPUTexture *GPU_texture_from_preview(struct PreviewImage *prv, int mipmap);
@@ -128,12 +144,14 @@ void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
void GPU_texture_unbind(GPUTexture *tex);
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter);
+
GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex);
-int GPU_texture_target(GPUTexture *tex);
-int GPU_texture_opengl_width(GPUTexture *tex);
-int GPU_texture_opengl_height(GPUTexture *tex);
-int GPU_texture_opengl_bindcode(GPUTexture *tex);
+int GPU_texture_target(const GPUTexture *tex);
+int GPU_texture_opengl_width(const GPUTexture *tex);
+int GPU_texture_opengl_height(const GPUTexture *tex);
+int GPU_texture_opengl_bindcode(const GPUTexture *tex);
/* GPU Framebuffer
* - this is a wrapper for an OpenGL framebuffer object (FBO). in practice
@@ -142,12 +160,17 @@ int GPU_texture_opengl_bindcode(GPUTexture *tex);
* - after any of the GPU_framebuffer_* functions, GPU_framebuffer_restore must
* be called before rendering to the window framebuffer again */
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex);
+
GPUFrameBuffer *GPU_framebuffer_create(void);
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256]);
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex);
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *fb, GPUTexture *tex, int w, int h);
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256]);
+void GPU_framebuffer_texture_detach(GPUTexture *tex);
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *fb, GPUTexture *tex);
void GPU_framebuffer_free(GPUFrameBuffer *fb);
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256]);
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot);
void GPU_framebuffer_restore(void);
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex);
@@ -158,17 +181,42 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]);
void GPU_offscreen_free(GPUOffScreen *ofs);
-void GPU_offscreen_bind(GPUOffScreen *ofs);
-void GPU_offscreen_unbind(GPUOffScreen *ofs);
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save);
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore);
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels);
-int GPU_offscreen_width(GPUOffScreen *ofs);
-int GPU_offscreen_height(GPUOffScreen *ofs);
+int GPU_offscreen_width(const GPUOffScreen *ofs);
+int GPU_offscreen_height(const GPUOffScreen *ofs);
+
+/* Builtin/Non-generated shaders */
+typedef enum GPUProgramType {
+ GPU_PROGRAM_TYPE_FRAGMENT = 0
+} GPUProgramType;
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code);
+void GPU_program_free(GPUProgram *program);
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w);
+void GPU_program_bind(GPUProgram *);
+void GPU_program_unbind(GPUProgram *);
/* GPU Shader
* - only for fragment shaders now
* - must call texture bind before setting a texture as uniform! */
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines);
+GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *geocode, const char *libcode, const char *defines, int input, int output, int number);
+enum {
+ GPU_SHADER_FLAGS_NONE = 0,
+ GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV = (1 << 0),
+};
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags);
void GPU_shader_free(GPUShader *shader);
void GPU_shader_bind(GPUShader *shader);
@@ -176,24 +224,36 @@ void GPU_shader_unbind(void);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
void GPU_shader_uniform_vector(GPUShader *shader, int location, int length,
- int arraysize, float *value);
+ int arraysize, const float *value);
+void GPU_shader_uniform_vector_int(GPUShader *shader, int location, int length,
+ int arraysize, const int *value);
+
void GPU_shader_uniform_texture(GPUShader *shader, int location, GPUTexture *tex);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number);
int GPU_shader_get_attribute(GPUShader *shader, const char *name);
/* Builtin/Non-generated shaders */
typedef enum GPUBuiltinShader {
- GPU_SHADER_VSM_STORE = (1<<0),
- GPU_SHADER_SEP_GAUSSIAN_BLUR = (1<<1),
+ GPU_SHADER_VSM_STORE = 0,
+ GPU_SHADER_SEP_GAUSSIAN_BLUR = 1,
} GPUBuiltinShader;
+typedef enum GPUBuiltinProgram {
+ GPU_PROGRAM_SMOKE = 0,
+ GPU_PROGRAM_SMOKE_COLORED = 1,
+} GPUBuiltinProgram;
+
GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader);
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program);
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp);
+
void GPU_shader_free_builtin_shaders(void);
/* Vertex attributes for shaders */
-#define GPU_MAX_ATTRIB 32
+#define GPU_MAX_ATTRIB 32
typedef struct GPUVertexAttribs {
struct {
diff --git a/source/blender/gpu/GPU_glew.h b/source/blender/gpu/GPU_glew.h
new file mode 100644
index 00000000000..94217863fd6
--- /dev/null
+++ b/source/blender/gpu/GPU_glew.h
@@ -0,0 +1,37 @@
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/GPU_glew.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_GLEW_H__
+#define __GPU_GLEW_H__
+
+#include "glew-mx.h"
+
+#endif /* __GPU_GLEW_H__ */
diff --git a/source/blender/gpu/GPU_init_exit.h b/source/blender/gpu/GPU_init_exit.h
new file mode 100644
index 00000000000..e89c970b7d9
--- /dev/null
+++ b/source/blender/gpu/GPU_init_exit.h
@@ -0,0 +1,46 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/GPU_init_exit.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_INIT_EXIT_H__
+#define __GPU_INIT_EXIT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void GPU_init(void);
+void GPU_exit(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GPU_INIT_EXIT_H__ */
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 8d44ad87916..dd08ed83e5a 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -32,8 +32,11 @@
#ifndef __GPU_MATERIAL_H__
#define __GPU_MATERIAL_H__
+#include "DNA_customdata_types.h" /* for CustomDataType */
#include "DNA_listBase.h"
+#include "BLI_sys_types.h" /* for bool */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -42,10 +45,7 @@ struct Image;
struct ImageUser;
struct Material;
struct Object;
-struct Lamp;
struct Image;
-struct bNode;
-struct LinkNode;
struct Scene;
struct SceneRenderLayer;
struct GPUVertexAttribs;
@@ -56,15 +56,18 @@ struct GPUMaterial;
struct GPUTexture;
struct GPULamp;
struct PreviewImage;
+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 */
typedef enum GPUType {
+ /* The value indicates the number of elements in each type */
GPU_NONE = 0,
GPU_FLOAT = 1,
GPU_VEC2 = 2,
@@ -72,20 +75,26 @@ typedef enum GPUType {
GPU_VEC4 = 4,
GPU_MAT3 = 9,
GPU_MAT4 = 16,
+
GPU_TEX2D = 1002,
GPU_SHADOW2D = 1003,
GPU_ATTRIB = 3001
} GPUType;
typedef enum GPUBuiltin {
- GPU_VIEW_MATRIX = 1,
- GPU_OBJECT_MATRIX = 2,
- GPU_INVERSE_VIEW_MATRIX = 4,
- GPU_INVERSE_OBJECT_MATRIX = 8,
- GPU_VIEW_POSITION = 16,
- GPU_VIEW_NORMAL = 32,
- GPU_OBCOLOR = 64,
- GPU_AUTO_BUMPSCALE = 128,
+ GPU_VIEW_MATRIX = (1 << 0),
+ GPU_OBJECT_MATRIX = (1 << 1),
+ GPU_INVERSE_VIEW_MATRIX = (1 << 2),
+ GPU_INVERSE_OBJECT_MATRIX = (1 << 3),
+ GPU_VIEW_POSITION = (1 << 4),
+ GPU_VIEW_NORMAL = (1 << 5),
+ GPU_OBCOLOR = (1 << 6),
+ GPU_AUTO_BUMPSCALE = (1 << 7),
+ GPU_CAMERA_TEXCO_FACTORS = (1 << 8),
+ GPU_PARTICLE_SCALAR_PROPS = (1 << 9),
+ GPU_PARTICLE_LOCATION = (1 << 10),
+ GPU_PARTICLE_VELOCITY = (1 << 11),
+ GPU_PARTICLE_ANG_VELOCITY = (1 << 12),
} GPUBuiltin;
typedef enum GPUOpenGLBuiltin {
@@ -93,12 +102,19 @@ typedef enum GPUOpenGLBuiltin {
GPU_COLOR = 2,
} GPUOpenGLBuiltin;
+typedef enum GPUMatType {
+ GPU_MATERIAL_TYPE_MESH = 1,
+ GPU_MATERIAL_TYPE_WORLD = 2,
+} GPUMatType;
+
+
typedef enum GPUBlendMode {
GPU_BLEND_SOLID = 0,
GPU_BLEND_ADD = 1,
GPU_BLEND_ALPHA = 2,
GPU_BLEND_CLIP = 4,
- GPU_BLEND_ALPHA_SORT = 8
+ GPU_BLEND_ALPHA_SORT = 8,
+ GPU_BLEND_ALPHA_TO_COVERAGE = 16
} GPUBlendMode;
typedef struct GPUNodeStack {
@@ -111,15 +127,74 @@ typedef struct GPUNodeStack {
short sockettype;
} GPUNodeStack;
-GPUNodeLink *GPU_attribute(int type, const char *name);
+
+#define GPU_DYNAMIC_GROUP_FROM_TYPE(f) ((f) & 0xFFFF0000)
+
+#define GPU_DYNAMIC_GROUP_MISC 0x00010000
+#define GPU_DYNAMIC_GROUP_LAMP 0x00020000
+#define GPU_DYNAMIC_GROUP_OBJECT 0x00030000
+#define GPU_DYNAMIC_GROUP_SAMPLER 0x00040000
+#define GPU_DYNAMIC_GROUP_MIST 0x00050000
+#define GPU_DYNAMIC_GROUP_WORLD 0x00060000
+#define GPU_DYNAMIC_GROUP_MAT 0x00070000
+
+typedef enum GPUDynamicType {
+
+ GPU_DYNAMIC_NONE = 0,
+
+ GPU_DYNAMIC_OBJECT_VIEWMAT = 1 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_MAT = 2 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_VIEWIMAT = 3 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_IMAT = 4 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_COLOR = 5 | GPU_DYNAMIC_GROUP_OBJECT,
+ GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 6 | GPU_DYNAMIC_GROUP_OBJECT,
+
+ GPU_DYNAMIC_LAMP_DYNVEC = 1 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNCO = 2 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNIMAT = 3 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNPERSMAT = 4 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNENERGY = 5 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DYNCOL = 6 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_DISTANCE = 7 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_ATT1 = 8 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_ATT2 = 9 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTSIZE = 10 | GPU_DYNAMIC_GROUP_LAMP,
+ GPU_DYNAMIC_LAMP_SPOTBLEND = 11 | GPU_DYNAMIC_GROUP_LAMP,
+
+ GPU_DYNAMIC_SAMPLER_2DBUFFER = 1 | GPU_DYNAMIC_GROUP_SAMPLER,
+ GPU_DYNAMIC_SAMPLER_2DIMAGE = 2 | GPU_DYNAMIC_GROUP_SAMPLER,
+ GPU_DYNAMIC_SAMPLER_2DSHADOW = 3 | GPU_DYNAMIC_GROUP_SAMPLER,
+
+ GPU_DYNAMIC_MIST_ENABLE = 1 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_START = 2 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_DISTANCE = 3 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_INTENSITY = 4 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_TYPE = 5 | GPU_DYNAMIC_GROUP_MIST,
+ GPU_DYNAMIC_MIST_COLOR = 6 | GPU_DYNAMIC_GROUP_MIST,
+
+ GPU_DYNAMIC_HORIZON_COLOR = 1 | GPU_DYNAMIC_GROUP_WORLD,
+ GPU_DYNAMIC_AMBIENT_COLOR = 2 | GPU_DYNAMIC_GROUP_WORLD,
+
+ GPU_DYNAMIC_MAT_DIFFRGB = 1 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_REF = 2 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_SPECRGB = 3 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_SPEC = 4 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_HARD = 5 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_EMIT = 6 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_AMB = 7 | GPU_DYNAMIC_GROUP_MAT,
+ GPU_DYNAMIC_MAT_ALPHA = 8 | GPU_DYNAMIC_GROUP_MAT
+} GPUDynamicType;
+
+GPUNodeLink *GPU_attribute(CustomDataType type, const char *name);
GPUNodeLink *GPU_uniform(float *num);
-GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data);
+GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_image(struct Image *ima, struct ImageUser *iuser, bool is_data);
GPUNodeLink *GPU_image_preview(struct PreviewImage *prv);
GPUNodeLink *GPU_texture(int size, float *pixels);
-GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, int dynamictype, void *data);
+GPUNodeLink *GPU_dynamic_texture(struct GPUTexture *tex, GPUDynamicType dynamictype, void *data);
GPUNodeLink *GPU_builtin(GPUBuiltin builtin);
GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin);
+void GPU_node_link_set_type(GPUNodeLink *link, GPUType type);
bool GPU_link(GPUMaterial *mat, const char *name, ...);
bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNodeStack *out, ...);
@@ -129,19 +204,21 @@ void GPU_material_enable_alpha(GPUMaterial *material);
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4]);
/* High level functions to create and use GPU materials */
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo);
-GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma);
-GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma);
-void GPU_material_free(struct Material *ma);
+GPUMaterial *GPU_material_from_blender(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+GPUMaterial *GPU_material_matcap(struct Scene *scene, struct Material *ma, bool use_opensubdiv);
+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], bool scenelock);
-void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale);
+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);
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo *pi);
void GPU_material_unbind(GPUMaterial *material);
-int GPU_material_bound(GPUMaterial *material);
+bool GPU_material_bound(GPUMaterial *material);
struct Scene *GPU_material_scene(GPUMaterial *material);
+GPUMatType GPU_Material_get_type(GPUMaterial *material);
void GPU_material_vertex_attributes(GPUMaterial *material,
struct GPUVertexAttribs *attrib);
@@ -157,6 +234,7 @@ typedef struct GPUShadeInput {
GPUNodeLink *rgb, *specrgb, *vn, *view, *vcol, *ref;
GPUNodeLink *alpha, *refl, *spec, *emit, *har, *amb;
+ GPUNodeLink *spectra;
} GPUShadeInput;
typedef struct GPUShadeResult {
@@ -168,36 +246,9 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr);
/* Export GLSL shader */
-typedef enum GPUDynamicType {
- GPU_DYNAMIC_NONE = 0,
- GPU_DYNAMIC_OBJECT_VIEWMAT = 1,
- GPU_DYNAMIC_OBJECT_MAT = 2,
- GPU_DYNAMIC_OBJECT_VIEWIMAT = 3,
- GPU_DYNAMIC_OBJECT_IMAT = 4,
- GPU_DYNAMIC_OBJECT_COLOR = 5,
- GPU_DYNAMIC_OBJECT_AUTOBUMPSCALE = 15,
-
- GPU_DYNAMIC_LAMP_FIRST = 6,
- GPU_DYNAMIC_LAMP_DYNVEC = 6,
- GPU_DYNAMIC_LAMP_DYNCO = 7,
- GPU_DYNAMIC_LAMP_DYNIMAT = 8,
- GPU_DYNAMIC_LAMP_DYNPERSMAT = 9,
- GPU_DYNAMIC_LAMP_DYNENERGY = 10,
- GPU_DYNAMIC_LAMP_DYNCOL = 11,
- GPU_DYNAMIC_LAMP_LAST = 11,
- GPU_DYNAMIC_SAMPLER_2DBUFFER = 12,
- GPU_DYNAMIC_SAMPLER_2DIMAGE = 13,
- GPU_DYNAMIC_SAMPLER_2DSHADOW = 14,
- GPU_DYNAMIC_LAMP_DISTANCE = 16,
- GPU_DYNAMIC_LAMP_ATT1 = 17,
- GPU_DYNAMIC_LAMP_ATT2 = 18,
- GPU_DYNAMIC_LAMP_SPOTSIZE = 19,
- GPU_DYNAMIC_LAMP_SPOTBLEND = 20,
-} GPUDynamicType;
-
typedef enum GPUDataType {
GPU_DATA_NONE = 0,
- GPU_DATA_1I = 1, // 1 integer
+ GPU_DATA_1I = 1, /* 1 integer */
GPU_DATA_1F = 2,
GPU_DATA_2F = 3,
GPU_DATA_3F = 4,
@@ -210,23 +261,23 @@ typedef enum GPUDataType {
/* this structure gives information of each uniform found in the shader */
typedef struct GPUInputUniform {
struct GPUInputUniform *next, *prev;
- char varname[32]; /* name of uniform in shader */
- GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
- GPUDataType datatype; /* type of uniform data */
- struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
- struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
- int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
- unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
- int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
+ char varname[32]; /* name of uniform in shader */
+ GPUDynamicType type; /* type of uniform, data format and calculation derive from it */
+ GPUDataType datatype; /* type of uniform data */
+ struct Object *lamp; /* when type=GPU_DYNAMIC_LAMP_... or GPU_DYNAMIC_SAMPLER_2DSHADOW */
+ struct Image *image; /* when type=GPU_DYNAMIC_SAMPLER_2DIMAGE */
+ int texnumber; /* when type=GPU_DYNAMIC_SAMPLER, texture number: 0.. */
+ unsigned char *texpixels; /* for internally generated texture, pixel data in RGBA format */
+ int texsize; /* size in pixel of the texture in texpixels buffer: for 2D textures, this is S and T size (square texture) */
} GPUInputUniform;
typedef struct GPUInputAttribute {
struct GPUInputAttribute *next, *prev;
- char varname[32]; /* name of attribute in shader */
- int type; /* from CustomData.type, data type derives from it */
- GPUDataType datatype; /* type of attribute data */
- const char *name; /* layer name */
- int number; /* generic attribute number */
+ char varname[32]; /* name of attribute in shader */
+ int type; /* from CustomData.type, data type derives from it */
+ GPUDataType datatype; /* type of attribute data */
+ const char *name; /* layer name */
+ int number; /* generic attribute number */
} GPUInputAttribute;
typedef struct GPUShaderExport {
@@ -255,7 +306,27 @@ void GPU_lamp_update_colors(GPULamp *lamp, float r, float g, float b, float ener
void GPU_lamp_update_distance(GPULamp *lamp, float distance, float att1, float att2);
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, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow);
+GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow, GPUNodeLink **energy);
+
+/* World */
+void GPU_mist_update_enable(short enable);
+void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3]);
+void GPU_horizon_update_color(float color[3]);
+void GPU_ambient_update_color(float color[3]);
+
+typedef struct GPUParticleInfo
+{
+ float scalprops[4];
+ float location[3];
+ float velocity[3];
+ float angular_velocity[3];
+} GPUParticleInfo;
+
+#ifdef WITH_OPENSUBDIV
+struct DerivedMesh;
+void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
+ struct DerivedMesh *dm);
+#endif
#ifdef __cplusplus
}
diff --git a/source/blender/gpu/GPU_select.h b/source/blender/gpu/GPU_select.h
index 1a274e0ad9d..09137fc998b 100644
--- a/source/blender/gpu/GPU_select.h
+++ b/source/blender/gpu/GPU_select.h
@@ -27,8 +27,8 @@
* \ingroup gpu
*/
-#ifndef __GPU_SELECT__
-#define __GPU_SELECT__
+#ifndef __GPU_SELECT_H__
+#define __GPU_SELECT_H__
#include "DNA_vec_types.h" /* rcft */
#include "BLI_sys_types.h"
diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h
index c8fb1f09b04..239296209b4 100644
--- a/source/blender/gpu/GPU_simple_shader.h
+++ b/source/blender/gpu/GPU_simple_shader.h
@@ -42,11 +42,11 @@ extern "C" {
typedef enum GPUSimpleShaderOption {
GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */
- GPU_SHADER_LIGHTING = (1<<1), /* use lighting */
- GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */
- GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */
+ GPU_SHADER_LIGHTING = (1<<1), /* use lighting */
+ GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */
+ GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */
- GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
+ GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */
GPU_SHADER_OPTIONS_NUM = 5,
GPU_SHADER_OPTION_COMBINATIONS = (1<<GPU_SHADER_OPTIONS_NUM)
} GPUSimpleShaderOption;
diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript
index e9320f08eff..d27d5b09b56 100644
--- a/source/blender/gpu/SConscript
+++ b/source/blender/gpu/SConscript
@@ -30,13 +30,15 @@ Import ('env')
sources = env.Glob('intern/*.c')
sources += env.Glob('shaders/*.c')
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
+ '#/intern/glew-mx',
'#/intern/guardedalloc',
+ env['BF_GLEW_INC'],
'#/intern/smoke/extern',
- '#/extern/glew/include',
'../blenkernel',
'../blenlib',
'../bmesh',
@@ -46,7 +48,6 @@ incs = [
'../makesrna',
'../nodes',
'../nodes/intern',
- env['BF_OPENGL_INC'],
]
if env['WITH_BF_GAMEENGINE']:
@@ -60,15 +61,31 @@ if env['WITH_BF_SMOKE']:
if env['WITH_BF_DDS']:
defs.append('WITH_DDS')
+if env['WITH_BF_OPENSUBDIV']:
+ defs.append('WITH_OPENSUBDIV')
+
# generated data files
import os
sources.extend((
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_geometry.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_program_smoke_color_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_ssao_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_hq_geo.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_frag.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_dof_vert.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_depth_resolve.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_lib.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_fx_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"),
+ os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex_world.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"),
os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"),
))
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index 5d2c9cd3a90..b4617b9790e 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -36,7 +36,7 @@
#include <stddef.h>
#include <string.h>
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "MEM_guardedalloc.h"
@@ -46,13 +46,12 @@
#include "BLI_ghash.h"
#include "BLI_threads.h"
-#include "DNA_material_types.h"
#include "DNA_meshdata_types.h"
#include "BKE_ccg.h"
#include "BKE_DerivedMesh.h"
#include "BKE_paint.h"
-#include "BKE_material.h"
+#include "BKE_mesh.h"
#include "BKE_pbvh.h"
#include "DNA_userdef_types.h"
@@ -71,17 +70,80 @@ typedef enum {
GPU_BUFFER_ELEMENT_STATE = (1 << 5),
} GPUBufferState;
+typedef struct {
+ GLenum gl_buffer_type;
+ int num_components; /* number of data components for one vertex */
+} GPUBufferTypeSettings;
+
+
+static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type);
+
+const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
+ /* vertex */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* normal */
+ {GL_ARRAY_BUFFER_ARB, 4}, /* we copy 3 shorts per normal but we add a fourth for alignment */
+ /* mcol */
+ {GL_ARRAY_BUFFER_ARB, 3},
+ /* uv */
+ {GL_ARRAY_BUFFER_ARB, 2},
+ /* uv for texpaint */
+ {GL_ARRAY_BUFFER_ARB, 4},
+ /* edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
+ /* uv edge */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 4},
+ /* triangles, 1 point since we are allocating from tottriangle points, which account for all points */
+ {GL_ELEMENT_ARRAY_BUFFER_ARB, 1},
+};
+
#define MAX_GPU_ATTRIB_DATA 32
#define BUFFER_OFFSET(n) ((GLubyte *)NULL + (n))
/* -1 - undefined, 0 - vertex arrays, 1 - VBOs */
-static int useVBOs = -1;
static GPUBufferState GLStates = 0;
static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } };
static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
+/* multires global buffer, can be used for many grids having the same grid size */
+static GPUBuffer *mres_glob_buffer = NULL;
+static int mres_prev_gridsize = -1;
+static GLenum mres_prev_index_type = 0;
+static unsigned mres_prev_totquad = 0;
+
+void GPU_buffer_material_finalize(GPUDrawObject *gdo, GPUBufferMaterial *matinfo, int totmat)
+{
+ int i, curmat, curelement;
+
+ /* count the number of materials used by this DerivedMesh */
+ for (i = 0; i < totmat; i++) {
+ if (matinfo[i].totelements > 0)
+ gdo->totmaterial++;
+ }
+
+ /* allocate an array of materials used by this DerivedMesh */
+ gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
+ "GPUDrawObject.materials");
+
+ /* initialize the materials array */
+ for (i = 0, curmat = 0, curelement = 0; i < totmat; i++) {
+ if (matinfo[i].totelements > 0) {
+ gdo->materials[curmat] = matinfo[i];
+ gdo->materials[curmat].start = curelement;
+ gdo->materials[curmat].mat_nr = i;
+ gdo->materials[curmat].polys = MEM_mallocN(sizeof(int) * matinfo[i].totpolys, "GPUBufferMaterial.polys");
+
+ curelement += matinfo[i].totelements;
+ curmat++;
+ }
+ }
+
+ MEM_freeN(matinfo);
+}
+
+
/* stores recently-deleted buffers so that new buffers won't have to
* be recreated as often
*
@@ -96,33 +158,22 @@ static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER;
typedef struct GPUBufferPool {
/* number of allocated buffers stored */
int totbuf;
- int totpbvhbufids;
/* actual allocated length of the arrays */
int maxsize;
- int maxpbvhsize;
GPUBuffer **buffers;
- GLuint *pbvhbufids;
} GPUBufferPool;
#define MAX_FREE_GPU_BUFFERS 8
-#define MAX_FREE_GPU_BUFF_IDS 100
/* create a new GPUBufferPool */
static GPUBufferPool *gpu_buffer_pool_new(void)
{
GPUBufferPool *pool;
- /* enable VBOs if supported */
- if (useVBOs == -1)
- useVBOs = (GLEW_ARB_vertex_buffer_object ? 1 : 0);
-
pool = MEM_callocN(sizeof(GPUBufferPool), "GPUBuffer_Pool");
pool->maxsize = MAX_FREE_GPU_BUFFERS;
- pool->maxpbvhsize = MAX_FREE_GPU_BUFF_IDS;
pool->buffers = MEM_mallocN(sizeof(*pool->buffers) * pool->maxsize,
"GPUBufferPool.buffers");
- pool->pbvhbufids = MEM_mallocN(sizeof(*pool->pbvhbufids) * pool->maxpbvhsize,
- "GPUBufferPool.pbvhbuffers");
return pool;
}
@@ -158,7 +209,7 @@ static void gpu_buffer_pool_delete_last(GPUBufferPool *pool)
return;
/* delete the buffer's data */
- if (useVBOs)
+ if (last->use_vbo)
glDeleteBuffersARB(1, &last->id);
else
MEM_freeN(last->pointer);
@@ -180,7 +231,6 @@ static void gpu_buffer_pool_free(GPUBufferPool *pool)
gpu_buffer_pool_delete_last(pool);
MEM_freeN(pool->buffers);
- MEM_freeN(pool->pbvhbufids);
MEM_freeN(pool);
}
@@ -194,9 +244,6 @@ static void gpu_buffer_pool_free_unused(GPUBufferPool *pool)
while (pool->totbuf)
gpu_buffer_pool_delete_last(pool);
- glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
- pool->totpbvhbufids = 0;
-
BLI_mutex_unlock(&buffer_mutex);
}
@@ -226,11 +273,12 @@ void GPU_global_buffer_pool_free_unused(void)
*
* Thread-unsafe version for internal usage only.
*/
-static GPUBuffer *gpu_buffer_alloc_intern(int size)
+static GPUBuffer *gpu_buffer_alloc_intern(size_t size, bool use_VBO)
{
GPUBufferPool *pool;
GPUBuffer *buf;
- int i, bufsize, bestfit = -1;
+ int i, bestfit = -1;
+ size_t bufsize;
/* bad case, leads to leak of buf since buf->pointer will allocate
* NULL, leading to return without cleanup. In any case better detect early
@@ -251,6 +299,11 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
for (i = 0; i < pool->totbuf; i++) {
bufsize = pool->buffers[i]->size;
+ /* only return a buffer that matches the VBO preference */
+ if (pool->buffers[i]->use_vbo != use_VBO) {
+ continue;
+ }
+
/* check for an exact size match */
if (bufsize == size) {
bestfit = i;
@@ -279,8 +332,9 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
/* no acceptable buffer found in the pool, create a new one */
buf = MEM_callocN(sizeof(GPUBuffer), "GPUBuffer");
buf->size = size;
+ buf->use_vbo = use_VBO;
- if (useVBOs == 1) {
+ if (use_VBO) {
/* create a new VBO and initialize it to the requested
* size */
glGenBuffersARB(1, &buf->id);
@@ -289,8 +343,11 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
else {
+ static int time = 0;
+
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
-
+
+ time++;
/* purpose of this seems to be dealing with
* out-of-memory errors? looks a bit iffy to me
* though, at least on Linux I expect malloc() would
@@ -299,17 +356,20 @@ static GPUBuffer *gpu_buffer_alloc_intern(int size)
gpu_buffer_pool_delete_last(pool);
buf->pointer = MEM_mallocN(size, "GPUBuffer.pointer");
}
- if (!buf->pointer)
+ if (!buf->pointer) {
+ MEM_freeN(buf);
return NULL;
+ }
}
return buf;
}
/* Same as above, but safe for threading. */
-GPUBuffer *GPU_buffer_alloc(int size)
+GPUBuffer *GPU_buffer_alloc(size_t size, bool force_vertex_arrays)
{
GPUBuffer *buffer;
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO) && !force_vertex_arrays;
if (size == 0) {
/* Early out, no lock needed in this case. */
@@ -317,7 +377,7 @@ GPUBuffer *GPU_buffer_alloc(int size)
}
BLI_mutex_lock(&buffer_mutex);
- buffer = gpu_buffer_alloc_intern(size);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
BLI_mutex_unlock(&buffer_mutex);
return buffer;
@@ -381,224 +441,95 @@ void GPU_buffer_free(GPUBuffer *buffer)
BLI_mutex_unlock(&buffer_mutex);
}
-/* currently unused */
-// #define USE_GPU_POINT_LINK
-
-typedef struct GPUVertPointLink {
-#ifdef USE_GPU_POINT_LINK
- struct GPUVertPointLink *next;
-#endif
- /* -1 means uninitialized */
- int point_index;
-} GPUVertPointLink;
-
-
-/* add a new point to the list of points related to a particular
- * vertex */
-#ifdef USE_GPU_POINT_LINK
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
-{
- GPUVertPointLink *lnk;
-
- lnk = &gdo->vert_points[vert_index];
-
- /* if first link is in use, add a new link at the end */
- if (lnk->point_index != -1) {
- /* get last link */
- for (; lnk->next; lnk = lnk->next) ;
-
- /* add a new link from the pool */
- lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage];
- gdo->vert_points_usage++;
- }
-
- lnk->point_index = point_index;
-}
-
-#else
-
-static void gpu_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index)
+void GPU_buffer_multires_free(bool force)
{
- GPUVertPointLink *lnk;
- lnk = &gdo->vert_points[vert_index];
- if (lnk->point_index == -1) {
- lnk->point_index = point_index;
- }
-}
-
-#endif /* USE_GPU_POINT_LINK */
-
-/* update the vert_points and triangle_to_mface fields with a new
- * triangle */
-static void gpu_drawobject_add_triangle(GPUDrawObject *gdo,
- int base_point_index,
- int face_index,
- int v1, int v2, int v3)
-{
- int i, v[3] = {v1, v2, v3};
- for (i = 0; i < 3; i++)
- gpu_drawobject_add_vert_point(gdo, v[i], base_point_index + i);
- gdo->triangle_to_mface[base_point_index / 3] = face_index;
-}
-
-/* for each vertex, build a list of points related to it; these lists
- * are stored in an array sized to the number of vertices */
-static void gpu_drawobject_init_vert_points(GPUDrawObject *gdo, MFace *f, int totface, int totmat)
-{
- GPUBufferMaterial *mat;
- int i, *mat_orig_to_new;
-
- mat_orig_to_new = MEM_callocN(sizeof(*mat_orig_to_new) * totmat,
- "GPUDrawObject.mat_orig_to_new");
- /* allocate the array and space for links */
- gdo->vert_points = MEM_mallocN(sizeof(GPUVertPointLink) * gdo->totvert,
- "GPUDrawObject.vert_points");
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points_mem = MEM_callocN(sizeof(GPUVertPointLink) * gdo->tot_triangle_point,
- "GPUDrawObject.vert_points_mem");
- gdo->vert_points_usage = 0;
-#endif
-
- /* build a map from the original material indices to the new
- * GPUBufferMaterial indices */
- for (i = 0; i < gdo->totmaterial; i++)
- mat_orig_to_new[gdo->materials[i].mat_nr] = i;
-
- /* -1 indicates the link is not yet used */
- for (i = 0; i < gdo->totvert; i++) {
-#ifdef USE_GPU_POINT_LINK
- gdo->vert_points[i].link = NULL;
-#endif
- gdo->vert_points[i].point_index = -1;
+ if (!mres_glob_buffer) {
+ /* Early output, no need to lock in this case, */
+ return;
}
- for (i = 0; i < totface; i++, f++) {
- mat = &gdo->materials[mat_orig_to_new[f->mat_nr]];
-
- /* add triangle */
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v1, f->v2, f->v3);
- mat->totpoint += 3;
-
- /* add second triangle for quads */
- if (f->v4) {
- gpu_drawobject_add_triangle(gdo, mat->start + mat->totpoint,
- i, f->v3, f->v4, f->v1);
- mat->totpoint += 3;
+ if (force && BLI_thread_is_main()) {
+ if (mres_glob_buffer) {
+ if (mres_glob_buffer->id)
+ glDeleteBuffersARB(1, &mres_glob_buffer->id);
+ else if (mres_glob_buffer->pointer)
+ MEM_freeN(mres_glob_buffer->pointer);
+ MEM_freeN(mres_glob_buffer);
}
}
-
- /* map any unused vertices to loose points */
- for (i = 0; i < gdo->totvert; i++) {
- if (gdo->vert_points[i].point_index == -1) {
- gdo->vert_points[i].point_index = gdo->tot_triangle_point + gdo->tot_loose_point;
- gdo->tot_loose_point++;
- }
+ else {
+ BLI_mutex_lock(&buffer_mutex);
+ gpu_buffer_free_intern(mres_glob_buffer);
+ BLI_mutex_unlock(&buffer_mutex);
}
- MEM_freeN(mat_orig_to_new);
+ mres_glob_buffer = NULL;
+ mres_prev_gridsize = -1;
+ mres_prev_index_type = 0;
+ mres_prev_totquad = 0;
}
-/* see GPUDrawObject's structure definition for a description of the
- * data being initialized here */
-GPUDrawObject *GPU_drawobject_new(DerivedMesh *dm)
-{
- GPUDrawObject *gdo;
- MFace *mface;
- int totmat = dm->totmat;
- int *points_per_mat;
- int i, curmat, curpoint, totface;
-
- /* object contains at least one material (default included) so zero means uninitialized dm */
- BLI_assert(totmat != 0);
-
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
-
- /* get the number of points used by each material, treating
- * each quad as two triangles */
- points_per_mat = MEM_callocN(sizeof(*points_per_mat) * totmat, "GPU_drawobject_new.mat_orig_to_new");
- for (i = 0; i < totface; i++)
- points_per_mat[mface[i].mat_nr] += mface[i].v4 ? 6 : 3;
-
- /* create the GPUDrawObject */
- gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject");
- gdo->totvert = dm->getNumVerts(dm);
- gdo->totedge = dm->getNumEdges(dm);
-
- /* count the number of materials used by this DerivedMesh */
- for (i = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0)
- gdo->totmaterial++;
- }
-
- /* allocate an array of materials used by this DerivedMesh */
- gdo->materials = MEM_mallocN(sizeof(GPUBufferMaterial) * gdo->totmaterial,
- "GPUDrawObject.materials");
-
- /* initialize the materials array */
- for (i = 0, curmat = 0, curpoint = 0; i < totmat; i++) {
- if (points_per_mat[i] > 0) {
- gdo->materials[curmat].start = curpoint;
- gdo->materials[curmat].totpoint = 0;
- gdo->materials[curmat].mat_nr = i;
-
- curpoint += points_per_mat[i];
- curmat++;
- }
- }
-
- /* store total number of points used for triangles */
- gdo->tot_triangle_point = curpoint;
-
- gdo->triangle_to_mface = MEM_mallocN(sizeof(int) * (gdo->tot_triangle_point / 3),
- "GPUDrawObject.triangle_to_mface");
-
- gpu_drawobject_init_vert_points(gdo, mface, totface, totmat);
- MEM_freeN(points_per_mat);
-
- return gdo;
-}
void GPU_drawobject_free(DerivedMesh *dm)
{
GPUDrawObject *gdo;
+ int i;
if (!dm || !(gdo = dm->drawObject))
return;
+ for (i = 0; i < gdo->totmaterial; i++) {
+ if (gdo->materials[i].polys)
+ MEM_freeN(gdo->materials[i].polys);
+ }
+
MEM_freeN(gdo->materials);
- MEM_freeN(gdo->triangle_to_mface);
- MEM_freeN(gdo->vert_points);
+ if (gdo->vert_points)
+ MEM_freeN(gdo->vert_points);
#ifdef USE_GPU_POINT_LINK
MEM_freeN(gdo->vert_points_mem);
#endif
GPU_buffer_free(gdo->points);
GPU_buffer_free(gdo->normals);
GPU_buffer_free(gdo->uv);
+ GPU_buffer_free(gdo->uv_tex);
GPU_buffer_free(gdo->colors);
GPU_buffer_free(gdo->edges);
GPU_buffer_free(gdo->uvedges);
+ GPU_buffer_free(gdo->triangles);
MEM_freeN(gdo);
dm->drawObject = NULL;
}
-typedef void (*GPUBufferCopyFunc)(DerivedMesh *dm, float *varray, int *index,
- int *mat_orig_to_new, void *user_data);
+static GPUBuffer *gpu_try_realloc(GPUBufferPool *pool, GPUBuffer *buffer, size_t size, bool use_VBOs)
+{
+ /* try freeing an entry from the pool
+ * and reallocating the buffer */
+ gpu_buffer_free_intern(buffer);
+
+ buffer = NULL;
+
+ while (pool->totbuf && !buffer) {
+ gpu_buffer_pool_delete_last(pool);
+ buffer = gpu_buffer_alloc_intern(size, use_VBOs);
+ }
+
+ return buffer;
+}
static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
- int vector_size, int size, GLenum target,
- void *user, GPUBufferCopyFunc copy_f)
+ int type, void *user)
{
GPUBufferPool *pool;
GPUBuffer *buffer;
float *varray;
int *mat_orig_to_new;
- int *cur_index_per_mat;
int i;
- bool success;
+ const GPUBufferTypeSettings *ts = &gpu_buffer_type_settings[type];
+ GLenum target = ts->gl_buffer_type;
+ size_t size = gpu_buffer_size_from_type(dm, type);
+ bool use_VBOs = (GLEW_ARB_vertex_buffer_object) && !(U.gameflags & USER_DISABLE_VBO);
GLboolean uploaded;
pool = gpu_get_global_buffer_pool();
@@ -606,30 +537,21 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
BLI_mutex_lock(&buffer_mutex);
/* alloc a GPUBuffer; fall back to legacy mode on failure */
- if (!(buffer = gpu_buffer_alloc_intern(size)))
- dm->drawObject->legacy = 1;
-
- /* nothing to do for legacy mode */
- if (dm->drawObject->legacy) {
+ if (!(buffer = gpu_buffer_alloc_intern(size, use_VBOs))) {
BLI_mutex_unlock(&buffer_mutex);
return NULL;
}
mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat,
"GPU_buffer_setup.mat_orig_to_new");
- cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial,
- "GPU_buffer_setup.cur_index_per_mat");
for (i = 0; i < object->totmaterial; i++) {
- /* for each material, the current index to copy data to */
- cur_index_per_mat[i] = object->materials[i].start * vector_size;
-
/* map from original material index to new
* GPUBufferMaterial index */
mat_orig_to_new[object->materials[i].mat_nr] = i;
}
- if (useVBOs) {
- success = 0;
+ if (use_VBOs) {
+ bool success = false;
while (!success) {
/* bind the buffer and discard previous data,
@@ -639,36 +561,26 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
/* attempt to map the buffer */
if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) {
- /* failed to map the buffer; delete it */
- gpu_buffer_free_intern(buffer);
- gpu_buffer_pool_delete_last(pool);
- buffer = NULL;
-
- /* try freeing an entry from the pool
- * and reallocating the buffer */
- if (pool->totbuf > 0) {
- gpu_buffer_pool_delete_last(pool);
- buffer = gpu_buffer_alloc_intern(size);
- }
+ buffer = gpu_try_realloc(pool, buffer, size, true);
/* allocation still failed; fall back
* to legacy mode */
- if (!buffer) {
- dm->drawObject->legacy = 1;
- success = 1;
+ if (!(buffer && (varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB)))) {
+ use_VBOs = false;
+ success = true;
}
}
else {
- success = 1;
+ success = true;
}
}
/* check legacy fallback didn't happen */
- if (dm->drawObject->legacy == 0) {
+ if (use_VBOs) {
uploaded = GL_FALSE;
/* attempt to upload the data to the VBO */
while (uploaded == GL_FALSE) {
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
/* glUnmapBuffer returns GL_FALSE if
* the data store is corrupted; retry
* in that case */
@@ -677,18 +589,18 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
}
glBindBufferARB(target, 0);
}
- else {
+ if (!use_VBOs) {
/* VBO not supported, use vertex array fallback */
- if (buffer->pointer) {
- varray = buffer->pointer;
- (*copy_f)(dm, varray, cur_index_per_mat, mat_orig_to_new, user);
+ if (!buffer || !buffer->pointer) {
+ buffer = gpu_try_realloc(pool, buffer, size, false);
}
- else {
- dm->drawObject->legacy = 1;
+
+ if (buffer) {
+ varray = buffer->pointer;
+ dm->copy_gpu_data(dm, type, varray, mat_orig_to_new, user);
}
}
- MEM_freeN(cur_index_per_mat);
MEM_freeN(mat_orig_to_new);
BLI_mutex_unlock(&buffer_mutex);
@@ -696,316 +608,6 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object,
return buffer;
}
-static void GPU_buffer_copy_vertex(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- MVert *mvert;
- MFace *f;
- int i, j, start, totface;
-
- mvert = dm->getVertArray(dm);
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v3_v3(&varray[start], mvert[f->v1].co);
- copy_v3_v3(&varray[start + 3], mvert[f->v2].co);
- copy_v3_v3(&varray[start + 6], mvert[f->v3].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v3_v3(&varray[start + 9], mvert[f->v3].co);
- copy_v3_v3(&varray[start + 12], mvert[f->v4].co);
- copy_v3_v3(&varray[start + 15], mvert[f->v1].co);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-
- /* copy loose points */
- j = dm->drawObject->tot_triangle_point * 3;
- for (i = 0; i < dm->drawObject->totvert; i++) {
- if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_triangle_point) {
- copy_v3_v3(&varray[j], mvert[i].co);
- j += 3;
- }
- }
-}
-
-static void GPU_buffer_copy_normal(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int i, totface;
- int start;
- float f_no[3];
-
- const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL);
- short (*tlnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL);
- MVert *mvert = dm->getVertArray(dm);
- MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- const int smoothnormal = (f->flag & ME_SMOOTH);
-
- start = index[mat_orig_to_new[f->mat_nr]];
- index[mat_orig_to_new[f->mat_nr]] += f->v4 ? 18 : 9;
-
- if (tlnors) {
- short (*tlnor)[3] = tlnors[i];
- /* Copy loop normals */
- normal_short_to_float_v3(&varray[start], tlnor[0]);
- normal_short_to_float_v3(&varray[start + 3], tlnor[1]);
- normal_short_to_float_v3(&varray[start + 6], tlnor[2]);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], tlnor[2]);
- normal_short_to_float_v3(&varray[start + 12], tlnor[3]);
- normal_short_to_float_v3(&varray[start + 15], tlnor[0]);
- }
- }
- else if (smoothnormal) {
- /* copy vertex normal */
- normal_short_to_float_v3(&varray[start], mvert[f->v1].no);
- normal_short_to_float_v3(&varray[start + 3], mvert[f->v2].no);
- normal_short_to_float_v3(&varray[start + 6], mvert[f->v3].no);
-
- if (f->v4) {
- normal_short_to_float_v3(&varray[start + 9], mvert[f->v3].no);
- normal_short_to_float_v3(&varray[start + 12], mvert[f->v4].no);
- normal_short_to_float_v3(&varray[start + 15], mvert[f->v1].no);
- }
- }
- else if (nors) {
- /* copy cached face normal */
- copy_v3_v3(&varray[start], &nors[i * 3]);
- copy_v3_v3(&varray[start + 3], &nors[i * 3]);
- copy_v3_v3(&varray[start + 6], &nors[i * 3]);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], &nors[i * 3]);
- copy_v3_v3(&varray[start + 12], &nors[i * 3]);
- copy_v3_v3(&varray[start + 15], &nors[i * 3]);
- }
- }
- else {
- /* calculate face normal */
- if (f->v4)
- normal_quad_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co, mvert[f->v4].co);
- else
- normal_tri_v3(f_no, mvert[f->v1].co, mvert[f->v2].co, mvert[f->v3].co);
-
- copy_v3_v3(&varray[start], f_no);
- copy_v3_v3(&varray[start + 3], f_no);
- copy_v3_v3(&varray[start + 6], f_no);
-
- if (f->v4) {
- copy_v3_v3(&varray[start + 9], f_no);
- copy_v3_v3(&varray[start + 12], f_no);
- copy_v3_v3(&varray[start + 15], f_no);
- }
- }
- }
-}
-
-static void GPU_buffer_copy_uv(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- MTFace *mtface;
- MFace *f;
-
- if (!(mtface = DM_get_tessface_data_layer(dm, CD_MTFACE)))
- return;
- f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface[i].uv[0]);
- copy_v2_v2(&varray[start + 2], mtface[i].uv[1]);
- copy_v2_v2(&varray[start + 4], mtface[i].uv[2]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 6], mtface[i].uv[2]);
- copy_v2_v2(&varray[start + 8], mtface[i].uv[3]);
- copy_v2_v2(&varray[start + 10], mtface[i].uv[0]);
- index[mat_orig_to_new[f->mat_nr]] += 6;
- }
- }
-}
-
-
-static void GPU_buffer_copy_uv_texpaint(DerivedMesh *dm, float *varray, int *index, int *mat_orig_to_new, void *UNUSED(user))
-{
- int start;
- int i, totface;
-
- int totmaterial = dm->totmat;
- MTFace **mtface_base;
- MTFace *stencil_base;
- int stencil;
- MFace *mf;
-
- /* should have been checked for before, reassert */
- BLI_assert(DM_get_tessface_data_layer(dm, CD_MTFACE));
- mf = dm->getTessFaceArray(dm);
- mtface_base = MEM_mallocN(totmaterial * sizeof(*mtface_base), "texslots");
-
- for (i = 0; i < totmaterial; i++) {
- mtface_base[i] = DM_paint_uvlayer_active_get(dm, i);
- }
-
- stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE);
- stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil);
-
- totface = dm->getNumTessFaces(dm);
-
- for (i = 0; i < totface; i++, mf++) {
- int mat_i = mf->mat_nr;
- start = index[mat_orig_to_new[mat_i]];
-
- /* v1 v2 v3 */
- copy_v2_v2(&varray[start], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 2], stencil_base[i].uv[0]);
- copy_v2_v2(&varray[start + 4], mtface_base[mat_i][i].uv[1]);
- copy_v2_v2(&varray[start + 6], stencil_base[i].uv[1]);
- copy_v2_v2(&varray[start + 8], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 10], stencil_base[i].uv[2]);
- index[mat_orig_to_new[mat_i]] += 12;
-
- if (mf->v4) {
- /* v3 v4 v1 */
- copy_v2_v2(&varray[start + 12], mtface_base[mat_i][i].uv[2]);
- copy_v2_v2(&varray[start + 14], stencil_base[i].uv[2]);
- copy_v2_v2(&varray[start + 16], mtface_base[mat_i][i].uv[3]);
- copy_v2_v2(&varray[start + 18], stencil_base[i].uv[3]);
- copy_v2_v2(&varray[start + 20], mtface_base[mat_i][i].uv[0]);
- copy_v2_v2(&varray[start + 22], stencil_base[i].uv[0]);
- index[mat_orig_to_new[mat_i]] += 12;
- }
- }
-
- MEM_freeN(mtface_base);
-}
-
-
-static void copy_mcol_uc3(unsigned char *v, unsigned char *col)
-{
- v[0] = col[3];
- v[1] = col[2];
- v[2] = col[1];
-}
-
-/* treat varray_ as an array of MCol, four MCol's per face */
-static void GPU_buffer_copy_mcol(DerivedMesh *dm, float *varray_, int *index, int *mat_orig_to_new, void *user)
-{
- int i, totface;
- unsigned char *varray = (unsigned char *)varray_;
- unsigned char *mcol = (unsigned char *)user;
- MFace *f = dm->getTessFaceArray(dm);
-
- totface = dm->getNumTessFaces(dm);
- for (i = 0; i < totface; i++, f++) {
- int start = index[mat_orig_to_new[f->mat_nr]];
-
- /* v1 v2 v3 */
- copy_mcol_uc3(&varray[start], &mcol[i * 16]);
- copy_mcol_uc3(&varray[start + 3], &mcol[i * 16 + 4]);
- copy_mcol_uc3(&varray[start + 6], &mcol[i * 16 + 8]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
-
- if (f->v4) {
- /* v3 v4 v1 */
- copy_mcol_uc3(&varray[start + 9], &mcol[i * 16 + 8]);
- copy_mcol_uc3(&varray[start + 12], &mcol[i * 16 + 12]);
- copy_mcol_uc3(&varray[start + 15], &mcol[i * 16]);
- index[mat_orig_to_new[f->mat_nr]] += 9;
- }
- }
-}
-
-static void GPU_buffer_copy_edge(DerivedMesh *dm, float *varray_, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
-{
- MEdge *medge;
- unsigned int *varray = (unsigned int *)varray_;
- int i, totedge;
-
- medge = dm->getEdgeArray(dm);
- totedge = dm->getNumEdges(dm);
-
- for (i = 0; i < totedge; i++, medge++) {
- varray[i * 2] = dm->drawObject->vert_points[medge->v1].point_index;
- varray[i * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index;
- }
-}
-
-static void GPU_buffer_copy_uvedge(DerivedMesh *dm, float *varray, int *UNUSED(index), int *UNUSED(mat_orig_to_new), void *UNUSED(user))
-{
- MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE);
- int i, j = 0;
-
- if (!tf)
- return;
-
- for (i = 0; i < dm->numTessFaceData; i++, tf++) {
- MFace mf;
- dm->getTessFace(dm, i, &mf);
-
- copy_v2_v2(&varray[j], tf->uv[0]);
- copy_v2_v2(&varray[j + 2], tf->uv[1]);
-
- copy_v2_v2(&varray[j + 4], tf->uv[1]);
- copy_v2_v2(&varray[j + 6], tf->uv[2]);
-
- if (!mf.v4) {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[0]);
- j += 12;
- }
- else {
- copy_v2_v2(&varray[j + 8], tf->uv[2]);
- copy_v2_v2(&varray[j + 10], tf->uv[3]);
-
- copy_v2_v2(&varray[j + 12], tf->uv[3]);
- copy_v2_v2(&varray[j + 14], tf->uv[0]);
- j += 16;
- }
- }
-}
-
-typedef enum {
- GPU_BUFFER_VERTEX = 0,
- GPU_BUFFER_NORMAL,
- GPU_BUFFER_COLOR,
- GPU_BUFFER_UV,
- GPU_BUFFER_UV_TEXPAINT,
- GPU_BUFFER_EDGE,
- GPU_BUFFER_UVEDGE,
-} GPUBufferType;
-
-typedef struct {
- GPUBufferCopyFunc copy;
- GLenum gl_buffer_type;
- int vector_size;
-} GPUBufferTypeSettings;
-
-const GPUBufferTypeSettings gpu_buffer_type_settings[] = {
- {GPU_buffer_copy_vertex, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_normal, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_mcol, GL_ARRAY_BUFFER_ARB, 3},
- {GPU_buffer_copy_uv, GL_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uv_texpaint, GL_ARRAY_BUFFER_ARB, 4},
- {GPU_buffer_copy_edge, GL_ELEMENT_ARRAY_BUFFER_ARB, 2},
- {GPU_buffer_copy_uvedge, GL_ELEMENT_ARRAY_BUFFER_ARB, 4}
-};
-
/* get the GPUDrawObject buffer associated with a type */
static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBufferType type)
{
@@ -1019,39 +621,38 @@ static GPUBuffer **gpu_drawobject_buffer_from_type(GPUDrawObject *gdo, GPUBuffer
case GPU_BUFFER_UV:
return &gdo->uv;
case GPU_BUFFER_UV_TEXPAINT:
- return &gdo->uv;
+ return &gdo->uv_tex;
case GPU_BUFFER_EDGE:
return &gdo->edges;
case GPU_BUFFER_UVEDGE:
return &gdo->uvedges;
+ case GPU_BUFFER_TRIANGLES:
+ return &gdo->triangles;
default:
return NULL;
}
}
/* get the amount of space to allocate for a buffer of a particular type */
-static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
+static size_t gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
{
switch (type) {
case GPU_BUFFER_VERTEX:
- return sizeof(float) * 3 * (dm->drawObject->tot_triangle_point + dm->drawObject->tot_loose_point);
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * (dm->drawObject->tot_loop_verts + dm->drawObject->tot_loose_point);
case GPU_BUFFER_NORMAL:
- return sizeof(float) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(short) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_COLOR:
- return sizeof(char) * 3 * dm->drawObject->tot_triangle_point;
+ return sizeof(char) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_UV:
- return sizeof(float) * 2 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_UV_TEXPAINT:
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(float) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
case GPU_BUFFER_EDGE:
- return sizeof(int) * 2 * dm->drawObject->totedge;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->totedge;
case GPU_BUFFER_UVEDGE:
- /* each face gets 3 points, 3 edges per triangle, and
- * each edge has its own, non-shared coords, so each
- * tri corner needs minimum of 4 floats, quads used
- * less so here we can over allocate and assume all
- * tris. */
- return sizeof(float) * 4 * dm->drawObject->tot_triangle_point;
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_loop_verts;
+ case GPU_BUFFER_TRIANGLES:
+ return sizeof(int) * gpu_buffer_type_settings[type].num_components * dm->drawObject->tot_triangle_point;
default:
return -1;
}
@@ -1060,25 +661,20 @@ static int gpu_buffer_size_from_type(DerivedMesh *dm, GPUBufferType type)
/* call gpu_buffer_setup with settings for a particular type of buffer */
static GPUBuffer *gpu_buffer_setup_type(DerivedMesh *dm, GPUBufferType type)
{
- const GPUBufferTypeSettings *ts;
void *user_data = NULL;
GPUBuffer *buf;
- ts = &gpu_buffer_type_settings[type];
-
/* special handling for MCol and UV buffers */
if (type == GPU_BUFFER_COLOR) {
- if (!(user_data = DM_get_tessface_data_layer(dm, dm->drawObject->colType)))
+ if (!(user_data = DM_get_loop_data_layer(dm, dm->drawObject->colType)))
return NULL;
}
else if (ELEM(type, GPU_BUFFER_UV, GPU_BUFFER_UV_TEXPAINT)) {
- if (!DM_get_tessface_data_layer(dm, CD_MTFACE))
+ if (!DM_get_loop_data_layer(dm, CD_MLOOPUV))
return NULL;
}
- buf = gpu_buffer_setup(dm, dm->drawObject, ts->vector_size,
- gpu_buffer_size_from_type(dm, type),
- ts->gl_buffer_type, user_data, ts->copy);
+ buf = gpu_buffer_setup(dm, dm->drawObject, type, user_data);
return buf;
}
@@ -1090,7 +686,7 @@ static GPUBuffer *gpu_buffer_setup_common(DerivedMesh *dm, GPUBufferType type)
GPUBuffer **buf;
if (!dm->drawObject)
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
buf = gpu_drawobject_buffer_from_type(dm->drawObject, type);
if (!(*buf))
@@ -1105,7 +701,7 @@ void GPU_vertex_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1122,12 +718,12 @@ void GPU_normal_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_NORMAL_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->normals->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->normals->id);
- glNormalPointer(GL_FLOAT, 0, 0);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), 0);
}
else {
- glNormalPointer(GL_FLOAT, 0, dm->drawObject->normals->pointer);
+ glNormalPointer(GL_SHORT, 4 * sizeof(short), dm->drawObject->normals->pointer);
}
GLStates |= GPU_BUFFER_NORMAL_STATE;
@@ -1139,7 +735,7 @@ void GPU_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uv->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
}
@@ -1156,8 +752,8 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv->id);
+ if (dm->drawObject->uv_tex->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uv_tex->id);
glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), 0);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
@@ -1165,10 +761,10 @@ void GPU_texpaint_uv_setup(DerivedMesh *dm)
glClientActiveTexture(GL_TEXTURE0);
}
else {
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv->pointer);
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), dm->drawObject->uv_tex->pointer);
glClientActiveTexture(GL_TEXTURE2);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv->pointer + 2 * sizeof(float));
+ glTexCoordPointer(2, GL_FLOAT, 4 * sizeof(float), (char *)dm->drawObject->uv_tex->pointer + 2 * sizeof(float));
glClientActiveTexture(GL_TEXTURE0);
}
@@ -1181,7 +777,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
if (!dm->drawObject) {
/* XXX Not really nice, but we need a valid gpu draw object to set the colType...
* Else we would have to add a new param to gpu_buffer_setup_common. */
- dm->drawObject = GPU_drawobject_new(dm);
+ dm->drawObject = dm->gpuObjectNew(dm);
dm->dirty &= ~DM_DIRTY_MCOL_UPDATE_DRAW;
dm->drawObject->colType = colType;
}
@@ -1202,7 +798,7 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
return;
glEnableClientState(GL_COLOR_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->colors->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->colors->id);
glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);
}
@@ -1213,6 +809,21 @@ void GPU_color_setup(DerivedMesh *dm, int colType)
GLStates |= GPU_BUFFER_COLOR_STATE;
}
+void GPU_buffer_bind_as_color(GPUBuffer *buffer)
+{
+ glEnableClientState(GL_COLOR_ARRAY);
+ if (buffer->use_vbo) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, 0);
+ }
+ else {
+ glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer->pointer);
+ }
+
+ GLStates |= GPU_BUFFER_COLOR_STATE;
+}
+
+
void GPU_edge_setup(DerivedMesh *dm)
{
if (!gpu_buffer_setup_common(dm, GPU_BUFFER_EDGE))
@@ -1222,7 +833,7 @@ void GPU_edge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->points->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->points->id);
glVertexPointer(3, GL_FLOAT, 0, 0);
}
@@ -1232,7 +843,7 @@ void GPU_edge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
- if (useVBOs)
+ if (dm->drawObject->edges->use_vbo)
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->edges->id);
GLStates |= GPU_BUFFER_ELEMENT_STATE;
@@ -1244,7 +855,7 @@ void GPU_uvedge_setup(DerivedMesh *dm)
return;
glEnableClientState(GL_VERTEX_ARRAY);
- if (useVBOs) {
+ if (dm->drawObject->uvedges->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, dm->drawObject->uvedges->id);
glVertexPointer(2, GL_FLOAT, 0, 0);
}
@@ -1255,6 +866,18 @@ void GPU_uvedge_setup(DerivedMesh *dm)
GLStates |= GPU_BUFFER_VERTEX_STATE;
}
+void GPU_triangle_setup(struct DerivedMesh *dm)
+{
+ if (!gpu_buffer_setup_common(dm, GPU_BUFFER_TRIANGLES))
+ return;
+
+ if (dm->drawObject->triangles->use_vbo) {
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, dm->drawObject->triangles->id);
+ }
+
+ GLStates |= GPU_BUFFER_ELEMENT_STATE;
+}
+
static int GPU_typesize(int type)
{
switch (type) {
@@ -1285,11 +908,12 @@ int GPU_attrib_element_size(GPUAttrib data[], int numdata)
return elementsize;
}
-void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata)
+void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numdata, int element_size)
{
int i;
int elementsize;
intptr_t offset = 0;
+ char *basep;
for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
if (attribData[i].index != -1) {
@@ -1298,34 +922,47 @@ void GPU_interleaved_attrib_setup(GPUBuffer *buffer, GPUAttrib data[], int numda
else
break;
}
- elementsize = GPU_attrib_element_size(data, numdata);
+ if (element_size == 0)
+ elementsize = GPU_attrib_element_size(data, numdata);
+ else
+ elementsize = element_size;
- if (useVBOs) {
+ if (buffer->use_vbo) {
glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (void *)offset);
- offset += data[i].size * GPU_typesize(data[i].type);
-
- attribData[i].index = data[i].index;
- attribData[i].size = data[i].size;
- attribData[i].type = data[i].type;
- }
- attribData[numdata].index = -1;
+ basep = NULL;
}
else {
- for (i = 0; i < numdata; i++) {
- glEnableVertexAttribArrayARB(data[i].index);
- glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
- GL_FALSE, elementsize, (char *)buffer->pointer + offset);
- offset += data[i].size * GPU_typesize(data[i].type);
- }
+ basep = buffer->pointer;
}
+
+ for (i = 0; i < numdata; i++) {
+ glEnableVertexAttribArrayARB(data[i].index);
+ glVertexAttribPointerARB(data[i].index, data[i].size, data[i].type,
+ GL_FALSE, elementsize, (void *)(basep + offset));
+ offset += data[i].size * GPU_typesize(data[i].type);
+
+ attribData[i].index = data[i].index;
+ attribData[i].size = data[i].size;
+ attribData[i].type = data[i].type;
+ }
+
+ attribData[numdata].index = -1;
}
+void GPU_interleaved_attrib_unbind(void)
+{
+ int i;
+ for (i = 0; i < MAX_GPU_ATTRIB_DATA; i++) {
+ if (attribData[i].index != -1) {
+ glDisableVertexAttribArrayARB(attribData[i].index);
+ }
+ else
+ break;
+ }
+ attribData[0].index = -1;
+}
-void GPU_buffer_unbind(void)
+void GPU_buffers_unbind(void)
{
int i;
@@ -1343,7 +980,8 @@ void GPU_buffer_unbind(void)
if (GLStates & GPU_BUFFER_COLOR_STATE)
glDisableClientState(GL_COLOR_ARRAY);
if (GLStates & GPU_BUFFER_ELEMENT_STATE) {
- if (useVBOs) {
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object) {
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
}
@@ -1358,8 +996,10 @@ void GPU_buffer_unbind(void)
else
break;
}
+ attribData[0].index = -1;
- if (useVBOs)
+ /* not guaranteed we used VBOs but in that case it's just a no-op */
+ if (GLEW_ARB_vertex_buffer_object)
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
@@ -1377,29 +1017,23 @@ void GPU_color_switch(int mode)
}
}
-/* return 1 if drawing should be done using old immediate-mode
- * code, 0 otherwise */
-bool GPU_buffer_legacy(DerivedMesh *dm)
+static int gpu_binding_type_gl[] =
{
- int test = (U.gameflags & USER_DISABLE_VBO);
- if (test)
- return 1;
-
- if (dm->drawObject == NULL)
- dm->drawObject = GPU_drawobject_new(dm);
- return dm->drawObject->legacy;
-}
+ GL_ARRAY_BUFFER_ARB,
+ GL_ELEMENT_ARRAY_BUFFER_ARB
+};
-void *GPU_buffer_lock(GPUBuffer *buffer)
+void *GPU_buffer_lock(GPUBuffer *buffer, GPUBindingType binding)
{
float *varray;
if (!buffer)
return 0;
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
- varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
+ varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB);
return varray;
}
else {
@@ -1407,18 +1041,19 @@ void *GPU_buffer_lock(GPUBuffer *buffer)
}
}
-void *GPU_buffer_lock_stream(GPUBuffer *buffer)
+void *GPU_buffer_lock_stream(GPUBuffer *buffer, GPUBindingType binding)
{
float *varray;
if (!buffer)
return 0;
- if (useVBOs) {
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffer->id);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
/* discard previous data, avoid stalling gpu */
- glBufferDataARB(GL_ARRAY_BUFFER_ARB, buffer->size, 0, GL_STREAM_DRAW_ARB);
- varray = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ glBufferDataARB(bindtypegl, buffer->size, 0, GL_STREAM_DRAW_ARB);
+ varray = glMapBufferARB(bindtypegl, GL_WRITE_ONLY_ARB);
return varray;
}
else {
@@ -1426,15 +1061,30 @@ void *GPU_buffer_lock_stream(GPUBuffer *buffer)
}
}
-void GPU_buffer_unlock(GPUBuffer *buffer)
+void GPU_buffer_unlock(GPUBuffer *buffer, GPUBindingType binding)
{
- if (useVBOs) {
- if (buffer) {
- /* note: this operation can fail, could return
- * an error code from this function? */
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
- }
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ /* note: this operation can fail, could return
+ * an error code from this function? */
+ glUnmapBufferARB(bindtypegl);
+ glBindBufferARB(bindtypegl, 0);
+ }
+}
+
+void GPU_buffer_bind(GPUBuffer *buffer, GPUBindingType binding)
+{
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, buffer->id);
+ }
+}
+
+void GPU_buffer_unbind(GPUBuffer *buffer, GPUBindingType binding)
+{
+ if (buffer->use_vbo) {
+ int bindtypegl = gpu_binding_type_gl[binding];
+ glBindBufferARB(bindtypegl, 0);
}
}
@@ -1442,7 +1092,7 @@ void GPU_buffer_unlock(GPUBuffer *buffer)
void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start, int count)
{
glDrawElements(mode, count, GL_UNSIGNED_INT,
- (useVBOs ?
+ (elements->use_vbo ?
(void *)(start * sizeof(unsigned int)) :
((int *)elements->pointer) + start));
}
@@ -1451,14 +1101,6 @@ void GPU_buffer_draw_elements(GPUBuffer *elements, unsigned int mode, int start,
/* XXX: the rest of the code in this file is used for optimized PBVH
* drawing and doesn't interact at all with the buffer code above */
-/* Return false if VBO is either unavailable or disabled by the user,
- * true otherwise */
-static int gpu_vbo_enabled(void)
-{
- return (GLEW_ARB_vertex_buffer_object &&
- !(U.gameflags & USER_DISABLE_VBO));
-}
-
/* Convenience struct for building the VBO. */
typedef struct {
float co[3];
@@ -1474,14 +1116,20 @@ typedef struct {
struct GPU_PBVH_Buffers {
/* opengl buffer handles */
- GLuint vert_buf, index_buf;
+ GPUBuffer *vert_buf, *index_buf, *index_buf_fast;
GLenum index_type;
+ int *baseelemarray;
+ void **baseindex;
+
/* mesh pointers in case buffer allocation fails */
- MFace *mface;
- MVert *mvert;
+ const MPoly *mpoly;
+ const MLoop *mloop;
+ const MLoopTri *looptri;
+ const MVert *mvert;
+
const int *face_indices;
- int totface;
+ int face_indices_len;
const float *vmask;
/* grid pointers */
@@ -1505,6 +1153,7 @@ struct GPU_PBVH_Buffers {
bool use_matcaps;
float diffuse_color[4];
};
+
typedef enum {
VBO_ENABLED,
VBO_DISABLED
@@ -1541,22 +1190,6 @@ static void gpu_color_from_mask_copy(float mask, const float diffuse_color[4], u
out[2] = diffuse_color[2] * mask_color;
}
-static void gpu_color_from_mask_set(float mask, float diffuse_color[4])
-{
- float color = gpu_color_from_mask(mask);
- glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
-}
-
-static float gpu_color_from_mask_quad(const CCGKey *key,
- CCGElem *a, CCGElem *b,
- CCGElem *c, CCGElem *d)
-{
- return gpu_color_from_mask((*CCG_elem_mask(key, a) +
- *CCG_elem_mask(key, b) +
- *CCG_elem_mask(key, c) +
- *CCG_elem_mask(key, d)) * 0.25f);
-}
-
static void gpu_color_from_mask_quad_copy(const CCGKey *key,
CCGElem *a, CCGElem *b,
CCGElem *c, CCGElem *d,
@@ -1574,47 +1207,38 @@ static void gpu_color_from_mask_quad_copy(const CCGKey *key,
out[2] = diffuse_color[2] * mask_color;
}
-static void gpu_color_from_mask_quad_set(const CCGKey *key,
- CCGElem *a, CCGElem *b,
- CCGElem *c, CCGElem *d,
- const float diffuse_color[4])
-{
- float color = gpu_color_from_mask_quad(key, a, b, c, d);
- glColor3f(diffuse_color[0] * color, diffuse_color[1] * color, diffuse_color[2] * color);
-}
-
-void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
- int *vert_indices, int totvert, const float *vmask,
- int (*face_vert_indices)[4], bool show_diffuse_color)
+void GPU_update_mesh_pbvh_buffers(
+ GPU_PBVH_Buffers *buffers, const MVert *mvert,
+ const int *vert_indices, int totvert, const float *vmask,
+ const int (*face_vert_indices)[4], bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
- int i, j, k;
+ int i, j;
buffers->vmask = vmask;
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
- if (buffers->vert_buf) {
+ {
int totelem = (buffers->smooth ? totvert : (buffers->tot_tri * 3));
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 0.8f};
if (buffers->use_matcaps)
diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
else if (show_diffuse_color) {
- MFace *f = buffers->mface + buffers->face_indices[0];
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
copy_v4_v4(buffers->diffuse_color, diffuse_color);
/* Build VBO */
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totelem,
- NULL, GL_STATIC_DRAW_ARB);
-
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ if (buffers->vert_buf)
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totelem, false);
+ vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
/* Vertex data is shared if smooth-shaded, but separate
@@ -1622,7 +1246,7 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
* shouldn't be shared. */
if (buffers->smooth) {
for (i = 0; i < totvert; ++i) {
- MVert *v = mvert + vert_indices[i];
+ const MVert *v = &mvert[vert_indices[i]];
VertexBufferFormat *out = vert_data + i;
copy_v3_v3(out->co, v->co);
@@ -1638,118 +1262,114 @@ void GPU_update_mesh_pbvh_buffers(GPU_PBVH_Buffers *buffers, MVert *mvert,
rgb_float_to_uchar(out->color, diffuse_color); \
} (void)0
- for (i = 0; i < buffers->totface; i++) {
- MFace *f = buffers->mface + buffers->face_indices[i];
+ for (i = 0; i < buffers->face_indices_len; i++) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+ const unsigned int vtri[3] = {
+ buffers->mloop[lt->tri[0]].v,
+ buffers->mloop[lt->tri[1]].v,
+ buffers->mloop[lt->tri[2]].v,
+ };
- UPDATE_VERTEX(i, f->v1, 0, diffuse_color);
- UPDATE_VERTEX(i, f->v2, 1, diffuse_color);
- UPDATE_VERTEX(i, f->v3, 2, diffuse_color);
- if (f->v4)
- UPDATE_VERTEX(i, f->v4, 3, diffuse_color);
+ UPDATE_VERTEX(i, vtri[0], 0, diffuse_color);
+ UPDATE_VERTEX(i, vtri[1], 1, diffuse_color);
+ UPDATE_VERTEX(i, vtri[2], 2, diffuse_color);
}
#undef UPDATE_VERTEX
}
else {
- for (i = 0; i < buffers->totface; ++i) {
- const MFace *f = &buffers->mface[buffers->face_indices[i]];
- const unsigned int *fv = &f->v1;
- const int vi[2][3] = {{0, 1, 2}, {3, 0, 2}};
- float fno[3];
- short no[3];
+ /* calculate normal for each polygon only once */
+ unsigned int mpoly_prev = UINT_MAX;
+ short no[3];
+
+ for (i = 0; i < buffers->face_indices_len; ++i) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[i]];
+ const unsigned int vtri[3] = {
+ buffers->mloop[lt->tri[0]].v,
+ buffers->mloop[lt->tri[1]].v,
+ buffers->mloop[lt->tri[2]].v,
+ };
float fmask;
- if (paint_is_face_hidden(f, mvert))
+ if (paint_is_face_hidden(lt, mvert, buffers->mloop))
continue;
/* Face normal and mask */
- if (f->v4) {
- normal_quad_v3(fno,
- mvert[fv[0]].co,
- mvert[fv[1]].co,
- mvert[fv[2]].co,
- mvert[fv[3]].co);
- if (vmask) {
- fmask = (vmask[fv[0]] +
- vmask[fv[1]] +
- vmask[fv[2]] +
- vmask[fv[3]]) * 0.25f;
- }
+ if (lt->poly != mpoly_prev) {
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ float fno[3];
+ BKE_mesh_calc_poly_normal(mp, &buffers->mloop[mp->loopstart], mvert, fno);
+ normal_float_to_short_v3(no, fno);
+ mpoly_prev = lt->poly;
}
- else {
- normal_tri_v3(fno,
- mvert[fv[0]].co,
- mvert[fv[1]].co,
- mvert[fv[2]].co);
- if (vmask) {
- fmask = (vmask[fv[0]] +
- vmask[fv[1]] +
- vmask[fv[2]]) / 3.0f;
- }
+
+ if (vmask) {
+ fmask = (vmask[vtri[0]] +
+ vmask[vtri[1]] +
+ vmask[vtri[2]]) / 3.0f;
}
- normal_float_to_short_v3(no, fno);
- for (j = 0; j < (f->v4 ? 2 : 1); j++) {
- for (k = 0; k < 3; k++) {
- const MVert *v = &mvert[fv[vi[j][k]]];
- VertexBufferFormat *out = vert_data;
+ for (j = 0; j < 3; j++) {
+ const MVert *v = &mvert[vtri[j]];
+ VertexBufferFormat *out = vert_data;
- copy_v3_v3(out->co, v->co);
- memcpy(out->no, no, sizeof(short) * 3);
+ copy_v3_v3(out->co, v->co);
+ copy_v3_v3_short(out->no, no);
- if (vmask)
- gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
- else
- rgb_float_to_uchar(out->color, diffuse_color);
+ if (vmask)
+ gpu_color_from_mask_copy(fmask, diffuse_color, out->color);
+ else
+ rgb_float_to_uchar(out->color, diffuse_color);
- vert_data++;
- }
+ vert_data++;
}
}
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
}
else {
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
}
-
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
buffers->mvert = mvert;
}
-GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
- MFace *mface, MVert *mvert,
- int *face_indices,
- int totface)
+GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(
+ const int (*face_vert_indices)[4],
+ const MPoly *mpoly, const MLoop *mloop, const MLoopTri *looptri,
+ const MVert *mvert,
+ const int *face_indices,
+ const int face_indices_len)
{
GPU_PBVH_Buffers *buffers;
unsigned short *tri_data;
- int i, j, k, tottri;
+ int i, j, tottri;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
buffers->index_type = GL_UNSIGNED_SHORT;
- buffers->smooth = mface[face_indices[0]].flag & ME_SMOOTH;
+ buffers->smooth = mpoly[looptri[face_indices[0]].poly].flag & ME_SMOOTH;
buffers->show_diffuse_color = false;
buffers->use_matcaps = false;
/* Count the number of visible triangles */
- for (i = 0, tottri = 0; i < totface; ++i) {
- const MFace *f = &mface[face_indices[i]];
- if (!paint_is_face_hidden(f, mvert))
- tottri += f->v4 ? 2 : 1;
+ for (i = 0, tottri = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
+ if (!paint_is_face_hidden(lt, mvert, mloop))
+ tottri++;
}
if (tottri == 0) {
buffers->tot_tri = 0;
- buffers->mface = mface;
+ buffers->mpoly = mpoly;
+ buffers->mloop = mloop;
+ buffers->looptri = looptri;
buffers->face_indices = face_indices;
- buffers->totface = 0;
+ buffers->face_indices_len = 0;
return buffers;
}
@@ -1757,65 +1377,48 @@ GPU_PBVH_Buffers *GPU_build_mesh_pbvh_buffers(int (*face_vert_indices)[4],
/* An element index buffer is used for smooth shading, but flat
* shading requires separate vertex normals so an index buffer is
* can't be used there. */
- if (gpu_vbo_enabled() && buffers->smooth)
- glGenBuffersARB(1, &buffers->index_buf);
+ if (buffers->smooth)
+ buffers->index_buf = GPU_buffer_alloc(sizeof(unsigned short) * tottri * 3, false);
if (buffers->index_buf) {
- /* Generate index buffer object */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
- sizeof(unsigned short) * tottri * 3, NULL, GL_STATIC_DRAW_ARB);
-
/* Fill the triangle buffer */
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
if (tri_data) {
- for (i = 0; i < totface; ++i) {
- const MFace *f = mface + face_indices[i];
- int v[3];
+ for (i = 0; i < face_indices_len; ++i) {
+ const MLoopTri *lt = &looptri[face_indices[i]];
/* Skip hidden faces */
- if (paint_is_face_hidden(f, mvert))
+ if (paint_is_face_hidden(lt, mvert, mloop))
continue;
- v[0] = 0;
- v[1] = 1;
- v[2] = 2;
-
- for (j = 0; j < (f->v4 ? 2 : 1); ++j) {
- for (k = 0; k < 3; ++k) {
- *tri_data = face_vert_indices[i][v[k]];
- tri_data++;
- }
- v[0] = 3;
- v[1] = 0;
- v[2] = 2;
+ for (j = 0; j < 3; ++j) {
+ *tri_data = face_vert_indices[i][j];
+ tri_data++;
}
}
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
}
else {
- glDeleteBuffersARB(1, &buffers->index_buf);
- buffers->index_buf = 0;
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = NULL;
}
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
}
- if (gpu_vbo_enabled() && (buffers->index_buf || !buffers->smooth))
- glGenBuffersARB(1, &buffers->vert_buf);
-
buffers->tot_tri = tottri;
- buffers->mface = mface;
+ buffers->mpoly = mpoly;
+ buffers->mloop = mloop;
+ buffers->looptri = looptri;
+
buffers->face_indices = face_indices;
- buffers->totface = totface;
+ buffers->face_indices_len = face_indices_len;
return buffers;
}
void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
- const DMFlagMat *grid_flag_mats, int *grid_indices,
- int totgrid, const CCGKey *key, bool show_diffuse_color)
+ const DMFlagMat *grid_flag_mats, int *grid_indices,
+ int totgrid, const CCGKey *key, bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
int i, j, k, x, y;
@@ -1825,7 +1428,6 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
/* Build VBO */
if (buffers->vert_buf) {
- int totvert = key->grid_area * totgrid;
int smooth = grid_flag_mats[grid_indices[0]].flag & ME_SMOOTH;
const int has_mask = key->has_mask;
float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
@@ -1840,11 +1442,7 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
copy_v4_v4(buffers->diffuse_color, diffuse_color);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totvert,
- NULL, GL_STATIC_DRAW_ARB);
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ vert_data = GPU_buffer_lock_stream(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
for (i = 0; i < totgrid; ++i) {
VertexBufferFormat *vd = vert_data;
@@ -1905,13 +1503,13 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
vert_data += key->grid_area;
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
}
else {
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
}
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
buffers->grids = grids;
@@ -1928,107 +1526,112 @@ void GPU_update_grid_pbvh_buffers(GPU_PBVH_Buffers *buffers, CCGElem **grids,
/* Build the element array buffer of grid indices using either
* unsigned shorts or unsigned ints. */
#define FILL_QUAD_BUFFER(type_, tot_quad_, buffer_) \
- { \
- type_ *tri_data; \
- int offset = 0; \
- int i, j, k; \
- \
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
- sizeof(type_) * (tot_quad_) * 6, NULL, \
- GL_STATIC_DRAW_ARB); \
- \
- /* Fill the buffer */ \
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, \
- GL_WRITE_ONLY_ARB); \
- if (tri_data) { \
- for (i = 0; i < totgrid; ++i) { \
- BLI_bitmap *gh = NULL; \
- if (grid_hidden) \
- gh = grid_hidden[(grid_indices)[i]]; \
- \
- for (j = 0; j < gridsize - 1; ++j) { \
- for (k = 0; k < gridsize - 1; ++k) { \
- /* Skip hidden grid face */ \
- if (gh && \
- paint_is_grid_face_hidden(gh, \
- gridsize, k, j)) \
- continue; \
- \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- \
- *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
- *(tri_data++) = offset + j * gridsize + k + 1; \
- *(tri_data++) = offset + (j + 1) * gridsize + k; \
- } \
- } \
- \
- offset += gridsize * gridsize; \
- } \
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); \
- } \
- else { \
- glDeleteBuffersARB(1, &(buffer_)); \
- (buffer_) = 0; \
- } \
- } (void)0
+ { \
+ type_ *tri_data; \
+ int offset = 0; \
+ int i, j, k; \
+ buffer_ = GPU_buffer_alloc(sizeof(type_) * (tot_quad_) * 6, \
+ false); \
+ \
+ /* Fill the buffer */ \
+ tri_data = GPU_buffer_lock(buffer_, GPU_BINDING_INDEX); \
+ if (tri_data) { \
+ for (i = 0; i < totgrid; ++i) { \
+ BLI_bitmap *gh = NULL; \
+ if (grid_hidden) \
+ gh = grid_hidden[(grid_indices)[i]]; \
+ \
+ for (j = 0; j < gridsize - 1; ++j) { \
+ for (k = 0; k < gridsize - 1; ++k) { \
+ /* Skip hidden grid face */ \
+ if (gh && \
+ paint_is_grid_face_hidden(gh, \
+ gridsize, k, j)) \
+ continue; \
+ \
+ *(tri_data++) = offset + j * gridsize + k + 1; \
+ *(tri_data++) = offset + j * gridsize + k; \
+ *(tri_data++) = offset + (j + 1) * gridsize + k; \
+ \
+ *(tri_data++) = offset + (j + 1) * gridsize + k + 1; \
+ *(tri_data++) = offset + j * gridsize + k + 1; \
+ *(tri_data++) = offset + (j + 1) * gridsize + k; \
+ } \
+ } \
+ \
+ offset += gridsize * gridsize; \
+ } \
+ GPU_buffer_unlock(buffer_, GPU_BINDING_INDEX); \
+ } \
+ else { \
+ GPU_buffer_free(buffer_); \
+ (buffer_) = NULL; \
+ } \
+ } (void)0
/* end FILL_QUAD_BUFFER */
-static GLuint gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
+static GPUBuffer *gpu_get_grid_buffer(int gridsize, GLenum *index_type, unsigned *totquad)
{
- static int prev_gridsize = -1;
- static GLenum prev_index_type = 0;
- static GLuint buffer = 0;
- static unsigned prev_totquad;
-
/* used in the FILL_QUAD_BUFFER macro */
BLI_bitmap * const *grid_hidden = NULL;
const int *grid_indices = NULL;
int totgrid = 1;
- /* VBO is disabled; delete the previous buffer (if it exists) and
- * return an invalid handle */
- if (!gpu_vbo_enabled()) {
- if (buffer)
- glDeleteBuffersARB(1, &buffer);
- return 0;
- }
-
/* VBO is already built */
- if (buffer && prev_gridsize == gridsize) {
- *index_type = prev_index_type;
- *totquad = prev_totquad;
- return buffer;
+ if (mres_glob_buffer && mres_prev_gridsize == gridsize) {
+ *index_type = mres_prev_index_type;
+ *totquad = mres_prev_totquad;
+ return mres_glob_buffer;
+ }
+ /* we can't reuse old, delete the existing buffer */
+ else if (mres_glob_buffer) {
+ GPU_buffer_free(mres_glob_buffer);
}
/* Build new VBO */
- glGenBuffersARB(1, &buffer);
- if (buffer) {
- *totquad = (gridsize - 1) * (gridsize - 1);
+ *totquad = (gridsize - 1) * (gridsize - 1);
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
-
- if (gridsize * gridsize < USHRT_MAX) {
- *index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, *totquad, buffer);
- }
- else {
- *index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, *totquad, buffer);
- }
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ if (gridsize * gridsize < USHRT_MAX) {
+ *index_type = GL_UNSIGNED_SHORT;
+ FILL_QUAD_BUFFER(unsigned short, *totquad, mres_glob_buffer);
}
-
- prev_gridsize = gridsize;
- prev_index_type = *index_type;
- prev_totquad = *totquad;
- return buffer;
-}
+ else {
+ *index_type = GL_UNSIGNED_INT;
+ FILL_QUAD_BUFFER(unsigned int, *totquad, mres_glob_buffer);
+ }
+
+ mres_prev_gridsize = gridsize;
+ mres_prev_index_type = *index_type;
+ mres_prev_totquad = *totquad;
+ return mres_glob_buffer;
+}
+
+#define FILL_FAST_BUFFER(type_) \
+{ \
+ type_ *buffer; \
+ buffers->index_buf_fast = GPU_buffer_alloc(sizeof(type_) * 6 * totgrid, false); \
+ buffer = GPU_buffer_lock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ if (buffer) { \
+ int i; \
+ for (i = 0; i < totgrid; i++) { \
+ int currentquad = i * 6; \
+ buffer[currentquad] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 1] = i * gridsize * gridsize; \
+ buffer[currentquad + 2] = (i + 1) * gridsize * gridsize - gridsize; \
+ buffer[currentquad + 3] = (i + 1) * gridsize * gridsize - 1; \
+ buffer[currentquad + 4] = i * gridsize * gridsize + gridsize - 1; \
+ buffer[currentquad + 5] = (i + 1) * gridsize * gridsize - gridsize; \
+ } \
+ GPU_buffer_unlock(buffers->index_buf_fast, GPU_BINDING_INDEX); \
+ } \
+ else { \
+ GPU_buffer_free(buffers->index_buf_fast); \
+ buffers->index_buf_fast = NULL; \
+ } \
+} (void)0
GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
- BLI_bitmap **grid_hidden, int gridsize)
+ BLI_bitmap **grid_hidden, int gridsize, const CCGKey *key)
{
GPU_PBVH_Buffers *buffers;
int totquad;
@@ -2048,28 +1651,28 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
if (totquad == 0)
return buffers;
+ /* create and fill indices of the fast buffer too */
+ if (totgrid * gridsize * gridsize < USHRT_MAX) {
+ FILL_FAST_BUFFER(unsigned short);
+ }
+ else {
+ FILL_FAST_BUFFER(unsigned int);
+ }
+
if (totquad == fully_visible_totquad) {
buffers->index_buf = gpu_get_grid_buffer(gridsize, &buffers->index_type, &buffers->tot_quad);
buffers->has_hidden = 0;
}
- else if (GLEW_ARB_vertex_buffer_object && !(U.gameflags & USER_DISABLE_VBO)) {
- /* Build new VBO */
- glGenBuffersARB(1, &buffers->index_buf);
- if (buffers->index_buf) {
- buffers->tot_quad = totquad;
-
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
-
- if (totgrid * gridsize * gridsize < USHRT_MAX) {
- buffers->index_type = GL_UNSIGNED_SHORT;
- FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
- }
- else {
- buffers->index_type = GL_UNSIGNED_INT;
- FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
- }
+ else {
+ buffers->tot_quad = totquad;
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ if (totgrid * gridsize * gridsize < USHRT_MAX) {
+ buffers->index_type = GL_UNSIGNED_SHORT;
+ FILL_QUAD_BUFFER(unsigned short, totquad, buffers->index_buf);
+ }
+ else {
+ buffers->index_type = GL_UNSIGNED_INT;
+ FILL_QUAD_BUFFER(unsigned int, totquad, buffers->index_buf);
}
buffers->has_hidden = 1;
@@ -2077,7 +1680,19 @@ GPU_PBVH_Buffers *GPU_build_grid_pbvh_buffers(int *grid_indices, int totgrid,
/* Build coord/normal VBO */
if (buffers->index_buf)
- glGenBuffersARB(1, &buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totgrid * key->grid_area, false);
+
+ if (GLEW_ARB_draw_elements_base_vertex) {
+ int i;
+ buffers->baseelemarray = MEM_mallocN(sizeof(int) * totgrid * 2, "GPU_PBVH_Buffers.baseelemarray");
+ buffers->baseindex = MEM_mallocN(sizeof(void *) * totgrid, "GPU_PBVH_Buffers.baseindex");
+ for (i = 0; i < totgrid; i++) {
+ buffers->baseelemarray[i] = buffers->tot_quad * 6;
+ buffers->baseelemarray[i + totgrid] = i * key->grid_area;
+ buffers->baseindex[i] = buffers->index_buf && !buffers->index_buf->use_vbo ?
+ buffers->index_buf->pointer : NULL;
+ }
+ }
return buffers;
}
@@ -2110,7 +1725,6 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset),
diffuse_color,
vd->color);
-
/* Assign index for use in the triangle index buffer */
/* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
@@ -2160,11 +1774,11 @@ static int gpu_bmesh_face_visible_count(GSet *bm_faces)
/* Creates a vertex buffer (coordinate, normal, color) and, if smooth
* shading, an element index buffer. */
void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
- BMesh *bm,
- GSet *bm_faces,
- GSet *bm_unique_verts,
- GSet *bm_other_verts,
- bool show_diffuse_color)
+ BMesh *bm,
+ GSet *bm_faces,
+ GSet *bm_unique_verts,
+ GSet *bm_other_verts,
+ bool show_diffuse_color)
{
VertexBufferFormat *vert_data;
void *tri_data;
@@ -2177,9 +1791,6 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
buffers->show_diffuse_color = show_diffuse_color;
buffers->use_matcaps = GPU_material_use_matcaps_get();
- if (!buffers->vert_buf || (buffers->smooth && !buffers->index_buf))
- return;
-
/* Count visible triangles */
tottri = gpu_bmesh_face_visible_count(bm_faces);
@@ -2209,13 +1820,12 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
copy_v4_v4(buffers->diffuse_color, diffuse_color);
/* Initialize vertex buffer */
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
- glBufferDataARB(GL_ARRAY_BUFFER_ARB,
- sizeof(VertexBufferFormat) * totvert,
- NULL, GL_STATIC_DRAW_ARB);
+ if (buffers->vert_buf)
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = GPU_buffer_alloc(sizeof(VertexBufferFormat) * totvert, false);
/* Fill vertex buffer */
- vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ vert_data = GPU_buffer_lock(buffers->vert_buf, GPU_BINDING_ARRAY);
if (vert_data) {
int v_index = 0;
@@ -2253,7 +1863,9 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
float fmask = 0;
int i;
- // BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+#if 0
+ BM_iter_as_array(bm, BM_VERTS_OF_FACE, f, (void**)v, 3);
+#endif
BM_face_as_array_vert_tri(f, v);
/* Average mask value */
@@ -2273,15 +1885,15 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
buffers->tot_tri = tottri;
}
- glUnmapBufferARB(GL_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->vert_buf, GPU_BINDING_ARRAY);
/* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
bm->elem_index_dirty |= BM_VERT;
}
else {
/* Memory map failed */
- glDeleteBuffersARB(1, &buffers->vert_buf);
- buffers->vert_buf = 0;
+ GPU_buffer_free(buffers->vert_buf);
+ buffers->vert_buf = NULL;
return;
}
@@ -2289,15 +1901,14 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
const int use_short = (maxvert < USHRT_MAX);
/* Initialize triangle index buffer */
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
- glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB,
- (use_short ?
- sizeof(unsigned short) :
- sizeof(unsigned int)) * 3 * tottri,
- NULL, GL_STATIC_DRAW_ARB);
+ if (buffers->index_buf)
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = GPU_buffer_alloc((use_short ?
+ sizeof(unsigned short) :
+ sizeof(unsigned int)) * 3 * tottri, false);
/* Fill triangle index buffer */
- tri_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
+ tri_data = GPU_buffer_lock(buffers->index_buf, GPU_BINDING_INDEX);
if (tri_data) {
GSetIterator gs_iter;
@@ -2327,7 +1938,7 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
}
- glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
+ GPU_buffer_unlock(buffers->index_buf, GPU_BINDING_INDEX);
buffers->tot_tri = tottri;
buffers->index_type = (use_short ?
@@ -2336,10 +1947,13 @@ void GPU_update_bmesh_pbvh_buffers(GPU_PBVH_Buffers *buffers,
}
else {
/* Memory map failed */
- glDeleteBuffersARB(1, &buffers->index_buf);
- buffers->index_buf = 0;
+ GPU_buffer_free(buffers->index_buf);
+ buffers->index_buf = NULL;
}
}
+ else if (buffers->index_buf) {
+ GPU_buffer_free(buffers->index_buf);
+ }
}
GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
@@ -2347,9 +1961,6 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
GPU_PBVH_Buffers *buffers;
buffers = MEM_callocN(sizeof(GPU_PBVH_Buffers), "GPU_Buffers");
- if (smooth_shading)
- glGenBuffersARB(1, &buffers->index_buf);
- glGenBuffersARB(1, &buffers->vert_buf);
buffers->use_bmesh = true;
buffers->smooth = smooth_shading;
buffers->show_diffuse_color = false;
@@ -2358,217 +1969,17 @@ GPU_PBVH_Buffers *GPU_build_bmesh_pbvh_buffers(int smooth_shading)
return buffers;
}
-static void gpu_draw_buffers_legacy_mesh(GPU_PBVH_Buffers *buffers)
-{
- const MVert *mvert = buffers->mvert;
- int i, j;
- const int has_mask = (buffers->vmask != NULL);
- const MFace *face = &buffers->mface[buffers->face_indices[0]];
- float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
-
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (buffers->show_diffuse_color)
- GPU_material_diffuse_get(face->mat_nr + 1, diffuse_color);
-
- if (has_mask) {
- gpu_colors_enable(VBO_DISABLED);
- }
-
- for (i = 0; i < buffers->totface; ++i) {
- MFace *f = buffers->mface + buffers->face_indices[i];
- int S = f->v4 ? 4 : 3;
- unsigned int *fv = &f->v1;
-
- if (paint_is_face_hidden(f, buffers->mvert))
- continue;
-
- glBegin((f->v4) ? GL_QUADS : GL_TRIANGLES);
-
- if (buffers->smooth) {
- for (j = 0; j < S; j++) {
- if (has_mask) {
- gpu_color_from_mask_set(buffers->vmask[fv[j]], diffuse_color);
- }
- glNormal3sv(mvert[fv[j]].no);
- glVertex3fv(mvert[fv[j]].co);
- }
- }
- else {
- float fno[3];
-
- /* calculate face normal */
- if (f->v4) {
- normal_quad_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co,
- mvert[fv[2]].co, mvert[fv[3]].co);
- }
- else
- normal_tri_v3(fno, mvert[fv[0]].co, mvert[fv[1]].co, mvert[fv[2]].co);
- glNormal3fv(fno);
-
- if (has_mask) {
- float fmask;
-
- /* calculate face mask color */
- fmask = (buffers->vmask[fv[0]] +
- buffers->vmask[fv[1]] +
- buffers->vmask[fv[2]]);
- if (f->v4)
- fmask = (fmask + buffers->vmask[fv[3]]) * 0.25f;
- else
- fmask /= 3.0f;
- gpu_color_from_mask_set(fmask, diffuse_color);
- }
-
- for (j = 0; j < S; j++)
- glVertex3fv(mvert[fv[j]].co);
- }
-
- glEnd();
- }
-
- if (has_mask) {
- gpu_colors_disable(VBO_DISABLED);
- }
-}
-
-static void gpu_draw_buffers_legacy_grids(GPU_PBVH_Buffers *buffers)
-{
- const CCGKey *key = &buffers->gridkey;
- int i, j, x, y, gridsize = buffers->gridkey.grid_size;
- const int has_mask = key->has_mask;
- const DMFlagMat *flags = &buffers->grid_flag_mats[buffers->grid_indices[0]];
- float diffuse_color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
-
- if (buffers->use_matcaps)
- diffuse_color[0] = diffuse_color[1] = diffuse_color[2] = 1.0;
- else if (buffers->show_diffuse_color)
- GPU_material_diffuse_get(flags->mat_nr + 1, diffuse_color);
-
- if (has_mask) {
- gpu_colors_enable(VBO_DISABLED);
- }
-
- for (i = 0; i < buffers->totgrid; ++i) {
- int g = buffers->grid_indices[i];
- CCGElem *grid = buffers->grids[g];
- BLI_bitmap *gh = buffers->grid_hidden[g];
-
- /* TODO: could use strips with hiding as well */
-
- if (gh) {
- glBegin(GL_QUADS);
-
- for (y = 0; y < gridsize - 1; y++) {
- for (x = 0; x < gridsize - 1; x++) {
- CCGElem *e[4] = {
- CCG_grid_elem(key, grid, x + 1, y + 1),
- CCG_grid_elem(key, grid, x + 1, y),
- CCG_grid_elem(key, grid, x, y),
- CCG_grid_elem(key, grid, x, y + 1)
- };
-
- /* skip face if any of its corners are hidden */
- if (paint_is_grid_face_hidden(gh, gridsize, x, y))
- continue;
-
- if (buffers->smooth) {
- for (j = 0; j < 4; j++) {
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, e[j]), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, e[j]));
- glVertex3fv(CCG_elem_co(key, e[j]));
- }
- }
- else {
- float fno[3];
- normal_quad_v3(fno,
- CCG_elem_co(key, e[0]),
- CCG_elem_co(key, e[1]),
- CCG_elem_co(key, e[2]),
- CCG_elem_co(key, e[3]));
- glNormal3fv(fno);
-
- if (has_mask) {
- gpu_color_from_mask_quad_set(key, e[0], e[1], e[2], e[3], diffuse_color);
- }
-
- for (j = 0; j < 4; j++)
- glVertex3fv(CCG_elem_co(key, e[j]));
- }
- }
- }
-
- glEnd();
- }
- else if (buffers->smooth) {
- for (y = 0; y < gridsize - 1; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridsize; x++) {
- CCGElem *a = CCG_grid_elem(key, grid, x, y);
- CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
-
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, a), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, a));
- glVertex3fv(CCG_elem_co(key, a));
- if (has_mask) {
- gpu_color_from_mask_set(*CCG_elem_mask(key, b), diffuse_color);
- }
- glNormal3fv(CCG_elem_no(key, b));
- glVertex3fv(CCG_elem_co(key, b));
- }
- glEnd();
- }
- }
- else {
- for (y = 0; y < gridsize - 1; y++) {
- glBegin(GL_QUAD_STRIP);
- for (x = 0; x < gridsize; x++) {
- CCGElem *a = CCG_grid_elem(key, grid, x, y);
- CCGElem *b = CCG_grid_elem(key, grid, x, y + 1);
-
- if (x > 0) {
- CCGElem *c = CCG_grid_elem(key, grid, x - 1, y);
- CCGElem *d = CCG_grid_elem(key, grid, x - 1, y + 1);
-
- float fno[3];
- normal_quad_v3(fno,
- CCG_elem_co(key, d),
- CCG_elem_co(key, b),
- CCG_elem_co(key, a),
- CCG_elem_co(key, c));
- glNormal3fv(fno);
-
- if (has_mask) {
- gpu_color_from_mask_quad_set(key, a, b, c, d, diffuse_color);
- }
- }
-
- glVertex3fv(CCG_elem_co(key, a));
- glVertex3fv(CCG_elem_co(key, b));
- }
- glEnd();
- }
- }
- }
-
- if (has_mask) {
- gpu_colors_disable(VBO_DISABLED);
- }
-}
-
void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
- bool wireframe)
+ bool wireframe, bool fast)
{
+ bool do_fast = fast && buffers->index_buf_fast;
/* sets material from the first face, to solve properly face would need to
* be sorted in buckets by materials */
if (setMaterial) {
- if (buffers->totface) {
- const MFace *f = &buffers->mface[buffers->face_indices[0]];
- if (!setMaterial(f->mat_nr + 1, NULL))
+ if (buffers->face_indices_len) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
+ if (!setMaterial(mp->mat_nr + 1, NULL))
return;
}
else if (buffers->totgrid) {
@@ -2582,51 +1993,86 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
}
}
- glShadeModel((buffers->smooth || buffers->totface) ? GL_SMOOTH : GL_FLAT);
+ glShadeModel((buffers->smooth || buffers->face_indices_len) ? GL_SMOOTH : GL_FLAT);
if (buffers->vert_buf) {
+ char *base = NULL;
+ char *index_base = NULL;
glEnableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
glEnableClientState(GL_NORMAL_ARRAY);
gpu_colors_enable(VBO_ENABLED);
}
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, buffers->vert_buf);
+ GPU_buffer_bind(buffers->vert_buf, GPU_BINDING_ARRAY);
- if (buffers->index_buf)
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, buffers->index_buf);
+ if (!buffers->vert_buf->use_vbo)
+ base = (char *)buffers->vert_buf->pointer;
+
+ if (do_fast) {
+ GPU_buffer_bind(buffers->index_buf_fast, GPU_BINDING_INDEX);
+ if (!buffers->index_buf_fast->use_vbo)
+ index_base = buffers->index_buf_fast->pointer;
+ }
+ else if (buffers->index_buf) {
+ GPU_buffer_bind(buffers->index_buf, GPU_BINDING_INDEX);
+ if (!buffers->index_buf->use_vbo)
+ index_base = buffers->index_buf->pointer;
+ }
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
if (buffers->tot_quad) {
- const char *offset = 0;
- int i, last = buffers->has_hidden ? 1 : buffers->totgrid;
- for (i = 0; i < last; i++) {
+ const char *offset = base;
+ const bool drawall = !(buffers->has_hidden || do_fast);
+
+ if (GLEW_ARB_draw_elements_base_vertex && drawall) {
+
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, co));
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, no));
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
offset + offsetof(VertexBufferFormat, color));
-
- glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, 0);
- offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ glMultiDrawElementsBaseVertex(GL_TRIANGLES, buffers->baseelemarray, buffers->index_type,
+ (const void * const *)buffers->baseindex,
+ buffers->totgrid, &buffers->baseelemarray[buffers->totgrid]);
+ }
+ else {
+ int i, last = drawall ? buffers->totgrid : 1;
+
+ /* we could optimize this to one draw call, but it would need more memory */
+ for (i = 0; i < last; i++) {
+ glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, co));
+ glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, no));
+ glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
+ offset + offsetof(VertexBufferFormat, color));
+
+ if (do_fast)
+ glDrawElements(GL_TRIANGLES, buffers->totgrid * 6, buffers->index_type, index_base);
+ else
+ glDrawElements(GL_TRIANGLES, buffers->tot_quad * 6, buffers->index_type, index_base);
+
+ offset += buffers->gridkey.grid_area * sizeof(VertexBufferFormat);
+ }
}
}
else if (buffers->tot_tri) {
int totelem = buffers->tot_tri * 3;
glVertexPointer(3, GL_FLOAT, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, co));
+ (void *)(base + offsetof(VertexBufferFormat, co)));
glNormalPointer(GL_SHORT, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, no));
+ (void *)(base + offsetof(VertexBufferFormat, no)));
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(VertexBufferFormat),
- (void *)offsetof(VertexBufferFormat, color));
+ (void *)(base + offsetof(VertexBufferFormat, color)));
if (buffers->index_buf)
- glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, 0);
+ glDrawElements(GL_TRIANGLES, totelem, buffers->index_type, index_base);
else
glDrawArrays(GL_TRIANGLES, 0, totelem);
}
@@ -2634,9 +2080,9 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
if (wireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
- if (buffers->index_buf)
- glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ GPU_buffer_unbind(buffers->vert_buf, GPU_BINDING_ARRAY);
+ if (buffers->index_buf || do_fast)
+ GPU_buffer_unbind(do_fast ? buffers->index_buf_fast : buffers->index_buf, GPU_BINDING_INDEX);
glDisableClientState(GL_VERTEX_ARRAY);
if (!wireframe) {
@@ -2644,13 +2090,6 @@ void GPU_draw_pbvh_buffers(GPU_PBVH_Buffers *buffers, DMSetMaterial setMaterial,
gpu_colors_disable(VBO_ENABLED);
}
}
- /* fallbacks if we are out of memory or VBO is disabled */
- else if (buffers->totface) {
- gpu_draw_buffers_legacy_mesh(buffers);
- }
- else if (buffers->totgrid) {
- gpu_draw_buffers_legacy_grids(buffers);
- }
}
bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces, bool show_diffuse_color)
@@ -2667,13 +2106,14 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
if ((buffers->show_diffuse_color == false) || use_matcaps)
return false;
- if (buffers->mface) {
- MFace *f = buffers->mface + buffers->face_indices[0];
+ if (buffers->looptri) {
+ const MLoopTri *lt = &buffers->looptri[buffers->face_indices[0]];
+ const MPoly *mp = &buffers->mpoly[lt->poly];
- GPU_material_diffuse_get(f->mat_nr + 1, diffuse_color);
+ GPU_material_diffuse_get(mp->mat_nr + 1, diffuse_color);
}
else if (buffers->use_bmesh) {
- /* due to dynamc nature of dyntopo, only get first material */
+ /* due to dynamic nature of dyntopo, only get first material */
if (BLI_gset_size(bm_faces) > 0) {
GSetIterator gs_iter;
BMFace *f;
@@ -2695,50 +2135,19 @@ bool GPU_pbvh_buffers_diffuse_changed(GPU_PBVH_Buffers *buffers, GSet *bm_faces,
return !equals_v3v3(diffuse_color, buffers->diffuse_color);
}
-/* release a GPU_PBVH_Buffers id;
- *
- * Thread-unsafe version for internal usage only.
- */
-static void gpu_pbvh_buffer_free_intern(GLuint id)
-{
- GPUBufferPool *pool;
-
- /* zero id is vertex buffers off */
- if (!id)
- return;
-
- pool = gpu_get_global_buffer_pool();
-
- /* free the buffers immediately if we are on main thread */
- if (BLI_thread_is_main()) {
- glDeleteBuffersARB(1, &id);
-
- if (pool->totpbvhbufids > 0) {
- glDeleteBuffersARB(pool->totpbvhbufids, pool->pbvhbufids);
- pool->totpbvhbufids = 0;
- }
- return;
- }
- /* outside of main thread, can't safely delete the
- * buffer, so increase pool size */
- if (pool->maxpbvhsize == pool->totpbvhbufids) {
- pool->maxpbvhsize += MAX_FREE_GPU_BUFF_IDS;
- pool->pbvhbufids = MEM_reallocN(pool->pbvhbufids,
- sizeof(*pool->pbvhbufids) * pool->maxpbvhsize);
- }
-
- /* insert the buffer into the beginning of the pool */
- pool->pbvhbufids[pool->totpbvhbufids++] = id;
-}
-
-
void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
{
if (buffers) {
if (buffers->vert_buf)
- gpu_pbvh_buffer_free_intern(buffers->vert_buf);
+ GPU_buffer_free(buffers->vert_buf);
if (buffers->index_buf && (buffers->tot_tri || buffers->has_hidden))
- gpu_pbvh_buffer_free_intern(buffers->index_buf);
+ GPU_buffer_free(buffers->index_buf);
+ if (buffers->index_buf_fast)
+ GPU_buffer_free(buffers->index_buf_fast);
+ if (buffers->baseelemarray)
+ MEM_freeN(buffers->baseelemarray);
+ if (buffers->baseindex)
+ MEM_freeN(buffers->baseindex);
MEM_freeN(buffers);
}
@@ -2748,34 +2157,34 @@ void GPU_free_pbvh_buffers(GPU_PBVH_Buffers *buffers)
/* debug function, draws the pbvh BB */
void GPU_draw_pbvh_BB(float min[3], float max[3], bool leaf)
{
- 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]}
- },
+ 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)
@@ -2797,7 +2206,6 @@ void GPU_init_draw_pbvh_BB(void)
glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL);
glEnable(GL_BLEND);
- glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
void GPU_end_draw_pbvh_BB(void)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 6b46db89a93..496302bb44e 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -31,8 +31,6 @@
* Convert material node-trees to GLSL.
*/
-#include "GL/glew.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_customdata_types.h"
@@ -44,39 +42,59 @@
#include "BLI_dynstr.h"
#include "BLI_ghash.h"
+#include "GPU_glew.h"
#include "GPU_material.h"
#include "GPU_extensions.h"
-#include "BLI_sys_types.h" // for intptr_t support
+#include "BLI_sys_types.h" /* for intptr_t support */
#include "gpu_codegen.h"
-#include "node_util.h" /* For muting node stuff... */
-
#include <string.h>
#include <stdarg.h>
extern char datatoc_gpu_shader_material_glsl[];
extern char datatoc_gpu_shader_vertex_glsl[];
-
+extern char datatoc_gpu_shader_vertex_world_glsl[];
+extern char datatoc_gpu_shader_geometry_glsl[];
static char *glsl_material_library = NULL;
-/* structs and defines */
+/* type definitions and constants */
+
+enum {
+ MAX_FUNCTION_NAME = 64
+};
+enum {
+ MAX_PARAMETER = 32
+};
+typedef enum {
+ FUNCTION_QUAL_IN,
+ FUNCTION_QUAL_OUT,
+ FUNCTION_QUAL_INOUT
+} GPUFunctionQual;
+
+typedef struct GPUFunction {
+ char name[MAX_FUNCTION_NAME];
+ GPUType paramtype[MAX_PARAMETER];
+ GPUFunctionQual paramqual[MAX_PARAMETER];
+ int totparam;
+} GPUFunction;
+
+/* Indices match the GPUType enum */
static const char *GPU_DATATYPE_STR[17] = {"", "float", "vec2", "vec3", "vec4",
NULL, NULL, NULL, NULL, "mat3", NULL, NULL, NULL, NULL, NULL, NULL, "mat4"};
-#define LINK_IMAGE_BLENDER 1
-#define LINK_IMAGE_PREVIEW 2
-
/* GLSL code parsing for finding function definitions.
* These are stored in a hash for lookup when creating a material. */
-static GHash *FUNCTION_HASH= NULL;
-/* static char *FUNCTION_PROTOTYPES= NULL;
- * static GPUShader *FUNCTION_LIB= NULL;*/
+static GHash *FUNCTION_HASH = NULL;
+#if 0
+static char *FUNCTION_PROTOTYPES = NULL;
+static GPUShader *FUNCTION_LIB = NULL;
+#endif
static int gpu_str_prefix(const char *str, const char *prefix)
{
@@ -100,8 +118,8 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
if (ELEM(*str, ' ', '(', ')', ',', '\t', '\n', '\r'))
break;
else {
- if (token && len < max-1) {
- *token= *str;
+ if (token && len < max - 1) {
+ *token = *str;
token++;
len++;
}
@@ -110,7 +128,7 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
}
if (token)
- *token= '\0';
+ *token = '\0';
/* skip the next special characters:
* note the missing ')' */
@@ -127,7 +145,9 @@ static char *gpu_str_skip_token(char *str, char *token, int max)
static void gpu_parse_functions_string(GHash *hash, char *code)
{
GPUFunction *function;
- int i, type, qual;
+ GPUType type;
+ GPUFunctionQual qual;
+ int i;
while ((code = strstr(code, "void "))) {
function = MEM_callocN(sizeof(GPUFunction), "GPUFunction");
@@ -147,10 +167,10 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
code = gpu_str_skip_token(code, NULL, 0);
/* test for type */
- type= 0;
- for (i=1; i<=16; i++) {
+ type = GPU_NONE;
+ for (i = 1; i <= 16; i++) {
if (GPU_DATATYPE_STR[i] && gpu_str_prefix(code, GPU_DATATYPE_STR[i])) {
- type= i;
+ type = i;
break;
}
}
@@ -161,11 +181,11 @@ static void gpu_parse_functions_string(GHash *hash, char *code)
type= GPU_TEX2D;
if (type) {
- /* add paramater */
+ /* add parameter */
code = gpu_str_skip_token(code, NULL, 0);
code = gpu_str_skip_token(code, NULL, 0);
- function->paramqual[function->totparam]= qual;
- function->paramtype[function->totparam]= type;
+ function->paramqual[function->totparam] = qual;
+ function->paramtype[function->totparam] = type;
function->totparam++;
}
else {
@@ -202,7 +222,7 @@ static char *gpu_generate_function_prototyps(GHash *hash)
function = BLI_ghashIterator_getValue(ghi);
BLI_dynstr_appendf(ds, "void %s(", name);
- for (a=0; a<function->totparam; a++) {
+ for (a = 0; a < function->totparam; a++) {
if (function->paramqual[a] == FUNCTION_QUAL_OUT)
BLI_dynstr_append(ds, "out ");
else if (function->paramqual[a] == FUNCTION_QUAL_INOUT)
@@ -214,10 +234,11 @@ static char *gpu_generate_function_prototyps(GHash *hash)
BLI_dynstr_append(ds, "sampler2DShadow");
else
BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]);
-
- //BLI_dynstr_appendf(ds, " param%d", a);
-
- if (a != function->totparam-1)
+# if 0
+ BLI_dynstr_appendf(ds, " param%d", a);
+# endif
+
+ if (a != function->totparam - 1)
BLI_dynstr_append(ds, ", ");
}
BLI_dynstr_append(ds, ");\n");
@@ -232,27 +253,27 @@ static char *gpu_generate_function_prototyps(GHash *hash)
}
#endif
-GPUFunction *GPU_lookup_function(const char *name)
+static GPUFunction *gpu_lookup_function(const char *name)
{
if (!FUNCTION_HASH) {
FUNCTION_HASH = BLI_ghash_str_new("GPU_lookup_function gh");
gpu_parse_functions_string(FUNCTION_HASH, glsl_material_library);
}
- return (GPUFunction*)BLI_ghash_lookup(FUNCTION_HASH, (void *)name);
+ return BLI_ghash_lookup(FUNCTION_HASH, (const void *)name);
}
-void GPU_codegen_init(void)
+void gpu_codegen_init(void)
{
GPU_code_generate_glsl_lib();
}
-void GPU_codegen_exit(void)
+void gpu_codegen_exit(void)
{
- extern Material defmaterial; // render module abuse...
+ extern Material defmaterial; /* render module abuse... */
if (defmaterial.gpumaterial.first)
- GPU_material_free(&defmaterial);
+ GPU_material_free(&defmaterial.gpumaterial);
if (FUNCTION_HASH) {
BLI_ghash_free(FUNCTION_HASH, NULL, MEM_freeN);
@@ -266,14 +287,16 @@ void GPU_codegen_exit(void)
glsl_material_library = NULL;
}
- /*if (FUNCTION_PROTOTYPES) {
+#if 0
+ if (FUNCTION_PROTOTYPES) {
MEM_freeN(FUNCTION_PROTOTYPES);
FUNCTION_PROTOTYPES = NULL;
- }*/
- /*if (FUNCTION_LIB) {
+ }
+ if (FUNCTION_LIB) {
GPU_shader_free(FUNCTION_LIB);
FUNCTION_LIB = NULL;
- }*/
+ }
+#endif
}
/* GLSL code generation */
@@ -288,18 +311,16 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
BLI_dynstr_append(ds, name);
}
else if (to == GPU_FLOAT) {
- if (from == GPU_VEC4)
- BLI_dynstr_appendf(ds, "dot(%s.rgb, vec3(0.35, 0.45, 0.2))", name);
- else if (from == GPU_VEC3)
- BLI_dynstr_appendf(ds, "dot(%s, vec3(0.33))", name);
+ if (from == GPU_VEC4 || from == GPU_VEC3)
+ BLI_dynstr_appendf(ds, "(%s.r + %s.g + %s.b) / 3.0", name, name, name);
else if (from == GPU_VEC2)
BLI_dynstr_appendf(ds, "%s.r", name);
}
else if (to == GPU_VEC2) {
if (from == GPU_VEC4)
- BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.35, 0.45, 0.2)), %s.a)", name, name);
+ BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, %s.a)", name, name, name, name);
else if (from == GPU_VEC3)
- BLI_dynstr_appendf(ds, "vec2(dot(%s.rgb, vec3(0.33)), 1.0)", name);
+ BLI_dynstr_appendf(ds, "vec2((%s.r + %s.g + %s.b) / 3.0, 1.0)", name, name, name);
else if (from == GPU_FLOAT)
BLI_dynstr_appendf(ds, "vec2(%s, 1.0)", name);
}
@@ -321,15 +342,15 @@ static void codegen_convert_datatype(DynStr *ds, int from, int to, const char *t
}
}
-static void codegen_print_datatype(DynStr *ds, int type, float *data)
+static void codegen_print_datatype(DynStr *ds, const GPUType type, float *data)
{
int i;
BLI_dynstr_appendf(ds, "%s(", GPU_DATATYPE_STR[type]);
- for (i=0; i<type; i++) {
+ for (i = 0; i < type; i++) {
BLI_dynstr_appendf(ds, "%f", data[i]);
- if (i == type-1)
+ if (i == type - 1)
BLI_dynstr_append(ds, ")");
else
BLI_dynstr_append(ds, ", ");
@@ -364,10 +385,36 @@ const char *GPU_builtin_name(GPUBuiltin builtin)
return "unfobcolor";
else if (builtin == GPU_AUTO_BUMPSCALE)
return "unfobautobumpscale";
+ else if (builtin == GPU_CAMERA_TEXCO_FACTORS)
+ return "unfcameratexfactors";
+ else if (builtin == GPU_PARTICLE_SCALAR_PROPS)
+ return "unfparticlescalarprops";
+ else if (builtin == GPU_PARTICLE_LOCATION)
+ return "unfparticleco";
+ else if (builtin == GPU_PARTICLE_VELOCITY)
+ return "unfparticlevel";
+ else if (builtin == GPU_PARTICLE_ANG_VELOCITY)
+ return "unfparticleangvel";
else
return "";
}
+/* assign only one texid per buffer to avoid sampling the same texture twice */
+static void codegen_set_texid(GHash *bindhash, GPUInput *input, int *texid, void *key)
+{
+ if (BLI_ghash_haskey(bindhash, key)) {
+ /* Reuse existing texid */
+ input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, key));
+ }
+ else {
+ /* Allocate new texid */
+ input->texid = *texid;
+ (*texid)++;
+ input->bindtex = true;
+ BLI_ghash_insert(bindhash, key, SET_INT_IN_POINTER(input->texid));
+ }
+}
+
static void codegen_set_unique_ids(ListBase *nodes)
{
GHash *bindhash, *definehash;
@@ -376,75 +423,50 @@ static void codegen_set_unique_ids(ListBase *nodes)
GPUOutput *output;
int id = 1, texid = 0;
- bindhash= BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
- definehash= BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
+ bindhash = BLI_ghash_ptr_new("codegen_set_unique_ids1 gh");
+ definehash = BLI_ghash_ptr_new("codegen_set_unique_ids2 gh");
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
/* set id for unique names of uniform variables */
input->id = id++;
- input->bindtex = 0;
- input->definetex = 0;
+ input->bindtex = false;
+ input->definetex = false;
/* set texid used for settings texture slot with multitexture */
if (codegen_input_has_texture(input) &&
((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)))
{
+ /* assign only one texid per buffer to avoid sampling
+ * the same texture twice */
if (input->link) {
- /* input is texture from buffer, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->link)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->link, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->link));
+ /* input is texture from buffer */
+ codegen_set_texid(bindhash, input, &texid, input->link);
}
else if (input->ima) {
- /* input is texture from image, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->ima)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->ima, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->ima));
+ /* input is texture from image */
+ codegen_set_texid(bindhash, input, &texid, input->ima);
}
else if (input->prv) {
- /* input is texture from preview render, assign only one texid per
- * buffer to avoid sampling the same texture twice */
- if (!BLI_ghash_haskey(bindhash, input->prv)) {
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->prv, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->prv));
+ /* input is texture from preview render */
+ codegen_set_texid(bindhash, input, &texid, input->prv);
}
- else {
- if (!BLI_ghash_haskey(bindhash, input->tex)) {
- /* input is user created texture, check tex pointer */
- input->texid = texid++;
- input->bindtex = 1;
- BLI_ghash_insert(bindhash, input->tex, SET_INT_IN_POINTER(input->texid));
- }
- else
- input->texid = GET_INT_FROM_POINTER(BLI_ghash_lookup(bindhash, input->tex));
+ else if (input->tex) {
+ /* input is user created texture, check tex pointer */
+ codegen_set_texid(bindhash, input, &texid, input->tex);
}
/* make sure this pixel is defined exactly once */
if (input->source == GPU_SOURCE_TEX_PIXEL) {
if (input->ima) {
if (!BLI_ghash_haskey(definehash, input->ima)) {
- input->definetex = 1;
+ input->definetex = true;
BLI_ghash_insert(definehash, input->ima, SET_INT_IN_POINTER(input->texid));
}
}
else {
if (!BLI_ghash_haskey(definehash, input->link)) {
- input->definetex = 1;
+ input->definetex = true;
BLI_ghash_insert(definehash, input->link, SET_INT_IN_POINTER(input->texid));
}
}
@@ -452,7 +474,7 @@ static void codegen_set_unique_ids(ListBase *nodes)
}
}
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
/* set id for unique names of tmp variables storing output */
output->id = id++;
}
@@ -469,8 +491,8 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
int builtins = 0;
/* print uniforms */
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if ((input->source == GPU_SOURCE_TEX) || (input->source == GPU_SOURCE_TEX_PIXEL)) {
/* create exactly one sampler for each texture */
if (codegen_input_has_texture(input) && input->bindtex)
@@ -509,8 +531,19 @@ static int codegen_print_uniforms_functions(DynStr *ds, ListBase *nodes)
}
}
else if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+#ifdef WITH_OPENSUBDIV
+ bool skip_opensubdiv = input->attribtype == CD_TANGENT;
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "varying %s var%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
}
}
}
@@ -526,9 +559,9 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
GPUInput *input;
GPUOutput *output;
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
/* load pixels from textures */
- for (input=node->inputs.first; input; input=input->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX_PIXEL) {
if (codegen_input_has_texture(input) && input->definetex) {
BLI_dynstr_appendf(ds, "\tvec4 tex%d = texture2D(", input->texid);
@@ -539,7 +572,7 @@ static void codegen_declare_tmps(DynStr *ds, ListBase *nodes)
}
/* declare temporary variables for node output storage */
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
BLI_dynstr_appendf(ds, "\t%s tmp%d;\n",
GPU_DATATYPE_STR[output->type], output->id);
}
@@ -553,10 +586,10 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
GPUInput *input;
GPUOutput *output;
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
BLI_dynstr_appendf(ds, "\t%s(", node->name);
- for (input=node->inputs.first; input; input=input->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_TEX) {
BLI_dynstr_appendf(ds, "samp%d", input->texid);
if (input->link)
@@ -591,7 +624,7 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ", ");
}
- for (output=node->outputs.first; output; output=output->next) {
+ for (output = node->outputs.first; output; output = output->next) {
BLI_dynstr_appendf(ds, "tmp%d", output->id);
if (output->next)
BLI_dynstr_append(ds, ", ");
@@ -605,26 +638,63 @@ static void codegen_call_functions(DynStr *ds, ListBase *nodes, GPUOutput *final
BLI_dynstr_append(ds, ";\n");
}
-static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const char *UNUSED(name))
+static char *code_generate_fragment(ListBase *nodes, GPUOutput *output)
{
DynStr *ds = BLI_dynstr_new();
char *code;
int builtins;
- /*BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);*/
+#ifdef WITH_OPENSUBDIV
+ GPUNode *node;
+ GPUInput *input;
+#endif
+
+
+#if 0
+ BLI_dynstr_append(ds, FUNCTION_PROTOTYPES);
+#endif
codegen_set_unique_ids(nodes);
builtins = codegen_print_uniforms_functions(ds, nodes);
- //if (G.debug & G_DEBUG)
- // BLI_dynstr_appendf(ds, "/* %s */\n", name);
+#if 0
+ if (G.debug & G_DEBUG)
+ BLI_dynstr_appendf(ds, "/* %s */\n", name);
+#endif
BLI_dynstr_append(ds, "void main(void)\n");
BLI_dynstr_append(ds, "{\n");
if (builtins & GPU_VIEW_NORMAL)
BLI_dynstr_append(ds, "\tvec3 facingnormal = (gl_FrontFacing)? varnormal: -varnormal;\n");
-
+
+ /* Calculate tangent space. */
+#ifdef WITH_OPENSUBDIV
+ {
+ bool has_tangent = false;
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_TANGENT) {
+ BLI_dynstr_appendf(ds, "#ifdef USE_OPENSUBDIV\n");
+ BLI_dynstr_appendf(ds, "\t%s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ if (has_tangent == false) {
+ BLI_dynstr_appendf(ds, "\tvec3 Q1 = dFdx(inpt.v.position.xyz);\n");
+ BLI_dynstr_appendf(ds, "\tvec3 Q2 = dFdy(inpt.v.position.xyz);\n");
+ BLI_dynstr_appendf(ds, "\tvec2 st1 = dFdx(inpt.v.uv);\n");
+ BLI_dynstr_appendf(ds, "\tvec2 st2 = dFdy(inpt.v.uv);\n");
+ BLI_dynstr_appendf(ds, "\tvec3 T = normalize(Q1 * st2.t - Q2 * st1.t);\n");
+ }
+ BLI_dynstr_appendf(ds, "\tvar%d = vec4(T, 1.0);\n", input->attribid);
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+ }
+ }
+ }
+ }
+#endif
codegen_declare_tmps(ds, nodes);
codegen_call_functions(ds, nodes, output);
@@ -635,41 +705,86 @@ static char *code_generate_fragment(ListBase *nodes, GPUOutput *output, const ch
code = BLI_dynstr_get_cstring(ds);
BLI_dynstr_free(ds);
- //if (G.debug & G_DEBUG) printf("%s\n", code);
+#if 0
+ if (G.debug & G_DEBUG) printf("%s\n", code);
+#endif
return code;
}
-static char *code_generate_vertex(ListBase *nodes)
+static char *code_generate_vertex(ListBase *nodes, const GPUMatType type)
{
DynStr *ds = BLI_dynstr_new();
GPUNode *node;
GPUInput *input;
char *code;
+ char *vertcode = NULL;
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+#ifdef WITH_OPENSUBDIV
+ bool skip_opensubdiv = ELEM(input->attribtype, CD_MTFACE, CD_TANGENT);
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "attribute %s att%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
BLI_dynstr_appendf(ds, "varying %s var%d;\n",
GPU_DATATYPE_STR[input->type], input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (skip_opensubdiv) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
}
}
}
BLI_dynstr_append(ds, "\n");
- BLI_dynstr_append(ds, datatoc_gpu_shader_vertex_glsl);
- for (node=nodes->first; node; node=node->next)
- for (input=node->inputs.first; input; input=input->next)
+ switch (type) {
+ case GPU_MATERIAL_TYPE_MESH:
+ vertcode = datatoc_gpu_shader_vertex_glsl;
+ break;
+ case GPU_MATERIAL_TYPE_WORLD:
+ vertcode = datatoc_gpu_shader_vertex_world_glsl;
+ break;
+ default:
+ fprintf(stderr, "invalid material type, set one after GPU_material_construct_begin\n");
+ break;
+ }
+
+ BLI_dynstr_append(ds, vertcode);
+
+ for (node = nodes->first; node; node = node->next)
+ for (input = node->inputs.first; input; input = input->next)
if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
if (input->attribtype == CD_TANGENT) { /* silly exception */
- BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize((gl_ModelViewMatrix * vec4(att%d.xyz, 0)).xyz);\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+#endif
+ BLI_dynstr_appendf(ds, "\tvar%d.xyz = normalize(gl_NormalMatrix * att%d.xyz);\n", input->attribid, input->attribid);
BLI_dynstr_appendf(ds, "\tvar%d.w = att%d.w;\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ BLI_dynstr_appendf(ds, "#endif\n");
+#endif
}
- else
+ else {
+#ifdef WITH_OPENSUBDIV
+ bool is_mtface = input->attribtype == CD_MTFACE;
+ if (is_mtface) {
+ BLI_dynstr_appendf(ds, "#ifndef USE_OPENSUBDIV\n");
+ }
+#endif
BLI_dynstr_appendf(ds, "\tvar%d = att%d;\n", input->attribid, input->attribid);
+#ifdef WITH_OPENSUBDIV
+ if (is_mtface) {
+ BLI_dynstr_appendf(ds, "#endif\n");
+ }
+#endif
+ }
}
/* unfortunately special handling is needed here because we abuse gl_Color/gl_SecondaryColor flat shading */
else if (input->source == GPU_SOURCE_OPENGL_BUILTIN) {
@@ -690,14 +805,69 @@ static char *code_generate_vertex(ListBase *nodes)
BLI_dynstr_free(ds);
- //if (G.debug & G_DEBUG) printf("%s\n", code);
+#if 0
+ if (G.debug & G_DEBUG) printf("%s\n", code);
+#endif
return code;
}
-int GPU_bicubic_bump_support(void)
+static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv)
{
- return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ DynStr *ds = BLI_dynstr_new();
+ GPUNode *node;
+ GPUInput *input;
+ char *code;
+
+ /* Generate varying declarations. */
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_MTFACE) {
+ BLI_dynstr_appendf(ds, "varying %s var%d;\n",
+ GPU_DATATYPE_STR[input->type],
+ input->attribid);
+ BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n",
+ input->attribid);
+ }
+ }
+ }
+ }
+
+ BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl);
+
+ /* Generate varying assignments. */
+ /* TODO(sergey): Disabled for now, needs revisit. */
+#if 0
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
+ if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) {
+ if (input->attribtype == CD_MTFACE) {
+ BLI_dynstr_appendf(ds,
+ "\tINTERP_FACE_VARYING_2(var%d, "
+ "fvar%d_offset, st);\n",
+ input->attribid,
+ input->attribid);
+ }
+ }
+ }
+ }
+#endif
+
+ BLI_dynstr_append(ds, "}\n\n");
+ code = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ //if (G.debug & G_DEBUG) printf("%s\n", code);
+
+ return code;
+ }
+#else
+ UNUSED_VARS(nodes, use_opensubdiv);
+#endif
+ return NULL;
}
void GPU_code_generate_glsl_lib(void)
@@ -726,7 +896,7 @@ GPUShader *GPU_pass_shader(GPUPass *pass)
return pass->shader;
}
-static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
+static void gpu_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
{
GPUShader *shader = pass->shader;
GPUNode *node;
@@ -741,15 +911,35 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
GPU_shader_bind(shader);
- for (node=nodes->first; node; node=node->next) {
+ for (node = nodes->first; node; node = node->next) {
z = 0;
- for (input=node->inputs.first; input; input=next, z++) {
+ for (input = node->inputs.first; input; input = next, z++) {
next = input->next;
/* attributes don't need to be bound, they already have
* an id that the drawing functions will use */
- if (input->source == GPU_SOURCE_ATTRIB ||
- input->source == GPU_SOURCE_BUILTIN ||
+ if (input->source == GPU_SOURCE_ATTRIB) {
+#ifdef WITH_OPENSUBDIV
+ /* We do need mtface attributes for later, so we can
+ * update face-varuing variables offset in the texture
+ * buffer for proper sampling from the shader.
+ *
+ * We don't do anything about attribute itself, we
+ * only use it to learn which uniform name is to be
+ * updated.
+ *
+ * TODO(sergey): We can add ad extra uniform input
+ * for the offset, which will be purely internal and
+ * which would avoid having such an exceptions.
+ */
+ if (input->attribtype != CD_MTFACE) {
+ continue;
+ }
+#else
+ continue;
+#endif
+ }
+ if (input->source == GPU_SOURCE_BUILTIN ||
input->source == GPU_SOURCE_OPENGL_BUILTIN)
{
continue;
@@ -773,6 +963,14 @@ static void GPU_nodes_extract_dynamic_inputs(GPUPass *pass, ListBase *nodes)
if (extract)
input->shaderloc = GPU_shader_get_uniform(shader, input->shadername);
+#ifdef WITH_OPENSUBDIV
+ if (input->source == GPU_SOURCE_ATTRIB &&
+ input->attribtype == CD_MTFACE)
+ {
+ extract = 1;
+ }
+#endif
+
/* extract nodes */
if (extract) {
BLI_remlink(&node->inputs, input);
@@ -796,7 +994,7 @@ void GPU_pass_bind(GPUPass *pass, double time, int mipmap)
GPU_shader_bind(shader);
/* now bind the textures */
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->ima)
input->tex = GPU_texture_from_blender(input->ima, input->iuser, input->image_isdata, time, mipmap);
else if (input->prv)
@@ -820,10 +1018,19 @@ void GPU_pass_update_uniforms(GPUPass *pass)
return;
/* pass dynamic inputs to opengl, others were removed */
- for (input=inputs->first; input; input=input->next)
- if (!(input->ima || input->tex || input->prv))
- GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
- input->dynamicvec);
+ for (input = inputs->first; input; input = input->next) {
+ if (!(input->ima || input->tex || input->prv)) {
+ if (input->dynamictype == GPU_DYNAMIC_MAT_HARD) {
+ // The hardness is actually a short pointer, so we convert it here
+ float val = (float)(*(short*)input->dynamicvec);
+ GPU_shader_uniform_vector(shader, input->shaderloc, 1, 1, &val);
+ }
+ else {
+ GPU_shader_uniform_vector(shader, input->shaderloc, input->type, 1,
+ input->dynamicvec);
+ }
+ }
+ }
}
void GPU_pass_unbind(GPUPass *pass)
@@ -835,7 +1042,7 @@ void GPU_pass_unbind(GPUPass *pass)
if (!shader)
return;
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->tex && input->bindtex)
GPU_texture_unbind(input->tex);
@@ -848,16 +1055,16 @@ void GPU_pass_unbind(GPUPass *pass)
/* Node Link Functions */
-static GPUNodeLink *GPU_node_link_create(int type)
+static GPUNodeLink *GPU_node_link_create(void)
{
GPUNodeLink *link = MEM_callocN(sizeof(GPUNodeLink), "GPUNodeLink");
- link->type = type;
+ link->type = GPU_NONE;
link->users++;
return link;
}
-static void GPU_node_link_free(GPUNodeLink *link)
+static void gpu_node_link_free(GPUNodeLink *link)
{
link->users--;
@@ -877,17 +1084,12 @@ static GPUNode *GPU_node_begin(const char *name)
{
GPUNode *node = MEM_callocN(sizeof(GPUNode), "GPUNode");
- node->name= name;
+ node->name = name;
return node;
}
-static void GPU_node_end(GPUNode *UNUSED(node))
-{
- /* empty */
-}
-
-static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
+static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, const GPUType type)
{
GPUInput *input;
GPUNode *outnode;
@@ -896,8 +1098,11 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
if (link->output) {
outnode = link->output->node;
name = outnode->name;
+ input = outnode->inputs.first;
- if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+ if ((STREQ(name, "set_value") || STREQ(name, "set_rgb")) &&
+ (input->type == type))
+ {
input = MEM_dupallocN(outnode->inputs.first);
input->type = type;
if (input->link)
@@ -941,7 +1146,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->tex = link->dynamictex;
input->textarget = GL_TEXTURE_2D;
input->textype = type;
- input->dynamictex = 1;
+ input->dynamictex = true;
input->dynamicdata = link->ptr2;
MEM_freeN(link);
}
@@ -951,8 +1156,10 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->source = GPU_SOURCE_TEX;
input->textype = type;
- //input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
- input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, NULL);
+#if 0
+ input->tex = GPU_texture_create_2D(link->texturesize, link->texturesize, link->ptr2, NULL);
+#endif
+ input->tex = GPU_texture_create_2D(link->texturesize, 1, link->ptr1, GPU_HDR_NONE, NULL);
input->textarget = GL_TEXTURE_2D;
MEM_freeN(link->ptr1);
@@ -963,7 +1170,7 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
input->type = GPU_VEC4;
input->source = GPU_SOURCE_TEX;
- if (link->image == LINK_IMAGE_PREVIEW)
+ if (link->image == GPU_NODE_LINK_IMAGE_PREVIEW)
input->prv = link->ptr1;
else {
input->ima = link->ptr1;
@@ -990,9 +1197,9 @@ static void gpu_node_input_link(GPUNode *node, GPUNodeLink *link, int type)
memcpy(input->vec, link->ptr1, type*sizeof(float));
if (link->dynamic) {
- input->dynamicvec= link->ptr1;
- input->dynamictype= link->dynamictype;
- input->dynamicdata= link->ptr2;
+ input->dynamicvec = link->ptr1;
+ input->dynamictype = link->dynamictype;
+ input->dynamicdata = link->ptr2;
}
MEM_freeN(link);
}
@@ -1008,13 +1215,13 @@ static void gpu_node_input_socket(GPUNode *node, GPUNodeStack *sock)
gpu_node_input_link(node, sock->link, sock->type);
}
else {
- link = GPU_node_link_create(0);
+ link = GPU_node_link_create();
link->ptr1 = sock->vec;
gpu_node_input_link(node, link, sock->type);
}
}
-static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), GPUNodeLink **link)
+static void gpu_node_output(GPUNode *node, const GPUType type, GPUNodeLink **link)
{
GPUOutput *output = MEM_callocN(sizeof(GPUOutput), "GPUOutput");
@@ -1022,10 +1229,11 @@ static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), G
output->node = node;
if (link) {
- *link = output->link = GPU_node_link_create(type);
+ *link = output->link = GPU_node_link_create();
+ output->link->type = type;
output->link->output = output;
- /* note: the caller owns the reference to the linkfer, GPUOutput
+ /* note: the caller owns the reference to the link, GPUOutput
* merely points to it, and if the node is destroyed it will
* set that pointer to NULL */
}
@@ -1033,13 +1241,13 @@ static void GPU_node_output(GPUNode *node, int type, const char *UNUSED(name), G
BLI_addtail(&node->outputs, output);
}
-static void GPU_inputs_free(ListBase *inputs)
+static void gpu_inputs_free(ListBase *inputs)
{
GPUInput *input;
- for (input=inputs->first; input; input=input->next) {
+ for (input = inputs->first; input; input = input->next) {
if (input->link)
- GPU_node_link_free(input->link);
+ gpu_node_link_free(input->link);
else if (input->tex && !input->dynamictex)
GPU_texture_free(input->tex);
}
@@ -1047,28 +1255,28 @@ static void GPU_inputs_free(ListBase *inputs)
BLI_freelistN(inputs);
}
-static void GPU_node_free(GPUNode *node)
+static void gpu_node_free(GPUNode *node)
{
GPUOutput *output;
- GPU_inputs_free(&node->inputs);
+ gpu_inputs_free(&node->inputs);
- for (output=node->outputs.first; output; output=output->next)
+ for (output = node->outputs.first; output; output = output->next)
if (output->link) {
output->link->output = NULL;
- GPU_node_link_free(output->link);
+ gpu_node_link_free(output->link);
}
BLI_freelistN(&node->outputs);
MEM_freeN(node);
}
-static void GPU_nodes_free(ListBase *nodes)
+static void gpu_nodes_free(ListBase *nodes)
{
GPUNode *node;
while ((node = BLI_pophead(nodes))) {
- GPU_node_free(node);
+ gpu_node_free(node);
}
}
@@ -1085,12 +1293,12 @@ static void gpu_nodes_get_vertex_attributes(ListBase *nodes, GPUVertexAttribs *a
memset(attribs, 0, sizeof(*attribs));
- for (node=nodes->first; node; node=node->next) {
- for (input=node->inputs.first; input; input=input->next) {
+ for (node = nodes->first; node; node = node->next) {
+ for (input = node->inputs.first; input; input = input->next) {
if (input->source == GPU_SOURCE_ATTRIB) {
- for (a=0; a<attribs->totlayer; a++) {
+ for (a = 0; a < attribs->totlayer; a++) {
if (attribs->layer[a].type == input->attribtype &&
- strcmp(attribs->layer[a].name, input->attribname) == 0)
+ STREQ(attribs->layer[a].name, input->attribname))
{
break;
}
@@ -1120,43 +1328,43 @@ static void gpu_nodes_get_builtin_flag(ListBase *nodes, int *builtin)
GPUNode *node;
GPUInput *input;
- *builtin= 0;
+ *builtin = 0;
- for (node=nodes->first; node; node=node->next)
- for (input=node->inputs.first; input; input=input->next)
+ for (node = nodes->first; node; node = node->next)
+ for (input = node->inputs.first; input; input = input->next)
if (input->source == GPU_SOURCE_BUILTIN)
*builtin |= input->builtin;
}
/* varargs linking */
-GPUNodeLink *GPU_attribute(int type, const char *name)
+GPUNodeLink *GPU_attribute(const CustomDataType type, const char *name)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->attribtype= type;
- link->attribname= name;
+ link->attribtype = type;
+ link->attribname = name;
return link;
}
GPUNodeLink *GPU_uniform(float *num)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->ptr1= num;
- link->ptr2= NULL;
+ link->ptr1 = num;
+ link->ptr2 = NULL;
return link;
}
-GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
+GPUNodeLink *GPU_dynamic_uniform(float *num, GPUDynamicType dynamictype, void *data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->ptr1= num;
- link->ptr2= data;
- link->dynamic= 1;
+ link->ptr1 = num;
+ link->ptr2 = data;
+ link->dynamic = true;
link->dynamictype = dynamictype;
@@ -1165,9 +1373,9 @@ GPUNodeLink *GPU_dynamic_uniform(float *num, int dynamictype, void *data)
GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->image = LINK_IMAGE_BLENDER;
+ link->image = GPU_NODE_LINK_IMAGE_BLENDER;
link->ptr1 = ima;
link->ptr2 = iuser;
link->image_isdata = is_data;
@@ -1177,10 +1385,10 @@ GPUNodeLink *GPU_image(Image *ima, ImageUser *iuser, bool is_data)
GPUNodeLink *GPU_image_preview(PreviewImage *prv)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->image= LINK_IMAGE_PREVIEW;
- link->ptr1= prv;
+ link->image = GPU_NODE_LINK_IMAGE_PREVIEW;
+ link->ptr1 = prv;
return link;
}
@@ -1188,20 +1396,20 @@ GPUNodeLink *GPU_image_preview(PreviewImage *prv)
GPUNodeLink *GPU_texture(int size, float *pixels)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->texture = 1;
+ link->texture = true;
link->texturesize = size;
- link->ptr1= pixels;
+ link->ptr1 = pixels;
return link;
}
-GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
+GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, GPUDynamicType dynamictype, void *data)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
- link->dynamic = 1;
+ link->dynamic = true;
link->dynamictex = tex;
link->dynamictype = dynamictype;
link->ptr2 = data;
@@ -1211,7 +1419,7 @@ GPUNodeLink *GPU_dynamic_texture(GPUTexture *tex, int dynamictype, void *data)
GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
link->builtin= builtin;
@@ -1220,7 +1428,7 @@ GPUNodeLink *GPU_builtin(GPUBuiltin builtin)
GPUNodeLink *GPU_opengl_builtin(GPUOpenGLBuiltin builtin)
{
- GPUNodeLink *link = GPU_node_link_create(0);
+ GPUNodeLink *link = GPU_node_link_create();
link->oglbuiltin = builtin;
@@ -1235,7 +1443,7 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
va_list params;
int i;
- function = GPU_lookup_function(name);
+ function = gpu_lookup_function(name);
if (!function) {
fprintf(stderr, "GPU failed to find function %s\n", name);
return 0;
@@ -1244,20 +1452,18 @@ bool GPU_link(GPUMaterial *mat, const char *name, ...)
node = GPU_node_begin(name);
va_start(params, name);
- for (i=0; i<function->totparam; i++) {
+ for (i = 0; i<function->totparam; i++) {
if (function->paramqual[i] != FUNCTION_QUAL_IN) {
- linkptr= va_arg(params, GPUNodeLink**);
- GPU_node_output(node, function->paramtype[i], "", linkptr);
+ linkptr = va_arg(params, GPUNodeLink**);
+ gpu_node_output(node, function->paramtype[i], linkptr);
}
else {
- link= va_arg(params, GPUNodeLink*);
+ link = va_arg(params, GPUNodeLink*);
gpu_node_input_link(node, link, function->paramtype[i]);
}
}
va_end(params);
- GPU_node_end(node);
-
gpu_material_add_node(mat, node);
return 1;
@@ -1271,7 +1477,7 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
va_list params;
int i, totin, totout;
- function = GPU_lookup_function(name);
+ function = gpu_lookup_function(name);
if (!function) {
fprintf(stderr, "GPU failed to find function %s\n", name);
return 0;
@@ -1290,24 +1496,24 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
if (out) {
for (i = 0; out[i].type != GPU_NONE; i++) {
- GPU_node_output(node, out[i].type, out[i].name, &out[i].link);
+ gpu_node_output(node, out[i].type, &out[i].link);
totout++;
}
}
va_start(params, out);
- for (i=0; i<function->totparam; i++) {
+ for (i = 0; i<function->totparam; i++) {
if (function->paramqual[i] != FUNCTION_QUAL_IN) {
if (totout == 0) {
- linkptr= va_arg(params, GPUNodeLink**);
- GPU_node_output(node, function->paramtype[i], "", linkptr);
+ linkptr = va_arg(params, GPUNodeLink**);
+ gpu_node_output(node, function->paramtype[i], linkptr);
}
else
totout--;
}
else {
if (totin == 0) {
- link= va_arg(params, GPUNodeLink*);
+ link = va_arg(params, GPUNodeLink*);
if (link->socket)
gpu_node_input_socket(node, link->socket);
else
@@ -1319,8 +1525,6 @@ bool GPU_stack_link(GPUMaterial *mat, const char *name, GPUNodeStack *in, GPUNod
}
va_end(params);
- GPU_node_end(node);
-
gpu_material_add_node(mat, node);
return 1;
@@ -1336,7 +1540,7 @@ int GPU_link_changed(GPUNodeLink *link)
node = link->output->node;
name = node->name;
- if (strcmp(name, "set_value")==0 || strcmp(name, "set_rgb")==0) {
+ if (STREQ(name, "set_value") || STREQ(name, "set_rgb")) {
input = node->inputs.first;
return (input->link != NULL);
}
@@ -1361,8 +1565,8 @@ static void gpu_nodes_tag(GPUNodeLink *link)
if (node->tag)
return;
- node->tag= 1;
- for (input=node->inputs.first; input; input=input->next)
+ node->tag = true;
+ for (input = node->inputs.first; input; input = input->next)
if (input->link)
gpu_nodes_tag(input->link);
}
@@ -1371,31 +1575,35 @@ static void gpu_nodes_prune(ListBase *nodes, GPUNodeLink *outlink)
{
GPUNode *node, *next;
- for (node=nodes->first; node; node=node->next)
- node->tag= 0;
+ for (node = nodes->first; node; node = node->next)
+ node->tag = false;
gpu_nodes_tag(outlink);
- for (node=nodes->first; node; node=next) {
+ for (node = nodes->first; node; node = next) {
next = node->next;
if (!node->tag) {
BLI_remlink(nodes, node);
- GPU_node_free(node);
+ gpu_node_free(node);
}
}
}
-GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttribs *attribs, int *builtins, const char *name)
+GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink,
+ GPUVertexAttribs *attribs, int *builtins,
+ const GPUMatType type, const char *UNUSED(name), const bool use_opensubdiv)
{
GPUShader *shader;
GPUPass *pass;
- char *vertexcode, *fragmentcode;
+ char *vertexcode, *geometrycode, *fragmentcode;
- /*if (!FUNCTION_LIB) {
+#if 0
+ if (!FUNCTION_LIB) {
GPU_nodes_free(nodes);
return NULL;
- }*/
+ }
+#endif
/* prune unused nodes */
gpu_nodes_prune(nodes, outlink);
@@ -1404,9 +1612,19 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
gpu_nodes_get_builtin_flag(nodes, builtins);
/* generate code and compile with opengl */
- fragmentcode = code_generate_fragment(nodes, outlink->output, name);
- vertexcode = code_generate_vertex(nodes);
- shader = GPU_shader_create(vertexcode, fragmentcode, glsl_material_library, NULL);
+ fragmentcode = code_generate_fragment(nodes, outlink->output);
+ vertexcode = code_generate_vertex(nodes, type);
+ geometrycode = code_generate_geometry(nodes, use_opensubdiv);
+ shader = GPU_shader_create_ex(vertexcode,
+ fragmentcode,
+ geometrycode,
+ glsl_material_library,
+ NULL,
+ 0,
+ 0,
+ 0,
+ use_opensubdiv ? GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV
+ : GPU_SHADER_FLAGS_NONE);
/* failed? */
if (!shader) {
@@ -1416,7 +1634,7 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
MEM_freeN(vertexcode);
memset(attribs, 0, sizeof(*attribs));
memset(builtins, 0, sizeof(*builtins));
- GPU_nodes_free(nodes);
+ gpu_nodes_free(nodes);
return NULL;
}
@@ -1426,12 +1644,13 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
pass->output = outlink->output;
pass->shader = shader;
pass->fragmentcode = fragmentcode;
+ pass->geometrycode = geometrycode;
pass->vertexcode = vertexcode;
pass->libcode = glsl_material_library;
/* extract dynamic inputs and throw away nodes */
- GPU_nodes_extract_dynamic_inputs(pass, nodes);
- GPU_nodes_free(nodes);
+ gpu_nodes_extract_dynamic_inputs(pass, nodes);
+ gpu_nodes_free(nodes);
return pass;
}
@@ -1439,11 +1658,12 @@ GPUPass *GPU_generate_pass(ListBase *nodes, GPUNodeLink *outlink, GPUVertexAttri
void GPU_pass_free(GPUPass *pass)
{
GPU_shader_free(pass->shader);
- GPU_inputs_free(&pass->inputs);
+ gpu_inputs_free(&pass->inputs);
if (pass->fragmentcode)
MEM_freeN(pass->fragmentcode);
+ if (pass->geometrycode)
+ MEM_freeN(pass->geometrycode);
if (pass->vertexcode)
MEM_freeN(pass->vertexcode);
MEM_freeN(pass);
}
-
diff --git a/source/blender/gpu/intern/gpu_codegen.h b/source/blender/gpu/intern/gpu_codegen.h
index b6db923e5c2..5aa187014ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.h
+++ b/source/blender/gpu/intern/gpu_codegen.h
@@ -33,34 +33,18 @@
#ifndef __GPU_CODEGEN_H__
#define __GPU_CODEGEN_H__
+#include "DNA_customdata_types.h"
#include "DNA_listBase.h"
#include "GPU_material.h"
-#include "GL/glew.h"
+#include "GPU_glew.h"
struct ListBase;
struct GPUShader;
struct GPUOutput;
struct GPUNode;
struct GPUVertexAttribs;
-struct GPUFrameBuffer;
struct PreviewImage;
-#define MAX_FUNCTION_NAME 64
-#define MAX_PARAMETER 32
-
-#define FUNCTION_QUAL_IN 0
-#define FUNCTION_QUAL_OUT 1
-#define FUNCTION_QUAL_INOUT 2
-
-typedef struct GPUFunction {
- char name[MAX_FUNCTION_NAME];
- int paramtype[MAX_PARAMETER];
- int paramqual[MAX_PARAMETER];
- int totparam;
-} GPUFunction;
-
-GPUFunction *GPU_lookup_function(const char *name);
-
/* Pass Generation
* - Takes a list of nodes and a desired output, and makes a pass. This
* will take ownership of the nodes and free them early if unused or
@@ -76,11 +60,19 @@ typedef enum GPUDataSource {
GPU_SOURCE_ATTRIB
} GPUDataSource;
+typedef enum {
+ GPU_NODE_LINK_IMAGE_NONE = 0,
+ GPU_NODE_LINK_IMAGE_BLENDER = 1,
+ GPU_NODE_LINK_IMAGE_PREVIEW = 2
+} GPUNodeLinkImage;
+
struct GPUNode {
struct GPUNode *next, *prev;
const char *name;
- int tag;
+
+ /* Internal flag to mark nodes during pruning */
+ bool tag;
ListBase inputs;
ListBase outputs;
@@ -89,24 +81,26 @@ struct GPUNode {
struct GPUNodeLink {
GPUNodeStack *socket;
- int attribtype;
+ CustomDataType attribtype;
const char *attribname;
- int image;
- int image_isdata;
+ GPUNodeLinkImage image;
+ bool image_isdata;
- int texture;
+ bool texture;
int texturesize;
void *ptr1, *ptr2;
- int dynamic;
- int dynamictype;
+ bool dynamic;
+ GPUDynamicType dynamictype;
+
+ GPUType type;
- int type;
+ /* Refcount */
int users;
- GPUTexture *dynamictex;
+ struct GPUTexture *dynamictex;
GPUBuiltin builtin;
GPUOpenGLBuiltin oglbuiltin;
@@ -118,9 +112,9 @@ typedef struct GPUOutput {
struct GPUOutput *next, *prev;
GPUNode *node;
- int type; /* data type = length of vector/matrix */
- GPUNodeLink *link; /* output link */
- int id; /* unique id as created by code generator */
+ GPUType type; /* data type = length of vector/matrix */
+ GPUNodeLink *link; /* output link */
+ int id; /* unique id as created by code generator */
} GPUOutput;
typedef struct GPUInput {
@@ -128,35 +122,35 @@ typedef struct GPUInput {
GPUNode *node;
- int type; /* datatype */
- int source; /* data source */
-
- int id; /* unique id as created by code generator */
- int texid; /* number for multitexture */
- int attribid; /* id for vertex attributes */
- int bindtex; /* input is responsible for binding the texture? */
- int definetex; /* input is responsible for defining the pixel? */
- int textarget; /* GL_TEXTURE_* */
- int textype; /* datatype */
-
- struct Image *ima; /* image */
- struct ImageUser *iuser;/* image user */
- struct PreviewImage *prv; /* preview images & icons */
- int image_isdata; /* image does not contain color data */
- float *dynamicvec; /* vector data in case it is dynamic */
- int dynamictype; /* origin of the dynamic uniform (GPUDynamicType) */
- void *dynamicdata; /* data source of the dynamic uniform */
- GPUTexture *tex; /* input texture, only set at runtime */
- int shaderloc; /* id from opengl */
- char shadername[32]; /* name in shader */
-
- float vec[16]; /* vector data */
+ GPUType type; /* datatype */
+ GPUDataSource source; /* data source */
+
+ int id; /* unique id as created by code generator */
+ int texid; /* number for multitexture, starting from zero */
+ int attribid; /* id for vertex attributes */
+ bool bindtex; /* input is responsible for binding the texture? */
+ bool definetex; /* input is responsible for defining the pixel? */
+ int textarget; /* GL texture target, e.g. GL_TEXTURE_2D */
+ GPUType textype; /* datatype */
+
+ struct Image *ima; /* image */
+ struct ImageUser *iuser; /* image user */
+ struct PreviewImage *prv; /* preview images & icons */
+ bool image_isdata; /* image does not contain color data */
+ float *dynamicvec; /* vector data in case it is dynamic */
+ GPUDynamicType dynamictype; /* origin of the dynamic uniform */
+ void *dynamicdata; /* data source of the dynamic uniform */
+ struct GPUTexture *tex; /* input texture, only set at runtime */
+ int shaderloc; /* id from opengl */
+ char shadername[32]; /* name in shader */
+
+ float vec[16]; /* vector data */
GPUNodeLink *link;
- int dynamictex; /* dynamic? */
- int attribtype; /* attribute type */
- char attribname[32]; /* attribute name */
- int attribfirst; /* this is the first one that is bound */
- GPUBuiltin builtin; /* builtin uniform */
+ bool dynamictex; /* dynamic? */
+ CustomDataType attribtype; /* attribute type */
+ char attribname[MAX_CUSTOMDATA_LAYER_NAME]; /* attribute name */
+ int attribfirst; /* this is the first one that is bound */
+ GPUBuiltin builtin; /* builtin uniform */
GPUOpenGLBuiltin oglbuiltin; /* opengl built in varying */
} GPUInput;
@@ -167,6 +161,7 @@ struct GPUPass {
struct GPUOutput *output;
struct GPUShader *shader;
char *fragmentcode;
+ char *geometrycode;
char *vertexcode;
const char *libcode;
};
@@ -175,7 +170,8 @@ struct GPUPass {
typedef struct GPUPass GPUPass;
GPUPass *GPU_generate_pass(ListBase *nodes, struct GPUNodeLink *outlink,
- struct GPUVertexAttribs *attribs, int *builtin, const char *name);
+ struct GPUVertexAttribs *attribs, int *builtin,
+ const GPUMatType type, const char *name, const bool use_opensubdiv);
struct GPUShader *GPU_pass_shader(GPUPass *pass);
@@ -185,8 +181,8 @@ void GPU_pass_unbind(GPUPass *pass);
void GPU_pass_free(GPUPass *pass);
-void GPU_codegen_init(void);
-void GPU_codegen_exit(void);
+void gpu_codegen_init(void);
+void gpu_codegen_exit(void);
/* Material calls */
diff --git a/source/blender/gpu/intern/gpu_compositing.c b/source/blender/gpu/intern/gpu_compositing.c
new file mode 100644
index 00000000000..da5db73d382
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_compositing.c
@@ -0,0 +1,1289 @@
+/*
+ * ***** 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): Antony Riakiotakis.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/gpu/intern/gpu_compositing.c
+ * \ingroup gpu
+ *
+ * System that manages framebuffer compositing.
+ */
+
+#include "BLI_sys_types.h"
+#include "BLI_rect.h"
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_linklist.h"
+
+#include "BLI_rand.h"
+#include "BLI_listbase.h"
+
+#include "DNA_vec_types.h"
+#include "DNA_view3d_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_object_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_gpu_types.h"
+
+#include "GPU_extensions.h"
+#include "GPU_compositing.h"
+
+#include "GPU_glew.h"
+
+#include "MEM_guardedalloc.h"
+
+static const float fullscreencos[4][2] = {{-1.0f, -1.0f}, {1.0f, -1.0f}, {-1.0f, 1.0f}, {1.0f, 1.0f}};
+static const float fullscreenuvs[4][2] = {{0.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 1.0f}, {1.0f, 1.0f}};
+
+struct GPUFX {
+ /* we borrow the term gbuffer from deferred rendering however this is just a regular
+ * depth/color framebuffer. Could be extended later though */
+ GPUFrameBuffer *gbuffer;
+
+ /* dimensions of the gbuffer */
+ int gbuffer_dim[2];
+
+ /* texture bound to the first color attachment of the gbuffer */
+ GPUTexture *color_buffer;
+
+ /* second texture used for ping-pong compositing */
+ GPUTexture *color_buffer_sec;
+ /* texture bound to the depth attachment of the gbuffer */
+ GPUTexture *depth_buffer;
+ GPUTexture *depth_buffer_xray;
+
+ /* texture used for jittering for various effects */
+ GPUTexture *jitter_buffer;
+
+ /* all those buffers below have to coexist. Fortunately they are all quarter sized (1/16th of memory) of original framebuffer */
+ int dof_downsampled_w;
+ int dof_downsampled_h;
+
+ /* texture used for near coc and color blurring calculation */
+ GPUTexture *dof_near_coc_buffer;
+ /* blurred near coc buffer. */
+ GPUTexture *dof_near_coc_blurred_buffer;
+ /* final near coc buffer. */
+ GPUTexture *dof_near_coc_final_buffer;
+
+ /* half size blur buffer */
+ GPUTexture *dof_half_downsampled_near;
+ GPUTexture *dof_half_downsampled_far;
+ /* high quality dof texture downsamplers. 6 levels means 64 pixels wide - should be enough */
+ GPUTexture *dof_nearfar_coc;
+ GPUTexture *dof_near_blur;
+ GPUTexture *dof_far_blur;
+
+ /* for high quality we use again a spiral texture with radius adapted */
+ bool dof_high_quality;
+
+ /* texture used for ssao */
+ int ssao_sample_count_cache;
+ GPUTexture *ssao_spiral_samples_tex;
+
+
+ GPUFXSettings settings;
+
+ /* or-ed flags of enabled effects */
+ int effects;
+
+ /* number of passes, needed to detect if ping pong buffer allocation is needed */
+ int num_passes;
+
+ /* we have a stencil, restore the previous state */
+ bool restore_stencil;
+
+ unsigned int vbuffer;
+};
+
+#if 0
+/* concentric mapping, see "A Low Distortion Map Between Disk and Square" and
+ * http://psgraphics.blogspot.nl/2011/01/improved-code-for-concentric-map.html */
+static GPUTexture * create_concentric_sample_texture(int side)
+{
+ GPUTexture *tex;
+ float midpoint = 0.5f * (side - 1);
+ float *texels = (float *)MEM_mallocN(sizeof(float) * 2 * side * side, "concentric_tex");
+ int i, j;
+
+ for (i = 0; i < side; i++) {
+ for (j = 0; j < side; j++) {
+ int index = (i * side + j) * 2;
+ float a = 1.0f - i / midpoint;
+ float b = 1.0f - j / midpoint;
+ float phi, r;
+ if (a * a > b * b) {
+ r = a;
+ phi = (M_PI_4) * (b / a);
+ }
+ else {
+ r = b;
+ phi = M_PI_2 - (M_PI_4) * (a / b);
+ }
+ texels[index] = r * cos(phi);
+ texels[index + 1] = r * sin(phi);
+ }
+ }
+
+ tex = GPU_texture_create_1D_procedural(side * side, texels, NULL);
+ MEM_freeN(texels);
+ return tex;
+}
+#endif
+
+static GPUTexture *create_spiral_sample_texture(int numsaples)
+{
+ GPUTexture *tex;
+ float (*texels)[2] = MEM_mallocN(sizeof(float[2]) * numsaples, "concentric_tex");
+ const float numsaples_inv = 1.0f / numsaples;
+ int i;
+ /* arbitrary number to ensure we don't get conciding samples every circle */
+ const float spirals = 7.357;
+
+ for (i = 0; i < numsaples; i++) {
+ float r = (i + 0.5f) * numsaples_inv;
+ float phi = r * spirals * (float)(2.0 * M_PI);
+ texels[i][0] = r * cosf(phi);
+ texels[i][1] = r * sinf(phi);
+ }
+
+ tex = GPU_texture_create_1D_procedural(numsaples, (float *)texels, NULL);
+ MEM_freeN(texels);
+ return tex;
+}
+
+/* generate a new FX compositor */
+GPUFX *GPU_fx_compositor_create(void)
+{
+ GPUFX *fx = MEM_callocN(sizeof(GPUFX), "GPUFX compositor");
+
+ if (GLEW_ARB_vertex_buffer_object) {
+ glGenBuffersARB(1, &fx->vbuffer);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, fx->vbuffer);
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, 16 * sizeof(float), NULL, GL_STATIC_DRAW);
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, 8 * sizeof(float), fullscreencos);
+ glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 8 * sizeof(float), 8 * sizeof(float), fullscreenuvs);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+ return fx;
+}
+
+static void cleanup_fx_dof_buffers(GPUFX *fx)
+{
+ if (fx->dof_near_coc_blurred_buffer) {
+ GPU_texture_free(fx->dof_near_coc_blurred_buffer);
+ fx->dof_near_coc_blurred_buffer = NULL;
+ }
+ if (fx->dof_near_coc_buffer) {
+ GPU_texture_free(fx->dof_near_coc_buffer);
+ fx->dof_near_coc_buffer = NULL;
+ }
+ if (fx->dof_near_coc_final_buffer) {
+ GPU_texture_free(fx->dof_near_coc_final_buffer);
+ fx->dof_near_coc_final_buffer = NULL;
+ }
+
+ if (fx->dof_half_downsampled_near) {
+ GPU_texture_free(fx->dof_half_downsampled_near);
+ fx->dof_half_downsampled_near = NULL;
+ }
+ if (fx->dof_half_downsampled_far) {
+ GPU_texture_free(fx->dof_half_downsampled_far);
+ fx->dof_half_downsampled_far = NULL;
+ }
+ if (fx->dof_nearfar_coc) {
+ GPU_texture_free(fx->dof_nearfar_coc);
+ fx->dof_nearfar_coc = NULL;
+ }
+ if (fx->dof_near_blur) {
+ GPU_texture_free(fx->dof_near_blur);
+ fx->dof_near_blur = NULL;
+ }
+ if (fx->dof_far_blur) {
+ GPU_texture_free(fx->dof_far_blur);
+ fx->dof_far_blur = NULL;
+ }
+}
+
+static void cleanup_fx_gl_data(GPUFX *fx, bool do_fbo)
+{
+ if (fx->color_buffer) {
+ GPU_framebuffer_texture_detach(fx->color_buffer);
+ GPU_texture_free(fx->color_buffer);
+ fx->color_buffer = NULL;
+ }
+
+ if (fx->color_buffer_sec) {
+ GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+ GPU_texture_free(fx->color_buffer_sec);
+ fx->color_buffer_sec = NULL;
+ }
+
+ if (fx->depth_buffer) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+ GPU_texture_free(fx->depth_buffer);
+ fx->depth_buffer = NULL;
+ }
+
+ if (fx->depth_buffer_xray) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+ GPU_texture_free(fx->depth_buffer_xray);
+ fx->depth_buffer_xray = NULL;
+ }
+
+ cleanup_fx_dof_buffers(fx);
+
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ fx->ssao_spiral_samples_tex = NULL;
+ }
+
+ if (fx->jitter_buffer && do_fbo) {
+ GPU_texture_free(fx->jitter_buffer);
+ fx->jitter_buffer = NULL;
+ }
+
+ if (fx->gbuffer && do_fbo) {
+ GPU_framebuffer_free(fx->gbuffer);
+ fx->gbuffer = NULL;
+ }
+}
+
+/* destroy a text compositor */
+void GPU_fx_compositor_destroy(GPUFX *fx)
+{
+ cleanup_fx_gl_data(fx, true);
+ if (GLEW_ARB_vertex_buffer_object)
+ glDeleteBuffersARB(1, &fx->vbuffer);
+ MEM_freeN(fx);
+}
+
+static GPUTexture * create_jitter_texture(void)
+{
+ float jitter [64 * 64][2];
+ int i;
+
+ for (i = 0; i < 64 * 64; i++) {
+ jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
+ jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
+ normalize_v2(jitter[i]);
+ }
+
+ return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], true, NULL);
+}
+
+
+bool GPU_fx_compositor_initialize_passes(
+ GPUFX *fx, const rcti *rect, const rcti *scissor_rect,
+ const GPUFXSettings *fx_settings)
+{
+ int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect);
+ char err_out[256];
+ int num_passes = 0;
+ char fx_flag;
+
+ fx->effects = 0;
+
+ if (!GPU_non_power_of_two_support() || !GLEW_EXT_framebuffer_object || !GLEW_ARB_fragment_shader)
+ return false;
+
+ if (!fx_settings) {
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ fx_flag = fx_settings->fx_flag;
+
+ /* disable effects if no options passed for them */
+ if (!fx_settings->dof) {
+ fx_flag &= ~GPU_FX_FLAG_DOF;
+ }
+ if (!fx_settings->ssao || fx_settings->ssao->samples < 1) {
+ fx_flag &= ~GPU_FX_FLAG_SSAO;
+ }
+
+ if (!fx_flag) {
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case
+ * add one to match viewport dimensions */
+ if (scissor_rect) {
+ w++, h++;
+ }
+
+ fx->num_passes = 0;
+ /* dof really needs a ping-pong buffer to work */
+ if (fx_flag & GPU_FX_FLAG_DOF)
+ num_passes++;
+
+ if (fx_flag & GPU_FX_FLAG_SSAO)
+ num_passes++;
+
+ if (!fx->gbuffer) {
+ fx->gbuffer = GPU_framebuffer_create();
+
+ if (!fx->gbuffer) {
+ return false;
+ }
+ }
+
+ /* try creating the jitter texture */
+ if (!fx->jitter_buffer)
+ fx->jitter_buffer = create_jitter_texture();
+
+ /* check if color buffers need recreation */
+ if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) {
+ cleanup_fx_gl_data(fx, false);
+
+ if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ printf(".256%s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+
+ if (fx_flag & GPU_FX_FLAG_SSAO) {
+ if (fx_settings->ssao->samples != fx->ssao_sample_count_cache || !fx->ssao_spiral_samples_tex) {
+ if (fx_settings->ssao->samples < 1)
+ fx_settings->ssao->samples = 1;
+
+ fx->ssao_sample_count_cache = fx_settings->ssao->samples;
+
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ }
+
+ fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
+ }
+ }
+ else {
+ if (fx->ssao_spiral_samples_tex) {
+ GPU_texture_free(fx->ssao_spiral_samples_tex);
+ fx->ssao_spiral_samples_tex = NULL;
+ }
+ }
+
+ /* create textures for dof effect */
+ if (fx_flag & GPU_FX_FLAG_DOF) {
+ bool dof_high_quality = (fx_settings->dof->high_quality != 0) &&
+ GPU_geometry_shader_support() && GPU_instanced_drawing_support();
+
+ /* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
+ if (dof_high_quality != fx->dof_high_quality)
+ cleanup_fx_dof_buffers(fx);
+
+ if (dof_high_quality) {
+ fx->dof_downsampled_w = w / 2;
+ fx->dof_downsampled_h = h / 2;
+
+ if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
+ !fx->dof_far_blur || !fx->dof_half_downsampled_far) {
+
+ if (!(fx->dof_half_downsampled_near = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_half_downsampled_far = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_nearfar_coc = GPU_texture_create_2D_procedural(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+
+ if (!(fx->dof_near_blur = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+
+ if (!(fx->dof_far_blur = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+ else {
+ fx->dof_downsampled_w = w / 4;
+ fx->dof_downsampled_h = h / 4;
+
+ if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {
+
+ if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D(
+ fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out)))
+ {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+
+ fx->dof_high_quality = dof_high_quality;
+ }
+ else {
+ /* cleanup unnecessary buffers */
+ cleanup_fx_dof_buffers(fx);
+ }
+
+ /* we need to pass data between shader stages, allocate an extra color buffer */
+ if (num_passes > 1) {
+ if (!fx->color_buffer_sec) {
+ if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) {
+ printf(".256%s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return false;
+ }
+ }
+ }
+ else {
+ if (fx->color_buffer_sec) {
+ GPU_framebuffer_texture_detach(fx->color_buffer_sec);
+ GPU_texture_free(fx->color_buffer_sec);
+ fx->color_buffer_sec = NULL;
+ }
+ }
+
+ /* bind the buffers */
+
+ /* first depth buffer, because system assumes read/write buffers */
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out))
+ printf("%.256s\n", err_out);
+
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out))
+ printf("%.256s\n", err_out);
+
+ if (!GPU_framebuffer_check_valid(fx->gbuffer, err_out))
+ printf("%.256s\n", err_out);
+
+ GPU_texture_bind_as_framebuffer(fx->color_buffer);
+
+ /* enable scissor test. It's needed to ensure sculpting works correctly */
+ if (scissor_rect) {
+ int w_sc = BLI_rcti_size_x(scissor_rect) + 1;
+ int h_sc = BLI_rcti_size_y(scissor_rect) + 1;
+ glPushAttrib(GL_SCISSOR_BIT);
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin,
+ w_sc, h_sc);
+ fx->restore_stencil = true;
+ }
+ else {
+ fx->restore_stencil = false;
+ }
+
+ fx->effects = fx_flag;
+
+ if (fx_settings)
+ fx->settings = *fx_settings;
+ fx->gbuffer_dim[0] = w;
+ fx->gbuffer_dim[1] = h;
+
+ fx->num_passes = num_passes;
+
+ return true;
+}
+
+static void gpu_fx_bind_render_target(int *passes_left, GPUFX *fx, struct GPUOffScreen *ofs, GPUTexture *target)
+{
+ if ((*passes_left)-- == 1) {
+ GPU_framebuffer_texture_unbind(fx->gbuffer, NULL);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else
+ GPU_framebuffer_restore();
+ }
+ else {
+ /* bind the ping buffer to the color buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, target, 0, NULL);
+ }
+}
+
+void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray)
+{
+ char err_out[256];
+
+ if (do_xray) {
+ if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) {
+ printf("%.256s\n", err_out);
+ cleanup_fx_gl_data(fx, true);
+ return;
+ }
+ }
+ else {
+ if (fx->depth_buffer_xray) {
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+ GPU_texture_free(fx->depth_buffer_xray);
+ fx->depth_buffer_xray = NULL;
+ }
+ return;
+ }
+
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+
+ /* first depth buffer, because system assumes read/write buffers */
+ if (!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out))
+ printf("%.256s\n", err_out);
+}
+
+
+void GPU_fx_compositor_XRay_resolve(GPUFX *fx)
+{
+ GPUShader *depth_resolve_shader;
+ GPU_framebuffer_texture_detach(fx->depth_buffer_xray);
+
+ /* attach regular framebuffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, NULL);
+
+ /* full screen quad where we will always write to depth buffer */
+ glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT);
+ glDepthFunc(GL_ALWAYS);
+ /* disable scissor from sculpt if any */
+ glDisable(GL_SCISSOR_TEST);
+ /* disable writing to color buffer, it's depth only pass */
+ glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ /* set up quad buffer */
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 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) {
+ int depth_uniform;
+
+ depth_uniform = GPU_shader_get_uniform(depth_resolve_shader, "depthbuffer");
+
+ GPU_shader_bind(depth_resolve_shader);
+
+ GPU_texture_bind(fx->depth_buffer_xray, 0);
+ GPU_texture_filter_mode(fx->depth_buffer_xray, false, true);
+ GPU_shader_uniform_texture(depth_resolve_shader, depth_uniform, fx->depth_buffer_xray);
+
+ /* draw */
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* disable bindings */
+ GPU_texture_filter_mode(fx->depth_buffer_xray, true, false);
+ GPU_texture_unbind(fx->depth_buffer_xray);
+
+ GPU_shader_unbind();
+ }
+
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glPopAttrib();
+}
+
+
+bool GPU_fx_do_composite_pass(GPUFX *fx, float projmat[4][4], bool is_persp, struct Scene *scene, struct GPUOffScreen *ofs)
+{
+ GPUTexture *src, *target;
+ int numslots = 0;
+ float invproj[4][4];
+ int i;
+ float dfdyfac[2];
+ /* number of passes left. when there are no more passes, the result is passed to the frambuffer */
+ int passes_left = fx->num_passes;
+ /* view vectors for the corners of the view frustum. Can be used to recreate the world space position easily */
+ float viewvecs[3][4] = {
+ {-1.0f, -1.0f, -1.0f, 1.0f},
+ {1.0f, -1.0f, -1.0f, 1.0f},
+ {-1.0f, 1.0f, -1.0f, 1.0f}
+ };
+
+ if (fx->effects == 0)
+ return false;
+
+ GPU_get_dfdy_factors(dfdyfac);
+ /* first, unbind the render-to-texture framebuffer */
+ GPU_framebuffer_texture_detach(fx->color_buffer);
+ GPU_framebuffer_texture_detach(fx->depth_buffer);
+
+ if (fx->restore_stencil)
+ glPopAttrib();
+
+ src = fx->color_buffer;
+ target = fx->color_buffer_sec;
+
+ /* set up quad buffer */
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 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 */
+ invert_m4_m4(invproj, projmat);
+
+ /* convert the view vectors to view space */
+ for (i = 0; i < 3; i++) {
+ mul_m4_v4(invproj, viewvecs[i]);
+ /* normalized trick see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]);
+ if (is_persp)
+ mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]);
+ viewvecs[i][3] = 1.0;
+ }
+
+ /* we need to store the differences */
+ viewvecs[1][0] -= viewvecs[0][0];
+ viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1];
+
+ /* calculate a depth offset as well */
+ if (!is_persp) {
+ float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f};
+ mul_m4_v4(invproj, vec_far);
+ mul_v3_fl(vec_far, 1.0f / vec_far[3]);
+ 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 */
+ if (fx->effects & GPU_FX_FLAG_SSAO) {
+ GPUShader *ssao_shader;
+ ssao_shader = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_SSAO, is_persp);
+ if (ssao_shader) {
+ const GPUSSAOSettings *fx_ssao = fx->settings.ssao;
+ int color_uniform, depth_uniform;
+ int ssao_uniform, ssao_color_uniform, viewvecs_uniform, ssao_sample_params_uniform;
+ int ssao_jitter_uniform, ssao_concentric_tex;
+ float ssao_params[4] = {fx_ssao->distance_max, fx_ssao->factor, fx_ssao->attenuation, 0.0f};
+ float sample_params[3];
+
+ sample_params[0] = fx->ssao_sample_count_cache;
+ /* multiplier so we tile the random texture on screen */
+ sample_params[1] = fx->gbuffer_dim[0] / 64.0;
+ sample_params[2] = fx->gbuffer_dim[1] / 64.0;
+
+ ssao_params[3] = (passes_left == 1 && !ofs) ? dfdyfac[0] : dfdyfac[1];
+
+ ssao_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_params");
+ ssao_color_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_color");
+ color_uniform = GPU_shader_get_uniform(ssao_shader, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(ssao_shader, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(ssao_shader, "viewvecs");
+ ssao_sample_params_uniform = GPU_shader_get_uniform(ssao_shader, "ssao_sample_params");
+ ssao_concentric_tex = GPU_shader_get_uniform(ssao_shader, "ssao_concentric_tex");
+ ssao_jitter_uniform = GPU_shader_get_uniform(ssao_shader, "jitter_tex");
+
+ GPU_shader_bind(ssao_shader);
+
+ GPU_shader_uniform_vector(ssao_shader, ssao_uniform, 4, 1, ssao_params);
+ GPU_shader_uniform_vector(ssao_shader, ssao_color_uniform, 4, 1, fx_ssao->color);
+ GPU_shader_uniform_vector(ssao_shader, viewvecs_uniform, 4, 3, viewvecs[0]);
+ GPU_shader_uniform_vector(ssao_shader, ssao_sample_params_uniform, 3, 1, sample_params);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, color_uniform, src);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(ssao_shader, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(fx->jitter_buffer, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, ssao_jitter_uniform, fx->jitter_buffer);
+
+ GPU_texture_bind(fx->ssao_spiral_samples_tex, numslots++);
+ GPU_shader_uniform_texture(ssao_shader, ssao_concentric_tex, fx->ssao_spiral_samples_tex);
+
+ /* draw */
+ gpu_fx_bind_render_target(&passes_left, fx, ofs, target);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* disable bindings */
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+ GPU_texture_unbind(fx->jitter_buffer);
+ GPU_texture_unbind(fx->ssao_spiral_samples_tex);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ /* swap here, after src/target have been unbound */
+ SWAP(GPUTexture *, target, src);
+ numslots = 0;
+ }
+ }
+
+ /* second pass, dof */
+ if (fx->effects & GPU_FX_FLAG_DOF) {
+ const GPUDOFSettings *fx_dof = fx->settings.dof;
+ float dof_params[4];
+ float scale = scene->unit.system ? scene->unit.scale_length : 1.0f;
+ /* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
+ * unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
+ * because the shader reads coordinates in world space, which is in blender units. */
+ float scale_camera = 0.001f / scale;
+ /* we want radius here for the aperture number */
+ float aperture = 0.5f * scale_camera * fx_dof->focal_length / fx_dof->fstop;
+
+ dof_params[0] = aperture * fabsf(scale_camera * fx_dof->focal_length / ((fx_dof->focus_distance / scale) - scale_camera * fx_dof->focal_length));
+ dof_params[1] = fx_dof->focus_distance / scale;
+ dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+ dof_params[3] = fx_dof->num_blades;
+
+ if (fx->dof_high_quality) {
+ GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3;
+
+ /* custom shaders close to the effect described in CryEngine 3 Graphics Gems */
+ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE, is_persp);
+ dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO, is_persp);
+ dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE, is_persp);
+
+ /* error occured, restore framebuffers and return */
+ 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();
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ return false;
+ }
+
+ /* pass first, downsample the color buffer to near/far targets and calculate coc texture */
+ {
+ int depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+ int invrendertargetdim_uniform, color_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
+
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass1);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(src, numslots++);
+ /* disable filtering for the texture so custom downsample can do the right thing */
+ GPU_texture_filter_mode(src, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, src);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_near, 0, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_half_downsampled_far, 1, NULL);
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_nearfar_coc, 2, NULL);
+ /* binding takes care of setting the viewport to the downsampled size */
+ GPU_framebuffer_slots_bind(fx->gbuffer, 0);
+
+ GPU_framebuffer_check_valid(fx->gbuffer, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_filter_mode(src, false, true);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_framebuffer_texture_detach(fx->dof_half_downsampled_near);
+ GPU_framebuffer_texture_detach(fx->dof_half_downsampled_far);
+ GPU_framebuffer_texture_detach(fx->dof_nearfar_coc);
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_half_downsampled_near);
+
+ numslots = 0;
+ }
+
+ /* second pass, shoot quads for every pixel in the downsampled buffers, scaling according
+ * to circle of confusion */
+ {
+ int rendertargetdim_uniform, coc_uniform, color_uniform, select_uniform, dof_uniform;
+ int rendertargetdim[2] = {fx->dof_downsampled_w, fx->dof_downsampled_h};
+ float selection[2] = {0.0f, 1.0f};
+
+ rendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "rendertargetdim");
+
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
+ coc_uniform = GPU_shader_get_uniform(dof_shader_pass2, "cocbuffer");
+ select_uniform = GPU_shader_get_uniform(dof_shader_pass2, "layerselection");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+
+ GPU_shader_bind(dof_shader_pass2);
+
+ GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector_int(dof_shader_pass2, rendertargetdim_uniform, 2, 1, rendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+
+ GPU_texture_bind(fx->dof_nearfar_coc, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, 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, color_uniform, fx->dof_half_downsampled_far);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_far, false, false);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_far_blur, 0, NULL);
+ GPU_texture_bind_as_framebuffer(fx->dof_far_blur);
+
+ glDisable(GL_DEPTH_TEST);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE);
+ /* have to clear the buffer unfortunately */
+ 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);
+
+ GPU_texture_unbind(fx->dof_half_downsampled_far);
+ GPU_framebuffer_texture_detach(fx->dof_far_blur);
+
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_half_downsampled_near);
+ GPU_texture_filter_mode(fx->dof_half_downsampled_near, false, false);
+
+ selection[0] = 1.0f;
+ selection[1] = 0.0f;
+
+ GPU_shader_uniform_vector(dof_shader_pass2, select_uniform, 2, 1, selection);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_blur, 0, NULL);
+ /* 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);
+
+ /* disable bindings */
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glDisable(GL_BLEND);
+
+ GPU_framebuffer_texture_detach(fx->dof_near_blur);
+
+ GPU_texture_unbind(fx->dof_half_downsampled_near);
+ GPU_texture_unbind(fx->dof_nearfar_coc);
+
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_far_blur);
+ }
+
+ /* third pass, accumulate the near/far blur fields */
+ {
+ int invrendertargetdim_uniform, near_uniform, color_uniform;
+ int dof_uniform, far_uniform, viewvecs_uniform, depth_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->dof_downsampled_w, 1.0f / fx->dof_downsampled_h};
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass3, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass3, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
+ far_uniform = GPU_shader_get_uniform(dof_shader_pass3, "farbuffer");
+ near_uniform = GPU_shader_get_uniform(dof_shader_pass3, "nearbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass3, "viewvecs");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass3, "depthbuffer");
+
+ GPU_shader_bind(dof_shader_pass3);
+
+ GPU_shader_uniform_vector(dof_shader_pass3, dof_uniform, 4, 1, dof_params);
+
+ GPU_shader_uniform_vector(dof_shader_pass3, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass3, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(fx->dof_near_blur, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_uniform, fx->dof_near_blur);
+ GPU_texture_filter_mode(fx->dof_near_blur, false, true);
+
+ GPU_texture_bind(fx->dof_far_blur, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, far_uniform, fx->dof_far_blur);
+ GPU_texture_filter_mode(fx->dof_far_blur, false, true);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, false);
+ GPU_shader_uniform_texture(dof_shader_pass3, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, color_uniform, src);
+
+ /* 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);
+
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_blur);
+ GPU_texture_unbind(fx->dof_far_blur);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ numslots = 0;
+ }
+ }
+ else {
+ GPUShader *dof_shader_pass1, *dof_shader_pass2, *dof_shader_pass3, *dof_shader_pass4, *dof_shader_pass5;
+
+ /* DOF effect has many passes but most of them are performed on a texture whose dimensions are 4 times less than the original
+ * (16 times lower than original screen resolution). Technique used is not very exact but should be fast enough and is based
+ * on "Practical Post-Process Depth of Field" see http://http.developer.nvidia.com/GPUGems3/gpugems3_ch28.html */
+ dof_shader_pass1 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE, is_persp);
+ dof_shader_pass2 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO, is_persp);
+ dof_shader_pass3 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE, is_persp);
+ dof_shader_pass4 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR, is_persp);
+ dof_shader_pass5 = GPU_shader_get_builtin_fx_shader(GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE, is_persp);
+
+ /* error occured, restore framebuffers and return */
+ 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();
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ return false;
+ }
+
+ /* pass first, first level of blur in low res buffer */
+ {
+ int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+
+ float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass1, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass1, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass1, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass1, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass1, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass1);
+
+ GPU_shader_uniform_vector(dof_shader_pass1, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass1, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass1, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass1, color_uniform, src);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass1, depth_uniform, fx->depth_buffer);
+
+ /* target is the downsampled coc buffer */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+ /* 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);
+ /* disable bindings */
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+ numslots = 0;
+ }
+
+ /* second pass, gaussian blur the downsampled image */
+ {
+ int invrendertargetdim_uniform, color_uniform, depth_uniform, dof_uniform;
+ int viewvecs_uniform;
+ float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+ float tmp = invrendertargetdim[0];
+ invrendertargetdim[0] = 0.0f;
+
+ dof_params[2] = GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer) / (scale_camera * fx_dof->sensor);
+
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass2, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass2, "invrendertargetdim");
+ color_uniform = GPU_shader_get_uniform(dof_shader_pass2, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass2, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass2, "viewvecs");
+
+ /* Blurring vertically */
+ GPU_shader_bind(dof_shader_pass2);
+
+ GPU_shader_uniform_vector(dof_shader_pass2, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass2, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass2, depth_uniform, fx->depth_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_buffer);
+
+ /* use final buffer as a temp here */
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+ /* Drawing quad */
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* *unbind/detach */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+ /* Blurring horizontally */
+ invrendertargetdim[0] = tmp;
+ invrendertargetdim[1] = 0.0f;
+ GPU_shader_uniform_vector(dof_shader_pass2, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass2, color_uniform, fx->dof_near_coc_final_buffer);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_blurred_buffer, 0, NULL);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ /* *unbind/detach */
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_blurred_buffer);
+
+ dof_params[2] = fx->gbuffer_dim[0] / (scale_camera * fx_dof->sensor);
+
+ numslots = 0;
+ }
+
+ /* third pass, calculate near coc */
+ {
+ int near_coc_downsampled, near_coc_blurred;
+
+ near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass3, "colorbuffer");
+ near_coc_blurred = GPU_shader_get_uniform(dof_shader_pass3, "blurredcolorbuffer");
+
+ GPU_shader_bind(dof_shader_pass3);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_coc_downsampled, fx->dof_near_coc_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass3, near_coc_blurred, fx->dof_near_coc_blurred_buffer);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_final_buffer, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+
+ /* unbinding here restores the size to the original */
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_final_buffer);
+
+ numslots = 0;
+ }
+
+ /* fourth pass blur final coc once to eliminate discontinuities */
+ {
+ int near_coc_downsampled;
+ int invrendertargetdim_uniform;
+ float invrendertargetdim[2] = {1.0f / GPU_texture_opengl_width(fx->dof_near_coc_blurred_buffer),
+ 1.0f / GPU_texture_opengl_height(fx->dof_near_coc_blurred_buffer)};
+
+ near_coc_downsampled = GPU_shader_get_uniform(dof_shader_pass4, "colorbuffer");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass4, "invrendertargetdim");
+
+ GPU_shader_bind(dof_shader_pass4);
+
+ GPU_texture_bind(fx->dof_near_coc_final_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass4, near_coc_downsampled, fx->dof_near_coc_final_buffer);
+ GPU_shader_uniform_vector(dof_shader_pass4, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+
+ GPU_framebuffer_texture_attach(fx->gbuffer, fx->dof_near_coc_buffer, 0, NULL);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_final_buffer);
+
+ /* unbinding here restores the size to the original */
+ GPU_framebuffer_texture_unbind(fx->gbuffer, fx->dof_near_coc_buffer);
+ GPU_framebuffer_texture_detach(fx->dof_near_coc_buffer);
+
+ numslots = 0;
+ }
+
+ /* final pass, merge blurred layers according to final calculated coc */
+ {
+ int medium_blurred_uniform, high_blurred_uniform, original_uniform, depth_uniform, dof_uniform;
+ int invrendertargetdim_uniform, viewvecs_uniform;
+ float invrendertargetdim[2] = {1.0f / fx->gbuffer_dim[0], 1.0f / fx->gbuffer_dim[1]};
+
+ medium_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "mblurredcolorbuffer");
+ high_blurred_uniform = GPU_shader_get_uniform(dof_shader_pass5, "blurredcolorbuffer");
+ dof_uniform = GPU_shader_get_uniform(dof_shader_pass5, "dof_params");
+ invrendertargetdim_uniform = GPU_shader_get_uniform(dof_shader_pass5, "invrendertargetdim");
+ original_uniform = GPU_shader_get_uniform(dof_shader_pass5, "colorbuffer");
+ depth_uniform = GPU_shader_get_uniform(dof_shader_pass5, "depthbuffer");
+ viewvecs_uniform = GPU_shader_get_uniform(dof_shader_pass5, "viewvecs");
+
+ GPU_shader_bind(dof_shader_pass5);
+
+ GPU_shader_uniform_vector(dof_shader_pass5, dof_uniform, 4, 1, dof_params);
+ GPU_shader_uniform_vector(dof_shader_pass5, invrendertargetdim_uniform, 2, 1, invrendertargetdim);
+ GPU_shader_uniform_vector(dof_shader_pass5, viewvecs_uniform, 4, 3, viewvecs[0]);
+
+ GPU_texture_bind(src, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, original_uniform, src);
+
+ GPU_texture_bind(fx->dof_near_coc_blurred_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, high_blurred_uniform, fx->dof_near_coc_blurred_buffer);
+
+ GPU_texture_bind(fx->dof_near_coc_buffer, numslots++);
+ GPU_shader_uniform_texture(dof_shader_pass5, medium_blurred_uniform, fx->dof_near_coc_buffer);
+
+ GPU_texture_bind(fx->depth_buffer, numslots++);
+ GPU_texture_filter_mode(fx->depth_buffer, false, true);
+ GPU_shader_uniform_texture(dof_shader_pass5, depth_uniform, fx->depth_buffer);
+
+ /* 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);
+ /* disable bindings */
+ GPU_texture_unbind(fx->dof_near_coc_buffer);
+ GPU_texture_unbind(fx->dof_near_coc_blurred_buffer);
+ GPU_texture_unbind(src);
+ GPU_texture_filter_mode(fx->depth_buffer, true, false);
+ GPU_texture_unbind(fx->depth_buffer);
+
+ /* may not be attached, in that case this just returns */
+ if (target) {
+ GPU_framebuffer_texture_detach(target);
+ if (ofs) {
+ GPU_offscreen_bind(ofs, false);
+ }
+ else {
+ GPU_framebuffer_restore();
+ }
+ }
+
+ SWAP(GPUTexture *, target, src);
+ numslots = 0;
+ }
+ }
+ }
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+ GPU_shader_unbind();
+
+ return true;
+}
+
+void GPU_fx_compositor_init_dof_settings(GPUDOFSettings *fx_dof)
+{
+ fx_dof->fstop = 128.0f;
+ fx_dof->focal_length = 1.0f;
+ fx_dof->focus_distance = 1.0f;
+ fx_dof->sensor = 1.0f;
+ fx_dof->num_blades = 6;
+}
+
+void GPU_fx_compositor_init_ssao_settings(GPUSSAOSettings *fx_ssao)
+{
+ fx_ssao->factor = 1.0f;
+ fx_ssao->distance_max = 0.2f;
+ fx_ssao->attenuation = 1.0f;
+ fx_ssao->samples = 20;
+}
diff --git a/source/blender/gpu/intern/gpu_debug.c b/source/blender/gpu/intern/gpu_debug.c
new file mode 100644
index 00000000000..1c194f517aa
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_debug.c
@@ -0,0 +1,724 @@
+/*
+ * ***** 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, Jason Wilkins.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_debug.c
+ * \ingroup gpu
+ */
+
+#include "BLI_sys_types.h"
+
+#include "BKE_global.h"
+
+#include "GPU_glew.h"
+#include "GPU_debug.h"
+#include "intern/gpu_private.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CASE_CODE_RETURN_STR(code) case code: return #code;
+
+static const char* gpu_gl_error_symbol(GLenum err)
+{
+ switch (err) {
+ CASE_CODE_RETURN_STR(GL_NO_ERROR)
+ CASE_CODE_RETURN_STR(GL_INVALID_ENUM)
+ CASE_CODE_RETURN_STR(GL_INVALID_VALUE)
+ CASE_CODE_RETURN_STR(GL_INVALID_OPERATION)
+ CASE_CODE_RETURN_STR(GL_STACK_OVERFLOW)
+ CASE_CODE_RETURN_STR(GL_STACK_UNDERFLOW)
+ CASE_CODE_RETURN_STR(GL_OUT_OF_MEMORY)
+
+#if GL_ARB_imaging
+ CASE_CODE_RETURN_STR(GL_TABLE_TOO_LARGE)
+#endif
+
+#if defined(WITH_GLU)
+ CASE_CODE_RETURN_STR(GLU_INVALID_ENUM)
+ CASE_CODE_RETURN_STR(GLU_INVALID_VALUE)
+ CASE_CODE_RETURN_STR(GLU_OUT_OF_MEMORY)
+#endif
+
+ default:
+ return "<unknown error>";
+ }
+}
+
+#undef CASE_CODE_RETURN_STR
+
+
+static bool gpu_report_gl_errors(const char *file, int line, const char *str)
+{
+ GLenum gl_error = glGetError();
+
+ if (gl_error == GL_NO_ERROR) {
+ return true;
+ }
+ else {
+ /* glGetError should have cleared the error flag, so if we get the
+ same flag twice that means glGetError itself probably triggered
+ the error. This happens on Windows if the GL context is invalid.
+ */
+ {
+ GLenum new_error = glGetError();
+ if (gl_error == new_error) {
+ fprintf(stderr, "GL: Possible context invalidation issue\n");
+ return false;
+ }
+ }
+
+ fprintf(
+ stderr,
+ "%s(%d): ``%s'' -> GL Error (0x%04X - %s): %s\n",
+ file,
+ line,
+ str,
+ gl_error,
+ gpu_gl_error_symbol(gl_error),
+ gpuErrorString(gl_error));
+
+ return false;
+ }
+}
+
+
+const char* gpuErrorString(GLenum err)
+{
+ switch (err) {
+ case GL_NO_ERROR:
+ return "No Error";
+
+ case GL_INVALID_ENUM:
+ return "Invalid Enumeration";
+
+ case GL_INVALID_VALUE:
+ return "Invalid Value";
+
+ case GL_INVALID_OPERATION:
+ return "Invalid Operation";
+
+ case GL_STACK_OVERFLOW:
+ return "Stack Overflow";
+
+ case GL_STACK_UNDERFLOW:
+ return "Stack Underflow";
+
+ case GL_OUT_OF_MEMORY:
+ return "Out of Memory";
+
+#if GL_ARB_imaging
+ case GL_TABLE_TOO_LARGE:
+ return "Table Too Large";
+#endif
+
+#if defined(WITH_GLU)
+ case GLU_INVALID_ENUM:
+ return "Invalid Enum (GLU)";
+
+ case GLU_INVALID_VALUE:
+ return "Invalid Value (GLU)";
+
+ case GLU_OUT_OF_MEMORY:
+ return "Out of Memory (GLU)";
+#endif
+
+ default:
+ return "<unknown error>";
+ }
+}
+
+
+/* Debug callbacks need the same calling convention as OpenGL functions.
+ */
+#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
+ /* Win32 but not WinCE */
+# define APIENTRY __stdcall
+#else
+# define APIENTRY
+#endif
+
+
+static void APIENTRY gpu_debug_proc(
+ GLenum source, GLenum type, GLuint UNUSED(id),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, const GLvoid *UNUSED(userParm))
+{
+ if (source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) {
+ fprintf(stderr, "GL: %s\n", message);
+ fflush(stderr);
+ }
+ else if (G.debug_value == 20) {
+ fprintf(stderr, "GL: %s\n", message);
+ fflush(stderr);
+ }
+}
+
+
+#ifndef GLEW_ES_ONLY
+static void APIENTRY gpu_debug_proc_amd(
+ GLuint UNUSED(id), GLenum UNUSED(category),
+ GLenum UNUSED(severity), GLsizei UNUSED(length),
+ const GLchar *message, GLvoid *UNUSED(userParm))
+{
+ fprintf(stderr, "GL: %s\n", message);
+}
+#endif
+
+
+#undef APIENTRY
+
+void gpu_debug_init(void)
+{
+ const char success[] = "Successfully hooked OpenGL debug callback.";
+
+#if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY)
+ if (GLEW_VERSION_4_3) {
+ glEnable(GL_DEBUG_OUTPUT);
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+ return;
+ }
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageCallbackARB(gpu_debug_proc, mxGetCurrentContext());
+ glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageCallbackAMD(gpu_debug_proc_amd, mxGetCurrentContext());
+ glDebugMessageEnableAMD(GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
+ GPU_string_marker(sizeof(success), success);
+
+ return;
+ }
+#endif
+
+ fprintf(stderr, "Failed to hook OpenGL debug callback.\n");
+
+ return;
+}
+
+
+void gpu_debug_exit(void)
+{
+#ifndef WITH_GLEW_ES
+#ifndef GLEW_ES_ONLY
+ if (GLEW_VERSION_4_3) {
+ glDebugMessageCallback(NULL, NULL);
+
+ return;
+ }
+#endif
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageCallback(NULL, NULL);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageCallbackARB(NULL, NULL);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageCallbackAMD(NULL, NULL);
+
+ return;
+ }
+#endif
+
+ return;
+}
+
+void GPU_string_marker(size_t length, const char *buf)
+{
+#ifndef WITH_GLEW_ES
+#ifndef GLEW_ES_ONLY
+ if (GLEW_VERSION_4_3) {
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, GL_DEBUG_SEVERITY_NOTIFICATION, length, buf);
+
+ return;
+ }
+#endif
+#endif
+
+ if (GLEW_KHR_debug) {
+#ifndef GLEW_ES_ONLY
+ glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_MARKER, 0, GL_DEBUG_SEVERITY_NOTIFICATION, length, buf);
+#endif
+ return;
+ }
+
+#ifndef GLEW_ES_ONLY
+ if (GLEW_ARB_debug_output) {
+ glDebugMessageInsertARB(GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_OTHER_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, length, buf);
+
+ return;
+ }
+
+ if (GLEW_AMD_debug_output) {
+ glDebugMessageInsertAMD(GL_DEBUG_CATEGORY_APPLICATION_AMD, GL_DEBUG_SEVERITY_LOW_AMD, 0, length, buf);
+
+ return;
+ }
+
+ if (GLEW_GREMEDY_string_marker) {
+ glStringMarkerGREMEDY(length, buf);
+
+ return;
+ }
+#endif
+
+ return;
+}
+
+void GPU_print_error_debug(const char *str)
+{
+ if (G.debug & G_DEBUG)
+ fprintf(stderr, "GPU: %s\n", str);
+}
+
+
+void GPU_assert_no_gl_errors(const char* file, int line, const char* str)
+{
+ if (G.debug) {
+ GLboolean gl_ok = gpu_report_gl_errors(file, line, str);
+
+ BLI_assert(gl_ok);
+ (void) gl_ok;
+ }
+}
+
+
+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)
+{
+ GPU_ASSERT_NO_GL_ERRORS("GPU_state_print"); /* clear any errors */
+
+ 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);
+ 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_MULTISAMPLE_ARB);
+ 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_CUBE_MAP_ARB);
+ 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 7295f0259c5..bf7b8fbc386 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -38,7 +38,8 @@
#include <string.h>
-#include "GL/glew.h"
+#include "GPU_glew.h"
+#include "GPU_debug.h"
#include "BLI_blenlib.h"
#include "BLI_linklist.h"
@@ -55,6 +56,7 @@
#include "DNA_scene_types.h"
#include "DNA_smoke_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_particle_types.h"
#include "MEM_guardedalloc.h"
@@ -69,6 +71,7 @@
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_subsurf.h"
#include "BKE_DerivedMesh.h"
#include "GPU_buffers.h"
@@ -80,6 +83,13 @@
#include "smoke_API.h"
+#ifdef WITH_OPENSUBDIV
+# include "DNA_mesh_types.h"
+# include "BKE_editmesh.h"
+
+# include "gpu_codegen.h"
+#endif
+
extern Material defmaterial; /* from material.c */
/* Text Rendering */
@@ -87,16 +97,22 @@ extern Material defmaterial; /* from material.c */
static void gpu_mcol(unsigned int ucol)
{
/* mcol order is swapped */
- const char *cp= (char *)&ucol;
+ const char *cp = (char *)&ucol;
glColor3ub(cp[3], cp[2], cp[1]);
}
-void GPU_render_text(MTFace *tface, int mode,
- const char *textstr, int textlen, unsigned int *col,
- float *v1, float *v2, float *v3, float *v4, int glattrib)
+void GPU_render_text(
+ MTexPoly *mtexpoly, int mode,
+ const char *textstr, int textlen, unsigned int *col,
+ const float *v_quad[4], const float *uv_quad[4],
+ int glattrib)
{
- if ((mode & GEMAT_TEXT) && (textlen>0) && tface->tpage) {
- Image* ima = (Image *)tface->tpage;
+ if ((mode & GEMAT_TEXT) && (textlen > 0) && mtexpoly->tpage) {
+ const float *v1 = v_quad[0];
+ const float *v2 = v_quad[1];
+ const float *v3 = v_quad[2];
+ const float *v4 = v_quad[3];
+ Image *ima = (Image *)mtexpoly->tpage;
ImBuf *first_ibuf;
const size_t textlen_st = textlen;
size_t index;
@@ -104,7 +120,7 @@ void GPU_render_text(MTFace *tface, int mode,
float advance_tab;
/* multiline */
- float line_start= 0.0f, line_height;
+ float line_start = 0.0f, line_height;
if (v4)
line_height = max_ffff(v1[1], v2[1], v3[1], v4[2]) - min_ffff(v1[1], v2[1], v3[1], v4[2]);
@@ -115,8 +131,8 @@ void GPU_render_text(MTFace *tface, int mode,
/* color has been set */
- if (tface->mode & TF_OBCOL)
- col= NULL;
+ if (mtexpoly->mode & TF_OBCOL)
+ col = NULL;
else if (!col)
glColor3f(1.0f, 1.0f, 1.0f);
@@ -127,23 +143,23 @@ void GPU_render_text(MTFace *tface, int mode,
matrixGlyph(first_ibuf, ' ', &centerx, &centery,
&sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
- advance_tab= advance * 4; /* tab width could also be an option */
+ advance_tab = advance * 4; /* tab width could also be an option */
for (index = 0; index < textlen_st; ) {
unsigned int character;
float uv[4][2];
- // lets calculate offset stuff
+ /* lets calculate offset stuff */
character = BLI_str_utf8_as_unicode_and_size_safe(textstr + index, &index);
- if (character=='\n') {
- glTranslatef(line_start, -line_height, 0.0);
+ if (character == '\n') {
+ glTranslatef(line_start, -line_height, 0.0f);
line_start = 0.0f;
continue;
}
- else if (character=='\t') {
- glTranslatef(advance_tab, 0.0, 0.0);
+ else if (character == '\t') {
+ glTranslatef(advance_tab, 0.0f, 0.0f);
line_start -= advance_tab; /* so we can go back to the start of the line */
continue;
@@ -153,17 +169,17 @@ void GPU_render_text(MTFace *tface, int mode,
character = '?';
}
- // space starts at offset 1
- // character = character - ' ' + 1;
+ /* space starts at offset 1 */
+ /* character = character - ' ' + 1; */
matrixGlyph(first_ibuf, character, & centerx, &centery,
&sizex, &sizey, &transx, &transy, &movex, &movey, &advance);
- uv[0][0] = (tface->uv[0][0] - centerx) * sizex + transx;
- uv[0][1] = (tface->uv[0][1] - centery) * sizey + transy;
- uv[1][0] = (tface->uv[1][0] - centerx) * sizex + transx;
- uv[1][1] = (tface->uv[1][1] - centery) * sizey + transy;
- uv[2][0] = (tface->uv[2][0] - centerx) * sizex + transx;
- uv[2][1] = (tface->uv[2][1] - centery) * sizey + transy;
+ uv[0][0] = (uv_quad[0][0] - centerx) * sizex + transx;
+ uv[0][1] = (uv_quad[0][1] - centery) * sizey + transy;
+ uv[1][0] = (uv_quad[1][0] - centerx) * sizex + transx;
+ uv[1][1] = (uv_quad[1][1] - centery) * sizey + transy;
+ uv[2][0] = (uv_quad[2][0] - centerx) * sizex + transx;
+ uv[2][1] = (uv_quad[2][1] - centery) * sizey + transy;
glBegin(GL_POLYGON);
if (glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[0]);
@@ -182,8 +198,8 @@ void GPU_render_text(MTFace *tface, int mode,
glVertex3f(sizex * v3[0] + movex, sizey * v3[1] + movey, v3[2]);
if (v4) {
- uv[3][0] = (tface->uv[3][0] - centerx) * sizex + transx;
- uv[3][1] = (tface->uv[3][1] - centery) * sizey + transy;
+ uv[3][0] = (uv_quad[3][0] - centerx) * sizex + transx;
+ uv[3][1] = (uv_quad[3][1] - centery) * sizey + transy;
if (glattrib >= 0) glVertexAttrib2fvARB(glattrib, uv[3]);
else glTexCoord2fv(uv[3]);
@@ -192,7 +208,7 @@ void GPU_render_text(MTFace *tface, int mode,
}
glEnd();
- glTranslatef(advance, 0.0, 0.0);
+ glTranslatef(advance, 0.0f, 0.0f);
line_start -= advance; /* so we can go back to the start of the line */
}
glPopMatrix();
@@ -238,14 +254,18 @@ static struct GPUTextureState {
int curtileYRep, tileYRep;
Image *ima, *curima;
- int domipmap, linearmipmap;
- int texpaint; /* store this so that new images created while texture painting won't be set to mipmapped */
+ /* also controls min/mag filtering */
+ bool domipmap;
+ /* only use when 'domipmap' is set */
+ bool linearmipmap;
+ /* store this so that new images created while texture painting won't be set to mipmapped */
+ bool texpaint;
int alphablend;
float anisotropic;
int gpu_mipmap;
- MTFace *lasttface;
-} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.f, 0, NULL};
+ MTexPoly *lasttface;
+} GTS = {0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, 1, 0, 0, -1, 1.0f, 0, NULL};
/* Mipmap settings */
@@ -280,49 +300,53 @@ static void gpu_generate_mipmap(GLenum target)
glDisable(target);
}
-void GPU_set_mipmap(int mipmap)
+void GPU_set_mipmap(bool mipmap)
{
- if (GTS.domipmap != (mipmap != 0)) {
+ if (GTS.domipmap != mipmap) {
GPU_free_images();
- GTS.domipmap = mipmap != 0;
+ GTS.domipmap = mipmap;
}
}
-void GPU_set_linear_mipmap(int linear)
+void GPU_set_linear_mipmap(bool linear)
{
- if (GTS.linearmipmap != (linear != 0)) {
- GPU_free_images();
- GTS.linearmipmap = linear != 0;
+ if (GTS.linearmipmap != linear) {
+ GTS.linearmipmap = linear;
}
}
-int GPU_get_mipmap(void)
+bool GPU_get_mipmap(void)
{
return GTS.domipmap && !GTS.texpaint;
}
-int GPU_get_linear_mipmap(void)
+bool GPU_get_linear_mipmap(void)
{
return GTS.linearmipmap;
}
-static GLenum gpu_get_mipmap_filter(int mag)
+static GLenum gpu_get_mipmap_filter(bool mag)
{
/* linearmipmap is off by default *when mipmapping is off,
* use unfiltered display */
if (mag) {
- if (GTS.linearmipmap || GTS.domipmap)
+ if (GTS.domipmap)
return GL_LINEAR;
else
return GL_NEAREST;
}
else {
- if (GTS.linearmipmap)
- return GL_LINEAR_MIPMAP_LINEAR;
- else if (GTS.domipmap)
- return GL_LINEAR_MIPMAP_NEAREST;
- else
+ if (GTS.domipmap) {
+ if (GTS.linearmipmap) {
+ return GL_LINEAR_MIPMAP_LINEAR;
+ }
+ else {
+ return GL_LINEAR_MIPMAP_NEAREST;
+ }
+ }
+ else {
return GL_NEAREST;
+ }
}
}
@@ -352,41 +376,41 @@ static void gpu_make_repbind(Image *ima)
ImBuf *ibuf;
ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
- if (ibuf==NULL)
+ if (ibuf == NULL)
return;
if (ima->repbind) {
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
MEM_freeN(ima->repbind);
- ima->repbind= NULL;
+ ima->repbind = NULL;
ima->tpageflag &= ~IMA_MIPMAP_COMPLETE;
}
- ima->totbind= ima->xrep*ima->yrep;
+ ima->totbind = ima->xrep*ima->yrep;
if (ima->totbind>1)
- ima->repbind= MEM_callocN(sizeof(int)*ima->totbind, "repbind");
+ ima->repbind = MEM_callocN(sizeof(int) * ima->totbind, "repbind");
BKE_image_release_ibuf(ima, ibuf, NULL);
}
void GPU_clear_tpage(bool force)
{
- if (GTS.lasttface==NULL && !force)
+ if (GTS.lasttface == NULL && !force)
return;
- GTS.lasttface= NULL;
- GTS.curtile= 0;
- GTS.curima= NULL;
- if (GTS.curtilemode!=0) {
+ GTS.lasttface = NULL;
+ GTS.curtile = 0;
+ GTS.curima = NULL;
+ if (GTS.curtilemode != 0) {
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
}
- GTS.curtilemode= 0;
- GTS.curtileXRep=0;
- GTS.curtileYRep=0;
- GTS.alphablend= -1;
+ GTS.curtilemode = 0;
+ GTS.curtileXRep = 0;
+ GTS.curtileYRep = 0;
+ GTS.alphablend = -1;
glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);
@@ -400,15 +424,18 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
if (alphablend == GPU_BLEND_SOLID) {
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
- else if (alphablend==GPU_BLEND_ADD) {
+ else if (alphablend == GPU_BLEND_ADD) {
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDisable(GL_ALPHA_TEST);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
else if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ALPHA_SORT)) {
glEnable(GL_BLEND);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
/* for OpenGL render we use the alpha channel, this makes alpha blend correct */
if (GLEW_VERSION_1_4)
@@ -428,11 +455,17 @@ static void gpu_set_alpha_blend(GPUBlendMode alphablend)
glAlphaFunc(GL_GREATER, U.glalphaclip);
}
}
- else if (alphablend==GPU_BLEND_CLIP) {
- glDisable(GL_BLEND);
+ else if (alphablend == GPU_BLEND_CLIP) {
+ glDisable(GL_BLEND);
+ glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0.5f);
}
+ else if (alphablend == GPU_BLEND_ALPHA_TO_COVERAGE) {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, U.glalphaclip);
+ glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+ }
}
static void gpu_verify_alpha_blend(int alphablend)
@@ -442,7 +475,7 @@ static void gpu_verify_alpha_blend(int alphablend)
return;
gpu_set_alpha_blend(alphablend);
- GTS.alphablend= alphablend;
+ GTS.alphablend = alphablend;
}
static void gpu_verify_reflection(Image *ima)
@@ -466,9 +499,9 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
{
ImBuf *ibuf = NULL;
unsigned int *bind = NULL;
- int rectw, recth, tpx=0, tpy=0, y;
- unsigned int *tilerect= NULL, *rect= NULL;
- float *ftilerect= NULL, *frect = NULL;
+ int rectw, recth, tpx = 0, tpy = 0, y;
+ unsigned int *tilerect = NULL, *rect = NULL;
+ float *ftilerect = NULL, *frect = NULL;
float *srgb_frect = NULL;
short texwindx, texwindy, texwinsx, texwinsy;
/* flag to determine whether high resolution format is used */
@@ -476,15 +509,15 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
/* initialize tile mode and number of repeats */
GTS.ima = ima;
- GTS.tilemode= (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
+ GTS.tilemode = (ima && (ima->tpageflag & (IMA_TILES|IMA_TWINANIM)));
GTS.tileXRep = 0;
GTS.tileYRep = 0;
/* setting current tile according to frame */
if (ima && (ima->tpageflag & IMA_TWINANIM))
- GTS.tile= ima->lastframe;
+ GTS.tile = ima->lastframe;
else
- GTS.tile= tftile;
+ GTS.tile = tftile;
GTS.tile = MAX2(0, GTS.tile);
@@ -502,26 +535,26 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
}
/* if tiling mode or repeat changed, change texture matrix to fit */
- if (GTS.tilemode!=GTS.curtilemode || GTS.curtileXRep!=GTS.tileXRep ||
+ if (GTS.tilemode != GTS.curtilemode || GTS.curtileXRep != GTS.tileXRep ||
GTS.curtileYRep != GTS.tileYRep)
{
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
if (ima && (ima->tpageflag & IMA_TILES))
- glScalef(ima->xrep, ima->yrep, 1.0);
+ glScalef(ima->xrep, ima->yrep, 1.0f);
glMatrixMode(GL_MODELVIEW);
}
/* check if we have a valid image */
- if (ima==NULL || ima->ok==0)
+ if (ima == NULL || ima->ok == 0)
return 0;
/* check if we have a valid image buffer */
- ibuf= BKE_image_acquire_ibuf(ima, iuser, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
- if (ibuf==NULL)
+ if (ibuf == NULL)
return 0;
if (ibuf->rect_float) {
@@ -551,59 +584,58 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
if (GTS.tilemode) {
/* tiled mode */
- if (ima->repbind==NULL) gpu_make_repbind(ima);
- if (GTS.tile>=ima->totbind) GTS.tile= 0;
+ if (ima->repbind == NULL) gpu_make_repbind(ima);
+ if (GTS.tile >= ima->totbind) GTS.tile = 0;
/* this happens when you change repeat buttons */
- if (ima->repbind) bind= &ima->repbind[GTS.tile];
- else bind= &ima->bindcode;
+ if (ima->repbind) bind = &ima->repbind[GTS.tile];
+ else bind = &ima->bindcode;
- if (*bind==0) {
-
- texwindx= ibuf->x/ima->xrep;
- texwindy= ibuf->y/ima->yrep;
+ if (*bind == 0) {
+ texwindx = ibuf->x / ima->xrep;
+ texwindy = ibuf->y / ima->yrep;
- if (GTS.tile>=ima->xrep*ima->yrep)
- GTS.tile= ima->xrep*ima->yrep-1;
+ if (GTS.tile >= ima->xrep * ima->yrep)
+ GTS.tile = ima->xrep * ima->yrep - 1;
- texwinsy= GTS.tile / ima->xrep;
- texwinsx= GTS.tile - texwinsy*ima->xrep;
+ texwinsy = GTS.tile / ima->xrep;
+ texwinsx = GTS.tile - texwinsy * ima->xrep;
- texwinsx*= texwindx;
- texwinsy*= texwindy;
+ texwinsx *= texwindx;
+ texwinsy *= texwindy;
- tpx= texwindx;
- tpy= texwindy;
+ tpx = texwindx;
+ tpy = texwindy;
if (use_high_bit_depth) {
if (do_color_management) {
- srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(float)*4, "floar_buf_col_cor");
+ srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(float) * 4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
IMB_buffer_float_unpremultiply(srgb_frect, ibuf->x, ibuf->y);
/* clamp buffer colors to 1.0 to avoid artifacts due to glu for hdr images */
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
- frect= srgb_frect + texwinsy*ibuf->x + texwinsx;
+ frect = srgb_frect + texwinsy*ibuf->x + texwinsx;
}
else
- frect= ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
+ frect = ibuf->rect_float + texwinsy*ibuf->x + texwinsx;
}
else
- rect= ibuf->rect + texwinsy*ibuf->x + texwinsx;
+ rect = ibuf->rect + texwinsy*ibuf->x + texwinsx;
}
}
else {
/* regular image mode */
bind= &ima->bindcode;
- if (*bind==0) {
- tpx= ibuf->x;
- tpy= ibuf->y;
- rect= ibuf->rect;
+ if (*bind == 0) {
+ tpx = ibuf->x;
+ tpy = ibuf->y;
+ rect = ibuf->rect;
if (use_high_bit_depth) {
if (do_color_management) {
- frect = srgb_frect = MEM_mallocN(ibuf->x*ibuf->y*sizeof(*srgb_frect)*4, "floar_buf_col_cor");
+ frect = srgb_frect = MEM_mallocN(ibuf->x * ibuf->y * sizeof(*srgb_frect) * 4, "floar_buf_col_cor");
IMB_buffer_float_from_float(srgb_frect, ibuf->rect_float,
ibuf->channels, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, true,
ibuf->x, ibuf->y, ibuf->x, ibuf->x);
@@ -612,7 +644,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
IMB_buffer_float_clamp(srgb_frect, ibuf->x, ibuf->y);
}
else
- frect= ibuf->rect_float;
+ frect = ibuf->rect_float;
}
}
}
@@ -632,35 +664,35 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
if (use_high_bit_depth) {
float *frectrow, *ftilerectrow;
- ftilerect= MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
+ ftilerect = MEM_mallocN(rectw*recth*sizeof(*ftilerect), "tilerect");
- for (y=0; y<recth; y++) {
- frectrow= &frect[y*ibuf->x];
- ftilerectrow= &ftilerect[y*rectw];
+ for (y = 0; y < recth; y++) {
+ frectrow = &frect[y * ibuf->x];
+ ftilerectrow = &ftilerect[y * rectw];
- memcpy(ftilerectrow, frectrow, tpx*sizeof(*frectrow));
+ memcpy(ftilerectrow, frectrow, tpx * sizeof(*frectrow));
}
- frect= ftilerect;
+ frect = ftilerect;
}
else {
unsigned int *rectrow, *tilerectrow;
- tilerect= MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
+ tilerect = MEM_mallocN(rectw*recth*sizeof(*tilerect), "tilerect");
- for (y=0; y<recth; y++) {
- rectrow= &rect[y*ibuf->x];
- tilerectrow= &tilerect[y*rectw];
+ for (y = 0; y < recth; y++) {
+ rectrow = &rect[y * ibuf->x];
+ tilerectrow = &tilerect[y * rectw];
- memcpy(tilerectrow, rectrow, tpx*sizeof(*rectrow));
+ memcpy(tilerectrow, rectrow, tpx * sizeof(*rectrow));
}
- rect= tilerect;
+ rect = tilerect;
}
}
#ifdef WITH_DDS
- if (ibuf->ftype & DDS)
+ if (ibuf->ftype == IMB_FTYPE_DDS)
GPU_create_gl_tex_compressed(bind, rect, rectw, recth, mipmap, ima, ibuf);
else
#endif
@@ -688,11 +720,10 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, bool compare, boo
}
/* Image *ima can be NULL */
-void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth,
+void GPU_create_gl_tex(unsigned int *bind, unsigned int *rect, float *frect, int rectw, int recth,
bool mipmap, bool use_high_bit_depth, Image *ima)
{
- unsigned int *scalerect = NULL;
- float *fscalerect = NULL;
+ ImBuf *ibuf = NULL;
int tpx = rectw;
int tpy = recth;
@@ -702,20 +733,20 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
* Then don't bother scaling for hardware that supports NPOT textures! */
if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) ||
is_over_resolution_limit(rectw, recth)) {
- rectw= smaller_power_of_2_limit(rectw);
- recth= smaller_power_of_2_limit(recth);
+ rectw = smaller_power_of_2_limit(rectw);
+ recth = smaller_power_of_2_limit(recth);
if (use_high_bit_depth) {
- fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
- gluScaleImage(GL_RGBA, tpx, tpy, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
+ ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
+ IMB_scaleImBuf(ibuf, rectw, recth);
- frect = fscalerect;
+ frect = ibuf->rect_float;
}
else {
- scalerect= MEM_mallocN(rectw*recth*sizeof(*scalerect), "scalerect");
- gluScaleImage(GL_RGBA, tpx, tpy, GL_UNSIGNED_BYTE, pix, rectw, recth, GL_UNSIGNED_BYTE, scalerect);
+ ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
+ IMB_scaleImBuf(ibuf, rectw, recth);
- pix= scalerect;
+ rect = ibuf->rect;
}
}
@@ -723,45 +754,64 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int
glGenTextures(1, (GLuint *)bind);
glBindTexture(GL_TEXTURE_2D, *bind);
- if (!(GPU_get_mipmap() && mipmap)) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
}
- else {
- if (GTS.gpu_mipmap) {
- if (use_high_bit_depth)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, rectw, recth, 0, GL_RGBA, GL_FLOAT, frect);
- else
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, pix);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
+ if (GPU_get_mipmap() && mipmap) {
+ if (GTS.gpu_mipmap) {
gpu_generate_mipmap(GL_TEXTURE_2D);
}
else {
- if (use_high_bit_depth)
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA16, rectw, recth, GL_RGBA, GL_FLOAT, frect);
- else
- gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, pix);
+ int i;
+
+ if (!ibuf) {
+ if (use_high_bit_depth) {
+ ibuf = IMB_allocFromBuffer(NULL, frect, tpx, tpy);
+ }
+ else {
+ ibuf = IMB_allocFromBuffer(rect, NULL, tpx, tpy);
+ }
+ }
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 1; i < ibuf->miptot; i++) {
+ ImBuf *mip = ibuf->mipmap[i - 1];
+ if (use_high_bit_depth) {
+ if (GLEW_ARB_texture_float)
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16F, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ else
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA16, mip->x, mip->y, 0, GL_RGBA, GL_FLOAT, mip->rect_float);
+ }
+ else {
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
+ }
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
if (ima)
ima->tpageflag |= IMA_MIPMAP_COMPLETE;
}
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
/* set to modulate with vertex color */
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- if (scalerect)
- MEM_freeN(scalerect);
- if (fscalerect)
- MEM_freeN(fscalerect);
+ if (ibuf)
+ IMB_freeImBuf(ibuf);
}
/**
@@ -788,12 +838,12 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
}
if (format == 0) {
- printf("Unable to find a suitable DXT compression, falling back to uncompressed\n");
+ fprintf(stderr, "Unable to find a suitable DXT compression, falling back to uncompressed\n");
return false;
}
if (!is_power_of_2_resolution(width, height)) {
- printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
+ fprintf(stderr, "Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n");
return false;
}
@@ -806,7 +856,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
- for (i=0; i<ibuf->dds_data.nummipmaps && (width||height); ++i) {
+ for (i = 0; i < ibuf->dds_data.nummipmaps && (width||height); ++i) {
if (width == 0)
width = 1;
if (height == 0)
@@ -823,7 +873,7 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf)
}
/* set number of mipmap levels we have, needed in case they don't go down to 1x1 */
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i-1);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, i - 1);
return true;
#else
@@ -864,26 +914,26 @@ static void gpu_verify_repeat(Image *ima)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
-int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
+int GPU_set_tpage(MTexPoly *mtexpoly, int mipmap, int alphablend)
{
Image *ima;
/* check if we need to clear the state */
- if (tface==NULL) {
+ if (mtexpoly == NULL) {
GPU_clear_tpage(false);
return 0;
}
- ima= tface->tpage;
- GTS.lasttface= tface;
+ ima = mtexpoly->tpage;
+ GTS.lasttface = mtexpoly;
gpu_verify_alpha_blend(alphablend);
gpu_verify_reflection(ima);
- if (GPU_verify_image(ima, NULL, tface->tile, 1, mipmap, false)) {
- GTS.curtile= GTS.tile;
- GTS.curima= GTS.ima;
- GTS.curtilemode= GTS.tilemode;
+ if (GPU_verify_image(ima, NULL, mtexpoly->tile, 1, mipmap, false)) {
+ GTS.curtile = GTS.tile;
+ GTS.curima = GTS.ima;
+ GTS.curtilemode = GTS.tilemode;
GTS.curtileXRep = GTS.tileXRep;
GTS.curtileYRep = GTS.tileYRep;
@@ -892,9 +942,9 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
else {
glDisable(GL_TEXTURE_2D);
- GTS.curtile= 0;
- GTS.curima= NULL;
- GTS.curtilemode= 0;
+ GTS.curtile = 0;
+ GTS.curima = NULL;
+ GTS.curtilemode = 0;
GTS.curtileXRep = 0;
GTS.curtileYRep = 0;
@@ -913,9 +963,9 @@ int GPU_set_tpage(MTFace *tface, int mipmap, int alphablend)
* temporary disabling/enabling mipmapping on all images for quick texture
* updates with glTexSubImage2D. images that didn't change don't have to be
* re-uploaded to OpenGL */
-void GPU_paint_set_mipmap(int mipmap)
+void GPU_paint_set_mipmap(bool mipmap)
{
- Image* ima;
+ Image *ima;
if (!GTS.domipmap)
return;
@@ -923,7 +973,7 @@ void GPU_paint_set_mipmap(int mipmap)
GTS.texpaint = !mipmap;
if (mipmap) {
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->bindcode) {
if (ima->tpageflag & IMA_MIPMAP_COMPLETE) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
@@ -939,7 +989,7 @@ void GPU_paint_set_mipmap(int mipmap)
}
else {
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->bindcode) {
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -977,16 +1027,16 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
if (rectw + x > x_limit) rectw--;
if (recth + y > y_limit) recth--;
- /* float rectangles are already continuous in memory so we can use gluScaleImage */
+ /* float rectangles are already continuous in memory so we can use IMB_scaleImBuf */
if (frect) {
- float *fscalerect = MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect");
- gluScaleImage(GL_RGBA, w, h, GL_FLOAT, frect, rectw, recth, GL_FLOAT, fscalerect);
+ ImBuf *ibuf = IMB_allocFromBuffer(NULL, frect, w, h);
+ IMB_scaleImBuf(ibuf, rectw, recth);
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, rectw, recth, GL_RGBA,
- GL_FLOAT, fscalerect);
+ GL_FLOAT, ibuf->rect_float);
- MEM_freeN(fscalerect);
+ IMB_freeImBuf(ibuf);
}
/* byte images are not continuous in memory so do manual interpolation */
else {
@@ -1022,11 +1072,11 @@ static bool GPU_check_scaled_image(ImBuf *ibuf, Image *ima, float *frect, int x,
return false;
}
-void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
+void GPU_paint_update_image(Image *ima, ImageUser *iuser, int x, int y, int w, int h)
{
ImBuf *ibuf;
- ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
if (ima->repbind || (GPU_get_mipmap() && !GTS.gpu_mipmap) || !ima->bindcode || !ibuf ||
(w == 0) || (h == 0))
@@ -1052,8 +1102,7 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h)
}
glBindTexture(GL_TEXTURE_2D, ima->bindcode);
- glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA,
- GL_FLOAT, buffer);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, GL_FLOAT, buffer);
MEM_freeN(buffer);
@@ -1108,16 +1157,16 @@ void GPU_update_images_framechange(void)
{
Image *ima;
- for (ima=G.main->image.first; ima; ima=ima->id.next) {
+ for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep*ima->yrep)
- ima->twend= ima->xrep*ima->yrep-1;
+ if (ima->twend >= ima->xrep * ima->yrep)
+ ima->twend = ima->xrep * ima->yrep - 1;
/* check: is bindcode not in the array? free. (to do) */
ima->lastframe++;
if (ima->lastframe > ima->twend)
- ima->lastframe= ima->twsta;
+ ima->lastframe = ima->twsta;
}
}
}
@@ -1125,33 +1174,33 @@ void GPU_update_images_framechange(void)
int GPU_update_image_time(Image *ima, double time)
{
int inc = 0;
- float diff;
+ float diff;
int newframe;
if (!ima)
return 0;
- if (ima->lastupdate<0)
+ if (ima->lastupdate < 0)
ima->lastupdate = 0;
if (ima->lastupdate > (float)time)
- ima->lastupdate=(float)time;
+ ima->lastupdate = (float)time;
if (ima->tpageflag & IMA_TWINANIM) {
- if (ima->twend >= ima->xrep*ima->yrep) ima->twend= ima->xrep*ima->yrep-1;
+ if (ima->twend >= ima->xrep * ima->yrep) ima->twend = ima->xrep * ima->yrep - 1;
/* check: is the bindcode not in the array? Then free. (still to do) */
diff = (float)((float)time - ima->lastupdate);
- inc = (int)(diff*(float)ima->animspeed);
+ inc = (int)(diff * (float)ima->animspeed);
- ima->lastupdate+=((float)inc/(float)ima->animspeed);
+ ima->lastupdate += ((float)inc / (float)ima->animspeed);
- newframe = ima->lastframe+inc;
+ newframe = ima->lastframe + inc;
if (newframe > (int)ima->twend) {
- if (ima->twend-ima->twsta != 0)
- newframe = (int)ima->twsta-1 + (newframe-ima->twend)%(ima->twend-ima->twsta);
+ if (ima->twend - ima->twsta != 0)
+ newframe = (int)ima->twsta - 1 + (newframe - ima->twend) % (ima->twend - ima->twsta);
else
newframe = ima->twsta;
}
@@ -1188,7 +1237,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
if (!sds->tex && !highres) {
/* rgba texture for color + density */
if (smoke_has_colors(sds->fluid)) {
- float *data = MEM_callocN(sizeof(float)*sds->total_cells*4, "smokeColorTexture");
+ float *data = MEM_callocN(sizeof(float) * sds->total_cells * 4, "smokeColorTexture");
smoke_get_rgba(sds->fluid, data, 0);
sds->tex = GPU_texture_create_3D(sds->res[0], sds->res[1], sds->res[2], 4, data);
MEM_freeN(data);
@@ -1202,7 +1251,7 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
else if (!sds->tex && highres) {
/* rgba texture for color + density */
if (smoke_turbulence_has_colors(sds->wt)) {
- float *data = MEM_callocN(sizeof(float)*smoke_turbulence_get_cells(sds->wt)*4, "smokeColorTexture");
+ float *data = MEM_callocN(sizeof(float) * smoke_turbulence_get_cells(sds->wt) * 4, "smokeColorTexture");
smoke_turbulence_get_rgba(sds->wt, data, 0);
sds->tex = GPU_texture_create_3D(sds->res_wt[0], sds->res_wt[1], sds->res_wt[2], 4, data);
MEM_freeN(data);
@@ -1218,9 +1267,9 @@ void GPU_create_smoke(SmokeModifierData *smd, int highres)
}
#else // WITH_SMOKE
(void)highres;
- smd->domain->tex= NULL;
- smd->domain->tex_flame= NULL;
- smd->domain->tex_shadow= NULL;
+ smd->domain->tex = NULL;
+ smd->domain->tex_flame = NULL;
+ smd->domain->tex_shadow = NULL;
#endif // WITH_SMOKE
}
@@ -1244,7 +1293,7 @@ void GPU_free_unused_buffers(void)
BLI_lock_thread(LOCK_OPENGL);
/* images */
- for (node=image_free_queue; node; node=node->next) {
+ for (node = image_free_queue; node; node = node->next) {
ima = node->link;
/* check in case it was freed in the meantime */
@@ -1271,13 +1320,13 @@ void GPU_free_image(Image *ima)
/* free regular image binding */
if (ima->bindcode) {
glDeleteTextures(1, (GLuint *)&ima->bindcode);
- ima->bindcode= 0;
+ ima->bindcode = 0;
}
/* free glsl image binding */
if (ima->gputexture) {
GPU_texture_free(ima->gputexture);
- ima->gputexture= NULL;
+ ima->gputexture = NULL;
}
/* free repeated image binding */
@@ -1285,7 +1334,7 @@ void GPU_free_image(Image *ima)
glDeleteTextures(ima->totbind, (GLuint *)ima->repbind);
MEM_freeN(ima->repbind);
- ima->repbind= NULL;
+ ima->repbind = NULL;
}
ima->tpageflag &= ~(IMA_MIPMAP_COMPLETE|IMA_GLBIND_IS_DATA);
@@ -1293,20 +1342,20 @@ void GPU_free_image(Image *ima)
void GPU_free_images(void)
{
- Image* ima;
+ Image *ima;
if (G.main)
- for (ima=G.main->image.first; ima; ima=ima->id.next)
+ for (ima = G.main->image.first; ima; ima = ima->id.next)
GPU_free_image(ima);
}
/* same as above but only free animated images */
void GPU_free_images_anim(void)
{
- Image* ima;
+ Image *ima;
if (G.main)
- for (ima=G.main->image.first; ima; ima=ima->id.next)
+ for (ima = G.main->image.first; ima; ima = ima->id.next)
if (BKE_image_is_animated(ima))
GPU_free_image(ima);
}
@@ -1352,7 +1401,7 @@ void GPU_free_images_old(void)
/* OpenGL Materials */
-#define FIXEDMAT 8
+#define FIXEDMAT 8
/* OpenGL state caching for materials */
@@ -1367,15 +1416,21 @@ static struct GPUMaterialState {
GPUMaterialFixed matbuf_fixed[FIXEDMAT];
int totmat;
+ /* set when called inside GPU_begin_object_materials / GPU_end_object_materials
+ * otherwise calling GPU_enable_material returns zero */
+ bool is_enabled;
+
Material **gmatbuf;
Material *gmatbuf_fixed[FIXEDMAT];
Material *gboundmat;
Object *gob;
+ DupliObject *dob;
Scene *gscene;
int glay;
bool gscenelock;
float (*gviewmat)[4];
float (*gviewinv)[4];
+ float (*gviewcamtexcofac);
bool backface_culling;
@@ -1386,30 +1441,50 @@ static struct GPUMaterialState {
int lastmatnr, lastretval;
GPUBlendMode lastalphablend;
+ bool is_opensubdiv;
} GMS = {NULL};
/* fixed function material, alpha handed by caller */
-static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes)
+static void gpu_material_to_fixed(GPUMaterialFixed *smat, const Material *bmat, const int gamma, const Object *ob, const int new_shading_nodes,
+ const bool dimdown)
{
- if (new_shading_nodes || bmat->mode & MA_SHLESS) {
+ if (bmat->mode & MA_SHLESS) {
copy_v3_v3(smat->diff, &bmat->r);
- smat->diff[3]= 1.0;
+ smat->diff[3] = 1.0;
if (gamma)
linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
zero_v4(smat->spec);
- smat->hard= 0;
+ smat->hard = 0;
+ }
+ else if (new_shading_nodes) {
+ copy_v3_v3(smat->diff, &bmat->r);
+ smat->diff[3] = 1.0;
+
+ copy_v3_v3(smat->spec, &bmat->specr);
+ smat->spec[3] = 1.0;
+ smat->hard = CLAMPIS(bmat->har, 0, 128);
+
+ if (dimdown) {
+ mul_v3_fl(smat->diff, 0.8f);
+ mul_v3_fl(smat->spec, 0.5f);
+ }
+
+ if (gamma) {
+ linearrgb_to_srgb_v3_v3(smat->diff, smat->diff);
+ linearrgb_to_srgb_v3_v3(smat->spec, smat->spec);
+ }
}
else {
mul_v3_v3fl(smat->diff, &bmat->r, bmat->ref + bmat->emit);
- smat->diff[3]= 1.0; /* caller may set this to bmat->alpha */
+ smat->diff[3] = 1.0; /* caller may set this to bmat->alpha */
if (bmat->shade_flag & MA_OBCOLOR)
mul_v3_v3(smat->diff, ob->col);
mul_v3_v3fl(smat->spec, &bmat->specr, bmat->spec);
- smat->spec[3]= 1.0; /* always 1 */
+ smat->spec[3] = 1.0; /* always 1 */
smat->hard= CLAMPIS(bmat->har, 0, 128);
if (gamma) {
@@ -1433,15 +1508,51 @@ static Material *gpu_active_node_material(Material *ma)
return ma;
}
+void GPU_begin_dupli_object(DupliObject *dob)
+{
+ GMS.dob = dob;
+}
+
+void GPU_end_dupli_object(void)
+{
+ GMS.dob = NULL;
+}
+
void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, Object *ob, bool glsl, bool *do_alpha_after)
{
Material *ma;
GPUMaterial *gpumat;
GPUBlendMode alphablend;
+ DupliObject *dob;
int a;
const bool gamma = BKE_scene_check_color_management_enabled(scene);
const bool new_shading_nodes = BKE_scene_use_new_shading_nodes(scene);
const bool use_matcap = (v3d->flag2 & V3D_SHOW_SOLID_MATCAP) != 0; /* assumes v3d->defmaterial->preview is set */
+ bool use_opensubdiv = false;
+
+#ifdef WITH_OPENSUBDIV
+ {
+ DerivedMesh *derivedFinal = NULL;
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em != NULL) {
+ derivedFinal = em->derivedFinal;
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
+ }
+ else {
+ derivedFinal = ob->derivedFinal;
+ }
+
+ if (derivedFinal != NULL && derivedFinal->type == DM_TYPE_CCGDM) {
+ CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) derivedFinal;
+ use_opensubdiv = ccgdm->useGpuBackend;
+ }
+ }
+#endif
#ifdef WITH_GAMEENGINE
if (rv3d->rflag & RV3D_IS_GAME_ENGINE) {
@@ -1450,7 +1561,11 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
#endif
/* initialize state */
+ /* DupliObject must be restored */
+ dob = GMS.dob;
memset(&GMS, 0, sizeof(GMS));
+ GMS.is_enabled = true;
+ GMS.dob = dob;
GMS.lastmatnr = -1;
GMS.lastretval = -1;
GMS.lastalphablend = GPU_BLEND_SOLID;
@@ -1460,11 +1575,13 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
GMS.gob = ob;
GMS.gscene = scene;
+ GMS.is_opensubdiv = use_opensubdiv;
GMS.totmat = use_matcap ? 1 : ob->totcol + 1; /* materials start from 1, default material is 0 */
- GMS.glay= (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
+ GMS.glay = (v3d->localvd)? v3d->localvd->lay: v3d->lay; /* keep lamps visible in local view */
GMS.gscenelock = (v3d->scenelock != 0);
- GMS.gviewmat= rv3d->viewmat;
- GMS.gviewinv= rv3d->viewinv;
+ GMS.gviewmat = rv3d->viewmat;
+ GMS.gviewinv = rv3d->viewinv;
+ GMS.gviewcamtexcofac = rv3d->viewcamtexcofac;
/* alpha pass setup. there's various cases to handle here:
* - object transparency on: only solid materials draw in the first pass,
@@ -1477,68 +1594,68 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
*do_alpha_after = false;
if (GMS.totmat > FIXEDMAT) {
- GMS.matbuf= MEM_callocN(sizeof(GPUMaterialFixed)*GMS.totmat, "GMS.matbuf");
- GMS.gmatbuf= MEM_callocN(sizeof(*GMS.gmatbuf)*GMS.totmat, "GMS.matbuf");
- GMS.alphablend= MEM_callocN(sizeof(*GMS.alphablend)*GMS.totmat, "GMS.matbuf");
+ GMS.matbuf = MEM_callocN(sizeof(GPUMaterialFixed) * GMS.totmat, "GMS.matbuf");
+ GMS.gmatbuf = MEM_callocN(sizeof(*GMS.gmatbuf) * GMS.totmat, "GMS.matbuf");
+ GMS.alphablend = MEM_callocN(sizeof(*GMS.alphablend) * GMS.totmat, "GMS.matbuf");
}
else {
- GMS.matbuf= GMS.matbuf_fixed;
- GMS.gmatbuf= GMS.gmatbuf_fixed;
- GMS.alphablend= GMS.alphablend_fixed;
+ GMS.matbuf = GMS.matbuf_fixed;
+ GMS.gmatbuf = GMS.gmatbuf_fixed;
+ GMS.alphablend = GMS.alphablend_fixed;
}
/* viewport material, setup in space_view3d, defaults to matcap using ma->preview now */
if (use_matcap) {
GMS.gmatbuf[0] = v3d->defmaterial;
- GPU_material_matcap(scene, v3d->defmaterial);
+ GPU_material_matcap(scene, v3d->defmaterial, use_opensubdiv);
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
- GMS.alphablend[0]= GPU_BLEND_SOLID;
+ GMS.alphablend[0] = GPU_BLEND_SOLID;
}
else {
/* no materials assigned? */
- if (ob->totcol==0) {
- gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes);
+ if (ob->totcol == 0) {
+ gpu_material_to_fixed(&GMS.matbuf[0], &defmaterial, 0, ob, new_shading_nodes, true);
/* do material 1 too, for displists! */
memcpy(&GMS.matbuf[1], &GMS.matbuf[0], sizeof(GPUMaterialFixed));
if (glsl) {
- GMS.gmatbuf[0]= &defmaterial;
- GPU_material_from_blender(GMS.gscene, &defmaterial);
+ GMS.gmatbuf[0] = &defmaterial;
+ GPU_material_from_blender(GMS.gscene, &defmaterial, GMS.is_opensubdiv);
}
- GMS.alphablend[0]= GPU_BLEND_SOLID;
+ GMS.alphablend[0] = GPU_BLEND_SOLID;
}
/* setup materials */
- for (a=1; a<=ob->totcol; a++) {
+ for (a = 1; a <= ob->totcol; a++) {
/* find a suitable material */
- ma= give_current_material(ob, a);
- if (!glsl && !new_shading_nodes) ma= gpu_active_node_material(ma);
- if (ma==NULL) ma= &defmaterial;
+ ma = give_current_material(ob, a);
+ if (!glsl && !new_shading_nodes) ma = gpu_active_node_material(ma);
+ if (ma == NULL) ma = &defmaterial;
/* create glsl material if requested */
- gpumat = (glsl)? GPU_material_from_blender(GMS.gscene, ma): NULL;
+ gpumat = glsl? GPU_material_from_blender(GMS.gscene, ma, GMS.is_opensubdiv): NULL;
if (gpumat) {
/* do glsl only if creating it succeed, else fallback */
- GMS.gmatbuf[a]= ma;
+ GMS.gmatbuf[a] = ma;
alphablend = GPU_material_alpha_blend(gpumat, ob->col);
}
else {
/* fixed function opengl materials */
- gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes);
+ gpu_material_to_fixed(&GMS.matbuf[a], ma, gamma, ob, new_shading_nodes, false);
if (GMS.use_alpha_pass && ((ma->mode & MA_TRANSP) || (new_shading_nodes && ma->alpha != 1.0f))) {
- GMS.matbuf[a].diff[3]= ma->alpha;
+ GMS.matbuf[a].diff[3] = ma->alpha;
alphablend = (ma->alpha == 1.0f)? GPU_BLEND_SOLID: GPU_BLEND_ALPHA;
}
else {
- GMS.matbuf[a].diff[3]= 1.0f;
+ GMS.matbuf[a].diff[3] = 1.0f;
alphablend = GPU_BLEND_SOLID;
}
}
@@ -1549,14 +1666,44 @@ void GPU_begin_object_materials(View3D *v3d, RegionView3D *rv3d, Scene *scene, O
if (ELEM(alphablend, GPU_BLEND_ALPHA, GPU_BLEND_ADD, GPU_BLEND_ALPHA_SORT))
*do_alpha_after = true;
- GMS.alphablend[a]= alphablend;
+ GMS.alphablend[a] = alphablend;
}
}
-
+
/* let's start with a clean state */
GPU_disable_material();
}
+static int GPU_get_particle_info(GPUParticleInfo *pi)
+{
+ ParticleData *p;
+ DupliObject *dob = GMS.dob;
+ int ind;
+ if (dob->particle_system) {
+ if (dob->persistent_id[0] < dob->particle_system->totpart)
+ ind = dob->persistent_id[0];
+ else {
+ ind = dob->particle_system->child[dob->persistent_id[0] - dob->particle_system->totpart].parent;
+ }
+ if (ind >= 0) {
+ p = &dob->particle_system->particles[ind];
+
+ pi->scalprops[0] = ind;
+ pi->scalprops[1] = GMS.gscene->r.cfra - p->time;
+ pi->scalprops[2] = p->lifetime;
+ pi->scalprops[3] = p->size;
+
+ copy_v3_v3(pi->location, p->state.co);
+ copy_v3_v3(pi->velocity, p->state.vel);
+ copy_v3_v3(pi->angular_velocity, p->state.ave);
+ return 1;
+ }
+ else return 0;
+ }
+ else
+ return 0;
+}
+
int GPU_enable_material(int nr, void *attribs)
{
GPUVertexAttribs *gattribs = attribs;
@@ -1570,10 +1717,10 @@ int GPU_enable_material(int nr, void *attribs)
memset(&GMS, 0, sizeof(GMS));
mul_v3_v3fl(diff, &defmaterial.r, defmaterial.ref + defmaterial.emit);
- diff[3]= 1.0;
+ diff[3] = 1.0;
mul_v3_v3fl(spec, &defmaterial.specr, defmaterial.spec);
- spec[3]= 1.0;
+ spec[3] = 1.0;
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diff);
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);
@@ -1583,21 +1730,21 @@ int GPU_enable_material(int nr, void *attribs)
}
/* prevent index to use un-initialized array items */
- if (nr>=GMS.totmat)
- nr= 0;
+ if (nr >= GMS.totmat)
+ nr = 0;
if (gattribs)
memset(gattribs, 0, sizeof(*gattribs));
/* keep current material */
- if (nr==GMS.lastmatnr)
+ if (nr == GMS.lastmatnr)
return GMS.lastretval;
/* unbind glsl material */
if (GMS.gboundmat) {
if (GMS.is_alpha_pass) glDepthMask(0);
- GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
- GMS.gboundmat= NULL;
+ GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
+ GMS.gboundmat = NULL;
}
/* draw materials with alpha in alpha pass */
@@ -1619,15 +1766,21 @@ int GPU_enable_material(int nr, void *attribs)
if (gattribs && GMS.gmatbuf[nr]) {
/* bind glsl material and get attributes */
Material *mat = GMS.gmatbuf[nr];
+ GPUParticleInfo partile_info;
+
float auto_bump_scale;
- gpumat = GPU_material_from_blender(GMS.gscene, mat);
+ gpumat = GPU_material_from_blender(GMS.gscene, mat, GMS.is_opensubdiv);
GPU_material_vertex_attributes(gpumat, gattribs);
- GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gscenelock);
+
+ if (GMS.dob)
+ GPU_get_particle_info(&partile_info);
+
+ GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv, GMS.gviewcamtexcofac, GMS.gscenelock);
auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale);
- GMS.gboundmat= mat;
+ GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale, &partile_info);
+ GMS.gboundmat = mat;
/* for glsl use alpha blend mode, unless it's set to solid and
* we are already drawing in an alpha pass */
@@ -1644,7 +1797,7 @@ int GPU_enable_material(int nr, void *attribs)
}
if (GMS.use_matcaps)
- glColor3f(1.0, 1.0, 1.0f);
+ glColor3f(1.0f, 1.0f, 1.0f);
}
else {
/* or do fixed function opengl material */
@@ -1676,16 +1829,16 @@ int GPU_get_material_alpha_blend(void)
void GPU_disable_material(void)
{
- GMS.lastmatnr= -1;
- GMS.lastretval= 1;
+ GMS.lastmatnr = -1;
+ GMS.lastretval = 1;
if (GMS.gboundmat) {
if (GMS.backface_culling)
glDisable(GL_CULL_FACE);
if (GMS.is_alpha_pass) glDepthMask(0);
- GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat));
- GMS.gboundmat= NULL;
+ GPU_material_unbind(GPU_material_from_blender(GMS.gscene, GMS.gboundmat, GMS.is_opensubdiv));
+ GMS.gboundmat = NULL;
}
GPU_set_material_alpha_blend(GPU_BLEND_SOLID);
@@ -1711,20 +1864,26 @@ bool GPU_material_use_matcaps_get(void)
return GMS.use_matcaps;
}
+bool GPU_object_materials_check(void)
+{
+ return GMS.is_enabled;
+}
void GPU_end_object_materials(void)
{
GPU_disable_material();
+ GMS.is_enabled = false;
+
if (GMS.matbuf && GMS.matbuf != GMS.matbuf_fixed) {
MEM_freeN(GMS.matbuf);
MEM_freeN(GMS.gmatbuf);
MEM_freeN(GMS.alphablend);
}
- GMS.matbuf= NULL;
- GMS.gmatbuf= NULL;
- GMS.alphablend= NULL;
+ GMS.matbuf = NULL;
+ GMS.gmatbuf = NULL;
+ GMS.alphablend = NULL;
/* resetting the texture matrix after the scaling needed for tiled textures */
if (GTS.tilemode) {
@@ -1742,57 +1901,57 @@ int GPU_default_lights(void)
int a, count = 0;
/* initialize */
- if (U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) {
- U.light[0].flag= 1;
- U.light[0].vec[0]= -0.3; U.light[0].vec[1]= 0.3; U.light[0].vec[2]= 0.9;
- U.light[0].col[0]= 0.8; U.light[0].col[1]= 0.8; U.light[0].col[2]= 0.8;
- U.light[0].spec[0]= 0.5; U.light[0].spec[1]= 0.5; U.light[0].spec[2]= 0.5;
- U.light[0].spec[3]= 1.0;
+ if (U.light[0].flag == 0 && U.light[1].flag == 0 && U.light[2].flag == 0) {
+ U.light[0].flag = 1;
+ U.light[0].vec[0] = -0.3; U.light[0].vec[1] = 0.3; U.light[0].vec[2] = 0.9;
+ U.light[0].col[0] = 0.8; U.light[0].col[1] = 0.8; U.light[0].col[2] = 0.8;
+ U.light[0].spec[0] = 0.5; U.light[0].spec[1] = 0.5; U.light[0].spec[2] = 0.5;
+ U.light[0].spec[3] = 1.0;
- U.light[1].flag= 0;
- U.light[1].vec[0]= 0.5; U.light[1].vec[1]= 0.5; U.light[1].vec[2]= 0.1;
- U.light[1].col[0]= 0.4; U.light[1].col[1]= 0.4; U.light[1].col[2]= 0.8;
- U.light[1].spec[0]= 0.3; U.light[1].spec[1]= 0.3; U.light[1].spec[2]= 0.5;
- U.light[1].spec[3]= 1.0;
+ U.light[1].flag = 0;
+ U.light[1].vec[0] = 0.5; U.light[1].vec[1] = 0.5; U.light[1].vec[2] = 0.1;
+ U.light[1].col[0] = 0.4; U.light[1].col[1] = 0.4; U.light[1].col[2] = 0.8;
+ U.light[1].spec[0] = 0.3; U.light[1].spec[1] = 0.3; U.light[1].spec[2] = 0.5;
+ U.light[1].spec[3] = 1.0;
- U.light[2].flag= 0;
- U.light[2].vec[0]= 0.3; U.light[2].vec[1]= -0.3; U.light[2].vec[2]= -0.2;
- U.light[2].col[0]= 0.8; U.light[2].col[1]= 0.5; U.light[2].col[2]= 0.4;
- U.light[2].spec[0]= 0.5; U.light[2].spec[1]= 0.4; U.light[2].spec[2]= 0.3;
- U.light[2].spec[3]= 1.0;
+ U.light[2].flag = 0;
+ U.light[2].vec[0] = 0.3; U.light[2].vec[1] = -0.3; U.light[2].vec[2] = -0.2;
+ U.light[2].col[0] = 0.8; U.light[2].col[1] = 0.5; U.light[2].col[2] = 0.4;
+ U.light[2].spec[0] = 0.5; U.light[2].spec[1] = 0.4; U.light[2].spec[2] = 0.3;
+ U.light[2].spec[3] = 1.0;
}
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
- for (a=0; a<8; a++) {
- if (a<3) {
+ for (a = 0; a < 8; a++) {
+ if (a < 3) {
if (U.light[a].flag) {
- glEnable(GL_LIGHT0+a);
+ glEnable(GL_LIGHT0 + a);
normalize_v3_v3(position, U.light[a].vec);
- position[3]= 0.0f;
+ position[3] = 0.0f;
- glLightfv(GL_LIGHT0+a, GL_POSITION, position);
- glLightfv(GL_LIGHT0+a, GL_DIFFUSE, U.light[a].col);
- glLightfv(GL_LIGHT0+a, GL_SPECULAR, U.light[a].spec);
+ glLightfv(GL_LIGHT0 + a, GL_POSITION, position);
+ glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, U.light[a].col);
+ glLightfv(GL_LIGHT0 + a, GL_SPECULAR, U.light[a].spec);
count++;
}
else {
- glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHT0 + a);
- glLightfv(GL_LIGHT0+a, GL_POSITION, zero);
- glLightfv(GL_LIGHT0+a, GL_DIFFUSE, zero);
- glLightfv(GL_LIGHT0+a, GL_SPECULAR, zero);
+ glLightfv(GL_LIGHT0 + a, GL_POSITION, zero);
+ glLightfv(GL_LIGHT0 + a, GL_DIFFUSE, zero);
+ glLightfv(GL_LIGHT0 + a, GL_SPECULAR, zero);
}
- // clear stuff from other opengl lamp usage
- glLightf(GL_LIGHT0+a, GL_SPOT_CUTOFF, 180.0);
- glLightf(GL_LIGHT0+a, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0+a, GL_LINEAR_ATTENUATION, 0.0);
+ /* clear stuff from other opengl lamp usage */
+ glLightf(GL_LIGHT0 + a, GL_SPOT_CUTOFF, 180.0);
+ glLightf(GL_LIGHT0 + a, GL_CONSTANT_ATTENUATION, 1.0);
+ glLightf(GL_LIGHT0 + a, GL_LINEAR_ATTENUATION, 0.0);
}
else
- glDisable(GL_LIGHT0+a);
+ glDisable(GL_LIGHT0 + a);
}
glDisable(GL_LIGHTING);
@@ -1810,74 +1969,105 @@ int GPU_scene_object_lights(Scene *scene, Object *ob, int lay, float viewmat[4][
float position[4], direction[4], energy[4];
/* disable all lights */
- for (count=0; count<8; count++)
- glDisable(GL_LIGHT0+count);
+ for (count = 0; count < 8; count++)
+ glDisable(GL_LIGHT0 + count);
- /* view direction for specular is not compute correct by default in
+ /* view direction for specular is not computed correct by default in
* opengl, so we set the settings ourselfs */
- glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (ortho)? GL_FALSE: GL_TRUE);
+ glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, ortho ? GL_FALSE : GL_TRUE);
- count= 0;
-
- for (base=scene->base.first; base; base=base->next) {
- if (base->object->type!=OB_LAMP)
+ count = 0;
+
+ for (base = scene->base.first; base; base = base->next) {
+ if (base->object->type != OB_LAMP)
continue;
if (!(base->lay & lay) || !(base->lay & ob->lay))
continue;
- la= base->object->data;
+ la = base->object->data;
/* setup lamp transform */
glPushMatrix();
glLoadMatrixf((float *)viewmat);
- if (la->type==LA_SUN) {
+ if (la->type == LA_SUN) {
/* sun lamp */
copy_v3_v3(direction, base->object->obmat[2]);
- direction[3]= 0.0;
+ direction[3] = 0.0;
glLightfv(GL_LIGHT0+count, GL_POSITION, direction);
}
else {
/* other lamps with attenuation */
copy_v3_v3(position, base->object->obmat[3]);
- position[3]= 1.0f;
+ position[3] = 1.0f;
glLightfv(GL_LIGHT0+count, GL_POSITION, position);
glLightf(GL_LIGHT0+count, GL_CONSTANT_ATTENUATION, 1.0);
- glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1/la->dist);
- glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2/(la->dist*la->dist));
+ glLightf(GL_LIGHT0+count, GL_LINEAR_ATTENUATION, la->att1 / la->dist);
+ glLightf(GL_LIGHT0+count, GL_QUADRATIC_ATTENUATION, la->att2 / (la->dist * la->dist));
- if (la->type==LA_SPOT) {
+ if (la->type == LA_SPOT) {
/* spot lamp */
negate_v3_v3(direction, base->object->obmat[2]);
- glLightfv(GL_LIGHT0+count, GL_SPOT_DIRECTION, direction);
- glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f));
- glLightf(GL_LIGHT0+count, GL_SPOT_EXPONENT, 128.0f*la->spotblend);
+ glLightfv(GL_LIGHT0 + count, GL_SPOT_DIRECTION, direction);
+ glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, RAD2DEGF(la->spotsize * 0.5f));
+ glLightf(GL_LIGHT0 + count, GL_SPOT_EXPONENT, 128.0f * la->spotblend);
}
else
- glLightf(GL_LIGHT0+count, GL_SPOT_CUTOFF, 180.0);
+ glLightf(GL_LIGHT0 + count, GL_SPOT_CUTOFF, 180.0);
}
/* setup energy */
mul_v3_v3fl(energy, &la->r, la->energy);
- energy[3]= 1.0;
+ energy[3] = 1.0;
- glLightfv(GL_LIGHT0+count, GL_DIFFUSE, energy);
- glLightfv(GL_LIGHT0+count, GL_SPECULAR, energy);
- glEnable(GL_LIGHT0+count);
+ glLightfv(GL_LIGHT0 + count, GL_DIFFUSE, energy);
+ glLightfv(GL_LIGHT0 + count, GL_SPECULAR, energy);
+ glEnable(GL_LIGHT0 + count);
glPopMatrix();
count++;
- if (count==8)
+ if (count == 8)
break;
}
return count;
}
+static void gpu_multisample(bool enable)
+{
+ if (GLEW_VERSION_1_3 || GLEW_ARB_multisample) {
+#ifdef __linux__
+ /* changing multisample from the default (enabled) causes problems on some
+ * systems (NVIDIA/Linux) when the pixel format doesn't have a multisample buffer */
+ bool toggle_ok = true;
+
+ if (GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_UNIX, GPU_DRIVER_ANY)) {
+ int samples = 0;
+ glGetIntegerv(GL_SAMPLES, &samples);
+
+ if (samples == 0)
+ toggle_ok = false;
+ }
+
+ if (toggle_ok) {
+ if (enable)
+ glEnable(GL_MULTISAMPLE);
+ else
+ glDisable(GL_MULTISAMPLE);
+ }
+#else
+ if (enable)
+ glEnable(GL_MULTISAMPLE);
+ else
+ glDisable(GL_MULTISAMPLE);
+#endif
+ }
+}
+
/* Default OpenGL State */
void GPU_state_init(void)
@@ -1886,8 +2076,8 @@ 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 };
int a, x, y;
- GLubyte pat[32*32];
- const GLubyte *patc= pat;
+ GLubyte pat[32 * 32];
+ const GLubyte *patc = pat;
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, mat_ambient);
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat_specular);
@@ -1932,14 +2122,14 @@ void GPU_state_init(void)
glPixelTransferi(GL_DEPTH_SCALE, 1);
glDepthRange(0.0, 1.0);
- a= 0;
- for (x=0; x<32; x++) {
- for (y=0; y<4; y++) {
- if ( (x) & 1) pat[a++]= 0x88;
- else pat[a++]= 0x22;
+ a = 0;
+ for (x = 0; x < 32; x++) {
+ for (y = 0; y < 4; y++) {
+ if (x & 1) pat[a++] = 0x88;
+ else pat[a++] = 0x22;
}
}
-
+
glPolygonStipple(patc);
glMatrixMode(GL_TEXTURE);
@@ -1950,395 +2140,34 @@ void GPU_state_init(void)
glCullFace(GL_BACK);
glDisable(GL_CULL_FACE);
- /* calling this makes drawing very slow when AA is not set up in ghost
- * on Linux/NVIDIA. */
- // glDisable(GL_MULTISAMPLE);
+ gpu_multisample(false);
}
-#ifdef DEBUG
-/* debugging aid */
-static void gpu_state_print_fl_ex(const char *name, GLenum type)
+#ifdef WITH_OPENSUBDIV
+/* Update face-varying variables offset which might be
+ * different from mesh to mesh sharing the same material.
+ */
+void GPU_draw_update_fvar_offset(DerivedMesh *dm)
{
- const unsigned char err_mark[4] = {0xff, 0xff, 0xff, 0xff};
+ int i;
- float value[32];
- int a;
+ /* Sanity check to be sure we only do this for OpenSubdiv draw. */
+ BLI_assert(dm->type == DM_TYPE_CCGDM);
+ BLI_assert(GMS.is_opensubdiv);
- memset(value, 0xff, sizeof(value));
- glGetFloatv(type, value);
+ for (i = 0; i < GMS.totmat; ++i) {
+ Material *material = GMS.gmatbuf[i];
+ GPUMaterial *gpu_material;
- printf("%s: ", name);
- for (a = 0; a < 32; a++) {
- if (memcmp(&value[a], err_mark, sizeof(value[a])) == 0) {
- break;
+ if (material == NULL) {
+ continue;
}
- printf("%.2f ", value[a]);
- }
- printf("\n");
-}
-#define gpu_state_print_fl(val) gpu_state_print_fl_ex(#val, val)
+ gpu_material = GPU_material_from_blender(GMS.gscene,
+ material,
+ GMS.is_opensubdiv);
-void GPU_state_print(void)
-{
- 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);
- 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_MULTISAMPLE_ARB);
- 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_CUBE_MAP_ARB);
- 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);
+ GPU_material_update_fvar_offset(gpu_material, dm);
+ }
}
-
-#undef gpu_state_print_fl
-
#endif
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index 17c495c82d6..e30eeebf934 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -33,8 +33,6 @@
*/
-#include "GL/glew.h"
-
#include "DNA_image_types.h"
#include "MEM_guardedalloc.h"
@@ -42,13 +40,18 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math_base.h"
+#include "BLI_math_vector.h"
#include "BKE_global.h"
+#include "GPU_glew.h"
+#include "GPU_debug.h"
#include "GPU_draw.h"
#include "GPU_extensions.h"
+#include "GPU_compositing.h"
#include "GPU_simple_shader.h"
-#include "gpu_codegen.h"
+
+#include "intern/gpu_private.h"
#include <stdlib.h>
#include <stdio.h>
@@ -58,7 +61,9 @@
# include "BLI_winstuff.h"
#endif
-#define MAX_DEFINE_LENGTH 72
+/* TODO(sergey): Find better default values for this constants. */
+#define MAX_DEFINE_LENGTH 1024
+#define MAX_EXT_DEFINE_LENGTH 1024
/* Extensions support */
@@ -73,14 +78,29 @@
*/
/* Non-generated shaders */
+extern char datatoc_gpu_program_smoke_frag_glsl[];
+extern char datatoc_gpu_program_smoke_color_frag_glsl[];
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_fx_ssao_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_frag_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_vert_glsl[];
+extern char datatoc_gpu_shader_fx_dof_hq_geo_glsl[];
+extern char datatoc_gpu_shader_fx_depth_resolve_glsl[];
+extern char datatoc_gpu_shader_fx_lib_glsl[];
typedef struct GPUShaders {
GPUShader *vsm_store;
GPUShader *sep_gaussian_blur;
+ GPUProgram *smoke;
+ GPUProgram *smoke_colored;
+ /* cache for shader fx. Those can exist in combinations so store them here */
+ GPUShader *fx_shaders[MAX_FX_SHADERS * 2];
} GPUShaders;
static struct GPUGlobal {
@@ -99,19 +119,30 @@ static struct GPUGlobal {
GPUTexture *invalid_tex_1D; /* texture used in place of invalid textures (not loaded correctly, missing) */
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
+ float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers
+ calculate dfdy in shader differently when drawing to an offscreen buffer. First
+ number is factor on screen and second is off-screen */
} GG = {1, 0};
+/* Number of maximum output slots. We support 4 outputs for now (usually we wouldn't need more to preserve fill rate) */
+#define GPU_FB_MAX_SLOTS 4
+
+struct GPUFrameBuffer {
+ GLuint object;
+ GPUTexture *colortex[GPU_FB_MAX_SLOTS];
+ GPUTexture *depthtex;
+};
+
+
/* GPU Types */
-int GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
+bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
{
return (GG.device & device) && (GG.os & os) && (GG.driver & driver);
}
/* GPU Extensions */
-static int gpu_extensions_init = 0;
-
void GPU_extensions_disable(void)
{
GG.extdisabled = 1;
@@ -122,17 +153,15 @@ int GPU_max_texture_size(void)
return GG.maxtexsize;
}
-void GPU_extensions_init(void)
+void GPU_get_dfdy_factors(float fac[2])
{
- GLint r, g, b;
- const char *vendor, *renderer;
-
- /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
- if (gpu_extensions_init) return;
- gpu_extensions_init= 1;
+ copy_v2_v2(fac, GG.dfdyfactors);
+}
- glewInit();
- GPU_codegen_init();
+void gpu_extensions_init(void)
+{
+ GLint r, g, b;
+ const char *vendor, *renderer, *version;
/* glewIsSupported("GL_VERSION_2_0") */
@@ -149,10 +178,11 @@ void GPU_extensions_init(void)
glGetIntegerv(GL_RED_BITS, &r);
glGetIntegerv(GL_GREEN_BITS, &g);
glGetIntegerv(GL_BLUE_BITS, &b);
- GG.colordepth = r+g+b; /* assumes same depth for RGB */
+ GG.colordepth = r + g + b; /* assumes same depth for RGB */
vendor = (const char *)glGetString(GL_VENDOR);
renderer = (const char *)glGetString(GL_RENDERER);
+ version = (const char *)glGetString(GL_VERSION);
if (strstr(vendor, "ATI")) {
GG.device = GPU_DEVICE_ATI;
@@ -229,85 +259,110 @@ void GPU_extensions_init(void)
#endif
+ /* df/dy calculation factors, those are dependent on driver */
+ if ((strstr(vendor, "ATI") && strstr(version, "3.3.10750"))) {
+ GG.dfdyfactors[0] = 1.0;
+ GG.dfdyfactors[1] = -1.0;
+ }
+ else if (GG.device == GPU_DEVICE_INTEL && GG.os == GPU_OS_WIN &&
+ (strstr(version, "4.0.0 - Build 10.18.10.3308") ||
+ strstr(version, "4.0.0 - Build 9.18.10.3186") ||
+ strstr(version, "4.0.0 - Build 9.18.10.3165") ||
+ strstr(version, "3.1.0 - Build 9.17.10.3347") ||
+ strstr(version, "3.1.0 - Build 9.17.10.4101")))
+ {
+ GG.dfdyfactors[0] = -1.0;
+ GG.dfdyfactors[1] = 1.0;
+ }
+ else {
+ GG.dfdyfactors[0] = 1.0;
+ GG.dfdyfactors[1] = 1.0;
+ }
+
+
GPU_invalid_tex_init();
GPU_simple_shaders_init();
}
-void GPU_extensions_exit(void)
+void gpu_extensions_exit(void)
{
- gpu_extensions_init = 0;
- GPU_codegen_exit();
GPU_simple_shaders_exit();
GPU_invalid_tex_free();
}
-int GPU_glsl_support(void)
+bool GPU_glsl_support(void)
{
return !GG.extdisabled && GG.glslsupport;
}
-int GPU_non_power_of_two_support(void)
+bool GPU_non_power_of_two_support(void)
{
if (GG.npotdisabled)
- return 0;
+ return false;
return GLEW_ARB_texture_non_power_of_two;
}
-int GPU_display_list_support(void)
+bool GPU_vertex_buffer_support(void)
+{
+ return GLEW_ARB_vertex_buffer_object || GLEW_VERSION_1_5;
+}
+
+bool GPU_display_list_support(void)
{
return !GG.dlistsdisabled;
}
-int GPU_color_depth(void)
+bool GPU_bicubic_bump_support(void)
{
- return GG.colordepth;
+ return GLEW_ARB_texture_query_lod && GLEW_VERSION_3_0;
}
-int GPU_print_error(const char *str)
+bool GPU_geometry_shader_support(void)
{
- GLenum errCode;
+ return GLEW_EXT_geometry_shader4 || GLEW_VERSION_3_2;
+}
- if (G.debug & G_DEBUG) {
- if ((errCode = glGetError()) != GL_NO_ERROR) {
- fprintf(stderr, "%s opengl error: %s\n", str, gluErrorString(errCode));
- return 1;
- }
- }
+bool GPU_instanced_drawing_support(void)
+{
+ return GLEW_ARB_draw_instanced;
+}
- return 0;
+int GPU_color_depth(void)
+{
+ return GG.colordepth;
}
static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
{
- const char *err= "unknown";
+ const char *err = "unknown";
switch (status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
break;
case GL_INVALID_OPERATION:
- err= "Invalid operation";
+ err = "Invalid operation";
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
- err= "Incomplete attachment";
+ err = "Incomplete attachment";
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
- err= "Unsupported framebuffer format";
+ err = "Unsupported framebuffer format";
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
- err= "Missing attachment";
+ err = "Missing attachment";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
- err= "Attached images must have same dimensions";
+ err = "Attached images must have same dimensions";
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
- err= "Attached images must have same format";
+ err = "Attached images must have same format";
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
- err= "Missing draw buffer";
+ err = "Missing draw buffer";
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
- err= "Missing read buffer";
+ err = "Missing read buffer";
break;
}
@@ -324,28 +379,30 @@ static void GPU_print_framebuffer_error(GLenum status, char err_out[256])
/* GPUTexture */
struct GPUTexture {
- int w, h; /* width/height */
- int number; /* number for multitexture binding */
- int refcount; /* reference count */
- GLenum target; /* GL_TEXTURE_* */
- GLuint bindcode; /* opengl identifier for texture */
- int fromblender; /* we got the texture from Blender */
-
- GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
- int depth; /* is a depth texture? */
+ int w, h; /* width/height */
+ int w_orig, h_orig; /* width/height (before power of 2 is applied) */
+ int number; /* number for multitexture binding */
+ int refcount; /* reference count */
+ GLenum target; /* GL_TEXTURE_* */
+ GLuint bindcode; /* opengl identifier for texture */
+ int fromblender; /* we got the texture from Blender */
+
+ GPUFrameBuffer *fb; /* GPUFramebuffer this texture is attached to */
+ int fb_attachment; /* slot the texture is attached to */
+ int depth; /* is a depth texture? if 3D how deep? */
+ int depth_orig; /* depth (before power of 2 is applied) */
};
-static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
+static unsigned char *GPU_texture_convert_pixels(int length, const float *fpixels)
{
unsigned char *pixels, *p;
- const float *fp;
- int a, len;
+ const float *fp = fpixels;
+ const int len = 4 * length;
+ int a;
- len = 4*length;
- fp = fpixels;
- p = pixels = MEM_callocN(sizeof(unsigned char)*len, "GPUTexturePixels");
+ p = pixels = MEM_callocN(sizeof(unsigned char) * len, "GPUTexturePixels");
- for (a=0; a<len; a++, p++, fp++)
+ for (a = 0; a < len; a++, p++, fp++)
*p = FTOCHAR((*fp));
return pixels;
@@ -353,7 +410,7 @@ static unsigned char *GPU_texture_convert_pixels(int length, float *fpixels)
static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, int w, int h)
{
- void *pixels = MEM_callocN(sizeof(char)*4*w*h, "GPUTextureEmptyPixels");
+ void *pixels = MEM_callocN(sizeof(char) * 4 * w * h, "GPUTextureEmptyPixels");
if (target == GL_TEXTURE_1D)
glTexSubImage1D(target, 0, x, w, format, GL_UNSIGNED_BYTE, pixels);
@@ -363,7 +420,9 @@ static void GPU_glTexSubImageEmpty(GLenum target, GLenum format, int x, int y, i
MEM_freeN(pixels);
}
-static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256])
+static GPUTexture *GPU_texture_create_nD(
+ int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components,
+ char err_out[256])
{
GPUTexture *tex;
GLenum type, format, internalformat;
@@ -373,12 +432,13 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
tex->number = -1;
tex->refcount = 1;
tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D;
- tex->depth = depth;
+ tex->depth = tex->depth_orig = depth;
+ tex->fb_attachment = -1;
glGenTextures(1, &tex->bindcode);
@@ -409,12 +469,45 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
internalformat = GL_DEPTH_COMPONENT;
}
else {
- type = GL_UNSIGNED_BYTE;
- format = GL_RGBA;
- internalformat = GL_RGBA8;
+ type = GL_FLOAT;
+
+ if (components == 4) {
+ format = GL_RGBA;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RGBA8;
+ break;
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RGBA16F;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RGBA32F;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (components == 2) {
+ format = GL_RG;
+ switch (hdr_type) {
+ case GPU_HDR_NONE:
+ internalformat = GL_RG8;
+ break;
+ case GPU_HDR_HALF_FLOAT:
+ internalformat = GL_RG16F;
+ break;
+ case GPU_HDR_FULL_FLOAT:
+ internalformat = GL_RG32F;
+ break;
+ default:
+ break;
+ }
+ }
- if (fpixels)
+ if (fpixels && hdr_type == GPU_HDR_NONE) {
+ type = GL_UNSIGNED_BYTE;
pixels = GPU_texture_convert_pixels(w*h, fpixels);
+ }
}
if (tex->target == GL_TEXTURE_1D) {
@@ -460,15 +553,8 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
if (tex->target != GL_TEXTURE_1D) {
- /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */
- GLenum wrapmode = (depth || tex->h == 1)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER;
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode);
- glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode);
-
-#if 0
- float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
-#endif
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
else
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -477,20 +563,21 @@ static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, in
}
-GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *fpixels)
+GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, const float *fpixels)
{
GPUTexture *tex;
GLenum type, format, internalformat;
void *pixels = NULL;
- float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ int r_width;
+ bool rescale = false;
if (!GLEW_VERSION_1_2)
return NULL;
tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->w = w;
- tex->h = h;
- tex->depth = depth;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
+ tex->depth = tex->depth_orig = depth;
tex->number = -1;
tex->refcount = 1;
tex->target = GL_TEXTURE_3D;
@@ -513,7 +600,7 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *
tex->number = 0;
glBindTexture(tex->target, tex->bindcode);
- GPU_print_error("3D glBindTexture");
+ GPU_ASSERT_NO_GL_ERRORS("3D glBindTexture");
type = GL_FLOAT;
if (channels == 4) {
@@ -525,35 +612,90 @@ GPUTexture *GPU_texture_create_3D(int w, int h, int depth, int channels, float *
internalformat = GL_INTENSITY;
}
- //if (fpixels)
- // pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+ /* 3D textures are quite heavy, test if it's possible to create them first */
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
- glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ while (r_width == 0) {
+ rescale = true;
+ tex->w /= 2;
+ tex->h /= 2;
+ tex->depth /= 2;
+ glTexImage3D(GL_PROXY_TEXTURE_3D, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &r_width);
+ }
+
+ /* really unlikely to happen but keep this just in case */
+ tex->w = max_ii(tex->w, 1);
+ tex->h = max_ii(tex->h, 1);
+ tex->depth = max_ii(tex->depth, 1);
- GPU_print_error("3D glTexImage3D");
+#if 0
+ if (fpixels)
+ pixels = GPU_texture_convert_pixels(w*h*depth, fpixels);
+#endif
- if (fpixels) {
- if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
- /* clear first to avoid unitialized pixels */
- float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
- glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero);
- MEM_freeN(zero);
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexImage3D");
+
+ /* hardcore stuff, 3D texture rescaling - warning, this is gonna hurt your performance a lot, but we need it
+ * for gooseberry */
+ if (rescale && fpixels) {
+ unsigned int i, j, k;
+ unsigned int xf = w / tex->w, yf = h / tex->h, zf = depth / tex->depth;
+ float *tex3d = MEM_mallocN(channels * sizeof(float)*tex->w*tex->h*tex->depth, "tex3d");
+
+ GPU_print_error_debug("You need to scale a 3D texture, feel the pain!");
+
+ for (k = 0; k < tex->depth; k++) {
+ for (j = 0; j < tex->h; j++) {
+ for (i = 0; i < tex->w; i++) {
+ /* obviously doing nearest filtering here, it's going to be slow in any case, let's not make it worse */
+ float xb = i * xf;
+ float yb = j * yf;
+ float zb = k * zf;
+ unsigned int offset = k * (tex->w * tex->h) + i * tex->h + j;
+ unsigned int offset_orig = (zb) * (w * h) + (xb) * h + (yb);
+
+ if (channels == 4) {
+ tex3d[offset * 4] = fpixels[offset_orig * 4];
+ tex3d[offset * 4 + 1] = fpixels[offset_orig * 4 + 1];
+ tex3d[offset * 4 + 2] = fpixels[offset_orig * 4 + 2];
+ tex3d[offset * 4 + 3] = fpixels[offset_orig * 4 + 3];
+ }
+ else
+ tex3d[offset] = fpixels[offset_orig];
+ }
+ }
}
- glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
- GPU_print_error("3D glTexSubImage3D");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, tex3d);
+
+ MEM_freeN(tex3d);
+ }
+ else {
+ if (fpixels) {
+ if (!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) {
+ /* clear first to avoid unitialized pixels */
+ float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero");
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, GL_INTENSITY, GL_FLOAT, zero);
+ glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels);
+ MEM_freeN(zero);
+ }
+ else {
+ glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, fpixels);
+ }
+
+ GPU_ASSERT_NO_GL_ERRORS("3D glTexSubImage3D");
+ }
}
- glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor);
- GPU_print_error("3D GL_TEXTURE_BORDER_COLOR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- GPU_print_error("3D GL_LINEAR");
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
- GPU_print_error("3D GL_CLAMP_TO_BORDER");
if (pixels)
MEM_freeN(pixels);
@@ -590,7 +732,7 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
ima->gputexture= tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_print_error("Blender Texture Not Loaded");
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
}
else {
glBindTexture(GL_TEXTURE_2D, tex->bindcode);
@@ -598,8 +740,8 @@ GPUTexture *GPU_texture_from_blender(Image *ima, ImageUser *iuser, bool is_data,
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_BORDER, &border);
- tex->w = w - border;
- tex->h = h - border;
+ tex->w = tex->w_orig = w - border;
+ tex->h = tex->h_orig = h - border;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -634,18 +776,18 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
tex->refcount = 1;
tex->target = GL_TEXTURE_2D;
- prv->gputexture[0]= tex;
+ prv->gputexture[0] = tex;
if (!glIsTexture(tex->bindcode)) {
- GPU_print_error("Blender Texture Not Loaded");
+ GPU_ASSERT_NO_GL_ERRORS("Blender Texture Not Loaded");
}
else {
glBindTexture(GL_TEXTURE_2D, tex->bindcode);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
- tex->w = w;
- tex->h = h;
+ tex->w = tex->w_orig = w;
+ tex->h = tex->h_orig = h;
}
glBindTexture(GL_TEXTURE_2D, lastbindcode);
@@ -654,9 +796,9 @@ GPUTexture *GPU_texture_from_preview(PreviewImage *prv, int mipmap)
}
-GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_1D(int w, const float *fpixels, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, 1, 1, fpixels, 0, GPU_HDR_NONE, 4, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -664,9 +806,9 @@ GPUTexture *GPU_texture_create_1D(int w, float *fpixels, char err_out[256])
return tex;
}
-GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256])
+GPUTexture *GPU_texture_create_2D(int w, int h, const float *fpixels, GPUHDRType hdr, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, fpixels, 0, hdr, 4, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -676,7 +818,7 @@ GPUTexture *GPU_texture_create_2D(int w, int h, float *fpixels, char err_out[256
GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, NULL, 1, GPU_HDR_NONE, 1, err_out);
if (tex)
GPU_texture_unbind(tex);
@@ -689,13 +831,47 @@ GPUTexture *GPU_texture_create_depth(int w, int h, char err_out[256])
*/
GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
{
- GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, err_out);
+ GPUTexture *tex = GPU_texture_create_nD(size, size, 2, NULL, 0, GPU_HDR_FULL_FLOAT, 2, err_out);
if (tex) {
/* Now we tweak some of the settings */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, size, size, 0, GL_RG, GL_FLOAT, NULL);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_2D_procedural(int w, int h, const float *pixels, bool repeat, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, h, 2, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ if (repeat) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ }
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
+ GPU_texture_unbind(tex);
+ }
+
+ return tex;
+}
+
+GPUTexture *GPU_texture_create_1D_procedural(int w, const float *pixels, char err_out[256])
+{
+ GPUTexture *tex = GPU_texture_create_nD(w, 0, 1, pixels, 0, GPU_HDR_HALF_FLOAT, 2, err_out);
+
+ if (tex) {
+ /* Now we tweak some of the settings */
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
GPU_texture_unbind(tex);
}
@@ -705,9 +881,9 @@ GPUTexture *GPU_texture_create_vsm_shadow_map(int size, char err_out[256])
void GPU_invalid_tex_init(void)
{
- float color[4] = {1.0f, 0.0f, 1.0f, 1.0};
+ const float color[4] = {1.0f, 0.0f, 1.0f, 1.0f};
GG.invalid_tex_1D = GPU_texture_create_1D(1, color, NULL);
- GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, NULL);
+ GG.invalid_tex_2D = GPU_texture_create_2D(1, 1, color, GPU_HDR_NONE, NULL);
GG.invalid_tex_3D = GPU_texture_create_3D(1, 1, 1, 4, color);
}
@@ -728,9 +904,12 @@ void GPU_invalid_tex_bind(int mode)
void GPU_invalid_tex_free(void)
{
- GPU_texture_free(GG.invalid_tex_1D);
- GPU_texture_free(GG.invalid_tex_2D);
- GPU_texture_free(GG.invalid_tex_3D);
+ if (GG.invalid_tex_1D)
+ GPU_texture_free(GG.invalid_tex_1D);
+ if (GG.invalid_tex_2D)
+ GPU_texture_free(GG.invalid_tex_2D);
+ if (GG.invalid_tex_3D)
+ GPU_texture_free(GG.invalid_tex_3D);
}
@@ -739,14 +918,20 @@ void GPU_texture_bind(GPUTexture *tex, int number)
GLenum arbnumber;
if (number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
- if (number == -1)
+ if ((G.debug & G_DEBUG)) {
+ if (tex->fb && tex->fb->object == GG.currentfb) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to bind texture attached to current framebuffer!\n");
+ }
+ }
+
+ if (number < 0)
return;
- GPU_print_error("Pre Texture Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Bind");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + number);
if (number != 0) glActiveTextureARB(arbnumber);
@@ -760,7 +945,7 @@ void GPU_texture_bind(GPUTexture *tex, int number)
tex->number = number;
- GPU_print_error("Post Texture Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Bind");
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -768,14 +953,14 @@ void GPU_texture_unbind(GPUTexture *tex)
GLenum arbnumber;
if (tex->number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
if (tex->number == -1)
return;
- GPU_print_error("Pre Texture Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
if (tex->number != 0) glActiveTextureARB(arbnumber);
@@ -785,7 +970,44 @@ void GPU_texture_unbind(GPUTexture *tex)
tex->number = -1;
- GPU_print_error("Post Texture Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
+}
+
+void GPU_texture_filter_mode(GPUTexture *tex, bool compare, bool use_filter)
+{
+ GLenum arbnumber;
+
+ if (tex->number >= GG.maxtextures) {
+ fprintf(stderr, "Not enough texture slots.");
+ return;
+ }
+
+ if (tex->number == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Texture Unbind");
+
+ arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
+ if (tex->number != 0) glActiveTextureARB(arbnumber);
+
+ if (tex->depth) {
+ if (compare)
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
+ else
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
+ }
+
+ if (use_filter) {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ }
+ else {
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
+ if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Texture Unbind");
}
void GPU_texture_free(GPUTexture *tex)
@@ -797,7 +1019,7 @@ void GPU_texture_free(GPUTexture *tex)
if (tex->refcount == 0) {
if (tex->fb)
- GPU_framebuffer_texture_detach(tex->fb, tex);
+ GPU_framebuffer_texture_detach(tex);
if (tex->bindcode && !tex->fromblender)
glDeleteTextures(1, &tex->bindcode);
@@ -810,22 +1032,22 @@ void GPU_texture_ref(GPUTexture *tex)
tex->refcount++;
}
-int GPU_texture_target(GPUTexture *tex)
+int GPU_texture_target(const GPUTexture *tex)
{
return tex->target;
}
-int GPU_texture_opengl_width(GPUTexture *tex)
+int GPU_texture_opengl_width(const GPUTexture *tex)
{
return tex->w;
}
-int GPU_texture_opengl_height(GPUTexture *tex)
+int GPU_texture_opengl_height(const GPUTexture *tex)
{
return tex->h;
}
-int GPU_texture_opengl_bindcode(GPUTexture *tex)
+int GPU_texture_opengl_bindcode(const GPUTexture *tex)
{
return tex->bindcode;
}
@@ -837,12 +1059,6 @@ GPUFrameBuffer *GPU_texture_framebuffer(GPUTexture *tex)
/* GPUFrameBuffer */
-struct GPUFrameBuffer {
- GLuint object;
- GPUTexture *colortex;
- GPUTexture *depthtex;
-};
-
GPUFrameBuffer *GPU_framebuffer_create(void)
{
GPUFrameBuffer *fb;
@@ -850,7 +1066,7 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
if (!GLEW_EXT_framebuffer_object)
return NULL;
- fb= MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
+ fb = MEM_callocN(sizeof(GPUFrameBuffer), "GPUFrameBuffer");
glGenFramebuffersEXT(1, &fb->object);
if (!fb->object) {
@@ -860,19 +1076,35 @@ GPUFrameBuffer *GPU_framebuffer_create(void)
return NULL;
}
+ /* make sure no read buffer is enabled, so completeness check will not fail. We set those at binding time */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
return fb;
}
-int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err_out[256])
+int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, int slot, char err_out[256])
{
- GLenum status;
GLenum attachment;
GLenum error;
+ if (slot >= GPU_FB_MAX_SLOTS) {
+ fprintf(stderr, "Attaching to index %d framebuffer slot unsupported in blender use at most %d\n", slot, GPU_FB_MAX_SLOTS);
+ return 0;
+ }
+
+ if ((G.debug & G_DEBUG)) {
+ if (tex->number != -1) {
+ fprintf(stderr, "Feedback loop warning!: Attempting to attach texture to framebuffer while still bound to texture unit for drawing!");
+ }
+ }
+
if (tex->depth)
attachment = GL_DEPTH_ATTACHMENT_EXT;
else
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + slot;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = fb->object;
@@ -891,42 +1123,29 @@ int GPU_framebuffer_texture_attach(GPUFrameBuffer *fb, GPUTexture *tex, char err
return 0;
}
- if (tex->depth) {
- glDrawBuffer(GL_NONE);
- glReadBuffer(GL_NONE);
- }
- else {
- glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
- glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
- }
-
- status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- GPU_framebuffer_restore();
- GPU_print_framebuffer_error(status, err_out);
- return 0;
- }
-
if (tex->depth)
fb->depthtex = tex;
else
- fb->colortex = tex;
+ fb->colortex[slot] = tex;
tex->fb= fb;
+ tex->fb_attachment = slot;
return 1;
}
-void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
+void GPU_framebuffer_texture_detach(GPUTexture *tex)
{
GLenum attachment;
+ GPUFrameBuffer *fb;
if (!tex->fb)
return;
- if (GG.currentfb != tex->fb->object) {
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ fb = tex->fb;
+
+ if (GG.currentfb != fb->object) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
GG.currentfb = tex->fb->object;
}
@@ -935,18 +1154,24 @@ void GPU_framebuffer_texture_detach(GPUFrameBuffer *fb, GPUTexture *tex)
attachment = GL_DEPTH_ATTACHMENT_EXT;
}
else {
- fb->colortex = NULL;
- attachment = GL_COLOR_ATTACHMENT0_EXT;
+ BLI_assert(fb->colortex[tex->fb_attachment] == tex);
+ fb->colortex[tex->fb_attachment] = NULL;
+ attachment = GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment;
}
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
- tex->target, 0, 0);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment, tex->target, 0, 0);
tex->fb = NULL;
+ tex->fb_attachment = -1;
}
-void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, int w, int h)
+void GPU_texture_bind_as_framebuffer(GPUTexture *tex)
{
+ if (!tex->fb) {
+ fprintf(stderr, "Error, texture not bound to framebuffer!");
+ return;
+ }
+
/* push attributes */
glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
glDisable(GL_SCISSOR_TEST);
@@ -954,8 +1179,18 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
/* bind framebuffer */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tex->fb->object);
+ if (tex->depth) {
+ glDrawBuffer(GL_NONE);
+ glReadBuffer(GL_NONE);
+ }
+ else {
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + tex->fb_attachment);
+ }
+
/* push matrices and set default viewport and matrix */
- glViewport(0, 0, w, h);
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
GG.currentfb = tex->fb->object;
glMatrixMode(GL_PROJECTION);
@@ -964,6 +1199,45 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i
glPushMatrix();
}
+void GPU_framebuffer_slots_bind(GPUFrameBuffer *fb, int slot)
+{
+ int numslots = 0, i;
+ GLenum attachments[4];
+
+ if (!fb->colortex[slot]) {
+ fprintf(stderr, "Error, framebuffer slot empty!");
+ return;
+ }
+
+ for (i = 0; i < 4; i++) {
+ if (fb->colortex[i]) {
+ attachments[numslots] = GL_COLOR_ATTACHMENT0_EXT + i;
+ numslots++;
+ }
+ }
+
+ /* push attributes */
+ glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT);
+ glDisable(GL_SCISSOR_TEST);
+
+ /* bind framebuffer */
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffers(numslots, attachments);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
+ GG.currentfb = fb->object;
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+}
+
+
void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex))
{
/* restore matrix */
@@ -974,15 +1248,53 @@ void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUS
/* restore attributes */
glPopAttrib();
- glEnable(GL_SCISSOR_TEST);
+}
+
+void GPU_framebuffer_bind_no_save(GPUFrameBuffer *fb, int slot)
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ /* last bound prevails here, better allow explicit control here too */
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + slot);
+
+ /* push matrices and set default viewport and matrix */
+ glViewport(0, 0, fb->colortex[slot]->w_orig, fb->colortex[slot]->h_orig);
+ GG.currentfb = fb->object;
+ GG.currentfb = fb->object;
+}
+
+bool GPU_framebuffer_check_valid(GPUFrameBuffer *fb, char err_out[256])
+{
+ GLenum status;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
+ GG.currentfb = fb->object;
+
+ /* Clean glError buffer. */
+ while (glGetError() != GL_NO_ERROR) {}
+
+ status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ GPU_framebuffer_restore();
+ GPU_print_framebuffer_error(status, err_out);
+ return false;
+ }
+
+ return true;
}
void GPU_framebuffer_free(GPUFrameBuffer *fb)
{
+ int i;
if (fb->depthtex)
- GPU_framebuffer_texture_detach(fb, fb->depthtex);
- if (fb->colortex)
- GPU_framebuffer_texture_detach(fb, fb->colortex);
+ GPU_framebuffer_texture_detach(fb->depthtex);
+
+ for (i = 0; i < GPU_FB_MAX_SLOTS; i++) {
+ if (fb->colortex[i]) {
+ GPU_framebuffer_texture_detach(fb->colortex[i]);
+ }
+ }
if (fb->object) {
glDeleteFramebuffersEXT(1, &fb->object);
@@ -1006,8 +1318,8 @@ void GPU_framebuffer_restore(void)
void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *blurfb, GPUTexture *blurtex)
{
- float scaleh[2] = {1.0f/GPU_texture_opengl_width(blurtex), 0.0f};
- float scalev[2] = {0.0f, 1.0f/GPU_texture_opengl_height(tex)};
+ const float scaleh[2] = {1.0f / blurtex->w_orig, 0.0f};
+ const float scalev[2] = {0.0f, 1.0f / tex->h_orig};
GPUShader *blur_shader = GPU_shader_get_builtin_shader(GPU_SHADER_SEP_GAUSSIAN_BLUR);
int scale_uniform, texture_source_uniform;
@@ -1023,11 +1335,15 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
/* We do the bind ourselves rather than using GPU_framebuffer_texture_bind() to avoid
* pushing unnecessary matrices onto the OpenGL stack. */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, blurfb->object);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ /* avoid warnings from texture binding */
+ GG.currentfb = blurfb->object;
GPU_shader_bind(blur_shader);
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scaleh);
+ 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_opengl_width(blurtex), GPU_texture_opengl_height(blurtex));
+ glViewport(0, 0, blurtex->w_orig, blurtex->h_orig);
/* Peparing to draw quad */
glMatrixMode(GL_MODELVIEW);
@@ -1048,12 +1364,16 @@ void GPU_framebuffer_blur(GPUFrameBuffer *fb, GPUTexture *tex, GPUFrameBuffer *b
glTexCoord2d(1, 1); glVertex2f(-1, -1);
glTexCoord2d(0, 1); glVertex2f(1, -1);
glEnd();
-
+
/* Blurring vertically */
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb->object);
- glViewport(0, 0, GPU_texture_opengl_width(tex), GPU_texture_opengl_height(tex));
- GPU_shader_uniform_vector(blur_shader, scale_uniform, 2, 1, (float *)scalev);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0);
+
+ GG.currentfb = fb->object;
+
+ glViewport(0, 0, tex->w_orig, tex->h_orig);
+ 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);
@@ -1073,19 +1393,13 @@ struct GPUOffScreen {
GPUFrameBuffer *fb;
GPUTexture *color;
GPUTexture *depth;
-
- /* requested width/height, may be smaller than actual texture size due
- * to missing non-power of two support, so we compensate for that */
- int w, h;
};
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
{
GPUOffScreen *ofs;
- ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
- ofs->w= width;
- ofs->h= height;
+ ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen");
ofs->fb = GPU_framebuffer_create();
if (!ofs->fb) {
@@ -1099,21 +1413,27 @@ GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256])
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
- ofs->color = GPU_texture_create_2D(width, height, NULL, err_out);
+ ofs->color = GPU_texture_create_2D(width, height, NULL, GPU_HDR_NONE, err_out);
if (!ofs->color) {
GPU_offscreen_free(ofs);
return NULL;
}
- if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) {
+ if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) {
GPU_offscreen_free(ofs);
return NULL;
}
+
+ /* check validity at the very end! */
+ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) {
+ GPU_offscreen_free(ofs);
+ return NULL;
+ }
GPU_framebuffer_restore();
@@ -1132,62 +1452,75 @@ void GPU_offscreen_free(GPUOffScreen *ofs)
MEM_freeN(ofs);
}
-void GPU_offscreen_bind(GPUOffScreen *ofs)
+void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
{
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(ofs->fb, ofs->color, ofs->w, ofs->h);
+ if (save)
+ GPU_texture_bind_as_framebuffer(ofs->color);
+ else {
+ GPU_framebuffer_bind_no_save(ofs->fb, 0);
+ }
}
-void GPU_offscreen_unbind(GPUOffScreen *ofs)
+void GPU_offscreen_unbind(GPUOffScreen *ofs, bool restore)
{
- GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
+ if (restore)
+ GPU_framebuffer_texture_unbind(ofs->fb, ofs->color);
GPU_framebuffer_restore();
glEnable(GL_SCISSOR_TEST);
}
void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels)
{
- glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels);
+ glReadPixels(0, 0, ofs->color->w_orig, ofs->color->h_orig, GL_RGBA, type, pixels);
}
-int GPU_offscreen_width(GPUOffScreen *ofs)
+int GPU_offscreen_width(const GPUOffScreen *ofs)
{
- return ofs->w;
+ return ofs->color->w_orig;
}
-int GPU_offscreen_height(GPUOffScreen *ofs)
+int GPU_offscreen_height(const GPUOffScreen *ofs)
{
- return ofs->h;
+ return ofs->color->h_orig;
}
/* GPUShader */
struct GPUShader {
- GLhandleARB object; /* handle for full shader */
- GLhandleARB vertex; /* handle for vertex shader */
- GLhandleARB fragment; /* handle for fragment shader */
- GLhandleARB lib; /* handle for libment shader */
- int totattrib; /* total number of attributes */
+ GLhandleARB object; /* handle for full shader */
+ GLhandleARB vertex; /* handle for vertex shader */
+ GLhandleARB fragment; /* handle for fragment shader */
+ GLhandleARB geometry; /* handle for geometry shader */
+ GLhandleARB lib; /* handle for libment shader */
+ int totattrib; /* total number of attributes */
+ int uniforms; /* required uniforms */
};
-static void shader_print_errors(const char *task, char *log, const char **code, int totcode)
+struct GPUProgram {
+ GPUProgramType type;
+ GLuint prog;
+};
+
+
+static void shader_print_errors(const char *task, const char *log, const char **code, int totcode)
{
int i;
+ int line = 1;
fprintf(stderr, "GPUShader: %s error:\n", task);
for (i = 0; i < totcode; i++) {
const char *c, *pos, *end = code[i] + strlen(code[i]);
- int line = 1;
-
- if (G.debug & G_DEBUG) {
+
+ if ((G.debug & G_DEBUG)) {
fprintf(stderr, "===== shader string %d ====\n", i + 1);
c = code[i];
while ((c < end) && (pos = strchr(c, '\n'))) {
fprintf(stderr, "%2d ", line);
- fwrite(c, (pos+1)-c, 1, stderr);
- c = pos+1;
+ fwrite(c, (pos + 1) - c, 1, stderr);
+ c = pos + 1;
line++;
}
@@ -1198,8 +1531,16 @@ static void shader_print_errors(const char *task, char *log, const char **code,
fprintf(stderr, "%s\n", log);
}
-static const char *gpu_shader_version(void)
+static const char *gpu_shader_version(bool use_opensubdiv)
{
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ return "#version 130\n";
+ }
+#else
+ UNUSED_VARS(use_opensubdiv);
+#endif
+
/* turn on glsl 1.30 for bicubic bump mapping and ATI clipping support */
if (GLEW_VERSION_3_0 &&
(GPU_bicubic_bump_support() || GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)))
@@ -1211,16 +1552,34 @@ static const char *gpu_shader_version(void)
}
-static const char *gpu_shader_standard_extensions(void)
+static void gpu_shader_standard_extensions(char defines[MAX_EXT_DEFINE_LENGTH], bool use_opensubdiv)
{
- /* need this extensions for high quality bump mapping */
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n"
+ "#extension GL_ARB_gpu_shader5 : enable\n"
+ "#extension GL_ARB_explicit_attrib_location : require\n");
+ }
+ else if (GPU_bicubic_bump_support())
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+#else
+ /* need this extension for high quality bump mapping */
if (GPU_bicubic_bump_support())
- return "#extension GL_ARB_texture_query_lod: enable\n";
+ strcat(defines, "#extension GL_ARB_texture_query_lod: enable\n");
+ (void) use_opensubdiv;
+#endif
- return "";
+ if (GPU_geometry_shader_support())
+ strcat(defines, "#extension GL_EXT_geometry_shader4: enable\n");
+
+ if (GPU_instanced_drawing_support()) {
+ strcat(defines, "#extension GL_EXT_gpu_shader4: enable\n");
+ strcat(defines, "#extension GL_ARB_draw_instanced: enable\n");
+ }
}
-static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
+static void gpu_shader_standard_defines(bool use_opensubdiv,
+ char defines[MAX_DEFINE_LENGTH])
{
/* some useful defines to detect GPU type */
if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) {
@@ -1235,18 +1594,144 @@ static void gpu_shader_standard_defines(char defines[MAX_DEFINE_LENGTH])
if (GPU_bicubic_bump_support())
strcat(defines, "#define BUMP_BICUBIC\n");
+
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Check whether we actually compiling shader for
+ * the OpenSubdiv mesh.
+ */
+ if (use_opensubdiv) {
+ strcat(defines, "#define USE_OPENSUBDIV\n");
+
+ /* TODO(sergey): not strictly speaking a define, but this is
+ * a global typedef which we don't have better place to define
+ * in yet.
+ */
+ strcat(defines, "struct VertexData {\n"
+ " vec4 position;\n"
+ " vec3 normal;\n"
+ " vec2 uv;"
+ "};\n");
+ }
+#else
+ UNUSED_VARS(use_opensubdiv);
+#endif
+
return;
}
-GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines)
+void GPU_program_bind(GPUProgram *program)
+{
+ glEnable(program->type);
+ glBindProgramARB(program->type, program->prog);
+}
+
+void GPU_program_unbind(GPUProgram *program)
+{
+ glDisable(program->type);
+ glBindProgramARB(program->type, 0);
+}
+
+
+GPUProgram *GPU_program_shader_create(GPUProgramType type, const char *code)
+{
+ GPUProgram *program;
+ GLint error_pos, is_native;
+
+ if (!(GLEW_ARB_fragment_program && type == GPU_PROGRAM_TYPE_FRAGMENT))
+ return NULL;
+
+ program = MEM_callocN(sizeof(GPUProgram), "GPUProgram");
+
+ switch (type) {
+ case GPU_PROGRAM_TYPE_FRAGMENT:
+ program->type = GL_FRAGMENT_PROGRAM_ARB;
+ break;
+ }
+
+ /* create the object and set its code string */
+ glGenProgramsARB(1, &program->prog);
+ glBindProgramARB(program->type, program->prog);
+
+ glProgramStringARB(program->type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(code), code);
+
+ glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
+ glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &is_native);
+ if ((error_pos == -1) && (is_native == 1)) {
+ return program;
+ }
+ else {
+ /* glGetError is set before that, clear it */
+ while (glGetError() != GL_NO_ERROR)
+ ;
+ shader_print_errors("compile", (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB), &code, 1);
+ MEM_freeN(program);
+ }
+
+ return NULL;
+}
+
+void GPU_program_free(GPUProgram *program)
+{
+ glDeleteProgramsARB(1, &program->prog);
+ MEM_freeN(program);
+}
+
+void GPU_program_parameter_4f(GPUProgram *program, unsigned int location, float x, float y, float z, float w)
{
+ glProgramLocalParameter4fARB(program->type, location, x, y, z, w);
+}
+
+GPUShader *GPU_shader_create(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number)
+{
+ return GPU_shader_create_ex(vertexcode,
+ fragcode,
+ geocode,
+ libcode,
+ defines,
+ input,
+ output,
+ number,
+ GPU_SHADER_FLAGS_NONE);
+}
+
+GPUShader *GPU_shader_create_ex(const char *vertexcode,
+ const char *fragcode,
+ const char *geocode,
+ const char *libcode,
+ const char *defines,
+ int input,
+ int output,
+ int number,
+ const int flags)
+{
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): used to add #version 150 to the geometry shader.
+ * Could safely be renamed to "use_geometry_code" since it's very
+ * likely any of geometry code will want to use GLSL 1.5.
+ */
+ bool use_opensubdiv = (flags & GPU_SHADER_FLAGS_SPECIAL_OPENSUBDIV) != 0;
+#else
+ bool use_opensubdiv = false;
+#endif
GLint status;
GLcharARB log[5000];
GLsizei length = 0;
GPUShader *shader;
char standard_defines[MAX_DEFINE_LENGTH] = "";
+ char standard_extensions[MAX_EXT_DEFINE_LENGTH] = "";
- if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader)
+#ifndef WITH_OPENSUBDIV
+ UNUSED_VARS(flags);
+#endif
+
+ if (!GLEW_ARB_vertex_shader || !GLEW_ARB_fragment_shader || (geocode && !GPU_geometry_shader_support()))
return NULL;
shader = MEM_callocN(sizeof(GPUShader), "GPUShader");
@@ -1255,30 +1740,35 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
shader->vertex = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
if (fragcode)
shader->fragment = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+ if (geocode)
+ shader->geometry = glCreateShaderObjectARB(GL_GEOMETRY_SHADER_EXT);
+
shader->object = glCreateProgramObjectARB();
if (!shader->object ||
(vertexcode && !shader->vertex) ||
- (fragcode && !shader->fragment))
+ (fragcode && !shader->fragment) ||
+ (geocode && !shader->geometry))
{
fprintf(stderr, "GPUShader, object creation failed.\n");
GPU_shader_free(shader);
return NULL;
}
- gpu_shader_standard_defines(standard_defines);
+ gpu_shader_standard_defines(use_opensubdiv, standard_defines);
+ gpu_shader_standard_extensions(standard_extensions, use_opensubdiv);
if (vertexcode) {
const char *source[5];
/* custom limit, may be too small, beware */
int num_source = 0;
- source[num_source++] = gpu_shader_version();
- source[num_source++] = gpu_shader_standard_extensions();
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
if (defines) source[num_source++] = defines;
- if (vertexcode) source[num_source++] = vertexcode;
+ source[num_source++] = vertexcode;
glAttachObjectARB(shader->object, shader->vertex);
glShaderSourceARB(shader->vertex, num_source, source, NULL);
@@ -1296,16 +1786,28 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
if (fragcode) {
- const char *source[6];
+ const char *source[7];
int num_source = 0;
- source[num_source++] = gpu_shader_version();
- source[num_source++] = gpu_shader_standard_extensions();
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
source[num_source++] = standard_defines;
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Move to fragment shader source code generation. */
+ if (use_opensubdiv) {
+ source[num_source++] =
+ "#ifdef USE_OPENSUBDIV\n"
+ "in block {\n"
+ " VertexData v;\n"
+ "} inpt;\n"
+ "#endif\n";
+ }
+#endif
+
if (defines) source[num_source++] = defines;
if (libcode) source[num_source++] = libcode;
- if (fragcode) source[num_source++] = fragcode;
+ source[num_source++] = fragcode;
glAttachObjectARB(shader->object, shader->fragment);
glShaderSourceARB(shader->fragment, num_source, source, NULL);
@@ -1322,11 +1824,54 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
}
}
+ if (geocode) {
+ const char *source[6];
+ int num_source = 0;
+
+ source[num_source++] = gpu_shader_version(use_opensubdiv);
+ source[num_source++] = standard_extensions;
+ source[num_source++] = standard_defines;
+
+ if (defines) source[num_source++] = defines;
+ source[num_source++] = geocode;
+
+ glAttachObjectARB(shader->object, shader->geometry);
+ glShaderSourceARB(shader->geometry, num_source, source, NULL);
+
+ glCompileShaderARB(shader->geometry);
+ glGetObjectParameterivARB(shader->geometry, GL_OBJECT_COMPILE_STATUS_ARB, &status);
+
+ if (!status) {
+ glGetInfoLogARB(shader->geometry, sizeof(log), &length, log);
+ shader_print_errors("compile", log, source, num_source);
+
+ GPU_shader_free(shader);
+ return NULL;
+ }
+
+ if (!use_opensubdiv) {
+ GPU_shader_geometry_stage_primitive_io(shader, input, output, number);
+ }
+ }
+
+
#if 0
if (lib && lib->lib)
glAttachObjectARB(shader->object, lib->lib);
#endif
+#ifdef WITH_OPENSUBDIV
+ if (use_opensubdiv) {
+ glBindAttribLocation(shader->object, 0, "position");
+ glBindAttribLocation(shader->object, 1, "normal");
+ GPU_shader_geometry_stage_primitive_io(shader,
+ GL_LINES_ADJACENCY_EXT,
+ GL_TRIANGLE_STRIP,
+ 4);
+
+ }
+#endif
+
glLinkProgramARB(shader->object);
glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status);
if (!status) {
@@ -1334,11 +1879,21 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const
if (fragcode) shader_print_errors("linking", log, &fragcode, 1);
else if (vertexcode) shader_print_errors("linking", log, &vertexcode, 1);
else if (libcode) shader_print_errors("linking", log, &libcode, 1);
+ else if (geocode) shader_print_errors("linking", log, &geocode, 1);
GPU_shader_free(shader);
return NULL;
}
+#ifdef WITH_OPENSUBDIV
+ /* TODO(sergey): Find a better place for this. */
+ if (use_opensubdiv && GLEW_VERSION_4_1) {
+ glProgramUniform1i(shader->object,
+ glGetUniformLocation(shader->object, "FVarDataBuffer"),
+ 31); /* GL_TEXTURE31 */
+ }
+#endif
+
return shader;
}
@@ -1382,16 +1937,16 @@ GPUShader *GPU_shader_create_lib(const char *code)
void GPU_shader_bind(GPUShader *shader)
{
- GPU_print_error("Pre Shader Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Bind");
glUseProgramObjectARB(shader->object);
- GPU_print_error("Post Shader Bind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Bind");
}
void GPU_shader_unbind(void)
{
- GPU_print_error("Pre Shader Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Shader Unbind");
glUseProgramObjectARB(0);
- GPU_print_error("Post Shader Unbind");
+ GPU_ASSERT_NO_GL_ERRORS("Post Shader Unbind");
}
void GPU_shader_free(GPUShader *shader)
@@ -1412,12 +1967,12 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
return glGetUniformLocationARB(shader->object, name);
}
-void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, float *value)
+void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int length, int arraysize, const float *value)
{
- if (location == -1)
+ if (location == -1 || value == NULL)
return;
- GPU_print_error("Pre Uniform Vector");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
if (length == 1) glUniform1fvARB(location, arraysize, value);
else if (length == 2) glUniform2fvARB(location, arraysize, value);
@@ -1426,7 +1981,22 @@ void GPU_shader_uniform_vector(GPUShader *UNUSED(shader), int location, int leng
else if (length == 9) glUniformMatrix3fvARB(location, arraysize, 0, value);
else if (length == 16) glUniformMatrix4fvARB(location, arraysize, 0, value);
- GPU_print_error("Post Uniform Vector");
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
+}
+
+void GPU_shader_uniform_vector_int(GPUShader *UNUSED(shader), int location, int length, int arraysize, const int *value)
+{
+ if (location == -1)
+ return;
+
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Vector");
+
+ if (length == 1) glUniform1ivARB(location, arraysize, value);
+ else if (length == 2) glUniform2ivARB(location, arraysize, value);
+ else if (length == 3) glUniform3ivARB(location, arraysize, value);
+ else if (length == 4) glUniform4ivARB(location, arraysize, value);
+
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Vector");
}
void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
@@ -1434,9 +2004,14 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
if (location == -1)
return;
- GPU_print_error("Pre Uniform Int");
- glUniform1iARB(location, value);
- GPU_print_error("Post Uniform Int");
+ GPU_CHECK_ERRORS_AROUND(glUniform1iARB(location, value));
+}
+
+void GPU_shader_geometry_stage_primitive_io(GPUShader *shader, int input, int output, int number)
+{
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_INPUT_TYPE_EXT, input);
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_OUTPUT_TYPE_EXT, output);
+ glProgramParameteriEXT(shader->object, GL_GEOMETRY_VERTICES_OUT_EXT, number);
}
void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
@@ -1444,7 +2019,7 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
GLenum arbnumber;
if (tex->number >= GG.maxtextures) {
- GPU_print_error("Not enough texture slots.");
+ fprintf(stderr, "Not enough texture slots.");
return;
}
@@ -1454,7 +2029,7 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
if (location == -1)
return;
- GPU_print_error("Pre Uniform Texture");
+ GPU_ASSERT_NO_GL_ERRORS("Pre Uniform Texture");
arbnumber = (GLenum)((GLuint)GL_TEXTURE0_ARB + tex->number);
@@ -1467,18 +2042,14 @@ void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUText
glEnable(tex->target);
if (tex->number != 0) glActiveTextureARB(GL_TEXTURE0_ARB);
- GPU_print_error("Post Uniform Texture");
+ GPU_ASSERT_NO_GL_ERRORS("Post Uniform Texture");
}
int GPU_shader_get_attribute(GPUShader *shader, const char *name)
{
int index;
- GPU_print_error("Pre Get Attribute");
-
- index = glGetAttribLocationARB(shader->object, name);
-
- GPU_print_error("Post Get Attribute");
+ GPU_CHECK_ERRORS_AROUND(index = glGetAttribLocationARB(shader->object, name));
return index;
}
@@ -1490,36 +2061,183 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader)
switch (shader) {
case GPU_SHADER_VSM_STORE:
if (!GG.shaders.vsm_store)
- GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL);
+ GG.shaders.vsm_store = GPU_shader_create(datatoc_gpu_shader_vsm_store_vert_glsl, datatoc_gpu_shader_vsm_store_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.vsm_store;
break;
case GPU_SHADER_SEP_GAUSSIAN_BLUR:
if (!GG.shaders.sep_gaussian_blur)
- GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL);
+ GG.shaders.sep_gaussian_blur = GPU_shader_create(datatoc_gpu_shader_sep_gaussian_blur_vert_glsl, datatoc_gpu_shader_sep_gaussian_blur_frag_glsl, NULL, NULL, NULL, 0, 0, 0);
retval = GG.shaders.sep_gaussian_blur;
break;
}
if (retval == NULL)
- printf("Unable to create a GPUShader for builtin shader: %d\n", shader);
+ printf("Unable to create a GPUShader for builtin shader: %u\n", shader);
return retval;
}
+GPUProgram *GPU_shader_get_builtin_program(GPUBuiltinProgram program)
+{
+ GPUProgram *retval = NULL;
+
+ switch (program) {
+ case GPU_PROGRAM_SMOKE:
+ if (!GG.shaders.smoke)
+ GG.shaders.smoke = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_frag_glsl);
+ retval = GG.shaders.smoke;
+ break;
+ case GPU_PROGRAM_SMOKE_COLORED:
+ if (!GG.shaders.smoke_colored)
+ GG.shaders.smoke_colored = GPU_program_shader_create(GPU_PROGRAM_TYPE_FRAGMENT, datatoc_gpu_program_smoke_color_frag_glsl);
+ retval = GG.shaders.smoke_colored;
+ break;
+ }
+
+ if (retval == NULL)
+ printf("Unable to create a GPUProgram for builtin program: %u\n", program);
+
+ return retval;
+}
+
+#define MAX_DEFINES 100
+
+GPUShader *GPU_shader_get_builtin_fx_shader(int effects, bool persp)
+{
+ int offset;
+ char defines[MAX_DEFINES] = "";
+ /* avoid shaders out of range */
+ if (effects >= MAX_FX_SHADERS)
+ return NULL;
+
+ offset = 2 * effects;
+
+ if (persp) {
+ offset += 1;
+ strcat(defines, "#define PERSP_MATRIX\n");
+ }
+
+ if (!GG.shaders.fx_shaders[offset]) {
+ GPUShader *shader;
+
+ switch (effects) {
+ case GPU_SHADER_FX_SSAO:
+ GG.shaders.fx_shaders[offset] = 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);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FOUR:
+ strcat(defines, "#define FOURTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_PASS_FIVE:
+ strcat(defines, "#define FIFTH_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_vert_glsl, datatoc_gpu_shader_fx_dof_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_ONE:
+ strcat(defines, "#define FIRST_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_TWO:
+ strcat(defines, "#define SECOND_PASS\n");
+ shader = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, datatoc_gpu_shader_fx_dof_hq_geo_glsl, datatoc_gpu_shader_fx_lib_glsl,
+ defines, GL_POINTS, GL_TRIANGLE_STRIP, 4);
+ GG.shaders.fx_shaders[offset] = shader;
+ break;
+
+ case GPU_SHADER_FX_DEPTH_OF_FIELD_HQ_PASS_THREE:
+ strcat(defines, "#define THIRD_PASS\n");
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_dof_hq_vert_glsl, datatoc_gpu_shader_fx_dof_hq_frag_glsl, NULL, datatoc_gpu_shader_fx_lib_glsl, defines, 0, 0, 0);
+ break;
+
+ case GPU_SHADER_FX_DEPTH_RESOLVE:
+ GG.shaders.fx_shaders[offset] = GPU_shader_create(datatoc_gpu_shader_fx_vert_glsl, datatoc_gpu_shader_fx_depth_resolve_glsl, NULL, NULL, defines, 0, 0, 0);
+ }
+ }
+
+ return GG.shaders.fx_shaders[offset];
+}
+
+
void GPU_shader_free_builtin_shaders(void)
{
+ int i;
+
if (GG.shaders.vsm_store) {
- MEM_freeN(GG.shaders.vsm_store);
+ GPU_shader_free(GG.shaders.vsm_store);
GG.shaders.vsm_store = NULL;
}
if (GG.shaders.sep_gaussian_blur) {
- MEM_freeN(GG.shaders.sep_gaussian_blur);
+ GPU_shader_free(GG.shaders.sep_gaussian_blur);
GG.shaders.sep_gaussian_blur = NULL;
}
+
+ if (GG.shaders.smoke) {
+ GPU_program_free(GG.shaders.smoke);
+ GG.shaders.smoke = NULL;
+ }
+
+ if (GG.shaders.smoke_colored) {
+ GPU_program_free(GG.shaders.smoke_colored);
+ GG.shaders.smoke_colored = NULL;
+ }
+
+ for (i = 0; i < 2 * MAX_FX_SHADERS; i++) {
+ if (GG.shaders.fx_shaders[i]) {
+ GPU_shader_free(GG.shaders.fx_shaders[i]);
+ GG.shaders.fx_shaders[i] = NULL;
+ }
+ }
}
-#if 0
+bool GPU_mem_stats_supported(void)
+{
+ return (GLEW_NVX_gpu_memory_info || (GLEW_ATI_meminfo)) && (G.debug & G_DEBUG_GPU_MEM);
+}
+
+
+void GPU_mem_stats_get(int *totalmem, int *freemem)
+{
+ if (GLEW_NVX_gpu_memory_info) {
+ /* returned value in Kb */
+ glGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, totalmem);
+
+ glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, freemem);
+ }
+ else if (GLEW_ATI_meminfo) {
+ int stats[4];
+
+ glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, stats);
+ *freemem = stats[0];
+ *totalmem = 0;
+ }
+ else {
+ *totalmem = 0;
+ *freemem = 0;
+ }
+}
+
+
+#if 0 /* unused */
+
/* GPUPixelBuffer */
typedef struct GPUPixelBuffer {
@@ -1545,7 +2263,7 @@ GPUPixelBuffer *gpu_pixelbuffer_create(int x, int y, int halffloat, int numbuffe
return NULL;
pb = MEM_callocN(sizeof(GPUPixelBuffer), "GPUPBO");
- pb->datasize = x*y*4*((halffloat)? 16: 8);
+ pb->datasize = x * y * 4 * (halffloat ? 16 : 8);
pb->numbuffers = numbuffers;
pb->halffloat = halffloat;
@@ -1573,10 +2291,13 @@ void GPU_pixelbuffer_texture(GPUTexture *tex, GPUPixelBuffer *pb)
GL_STREAM_DRAW_ARB);
pixels = glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, GL_WRITE_ONLY);
- /*memcpy(pixels, _oImage.data(), pb->datasize);*/
+
+# if 0
+ memcpy(pixels, _oImage.data(), pb->datasize);
+# endif
if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
- fprintf(stderr, "Could not unmap opengl PBO\n");
+ fprintf(stderr, "Could not unmap OpenGL PBO\n");
break;
}
}
@@ -1594,7 +2315,7 @@ static int pixelbuffer_map_into_gpu(GLuint bindcode)
/* do stuff in pixels */
if (!glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT)) {
- fprintf(stderr, "Could not unmap opengl PBO\n");
+ fprintf(stderr, "Could not unmap OpenGL PBO\n");
return 0;
}
@@ -1607,8 +2328,7 @@ static void pixelbuffer_copy_to_texture(GPUTexture *tex, GPUPixelBuffer *pb, GLu
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, tex->bindcode);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, bindcode);
- glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h,
- GL_RGBA, type, NULL);
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, tex->w, tex->h, GL_RGBA, type, NULL);
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 0);
@@ -1623,12 +2343,12 @@ void GPU_pixelbuffer_async_to_gpu(GPUTexture *tex, GPUPixelBuffer *pb)
pixelbuffer_map_into_gpu(pb->bindcode[0]);
}
else {
- pb->current = (pb->current+1)%pb->numbuffers;
- newbuffer = (pb->current+1)%pb->numbuffers;
+ pb->current = (pb->current + 1) % pb->numbuffers;
+ newbuffer = (pb->current + 1) % pb->numbuffers;
pixelbuffer_map_into_gpu(pb->bindcode[newbuffer]);
pixelbuffer_copy_to_texture(tex, pb, pb->bindcode[pb->current]);
}
}
-#endif
+#endif /* unused */
diff --git a/source/blender/gpu/intern/gpu_init_exit.c b/source/blender/gpu/intern/gpu_init_exit.c
new file mode 100644
index 00000000000..3a8a6fca23b
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_init_exit.c
@@ -0,0 +1,79 @@
+/*
+ * ***** 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) 2013 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Jason Wilkins
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file source/blender/gpu/intern/gpu_init_exit.c
+ * \ingroup gpu
+ */
+
+#include "BKE_DerivedMesh.h"
+
+#include "BLI_sys_types.h"
+#include "GPU_init_exit.h" /* interface */
+#include "GPU_buffers.h"
+
+#include "BKE_global.h"
+
+#include "intern/gpu_codegen.h"
+#include "intern/gpu_private.h"
+
+/**
+ * although the order of initialization and shutdown should not matter
+ * (except for the extensions), I chose alphabetical and reverse alphabetical order
+ */
+
+static bool initialized = false;
+
+void GPU_init(void)
+{
+ /* can't avoid calling this multiple times, see wm_window_add_ghostwindow */
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ gpu_extensions_init(); /* must come first */
+
+ gpu_codegen_init();
+
+ if (G.debug & G_DEBUG_GPU)
+ gpu_debug_init();
+
+}
+
+
+
+void GPU_exit(void)
+{
+ if (G.debug & G_DEBUG_GPU)
+ gpu_debug_exit();
+ gpu_codegen_exit();
+
+ gpu_extensions_exit(); /* must come last */
+ GPU_buffer_multires_free(true);
+
+ initialized = false;
+}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 81dcd9cf450..5b647232934 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -35,8 +35,6 @@
#include <math.h>
#include <string.h>
-#include "GL/glew.h"
-
#include "MEM_guardedalloc.h"
#include "DNA_lamp_types.h"
@@ -78,10 +76,25 @@ typedef enum DynMatProperty {
DYN_LAMP_PERSMAT = 8,
} DynMatProperty;
+static struct GPUWorld {
+ float mistenabled;
+ float mistype;
+ float miststart;
+ float mistdistance;
+ float mistintensity;
+ float mistcol[4];
+ float horicol[3];
+ float ambcol[4];
+} GPUWorld;
+
struct GPUMaterial {
Scene *scene;
Material *ma;
+ /* material for mesh surface, worlds or something else.
+ * some code generation is done differently depending on the use case */
+ int type;
+
/* for creating the material */
ListBase nodes;
GPUNodeLink *outlink;
@@ -89,7 +102,6 @@ struct GPUMaterial {
/* for binding the material */
GPUPass *pass;
GPUVertexAttribs attribs;
- int bound;
int builtins;
int alpha, obcolalpha;
int dynproperty;
@@ -98,8 +110,17 @@ struct GPUMaterial {
int viewmatloc, invviewmatloc;
int obmatloc, invobmatloc;
int obcolloc, obautobumpscaleloc;
+ int cameratexcofacloc;
+
+ int partscalarpropsloc;
+ int partcoloc;
+ int partvel;
+ int partangvel;
ListBase lamps;
+ bool bound;
+
+ bool is_opensubdiv;
};
struct GPULamp {
@@ -153,7 +174,7 @@ static GPUMaterial *GPU_material_construct_begin(Material *ma)
{
GPUMaterial *material = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
- material->ma= ma;
+ material->ma = ma;
return material;
}
@@ -166,14 +187,14 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
char name[32];
int a, b;
- attribs= &material->attribs;
- pass= material->pass;
+ attribs = &material->attribs;
+ pass = material->pass;
if (!pass) {
attribs->totlayer = 0;
return;
}
- shader= GPU_pass_shader(pass);
+ shader = GPU_pass_shader(pass);
if (!shader) {
attribs->totlayer = 0;
return;
@@ -183,7 +204,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
* in case the attrib does not get a valid index back, it was probably
* removed by the glsl compiler by dead code elimination */
- for (a=0, b=0; a<attribs->totlayer; a++) {
+ for (a = 0, b = 0; a < attribs->totlayer; a++) {
BLI_snprintf(name, sizeof(name), "att%d", attribs->layer[a].attribid);
attribs->layer[a].glindex = GPU_shader_get_attribute(shader, name);
@@ -196,7 +217,7 @@ static void gpu_material_set_attrib_id(GPUMaterial *material)
attribs->totlayer = b;
}
-static int GPU_material_construct_end(GPUMaterial *material)
+static int GPU_material_construct_end(GPUMaterial *material, const char *passname)
{
if (material->outlink) {
GPUNodeLink *outlink;
@@ -204,7 +225,8 @@ static int GPU_material_construct_end(GPUMaterial *material)
outlink = material->outlink;
material->pass = GPU_generate_pass(&material->nodes, outlink,
- &material->attribs, &material->builtins, material->ma->id.name);
+ &material->attribs, &material->builtins, material->type,
+ passname, material->is_opensubdiv);
if (!material->pass)
return 0;
@@ -225,39 +247,53 @@ static int GPU_material_construct_end(GPUMaterial *material)
material->obcolloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_OBCOLOR));
if (material->builtins & GPU_AUTO_BUMPSCALE)
material->obautobumpscaleloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_AUTO_BUMPSCALE));
+ if (material->builtins & GPU_CAMERA_TEXCO_FACTORS)
+ material->cameratexcofacloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_CAMERA_TEXCO_FACTORS));
+ if (material->builtins & GPU_PARTICLE_SCALAR_PROPS)
+ material->partscalarpropsloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_SCALAR_PROPS));
+ if (material->builtins & GPU_PARTICLE_LOCATION)
+ material->partcoloc = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_LOCATION));
+ if (material->builtins & GPU_PARTICLE_VELOCITY)
+ material->partvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_VELOCITY));
+ if (material->builtins & GPU_PARTICLE_ANG_VELOCITY)
+ material->partangvel = GPU_shader_get_uniform(shader, GPU_builtin_name(GPU_PARTICLE_ANG_VELOCITY));
return 1;
}
return 0;
}
-void GPU_material_free(Material *ma)
+void GPU_material_free(ListBase *gpumaterial)
{
LinkData *link;
LinkData *nlink, *mlink, *next;
- for (link=ma->gpumaterial.first; link; link=link->next) {
+ for (link = gpumaterial->first; link; link = link->next) {
GPUMaterial *material = link->data;
if (material->pass)
GPU_pass_free(material->pass);
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
+ for (nlink = material->lamps.first; nlink; nlink = nlink->next) {
GPULamp *lamp = nlink->data;
- for (mlink=lamp->materials.first; mlink; mlink=next) {
- next = mlink->next;
- if (mlink->data == ma)
- BLI_freelinkN(&lamp->materials, mlink);
+ if (material->ma) {
+ Material *ma = material->ma;
+
+ for (mlink = lamp->materials.first; mlink; mlink = next) {
+ next = mlink->next;
+ if (mlink->data == ma)
+ BLI_freelinkN(&lamp->materials, mlink);
+ }
}
}
-
+
BLI_freelistN(&material->lamps);
MEM_freeN(material);
}
- BLI_freelistN(&ma->gpumaterial);
+ BLI_freelistN(gpumaterial);
}
bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *ma)
@@ -270,7 +306,7 @@ bool GPU_lamp_override_visible(GPULamp *lamp, SceneRenderLayer *srl, Material *m
return true;
}
-void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4], bool scenelock)
+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)
{
if (material->pass) {
LinkData *nlink;
@@ -282,42 +318,44 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
viewlay &= srl->lay;
/* handle layer lamps */
- for (nlink=material->lamps.first; nlink; nlink=nlink->next) {
- lamp= nlink->data;
-
- if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
- && GPU_lamp_override_visible(lamp, srl, material->ma)) {
- lamp->dynenergy = lamp->energy;
- copy_v3_v3(lamp->dyncol, lamp->col);
- }
- else {
- lamp->dynenergy = 0.0f;
- lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f;
- }
-
- if (material->dynproperty & DYN_LAMP_VEC) {
- copy_v3_v3(lamp->dynvec, lamp->vec);
- normalize_v3(lamp->dynvec);
- negate_v3(lamp->dynvec);
- mul_mat3_m4_v3(viewmat, lamp->dynvec);
- }
-
- if (material->dynproperty & DYN_LAMP_CO) {
- copy_v3_v3(lamp->dynco, lamp->co);
- mul_m4_v3(viewmat, lamp->dynco);
- }
-
- if (material->dynproperty & DYN_LAMP_IMAT) {
- mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
- }
-
- if (material->dynproperty & DYN_LAMP_PERSMAT) {
- if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
- GPU_lamp_update_buffer_mats(lamp);
- mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ if (material->type == GPU_MATERIAL_TYPE_MESH) {
+ for (nlink = material->lamps.first; nlink; nlink = nlink->next) {
+ lamp = nlink->data;
+
+ if (!lamp->hide && (lamp->lay & viewlay) && (!(lamp->mode & LA_LAYER) || (lamp->lay & oblay))
+ && GPU_lamp_override_visible(lamp, srl, material->ma)) {
+ lamp->dynenergy = lamp->energy;
+ copy_v3_v3(lamp->dyncol, lamp->col);
+ }
+ else {
+ lamp->dynenergy = 0.0f;
+ lamp->dyncol[0] = lamp->dyncol[1] = lamp->dyncol[2] = 0.0f;
+ }
+
+ if (material->dynproperty & DYN_LAMP_VEC) {
+ copy_v3_v3(lamp->dynvec, lamp->vec);
+ normalize_v3(lamp->dynvec);
+ negate_v3(lamp->dynvec);
+ mul_mat3_m4_v3(viewmat, lamp->dynvec);
+ }
+
+ if (material->dynproperty & DYN_LAMP_CO) {
+ copy_v3_v3(lamp->dynco, lamp->co);
+ mul_m4_v3(viewmat, lamp->dynco);
+ }
+
+ if (material->dynproperty & DYN_LAMP_IMAT) {
+ mul_m4_m4m4(lamp->dynimat, lamp->imat, viewinv);
+ }
+
+ if (material->dynproperty & DYN_LAMP_PERSMAT) {
+ if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */
+ GPU_lamp_update_buffer_mats(lamp);
+ mul_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv);
+ }
}
}
-
+
/* note material must be bound before setting uniforms */
GPU_pass_bind(material->pass, time, mipmap);
@@ -328,6 +366,16 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
if (material->builtins & GPU_INVERSE_VIEW_MATRIX) {
GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv);
}
+ if (material->builtins & GPU_CAMERA_TEXCO_FACTORS) {
+ if (camerafactors) {
+ GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float*)camerafactors);
+ }
+ else {
+ /* use default, no scaling no offset */
+ float borders[4] = {1.0f, 1.0f, 0.0f, 0.0f};
+ GPU_shader_uniform_vector(shader, material->cameratexcofacloc, 4, 1, (float*)borders);
+ }
+ }
GPU_pass_update_uniforms(material->pass);
@@ -335,7 +383,7 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim
}
}
-void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale)
+void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale, GPUParticleInfo* pi)
{
if (material->pass) {
GPUShader *shader = GPU_pass_shader(material->pass);
@@ -357,6 +405,19 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float
if (material->builtins & GPU_AUTO_BUMPSCALE) {
GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale);
}
+ if (material->builtins & GPU_PARTICLE_SCALAR_PROPS) {
+ GPU_shader_uniform_vector(shader, material->partscalarpropsloc, 4, 1, pi->scalprops);
+ }
+ if (material->builtins & GPU_PARTICLE_LOCATION) {
+ GPU_shader_uniform_vector(shader, material->partcoloc, 3, 1, pi->location);
+ }
+ if (material->builtins & GPU_PARTICLE_VELOCITY) {
+ GPU_shader_uniform_vector(shader, material->partvel, 3, 1, pi->velocity);
+ }
+ if (material->builtins & GPU_PARTICLE_ANG_VELOCITY) {
+ GPU_shader_uniform_vector(shader, material->partangvel, 3, 1, pi->angular_velocity);
+ }
+
}
}
@@ -368,7 +429,7 @@ void GPU_material_unbind(GPUMaterial *material)
}
}
-int GPU_material_bound(GPUMaterial *material)
+bool GPU_material_bound(GPUMaterial *material)
{
return material->bound;
}
@@ -378,6 +439,12 @@ Scene *GPU_material_scene(GPUMaterial *material)
return material->scene;
}
+GPUMatType GPU_Material_get_type(GPUMaterial *material)
+{
+ return material->type;
+}
+
+
void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *attribs)
{
*attribs = material->attribs;
@@ -386,12 +453,12 @@ void GPU_material_vertex_attributes(GPUMaterial *material, GPUVertexAttribs *att
void GPU_material_output_link(GPUMaterial *material, GPUNodeLink *link)
{
if (!material->outlink)
- material->outlink= link;
+ material->outlink = link;
}
void GPU_material_enable_alpha(GPUMaterial *material)
{
- material->alpha= 1;
+ material->alpha = 1;
}
GPUBlendMode GPU_material_alpha_blend(GPUMaterial *material, float obcol[4])
@@ -414,7 +481,7 @@ bool GPU_material_do_color_management(GPUMaterial *mat)
if (!BKE_scene_check_color_management_enabled(mat->scene))
return false;
- return !((mat->scene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT));
+ return true;
}
bool GPU_material_use_new_shading_nodes(GPUMaterial *mat)
@@ -427,7 +494,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPUNodeLink *visifac, *inpr;
/* from get_lamp_visibility */
- if (lamp->type==LA_SUN || lamp->type==LA_HEMI) {
+ if (lamp->type == LA_SUN || lamp->type == LA_HEMI) {
mat->dynproperty |= DYN_LAMP_VEC;
GPU_link(mat, "lamp_visibility_sun_hemi", GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), lv, dist, &visifac);
return visifac;
@@ -436,7 +503,7 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
mat->dynproperty |= DYN_LAMP_CO;
GPU_link(mat, "lamp_visibility_other", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), lv, dist, &visifac);
- if (lamp->type==LA_AREA)
+ if (lamp->type == LA_AREA)
return visifac;
switch (lamp->falloff_type) {
@@ -452,15 +519,16 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
GPU_link(mat, "lamp_falloff_sliders", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_dynamic_uniform(&lamp->att1, GPU_DYNAMIC_LAMP_ATT1, lamp->ob), GPU_dynamic_uniform(&lamp->att2, GPU_DYNAMIC_LAMP_ATT2, lamp->ob), *dist, &visifac);
break;
case LA_FALLOFF_CURVE:
- {
- float *array;
- int size;
+ {
+ float *array;
+ int size;
+
+ curvemapping_initialize(lamp->curfalloff);
+ curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
+ GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac);
- curvemapping_initialize(lamp->curfalloff);
- curvemapping_table_RGBA(lamp->curfalloff, &array, &size);
- GPU_link(mat, "lamp_falloff_curve", GPU_dynamic_uniform(&lamp->dist, GPU_DYNAMIC_LAMP_DISTANCE, lamp->ob), GPU_texture(size, array), *dist, &visifac);
- }
break;
+ }
}
if (lamp->mode & LA_SPHERE)
@@ -488,34 +556,34 @@ static GPUNodeLink *lamp_get_visibility(GPUMaterial *mat, GPULamp *lamp, GPUNode
#if 0
static void area_lamp_vectors(LampRen *lar)
{
- float xsize= 0.5*lar->area_size, ysize= 0.5*lar->area_sizey, multifac;
+ float xsize = 0.5f * lar->area_size, ysize = 0.5f * lar->area_sizey, multifac;
/* make it smaller, so area light can be multisampled */
- multifac= 1.0f/sqrt((float)lar->ray_totsamp);
+ multifac = 1.0f / sqrtf((float)lar->ray_totsamp);
xsize *= multifac;
ysize *= multifac;
/* corner vectors */
- lar->area[0][0]= lar->co[0] - xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
- lar->area[0][1]= lar->co[1] - xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
- lar->area[0][2]= lar->co[2] - xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
+ lar->area[0][0] = lar->co[0] - xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
+ lar->area[0][1] = lar->co[1] - xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
+ lar->area[0][2] = lar->co[2] - xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[1][0]= lar->co[0] - xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
- lar->area[1][1]= lar->co[1] - xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
- lar->area[1][2]= lar->co[2] - xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
+ lar->area[1][0] = lar->co[0] - xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
+ lar->area[1][1] = lar->co[1] - xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
+ lar->area[1][2] = lar->co[2] - xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[2][0]= lar->co[0] + xsize*lar->mat[0][0] + ysize*lar->mat[1][0];
- lar->area[2][1]= lar->co[1] + xsize*lar->mat[0][1] + ysize*lar->mat[1][1];
- lar->area[2][2]= lar->co[2] + xsize*lar->mat[0][2] + ysize*lar->mat[1][2];
+ lar->area[2][0] = lar->co[0] + xsize * lar->mat[0][0] + ysize * lar->mat[1][0];
+ lar->area[2][1] = lar->co[1] + xsize * lar->mat[0][1] + ysize * lar->mat[1][1];
+ lar->area[2][2] = lar->co[2] + xsize * lar->mat[0][2] + ysize * lar->mat[1][2];
/* corner vectors */
- lar->area[3][0]= lar->co[0] + xsize*lar->mat[0][0] - ysize*lar->mat[1][0];
- lar->area[3][1]= lar->co[1] + xsize*lar->mat[0][1] - ysize*lar->mat[1][1];
- lar->area[3][2]= lar->co[2] + xsize*lar->mat[0][2] - ysize*lar->mat[1][2];
+ lar->area[3][0] = lar->co[0] + xsize * lar->mat[0][0] - ysize * lar->mat[1][0];
+ lar->area[3][1] = lar->co[1] + xsize * lar->mat[0][1] - ysize * lar->mat[1][1];
+ lar->area[3][2] = lar->co[2] + xsize * lar->mat[0][2] - ysize * lar->mat[1][2];
/* only for correction button size, matrix size works on energy */
- lar->areasize= lar->dist*lar->dist/(4.0*xsize*ysize);
+ lar->areasize = lar->dist * lar->dist / (4.0f * xsize * ysize);
}
#endif
@@ -549,8 +617,8 @@ static void do_colorband_blend(GPUMaterial *mat, ColorBand *coba, GPUNodeLink *f
static void ramp_diffuse_result(GPUShadeInput *shi, GPUNodeLink **diff)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac;
if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS)) {
@@ -579,18 +647,18 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G
else {
/* input */
switch (ma->rampin_col) {
- case MA_RAMP_IN_ENERGY:
- GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
- break;
- case MA_RAMP_IN_SHADER:
- fac= is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
+ case MA_RAMP_IN_ENERGY:
+ GPU_link(mat, "ramp_rgbtobw", rgb, &fac);
+ break;
+ case MA_RAMP_IN_SHADER:
+ fac= is;
+ break;
+ case MA_RAMP_IN_NOR:
+ GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
+ break;
+ default:
+ GPU_link(mat, "set_value_zero", &fac);
+ break;
}
/* colorband + blend */
@@ -606,12 +674,12 @@ static void add_to_diffuse(GPUMaterial *mat, Material *ma, GPUShadeInput *shi, G
static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac;
if (!(mat->scene->gm.flag & GAME_GLSL_NO_RAMPS) &&
- ma->ramp_spec && ma->rampin_spec==MA_RAMP_IN_RESULT)
+ ma->ramp_spec && ma->rampin_spec == MA_RAMP_IN_RESULT)
{
GPU_link(mat, "ramp_rgbtobw", *spec, &fac);
@@ -622,29 +690,29 @@ static void ramp_spec_result(GPUShadeInput *shi, GPUNodeLink **spec)
static void do_specular_ramp(GPUShadeInput *shi, GPUNodeLink *is, GPUNodeLink *t, GPUNodeLink **spec)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *fac, *tmp;
*spec = shi->specrgb;
/* MA_RAMP_IN_RESULT is exception */
- if (ma->ramp_spec && (ma->rampin_spec!=MA_RAMP_IN_RESULT)) {
+ if (ma->ramp_spec && (ma->rampin_spec != MA_RAMP_IN_RESULT)) {
/* input */
switch (ma->rampin_spec) {
- case MA_RAMP_IN_ENERGY:
- fac = t;
- break;
- case MA_RAMP_IN_SHADER:
- fac = is;
- break;
- case MA_RAMP_IN_NOR:
- GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
- break;
- default:
- GPU_link(mat, "set_value_zero", &fac);
- break;
+ case MA_RAMP_IN_ENERGY:
+ fac = t;
+ break;
+ case MA_RAMP_IN_SHADER:
+ fac = is;
+ break;
+ case MA_RAMP_IN_NOR:
+ GPU_link(mat, "vec_math_dot", shi->view, shi->vn, &tmp, &fac);
+ break;
+ default:
+ GPU_link(mat, "set_value_zero", &fac);
+ break;
}
/* colorband + blend */
@@ -666,10 +734,10 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **
int i;
float one = 1.f;
- for (i=0; i<MAX_MTEX; ++i) {
+ for (i = 0; i < MAX_MTEX; ++i) {
mtex = lamp->la->mtex[i];
- if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) {
+ if (mtex && mtex->tex->type & TEX_IMAGE && mtex->tex->ima) {
mat->dynproperty |= DYN_LAMP_PERSMAT;
GPU_link(mat, "shade_light_texture",
@@ -677,29 +745,31 @@ static void shade_light_textures(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **
GPU_image(mtex->tex->ima, &mtex->tex->iuser, false),
GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
&tex_rgb);
- texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb);
+ texture_rgb_blend(mat, tex_rgb, *rgb, GPU_uniform(&one), GPU_uniform(&mtex->colfac), mtex->blendtype, rgb);
}
}
}
static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *lamp)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *lv, *dist, *visifac, *is, *inp, *i, *vn, *view;
- GPUNodeLink *outcol, *specfac, *t, *shadfac= NULL, *lcol;
+ GPUNodeLink *outcol, *specfac, *t, *shadfac = NULL, *lcol;
float one = 1.0f;
if ((lamp->mode & LA_ONLYSHADOW) && !(ma->mode & MA_SHADOW))
return;
- vn= shi->vn;
- view= shi->view;
+ vn = shi->vn;
+ view = shi->view;
- visifac= lamp_get_visibility(mat, lamp, &lv, &dist);
+ visifac = lamp_get_visibility(mat, lamp, &lv, &dist);
- /*if (ma->mode & MA_TANGENT_V)
- GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);*/
+#if 0
+ if (ma->mode & MA_TANGENT_V)
+ GPU_link(mat, "shade_tangent_v", lv, GPU_attribute(CD_TANGENT, ""), &vn);
+#endif
GPU_link(mat, "shade_inp", vn, lv, &inp);
@@ -711,23 +781,23 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
}
else {
if (lamp->type == LA_AREA) {
- float area[4][4]= {{0.0f}}, areasize= 0.0f;
+ float area[4][4] = {{0.0f}}, areasize = 0.0f;
mat->dynproperty |= DYN_LAMP_VEC|DYN_LAMP_CO;
GPU_link(mat, "shade_inp_area", GPU_builtin(GPU_VIEW_POSITION), GPU_dynamic_uniform(lamp->dynco, GPU_DYNAMIC_LAMP_DYNCO, lamp->ob), GPU_dynamic_uniform(lamp->dynvec, GPU_DYNAMIC_LAMP_DYNVEC, lamp->ob), vn, GPU_uniform((float*)area),
GPU_uniform(&areasize), GPU_uniform(&lamp->k), &inp);
}
- is= inp; /* Lambert */
+ is = inp; /* Lambert */
if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADERS)) {
- if (ma->diff_shader==MA_DIFF_ORENNAYAR)
+ if (ma->diff_shader == MA_DIFF_ORENNAYAR)
GPU_link(mat, "shade_diffuse_oren_nayer", inp, vn, lv, view, GPU_uniform(&ma->roughness), &is);
- else if (ma->diff_shader==MA_DIFF_TOON)
+ else if (ma->diff_shader == MA_DIFF_TOON)
GPU_link(mat, "shade_diffuse_toon", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
- else if (ma->diff_shader==MA_DIFF_MINNAERT)
+ else if (ma->diff_shader == MA_DIFF_MINNAERT)
GPU_link(mat, "shade_diffuse_minnaert", inp, vn, view, GPU_uniform(&ma->darkness), &is);
- else if (ma->diff_shader==MA_DIFF_FRESNEL)
+ else if (ma->diff_shader == MA_DIFF_FRESNEL)
GPU_link(mat, "shade_diffuse_fresnel", vn, lv, view, GPU_uniform(&ma->param[0]), GPU_uniform(&ma->param[1]), &is);
}
}
@@ -739,8 +809,9 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
i = is;
GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i);
- GPU_link(mat, "set_value", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob), &lcol);
shade_light_textures(mat, lamp, &lcol);
+ GPU_link(mat, "shade_mul_value_v3", GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob), lcol, &lcol);
#if 0
if (ma->mode & MA_TANGENT_VN)
@@ -748,7 +819,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
#endif
/* this replaces if (i > 0.0) conditional until that is supported */
- // done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i);
+ /* done in shade_visifac now, GPU_link(mat, "mtex_value_clamp_positive", i, &i); */
if ((ma->mode & MA_SHADOW) && GPU_lamp_has_shadow_buffer(lamp)) {
if (!(mat->scene->gm.flag & GAME_GLSL_NO_SHADOWS)) {
@@ -821,18 +892,18 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la
GPU_link(mat, "shade_add_clamped", shr->spec, outcol, &shr->spec);
}
else {
- if (ma->spec_shader==MA_SPEC_PHONG)
+ if (ma->spec_shader == MA_SPEC_PHONG)
GPU_link(mat, "shade_phong_spec", vn, lv, view, shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_COOKTORR)
+ else if (ma->spec_shader == MA_SPEC_COOKTORR)
GPU_link(mat, "shade_cooktorr_spec", vn, lv, view, shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_BLINN)
+ else if (ma->spec_shader == MA_SPEC_BLINN)
GPU_link(mat, "shade_blinn_spec", vn, lv, view, GPU_uniform(&ma->refrac), shi->har, &specfac);
- else if (ma->spec_shader==MA_SPEC_WARDISO)
+ else if (ma->spec_shader == MA_SPEC_WARDISO)
GPU_link(mat, "shade_wardiso_spec", vn, lv, view, GPU_uniform(&ma->rms), &specfac);
else
GPU_link(mat, "shade_toon_spec", vn, lv, view, GPU_uniform(&ma->param[2]), GPU_uniform(&ma->param[3]), &specfac);
- if (lamp->type==LA_AREA)
+ if (lamp->type == LA_AREA)
GPU_link(mat, "shade_spec_area_inp", specfac, inp, &specfac);
GPU_link(mat, "shade_spec_t", shadfac, shi->spec, visifac, specfac, &t);
@@ -862,9 +933,9 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
GPULamp *lamp;
for (SETLOOPER(shi->gpumat->scene, sce_iter, base)) {
- ob= base->object;
+ ob = base->object;
- if (ob->type==OB_LAMP) {
+ if (ob->type == OB_LAMP) {
lamp = GPU_lamp_from_blender(shi->gpumat->scene, ob, NULL);
if (lamp)
shade_one_light(shi, shr, lamp);
@@ -874,10 +945,10 @@ static void material_lights(GPUShadeInput *shi, GPUShadeResult *shr)
DupliObject *dob;
ListBase *lb = object_duplilist(G.main->eval_ctx, shi->gpumat->scene, ob);
- for (dob=lb->first; dob; dob=dob->next) {
+ for (dob = lb->first; dob; dob = dob->next) {
Object *ob_iter = dob->ob;
- if (ob_iter->type==OB_LAMP) {
+ if (ob_iter->type == OB_LAMP) {
float omat[4][4];
copy_m4_m4(omat, ob_iter->obmat);
copy_m4_m4(ob_iter->obmat, dob->mat);
@@ -994,8 +1065,8 @@ static void texture_value_blend(GPUMaterial *mat, GPUNodeLink *tex, GPUNodeLink
static void do_material_tex(GPUShadeInput *shi)
{
- Material *ma= shi->mat;
- GPUMaterial *mat= shi->gpumat;
+ Material *ma = shi->mat;
+ GPUMaterial *mat = shi->gpumat;
MTex *mtex;
Tex *tex;
GPUNodeLink *texco, *tin, *trgb, *tnor, *tcol, *stencil, *tnorfac;
@@ -1006,9 +1077,9 @@ static void do_material_tex(GPUShadeInput *shi)
float one = 1.0f, norfac, ofs[3];
int tex_nr, rgbnor, talpha;
bool init_done = false;
- int iBumpSpacePrev = 0; /* Not necessary, quiting gcc warning. */
+ int iBumpSpacePrev = 0; /* Not necessary, quieting gcc warning. */
GPUNodeLink *vNorg, *vNacc, *fPrevMagnitude;
- int iFirstTimeNMap=1;
+ int iFirstTimeNMap = 1;
int found_deriv_map = 0;
GPU_link(mat, "set_value", GPU_uniform(&one), &stencil);
@@ -1018,44 +1089,46 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "texco_object", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
GPU_builtin(GPU_VIEW_POSITION), &texco_object);
- //GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
+#if 0
+ GPU_link(mat, "texco_tangent", GPU_attribute(CD_TANGENT, ""), &texco_tangent);
+#endif
GPU_link(mat, "texco_global", GPU_builtin(GPU_INVERSE_VIEW_MATRIX),
GPU_builtin(GPU_VIEW_POSITION), &texco_global);
orn= texco_norm;
/* go over texture slots */
- for (tex_nr=0; tex_nr<MAX_MTEX; tex_nr++) {
+ for (tex_nr = 0; tex_nr < MAX_MTEX; tex_nr++) {
/* separate tex switching */
- if (ma->septex & (1<<tex_nr)) continue;
+ if (ma->septex & (1 << tex_nr)) continue;
if (ma->mtex[tex_nr]) {
- mtex= ma->mtex[tex_nr];
+ mtex = ma->mtex[tex_nr];
- tex= mtex->tex;
+ tex = mtex->tex;
if (tex == NULL) continue;
/* which coords */
- if (mtex->texco==TEXCO_ORCO)
- texco= texco_orco;
- else if (mtex->texco==TEXCO_OBJECT)
- texco= texco_object;
- else if (mtex->texco==TEXCO_NORM)
- texco= orn;
- else if (mtex->texco==TEXCO_TANGENT)
- texco= texco_object;
- else if (mtex->texco==TEXCO_GLOB)
- texco= texco_global;
- else if (mtex->texco==TEXCO_REFL) {
+ if (mtex->texco == TEXCO_ORCO)
+ texco = texco_orco;
+ else if (mtex->texco == TEXCO_OBJECT)
+ texco = texco_object;
+ else if (mtex->texco == TEXCO_NORM)
+ texco = orn;
+ else if (mtex->texco == TEXCO_TANGENT)
+ texco = texco_object;
+ else if (mtex->texco == TEXCO_GLOB)
+ texco = texco_global;
+ else if (mtex->texco == TEXCO_REFL) {
GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
- texco= shi->ref;
+ texco = shi->ref;
}
- else if (mtex->texco==TEXCO_UV) {
+ else if (mtex->texco == TEXCO_UV) {
if (1) { //!(texco_uv && strcmp(mtex->uvname, lastuvname) == 0)) {
GPU_link(mat, "texco_uv", GPU_attribute(CD_MTFACE, mtex->uvname), &texco_uv);
/*lastuvname = mtex->uvname;*/ /*UNUSED*/
}
- texco= texco_uv;
+ texco = texco_uv;
}
else
continue;
@@ -1067,8 +1140,8 @@ static void do_material_tex(GPUShadeInput *shi)
if (mtex->size[0] != 1.0f || mtex->size[1] != 1.0f || mtex->size[2] != 1.0f)
GPU_link(mat, "mtex_mapping_size", texco, GPU_uniform(mtex->size), &texco);
- ofs[0] = mtex->ofs[0] + 0.5f - 0.5f*mtex->size[0];
- ofs[1] = mtex->ofs[1] + 0.5f - 0.5f*mtex->size[1];
+ ofs[0] = mtex->ofs[0] + 0.5f - 0.5f * mtex->size[0];
+ ofs[1] = mtex->ofs[1] + 0.5f - 0.5f * mtex->size[1];
ofs[2] = 0.0f;
if (ofs[0] != 0.0f || ofs[1] != 0.0f || ofs[2] != 0.0f)
GPU_link(mat, "mtex_mapping_ofs", texco, GPU_uniform(ofs), &texco);
@@ -1077,7 +1150,7 @@ static void do_material_tex(GPUShadeInput *shi)
if (tex && tex->type == TEX_IMAGE && tex->ima) {
GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, false), &tin, &trgb);
- rgbnor= TEX_RGB;
+ rgbnor = TEX_RGB;
talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0);
}
@@ -1122,7 +1195,7 @@ static void do_material_tex(GPUShadeInput *shi)
GPU_link(mat, "set_value_one", &tin);
}
- if (tex->type==TEX_IMAGE)
+ if (tex->type == TEX_IMAGE)
if (GPU_material_do_color_management(mat))
GPU_link(mat, "srgb_to_linearrgb", tcol, &tcol);
@@ -1146,7 +1219,7 @@ static void do_material_tex(GPUShadeInput *shi)
}
if (!(mat->scene->gm.flag & GAME_GLSL_NO_EXTRA_TEX) && (mtex->mapto & MAP_NORM)) {
- if (tex->type==TEX_IMAGE) {
+ if (tex->type == TEX_IMAGE) {
found_deriv_map = tex->imaflag & TEX_DERIVATIVEMAP;
if (tex->imaflag & TEX_NORMALMAP) {
@@ -1170,7 +1243,7 @@ static void do_material_tex(GPUShadeInput *shi)
}
else if (mtex->normapspace == MTEX_NSPACE_OBJECT) {
/* transform normal by object then view matrix */
- GPU_link(mat, "mtex_nspace_object", GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), tnor, &newnor);
+ GPU_link(mat, "mtex_nspace_object", tnor, &newnor);
}
else if (mtex->normapspace == MTEX_NSPACE_WORLD) {
/* transform normal by view matrix */
@@ -1196,44 +1269,43 @@ static void do_material_tex(GPUShadeInput *shi)
}
}
- else if ( (mtex->texflag & (MTEX_3TAP_BUMP|MTEX_5TAP_BUMP|MTEX_BICUBIC_BUMP)) || found_deriv_map) {
+ else if ((mtex->texflag & (MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) || found_deriv_map) {
/* ntap bumpmap image */
int iBumpSpace;
float ima_x, ima_y;
float hScale;
- float imag_tspace_dimension_x = 1024.0f; // only used for texture space variant
+ float imag_tspace_dimension_x = 1024.0f; /* only used for texture space variant */
float aspect = 1.0f;
- GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
GPUNodeLink *vR1, *vR2;
GPUNodeLink *dBs, *dBt, *fDet;
- hScale = 0.1; // compatibility adjustment factor for all bumpspace types
- if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
- hScale = 13.0f; // factor for scaling texspace bumps
+ hScale = 0.1; /* compatibility adjustment factor for all bumpspace types */
+ if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
+ hScale = 13.0f; /* factor for scaling texspace bumps */
else if (found_deriv_map!=0)
hScale = 1.0f;
- // resolve texture resolution
- if ( (mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map ) {
- ImBuf *ibuf= BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
- ima_x= 512.0f; ima_y= 512.f; // prevent calling textureSize, glsl 1.3 only
+ /* resolve texture resolution */
+ if ((mtex->texflag & MTEX_BUMP_TEXTURESPACE) || found_deriv_map) {
+ ImBuf *ibuf = BKE_image_acquire_ibuf(tex->ima, &tex->iuser, NULL);
+ ima_x = 512.0f; ima_y = 512.f; /* prevent calling textureSize, glsl 1.3 only */
if (ibuf) {
- ima_x= ibuf->x;
- ima_y= ibuf->y;
- aspect = ((float) ima_y) / ima_x;
+ ima_x = ibuf->x;
+ ima_y = ibuf->y;
+ aspect = (float)ima_y / ima_x;
}
BKE_image_release_ibuf(tex->ima, ibuf, NULL);
}
- // The negate on norfac is done because the
- // normal in the renderer points inward which corresponds
- // to inverting the bump map. Should this ever change
- // this negate must be removed.
+ /* The negate on norfac is done because the
+ * normal in the renderer points inward which corresponds
+ * to inverting the bump map. Should this ever change
+ * this negate must be removed. */
norfac = -hScale * mtex->norfac;
if (found_deriv_map) {
- float fVirtDim = sqrtf(fabsf(ima_x*mtex->size[0]*ima_y*mtex->size[1]));
+ float fVirtDim = sqrtf(fabsf(ima_x * mtex->size[0] * ima_y * mtex->size[1]));
norfac /= MAX2(fVirtDim, FLT_EPSILON);
}
@@ -1245,25 +1317,26 @@ static void do_material_tex(GPUShadeInput *shi)
if (GPU_link_changed(stencil))
GPU_link(mat, "math_multiply", tnorfac, stencil, &tnorfac);
- if ( !init_done ) {
- // copy shi->vn to vNorg and vNacc, set magnitude to 1
+ if (!init_done) {
+ /* copy shi->vn to vNorg and vNacc, set magnitude to 1 */
GPU_link(mat, "mtex_bump_normals_init", shi->vn, &vNorg, &vNacc, &fPrevMagnitude);
iBumpSpacePrev = 0;
init_done = true;
}
// find current bump space
- if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
+ if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
iBumpSpace = 1;
- else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
+ else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
iBumpSpace = 2;
else
- iBumpSpace = 4; // ViewSpace
+ iBumpSpace = 4; /* ViewSpace */
- // re-initialize if bump space changed
- if ( iBumpSpacePrev != iBumpSpace ) {
-
- if ( mtex->texflag & MTEX_BUMP_OBJECTSPACE )
+ /* re-initialize if bump space changed */
+ if (iBumpSpacePrev != iBumpSpace) {
+ GPUNodeLink *surf_pos = GPU_builtin(GPU_VIEW_POSITION);
+
+ if (mtex->texflag & MTEX_BUMP_OBJECTSPACE)
GPU_link(mat, "mtex_bump_init_objspace",
surf_pos, vNorg,
GPU_builtin(GPU_VIEW_MATRIX), GPU_builtin(GPU_INVERSE_VIEW_MATRIX), GPU_builtin(GPU_OBJECT_MATRIX), GPU_builtin(GPU_INVERSE_OBJECT_MATRIX),
@@ -1271,7 +1344,7 @@ static void do_material_tex(GPUShadeInput *shi)
&fPrevMagnitude, &vNacc,
&vR1, &vR2, &fDet);
- else if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE )
+ else if (mtex->texflag & MTEX_BUMP_TEXTURESPACE)
GPU_link(mat, "mtex_bump_init_texturespace",
surf_pos, vNorg,
fPrevMagnitude, vNacc,
@@ -1292,17 +1365,17 @@ static void do_material_tex(GPUShadeInput *shi)
if (found_deriv_map) {
GPU_link(mat, "mtex_bump_deriv",
texco, GPU_image(tex->ima, &tex->iuser, true), GPU_uniform(&ima_x), GPU_uniform(&ima_y), tnorfac,
- &dBs, &dBt );
+ &dBs, &dBt);
}
- else if ( mtex->texflag & MTEX_3TAP_BUMP)
+ else if (mtex->texflag & MTEX_3TAP_BUMP)
GPU_link(mat, "mtex_bump_tap3",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt );
- else if ( mtex->texflag & MTEX_5TAP_BUMP)
+ &dBs, &dBt);
+ else if (mtex->texflag & MTEX_5TAP_BUMP)
GPU_link(mat, "mtex_bump_tap5",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
- &dBs, &dBt );
- else if ( mtex->texflag & MTEX_BICUBIC_BUMP ) {
+ &dBs, &dBt);
+ else if (mtex->texflag & MTEX_BICUBIC_BUMP) {
if (GPU_bicubic_bump_support()) {
GPU_link(mat, "mtex_bump_bicubic",
texco, GPU_image(tex->ima, &tex->iuser, true), tnorfac,
@@ -1316,18 +1389,18 @@ static void do_material_tex(GPUShadeInput *shi)
}
- if ( mtex->texflag & MTEX_BUMP_TEXTURESPACE ) {
- float imag_tspace_dimension_y = aspect*imag_tspace_dimension_x;
+ if (mtex->texflag & MTEX_BUMP_TEXTURESPACE) {
+ float imag_tspace_dimension_y = aspect * imag_tspace_dimension_x;
GPU_link(mat, "mtex_bump_apply_texspace",
fDet, dBs, dBt, vR1, vR2,
GPU_image(tex->ima, &tex->iuser, true), texco,
GPU_uniform(&imag_tspace_dimension_x), GPU_uniform(&imag_tspace_dimension_y), vNacc,
- &vNacc, &shi->vn );
+ &vNacc, &shi->vn);
}
else
GPU_link(mat, "mtex_bump_apply",
fDet, dBs, dBt, vR1, vR2, vNacc,
- &vNacc, &shi->vn );
+ &vNacc, &shi->vn);
}
}
@@ -1405,7 +1478,6 @@ static void do_material_tex(GPUShadeInput *shi)
void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
{
- float hard = ma->har;
float one = 1.0f;
memset(shi, 0, sizeof(*shi));
@@ -1413,20 +1485,21 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
shi->gpumat = mat;
shi->mat = ma;
- GPU_link(mat, "set_rgb", GPU_uniform(&ma->r), &shi->rgb);
- GPU_link(mat, "set_rgb", GPU_uniform(&ma->specr), &shi->specrgb);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->r, GPU_DYNAMIC_MAT_DIFFRGB, NULL), &shi->rgb);
+ GPU_link(mat, "set_rgb", GPU_dynamic_uniform(&ma->specr, GPU_DYNAMIC_MAT_SPECRGB, NULL), &shi->specrgb);
GPU_link(mat, "shade_norm", GPU_builtin(GPU_VIEW_NORMAL), &shi->vn);
if (mat->alpha)
- GPU_link(mat, "set_value", GPU_uniform(&ma->alpha), &shi->alpha);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->alpha, GPU_DYNAMIC_MAT_ALPHA, NULL), &shi->alpha);
else
GPU_link(mat, "set_value", GPU_uniform(&one), &shi->alpha);
- GPU_link(mat, "set_value", GPU_uniform(&ma->ref), &shi->refl);
- GPU_link(mat, "set_value", GPU_uniform(&ma->spec), &shi->spec);
- GPU_link(mat, "set_value", GPU_uniform(&ma->emit), &shi->emit);
- GPU_link(mat, "set_value", GPU_uniform(&hard), &shi->har);
- GPU_link(mat, "set_value", GPU_uniform(&ma->amb), &shi->amb);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->ref, GPU_DYNAMIC_MAT_REF, NULL), &shi->refl);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->spec, GPU_DYNAMIC_MAT_SPEC, NULL), &shi->spec);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->emit, GPU_DYNAMIC_MAT_EMIT, NULL), &shi->emit);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform((float*)&ma->har, GPU_DYNAMIC_MAT_HARD, NULL), &shi->har);
+ GPU_link(mat, "set_value", GPU_dynamic_uniform(&ma->amb, GPU_DYNAMIC_MAT_AMB, NULL), &shi->amb);
+ GPU_link(mat, "set_value", GPU_uniform(&ma->spectra), &shi->spectra);
GPU_link(mat, "shade_view", GPU_builtin(GPU_VIEW_POSITION), &shi->view);
GPU_link(mat, "vcol_attribute", GPU_attribute(CD_MCOL, ""), &shi->vcol);
if (GPU_material_do_color_management(mat))
@@ -1434,13 +1507,39 @@ void GPU_shadeinput_set(GPUMaterial *mat, Material *ma, GPUShadeInput *shi)
GPU_link(mat, "texco_refl", shi->vn, shi->view, &shi->ref);
}
+void GPU_mist_update_enable(short enable)
+{
+ GPUWorld.mistenabled = (float)enable;
+}
+
+void GPU_mist_update_values(int type, float start, float dist, float inten, float color[3])
+{
+ GPUWorld.mistype = (float)type;
+ GPUWorld.miststart = start;
+ GPUWorld.mistdistance = dist;
+ GPUWorld.mistintensity = inten;
+ copy_v3_v3(GPUWorld.mistcol, color);
+ GPUWorld.mistcol[3] = 1.0f;
+}
+
+void GPU_horizon_update_color(float color[3])
+{
+ copy_v3_v3(GPUWorld.horicol, color);
+}
+
+void GPU_ambient_update_color(float color[3])
+{
+ copy_v3_v3(GPUWorld.ambcol, color);
+ GPUWorld.ambcol[3] = 1.0f;
+}
+
void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
{
- GPUMaterial *mat= shi->gpumat;
+ GPUMaterial *mat = shi->gpumat;
GPUNodeLink *emit, *ulinfac, *ulogfac, *mistfac;
- Material *ma= shi->mat;
- World *world= mat->scene->world;
- float linfac, logfac, misttype;
+ Material *ma = shi->mat;
+ World *world = mat->scene->world;
+ float linfac, logfac;
memset(shr, 0, sizeof(*shr));
@@ -1457,7 +1556,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
}
else {
if (GPU_link_changed(shi->emit) || ma->emit != 0.0f) {
- if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP))== MA_VERTEXCOL) {
+ if ((ma->mode & (MA_VERTEXCOL|MA_VERTEXCOLP)) == MA_VERTEXCOL) {
GPU_link(mat, "shade_add", shi->emit, shi->vcol, &emit);
GPU_link(mat, "shade_mul", emit, shi->rgb, &shr->diff);
}
@@ -1477,9 +1576,9 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
if (world) {
/* exposure correction */
- if (world->exp!=0.0f || world->range!=1.0f) {
- linfac= 1.0f + powf((2.0f*world->exp + 0.5f), -10);
- logfac= logf((linfac-1.0f)/linfac)/world->range;
+ if (world->exp != 0.0f || world->range != 1.0f) {
+ linfac = 1.0f + powf((2.0f * world->exp + 0.5f), -10);
+ logfac = logf((linfac - 1.0f) / linfac) / world->range;
GPU_link(mat, "set_value", GPU_uniform(&linfac), &ulinfac);
GPU_link(mat, "set_value", GPU_uniform(&logfac), &ulogfac);
@@ -1491,13 +1590,19 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
}
/* ambient color */
- if (world->ambr!=0.0f || world->ambg!=0.0f || world->ambb!=0.0f) {
- if (GPU_link_changed(shi->amb) || ma->amb != 0.0f)
- GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
- GPU_uniform(&world->ambr), &shr->combined);
+ if (GPU_link_changed(shi->amb) || ma->amb != 0.0f) {
+ GPU_link(mat, "shade_maddf", shr->combined, GPU_uniform(&ma->amb),
+ GPU_dynamic_uniform(GPUWorld.ambcol, GPU_DYNAMIC_AMBIENT_COLOR, NULL),
+ &shr->combined);
}
}
+ if (ma->mode & MA_TRANSP && (ma->mode & (MA_ZTRANSP|MA_RAYTRANSP))) {
+ if (GPU_link_changed(shi->spectra) || ma->spectra != 0.0f)
+ GPU_link(mat, "alpha_spec_correction", shr->spec, shi->spectra,
+ shi->alpha, &shr->alpha);
+ }
+
if (ma->mode & MA_RAMP_COL) ramp_diffuse_result(shi, &shr->combined);
if (ma->mode & MA_RAMP_SPEC) ramp_spec_result(shi, &shr->spec);
@@ -1510,21 +1615,22 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr)
if (ma->shade_flag & MA_OBCOLOR)
GPU_link(mat, "shade_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined);
- if (world && (world->mode & WO_MIST) && !(ma->mode & MA_NOMIST)) {
- misttype = world->mistype;
-
+ if (!(ma->mode & MA_NOMIST)) {
GPU_link(mat, "shade_mist_factor", GPU_builtin(GPU_VIEW_POSITION),
- GPU_uniform(&world->miststa), GPU_uniform(&world->mistdist),
- GPU_uniform(&misttype), GPU_uniform(&world->misi), &mistfac);
+ GPU_dynamic_uniform(&GPUWorld.mistenabled, GPU_DYNAMIC_MIST_ENABLE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.miststart, GPU_DYNAMIC_MIST_START, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistdistance, GPU_DYNAMIC_MIST_DISTANCE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistype, GPU_DYNAMIC_MIST_TYPE, NULL),
+ GPU_dynamic_uniform(&GPUWorld.mistintensity, GPU_DYNAMIC_MIST_INTENSITY, NULL), &mistfac);
GPU_link(mat, "mix_blend", mistfac, shr->combined,
- GPU_uniform(&world->horr), &shr->combined);
+ GPU_dynamic_uniform(GPUWorld.mistcol, GPU_DYNAMIC_MIST_COLOR, NULL), &shr->combined);
}
if (!mat->alpha) {
if (world && (GPU_link_changed(shr->alpha) || ma->alpha != 1.0f))
- GPU_link(mat, "shade_world_mix", GPU_uniform(&world->horr),
- shr->combined, &shr->combined);
+ GPU_link(mat, "shade_world_mix", GPU_dynamic_uniform(GPUWorld.horicol, GPU_DYNAMIC_HORIZON_COLOR, NULL),
+ shr->combined, &shr->combined);
GPU_link(mat, "shade_alpha_opaque", shr->combined, &shr->combined);
}
@@ -1570,20 +1676,27 @@ static GPUNodeLink *gpu_material_preview_matcap(GPUMaterial *mat, Material *ma)
}
/* new solid draw mode with glsl matcaps */
-GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
+GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma, bool use_opensubdiv)
{
GPUMaterial *mat;
GPUNodeLink *outlink;
LinkData *link;
- for (link=ma->gpumaterial.first; link; link=link->next)
- if (((GPUMaterial*)link->data)->scene == scene)
- return link->data;
+ for (link = ma->gpumaterial.first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial*)link->data;
+ if (current_material->scene == scene &&
+ current_material->is_opensubdiv == use_opensubdiv)
+ {
+ return current_material;
+ }
+ }
/* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
-
+ mat->type = GPU_MATERIAL_TYPE_MESH;
+ mat->is_opensubdiv = use_opensubdiv;
+
if (ma->preview && ma->preview->rect[0]) {
outlink = gpu_material_preview_matcap(mat, ma);
}
@@ -1593,7 +1706,7 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
GPU_material_output_link(mat, outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, "matcap_pass");
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1606,19 +1719,65 @@ GPUMaterial *GPU_material_matcap(Scene *scene, Material *ma)
return mat;
}
-GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
+GPUMaterial *GPU_material_world(struct Scene *scene, struct World *wo)
{
- GPUMaterial *mat;
- GPUNodeLink *outlink;
LinkData *link;
+ GPUMaterial *mat;
- for (link=ma->gpumaterial.first; link; link=link->next)
+ for (link = wo->gpumaterial.first; link; link = link->next)
if (((GPUMaterial*)link->data)->scene == scene)
return link->data;
/* allocate material */
+ mat = GPU_material_construct_begin(NULL);
+ mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_WORLD;
+
+ /* create nodes */
+ if (BKE_scene_use_new_shading_nodes(scene) && wo->nodetree && wo->use_nodes)
+ ntreeGPUMaterialNodes(wo->nodetree, mat, NODE_NEW_SHADING);
+ else {
+ /* old fixed function world */
+ }
+
+ if (GPU_material_do_color_management(mat))
+ if (mat->outlink)
+ GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
+
+ GPU_material_construct_end(mat, wo->id.name);
+
+ /* note that even if building the shader fails in some way, we still keep
+ * it to avoid trying to compile again and again, and simple do not use
+ * the actual shader on drawing */
+
+ link = MEM_callocN(sizeof(LinkData), "GPUMaterialLink");
+ link->data = mat;
+ BLI_addtail(&wo->gpumaterial, link);
+
+ return mat;
+}
+
+
+GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma, bool use_opensubdiv)
+{
+ GPUMaterial *mat;
+ GPUNodeLink *outlink;
+ LinkData *link;
+
+ for (link = ma->gpumaterial.first; link; link = link->next) {
+ GPUMaterial *current_material = (GPUMaterial*)link->data;
+ if (current_material->scene == scene &&
+ current_material->is_opensubdiv == use_opensubdiv)
+ {
+ return current_material;
+ }
+ }
+
+ /* allocate material */
mat = GPU_material_construct_begin(ma);
mat->scene = scene;
+ mat->type = GPU_MATERIAL_TYPE_MESH;
+ mat->is_opensubdiv = use_opensubdiv;
/* render pipeline option */
if (ma->mode & MA_TRANSP)
@@ -1648,7 +1807,7 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma)
if (mat->outlink)
GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink);
- GPU_material_construct_end(mat);
+ GPU_material_construct_end(mat, ma->id.name);
/* note that even if building the shader fails in some way, we still keep
* it to avoid trying to compile again and again, and simple do not use
@@ -1665,14 +1824,18 @@ void GPU_materials_free(void)
{
Object *ob;
Material *ma;
+ World *wo;
extern Material defmaterial;
- for (ma=G.main->mat.first; ma; ma=ma->id.next)
- GPU_material_free(ma);
+ for (ma = G.main->mat.first; ma; ma = ma->id.next)
+ GPU_material_free(&ma->gpumaterial);
- GPU_material_free(&defmaterial);
+ for (wo = G.main->world.first; wo; wo = wo->id.next)
+ GPU_material_free(&wo->gpumaterial);
+
+ GPU_material_free(&defmaterial.gpumaterial);
- for (ob=G.main->object.first; ob; ob=ob->id.next)
+ for (ob = G.main->object.first; ob; ob = ob->id.next)
GPU_lamp_free(ob);
}
@@ -1687,10 +1850,10 @@ static void gpu_lamp_calc_winmat(GPULamp *lamp)
orthographic_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
}
else {
- angle= saacos(lamp->spotsi);
- temp= 0.5f*lamp->size*cosf(angle)/sinf(angle);
- pixsize= (lamp->d)/temp;
- wsize= pixsize*0.5f*lamp->size;
+ angle = saacos(lamp->spotsi);
+ temp = 0.5f * lamp->size * cosf(angle) / sinf(angle);
+ pixsize = lamp->d / temp;
+ wsize = pixsize * 0.5f * lamp->size;
perspective_m4(lamp->winmat, -wsize, wsize, -wsize, wsize, lamp->d, lamp->clipend);
}
}
@@ -1714,11 +1877,11 @@ 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)
{
lamp->energy = energy;
- if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
- lamp->col[0]= r* lamp->energy;
- lamp->col[1]= g* lamp->energy;
- lamp->col[2]= b* 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)
@@ -1748,11 +1911,11 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
lamp->type = la->type;
lamp->energy = la->energy;
- if (lamp->mode & LA_NEG) lamp->energy= -lamp->energy;
+ if (lamp->mode & LA_NEG) lamp->energy = -lamp->energy;
- lamp->col[0]= la->r*lamp->energy;
- lamp->col[1]= la->g*lamp->energy;
- lamp->col[2]= la->b*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);
@@ -1761,20 +1924,20 @@ static void gpu_lamp_from_blender(Scene *scene, Object *ob, Object *par, Lamp *l
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->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->curfalloff= la->curfalloff;
+ lamp->dist = la->dist;
+ lamp->falloff_type = la->falloff_type;
+ lamp->att1 = la->att1;
+ lamp->att2 = la->att2;
+ lamp->curfalloff = la->curfalloff;
/* initshadowbuf */
- lamp->bias = 0.02f*la->bias;
+ lamp->bias = 0.02f * la->bias;
lamp->size = la->bufsize;
- lamp->d= la->clipsta;
- lamp->clipend= la->clipend;
+ lamp->d = la->clipsta;
+ lamp->clipend = la->clipend;
/* arbitrary correction for the fact we do no soft transition */
lamp->bias *= 0.25f;
@@ -1787,23 +1950,23 @@ static void gpu_lamp_shadow_free(GPULamp *lamp)
{
if (lamp->tex) {
GPU_texture_free(lamp->tex);
- lamp->tex= NULL;
+ lamp->tex = NULL;
}
if (lamp->depthtex) {
GPU_texture_free(lamp->depthtex);
- lamp->depthtex= NULL;
+ lamp->depthtex = NULL;
}
if (lamp->fb) {
GPU_framebuffer_free(lamp->fb);
- lamp->fb= NULL;
+ lamp->fb = NULL;
}
if (lamp->blurtex) {
GPU_texture_free(lamp->blurtex);
- lamp->blurtex= NULL;
+ lamp->blurtex = NULL;
}
if (lamp->blurfb) {
GPU_framebuffer_free(lamp->blurfb);
- lamp->blurfb= NULL;
+ lamp->blurfb = NULL;
}
}
@@ -1813,7 +1976,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
GPULamp *lamp;
LinkData *link;
- for (link=ob->gpulamp.first; link; link=link->next) {
+ for (link = ob->gpulamp.first; link; link = link->next) {
lamp = (GPULamp*)link->data;
if (lamp->par == par && lamp->scene == scene)
@@ -1829,7 +1992,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
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))) {
+ 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) {
@@ -1845,7 +2008,7 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->depthtex, 0, NULL)) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
@@ -1857,11 +2020,16 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
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) {
@@ -1869,16 +2037,26 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size*0.5, NULL);
+ lamp->blurtex = GPU_texture_create_vsm_shadow_map(lamp->size * 0.5, NULL);
if (!lamp->blurtex) {
gpu_lamp_shadow_free(lamp);
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->blurfb, lamp->blurtex, 0, NULL)) {
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);
@@ -1887,10 +2065,15 @@ GPULamp *GPU_lamp_from_blender(Scene *scene, Object *ob, Object *par)
return lamp;
}
- if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, NULL)) {
+ if (!GPU_framebuffer_texture_attach(lamp->fb, lamp->tex, 0, NULL)) {
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();
@@ -1915,7 +2098,7 @@ void GPU_lamp_free(Object *ob)
LinkData *nlink;
Material *ma;
- for (link=ob->gpulamp.first; link; link=link->next) {
+ for (link = ob->gpulamp.first; link; link = link->next) {
lamp = link->data;
while (lamp->materials.first) {
@@ -1924,7 +2107,7 @@ void GPU_lamp_free(Object *ob)
BLI_freelinkN(&lamp->materials, nlink);
if (ma->gpumaterial.first)
- GPU_material_free(ma);
+ GPU_material_free(&ma->gpumaterial);
}
gpu_lamp_shadow_free(lamp);
@@ -1973,8 +2156,7 @@ void GPU_lamp_shadow_buffer_bind(GPULamp *lamp, float viewmat[4][4], int *winsiz
/* opengl */
glDisable(GL_SCISSOR_TEST);
- GPU_framebuffer_texture_bind(lamp->fb, lamp->tex,
- GPU_texture_opengl_width(lamp->tex), GPU_texture_opengl_height(lamp->tex));
+ 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));
@@ -2009,12 +2191,14 @@ int GPU_lamp_shadow_layer(GPULamp *lamp)
return -1;
}
-GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow)
+GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **col, GPUNodeLink **lv, GPUNodeLink **dist, GPUNodeLink **shadow, GPUNodeLink **energy)
{
GPUNodeLink *visifac;
*col = GPU_dynamic_uniform(lamp->dyncol, GPU_DYNAMIC_LAMP_DYNCOL, lamp->ob);
+ *energy = GPU_dynamic_uniform(&lamp->dynenergy, GPU_DYNAMIC_LAMP_DYNENERGY, lamp->ob);
visifac = lamp_get_visibility(mat, lamp, lv, dist);
+
shade_light_textures(mat, lamp, col);
if (GPU_lamp_has_shadow_buffer(lamp)) {
@@ -2026,18 +2210,18 @@ GPUNodeLink *GPU_lamp_get_data(GPUMaterial *mat, GPULamp *lamp, GPUNodeLink **co
if (lamp->la->shadowmap_type == LA_SHADMAP_VARIANCE) {
GPU_link(mat, "shadows_only_vsm",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias),
- GPU_uniform(lamp->shadow_color), inp, shadow);
+ GPU_builtin(GPU_VIEW_POSITION),
+ GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
+ GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
+ GPU_uniform(&lamp->bias), GPU_uniform(&lamp->la->bleedbias),
+ GPU_uniform(lamp->shadow_color), inp, shadow);
}
else {
GPU_link(mat, "shadows_only",
- GPU_builtin(GPU_VIEW_POSITION),
- GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
- GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
- GPU_uniform(&lamp->bias), GPU_uniform(lamp->shadow_color), inp, shadow);
+ GPU_builtin(GPU_VIEW_POSITION),
+ GPU_dynamic_texture(lamp->tex, GPU_DYNAMIC_SAMPLER_2DSHADOW, lamp->ob),
+ GPU_dynamic_uniform((float*)lamp->dynpersmat, GPU_DYNAMIC_LAMP_DYNPERSMAT, lamp->ob),
+ GPU_uniform(&lamp->bias), GPU_uniform(lamp->shadow_color), inp, shadow);
}
}
else {
@@ -2081,7 +2265,8 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
if (!GPU_glsl_support())
return NULL;
- mat = GPU_material_from_blender(scene, ma);
+ /* TODO(sergey): How to detemine whether we need OSD or not here? */
+ mat = GPU_material_from_blender(scene, ma, false);
pass = (mat)? mat->pass: NULL;
if (pass && pass->fragmentcode && pass->vertexcode) {
@@ -2120,33 +2305,49 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
glBindTexture(GL_TEXTURE_2D, lastbindcode);
}
break;
+
+ case GPU_NONE:
+ case GPU_FLOAT:
+ case GPU_VEC2:
+ case GPU_VEC3:
+ case GPU_VEC4:
+ case GPU_MAT3:
+ case GPU_MAT4:
+ case GPU_ATTRIB:
+ break;
}
}
else {
uniform->type = input->dynamictype;
BLI_strncpy(uniform->varname, input->shadername, sizeof(uniform->varname));
switch (input->type) {
- case 1:
+ case GPU_FLOAT:
uniform->datatype = GPU_DATA_1F;
break;
- case 2:
+ case GPU_VEC2:
uniform->datatype = GPU_DATA_2F;
break;
- case 3:
+ case GPU_VEC3:
uniform->datatype = GPU_DATA_3F;
break;
- case 4:
+ case GPU_VEC4:
uniform->datatype = GPU_DATA_4F;
break;
- case 9:
+ case GPU_MAT3:
uniform->datatype = GPU_DATA_9F;
break;
- case 16:
+ case GPU_MAT4:
uniform->datatype = GPU_DATA_16F;
break;
+
+ case GPU_NONE:
+ case GPU_TEX2D:
+ case GPU_SHADOW2D:
+ case GPU_ATTRIB:
+ break;
}
- if (uniform->type >= GPU_DYNAMIC_LAMP_FIRST && uniform->type <= GPU_DYNAMIC_LAMP_LAST)
+ if (GPU_DYNAMIC_GROUP_FROM_TYPE(uniform->type) == GPU_DYNAMIC_GROUP_LAMP)
uniform->lamp = input->dynamicdata;
}
@@ -2157,7 +2358,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
}
/* process builtin uniform */
- for (i=0; builtins[i].gputype; i++) {
+ for (i = 0; builtins[i].gputype; i++) {
if (mat->builtins & builtins[i].gputype) {
uniform = MEM_callocN(sizeof(GPUInputUniform), "GPUInputUniform");
uniform->type = builtins[i].dynamictype;
@@ -2171,14 +2372,14 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
/* TBD: remove the function that are not used in the main function */
liblen = (pass->libcode) ? strlen(pass->libcode) : 0;
fraglen = strlen(pass->fragmentcode);
- shader->fragment = (char *)MEM_mallocN(liblen+fraglen+1, "GPUFragShader");
+ shader->fragment = (char *)MEM_mallocN(liblen + fraglen + 1, "GPUFragShader");
if (pass->libcode)
memcpy(shader->fragment, pass->libcode, liblen);
memcpy(&shader->fragment[liblen], pass->fragmentcode, fraglen);
- shader->fragment[liblen+fraglen] = 0;
+ shader->fragment[liblen + fraglen] = 0;
// export the attribute
- for (i=0; i<mat->attribs.totlayer; i++) {
+ for (i = 0; i < mat->attribs.totlayer; i++) {
attribute = MEM_callocN(sizeof(GPUInputAttribute), "GPUInputAttribute");
attribute->type = mat->attribs.layer[i].type;
attribute->number = mat->attribs.layer[i].glindex;
@@ -2207,7 +2408,7 @@ GPUShaderExport *GPU_shader_export(struct Scene *scene, struct Material *ma)
MEM_freeN(attribute);
}
- // export the vertex shader
+ /* export the vertex shader */
shader->vertex = BLI_strdup(pass->vertexcode);
}
@@ -2221,7 +2422,7 @@ void GPU_free_shader_export(GPUShaderExport *shader)
if (shader == NULL)
return;
- for (uniform = shader->uniforms.first; uniform; uniform=uniform->next)
+ for (uniform = shader->uniforms.first; uniform; uniform = uniform->next)
if (uniform->texpixels)
MEM_freeN(uniform->texpixels);
@@ -2236,3 +2437,54 @@ void GPU_free_shader_export(GPUShaderExport *shader)
MEM_freeN(shader);
}
+#ifdef WITH_OPENSUBDIV
+void GPU_material_update_fvar_offset(GPUMaterial *gpu_material,
+ DerivedMesh *dm)
+{
+ GPUPass *pass = gpu_material->pass;
+ GPUShader *shader = (pass != NULL ? pass->shader : NULL);
+ ListBase *inputs = (pass != NULL ? &pass->inputs : NULL);
+ GPUInput *input;
+
+ if (shader == NULL) {
+ return;
+ }
+
+ GPU_shader_bind(shader);
+
+ for (input = inputs->first;
+ input != NULL;
+ input = input->next)
+ {
+ if (input->source == GPU_SOURCE_ATTRIB &&
+ input->attribtype == CD_MTFACE)
+ {
+ char name[64];
+ /* TODO(sergey): This will work for until names are
+ * consistent, we'll need to solve this somehow in the future.
+ */
+ int layer_index;
+ int location;
+
+ if (input->attribname[0] != '\0') {
+ layer_index = CustomData_get_named_layer(&dm->loopData,
+ CD_MLOOPUV,
+ input->attribname);
+ }
+ else {
+ layer_index = CustomData_get_active_layer(&dm->loopData,
+ CD_MLOOPUV);
+ }
+
+ BLI_snprintf(name, sizeof(name),
+ "fvar%d_offset",
+ input->attribid);
+ location = GPU_shader_get_uniform(shader, name);
+ /* Multiply by 2 because we're offseting U and V variables. */
+ GPU_shader_uniform_int(shader, location, layer_index * 2);
+ }
+ }
+
+ GPU_shader_unbind();
+}
+#endif
diff --git a/source/blender/gpu/intern/gpu_private.h b/source/blender/gpu/intern/gpu_private.h
new file mode 100644
index 00000000000..72627e3563e
--- /dev/null
+++ b/source/blender/gpu/intern/gpu_private.h
@@ -0,0 +1,36 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file gpu_private.h
+ * \ingroup gpu
+ */
+
+#ifndef __GPU_PRIVATE_H__
+#define __GPU_PRIVATE_H__
+
+/* call this before running any of the functions below */
+void gpu_extensions_init(void);
+void gpu_extensions_exit(void);
+
+/* gpu_debug.c */
+void gpu_debug_init(void);
+void gpu_debug_exit(void);
+
+#endif /* __GPU_PRIVATE_H__ */
diff --git a/source/blender/gpu/intern/gpu_select.c b/source/blender/gpu/intern/gpu_select.c
index 1d448231dda..4978229a350 100644
--- a/source/blender/gpu/intern/gpu_select.c
+++ b/source/blender/gpu/intern/gpu_select.c
@@ -31,14 +31,13 @@
*/
#include "GPU_select.h"
#include "GPU_extensions.h"
-
-#include "BLI_utildefines.h"
-
+#include "GPU_glew.h"
+
#include "MEM_guardedalloc.h"
#include "DNA_userdef_types.h"
-#include <GL/glew.h>
+#include "BLI_utildefines.h"
/* Ad hoc number of queries to allocate to skip doing many glGenQueries */
#define ALLOC_QUERIES 200
@@ -60,6 +59,7 @@ typedef struct GPUQueryState {
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;
@@ -83,7 +83,7 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
g_query_state.oldhits = oldhits;
if (!g_query_state.use_gpu_select) {
- glSelectBuffer( bufsize, (GLuint *)buffer);
+ glSelectBuffer(bufsize, (GLuint *)buffer);
glRenderMode(GL_SELECT);
glInitNames();
glPushName(-1);
@@ -93,8 +93,8 @@ void GPU_select_begin(unsigned int *buffer, unsigned int bufsize, rctf *input, c
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");
+ 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");
glGenQueriesARB(g_query_state.num_of_queries, g_query_state.queries);
glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT);
@@ -136,7 +136,7 @@ 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_query_state.select_is_active)
return true;
if (!g_query_state.use_gpu_select) {
@@ -159,7 +159,7 @@ bool GPU_select_load_id(unsigned int id)
g_query_state.active_query++;
g_query_state.query_issued = true;
- if (g_query_state.mode == GPU_SELECT_NEAREST_SECOND_PASS) {
+ 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;
@@ -192,7 +192,9 @@ unsigned int GPU_select_end(void)
glGetQueryObjectuivARB(g_query_state.queries[i], GL_QUERY_RESULT_ARB, &result);
if (result > 0) {
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
- if(hits < g_query_state.bufsize) {
+ 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;
diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c
index 0cb712d220f..89d3c0f59df 100644
--- a/source/blender/gpu/intern/gpu_simple_shader.c
+++ b/source/blender/gpu/intern/gpu_simple_shader.c
@@ -42,14 +42,11 @@
* - Optimize for case where no texture matrix is used.
*/
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
-#include "DNA_mesh_types.h"
-#include "DNA_object_types.h"
-
#include "GPU_extensions.h"
#include "GPU_simple_shader.h"
@@ -154,7 +151,9 @@ static GPUShader *gpu_simple_shader(int options)
shader = GPU_shader_create(
datatoc_gpu_shader_simple_vert_glsl,
datatoc_gpu_shader_simple_frag_glsl,
- NULL, defines);
+ NULL,
+ NULL,
+ defines, 0, 0, 0);
if (shader) {
/* set texture map to first texture unit */
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
new file mode 100644
index 00000000000..a94c823f408
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_color_frag.glsl
@@ -0,0 +1,32 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 1.442695041};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# unpremultiply volume texture
+RCP value.r, temp.a;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 value.r, -value.r;
+# alpha
+SUB temp.a, 1.0, value.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, value.r;
+MUL temp.g, temp.g, value.r;
+MUL temp.b, temp.b, value.r;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END
diff --git a/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
new file mode 100644
index 00000000000..04b171d24bd
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_program_smoke_frag.glsl
@@ -0,0 +1,27 @@
+!!ARBfp1.0
+PARAM dx = program.local[0];
+PARAM darkness = program.local[1];
+PARAM render = program.local[2];
+PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};
+TEMP temp, shadow, flame, spec, value;
+TEX temp, fragment.texcoord[0], texture[0], 3D;
+TEX shadow, fragment.texcoord[0], texture[1], 3D;
+TEX flame, fragment.texcoord[0], texture[2], 3D;
+TEX spec, flame.r, texture[3], 1D;
+# calculate shading factor from density
+MUL value.r, temp.a, darkness.a;
+MUL value.r, value.r, dx.r;
+MUL value.r, value.r, f.r;
+EX2 temp, -value.r;
+# alpha
+SUB temp.a, 1.0, temp.r;
+# shade colors
+MUL temp.r, temp.r, shadow.r;
+MUL temp.g, temp.g, shadow.r;
+MUL temp.b, temp.b, shadow.r;
+MUL temp.r, temp.r, darkness.r;
+MUL temp.g, temp.g, darkness.g;
+MUL temp.b, temp.b, darkness.b;
+# for now this just replace smoke shading if rendering fire
+CMP result.color, render.r, temp, spec;
+END
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
new file mode 100644
index 00000000000..e04cd7d3306
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_depth_resolve.glsl
@@ -0,0 +1,14 @@
+uniform sampler2D depthbuffer;
+varying vec4 uvcoordsvar;
+
+void main(void)
+{
+ float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+
+ /* XRay background, discard */
+ if (depth >= 1.0) {
+ discard;
+ }
+
+ gl_FragDepth = depth;
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
new file mode 100644
index 00000000000..e9dab04de5d
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_frag.glsl
@@ -0,0 +1,208 @@
+/* amount of offset to move one pixel left-right.
+ * In second pass some dimensions are zero to control verical/horizontal convolution */
+uniform vec2 invrendertargetdim;
+// color buffer
+uniform sampler2D colorbuffer;
+//blurred color buffer for DOF effect
+uniform sampler2D blurredcolorbuffer;
+// slightly blurred buffer
+uniform sampler2D mblurredcolorbuffer;
+// depth buffer
+uniform sampler2D depthbuffer;
+
+// this includes focal distance in x and aperture size in y
+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;
+
+
+float calculate_far_coc(in float zdepth)
+{
+ float coc = dof_params.x * max(1.0 - dof_params.y / zdepth, 0.0);
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+/* near coc only! when distance is nearer than focus plane first term is bigger than one */
+vec4 calculate_near_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_params.x * max(vec4(dof_params.y) / zdepth - vec4(1.0), vec4(0.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+/* first pass blurs the color buffer heavily and gets the near coc only.
+ * There are many texture accesses here but they are done on a
+ * lower resolution image so overall bandwidth is not a concern */
+void first_pass()
+{
+ vec4 depth;
+ vec4 zdepth;
+ vec4 coc;
+ float final_coc;
+
+ /* amount to add to uvs so that they move one row further */
+ vec2 offset_row[3];
+ offset_row[0] = vec2(0.0, invrendertargetdim.y);
+ offset_row[1] = 2.0 * offset_row[0];
+ offset_row[2] = 3.0 * offset_row[0];
+
+ /* heavily blur the image */
+ vec4 color = texture2D(colorbuffer, color_uv1);
+ color += texture2D(colorbuffer, color_uv1 + offset_row[1]);
+ color += texture2D(colorbuffer, color_uv2);
+ color += texture2D(colorbuffer, color_uv2 + offset_row[1]);
+ color /= 4.0;
+
+ depth.r = texture2D(depthbuffer, depth_uv1).r;
+ depth.g = texture2D(depthbuffer, depth_uv2).r;
+ depth.b = texture2D(depthbuffer, depth_uv3).r;
+ depth.a = texture2D(depthbuffer, depth_uv4).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = calculate_near_coc(zdepth);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[0]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[0]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[0]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[0]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = max(calculate_near_coc(zdepth), coc);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[1]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[1]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[1]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[1]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = max(calculate_near_coc(zdepth), coc);
+
+ depth.r = texture2D(depthbuffer, depth_uv1 + offset_row[2]).r;
+ depth.g = texture2D(depthbuffer, depth_uv2 + offset_row[2]).r;
+ depth.b = texture2D(depthbuffer, depth_uv3 + offset_row[2]).r;
+ depth.a = texture2D(depthbuffer, depth_uv4 + offset_row[2]).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ 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);
+}
+
+/* second pass, gaussian blur the downsampled image */
+void second_pass()
+{
+ vec4 depth = vec4(texture2D(depthbuffer, uvcoordsvar.xy).r);
+
+ /* clever sampling to sample 2 pixels at once. Of course it's not real gaussian sampling this way */
+ vec4 color = texture2D(colorbuffer, uvcoordsvar.xy) * 0.3125;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + invrendertargetdim) * 0.234375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + 2.5 * invrendertargetdim) * 0.09375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy + 4.5 * invrendertargetdim) * 0.015625;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -invrendertargetdim) * 0.234375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -2.5 * invrendertargetdim) * 0.09375;
+ color += texture2D(colorbuffer, uvcoordsvar.xy -4.5 * invrendertargetdim) * 0.015625;
+
+ gl_FragColor = color;
+}
+
+
+/* third pass, calculate the final coc from blurred and unblurred images */
+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);
+}
+
+
+/* fourth pass, blur the final coc once to get rid of discontinuities */
+void fourth_pass()
+{
+ vec4 color = texture2D(colorbuffer, uvcoordsvar.xz);
+ color += texture2D(colorbuffer, uvcoordsvar.yz);
+ color += texture2D(colorbuffer, uvcoordsvar.xw);
+ color += texture2D(colorbuffer, uvcoordsvar.yw);
+
+ gl_FragColor = color / 4.0;
+}
+
+vec4 small_sample_blur(in sampler2D colorbuffer, in vec2 uv, in vec4 color)
+{
+ float weight = 1.0/ 17.0;
+ vec4 result = weight * color;
+ weight *= 4.0;
+
+ result += weight * texture2D(colorbuffer, uv + color_uv1.xy);
+ result += weight * texture2D(colorbuffer, uv - color_uv1.xy);
+ result += weight * texture2D(colorbuffer, uv + color_uv1.yx);
+ result += weight * texture2D(colorbuffer, uv - color_uv1.yx);
+
+ return result;
+}
+
+
+/* fourth pass, just visualize the third pass contents */
+void fifth_pass()
+{
+ vec4 factors;
+ vec4 color_orig = texture2D(colorbuffer, uvcoordsvar.xy);
+ vec4 highblurred = texture2D(blurredcolorbuffer, uvcoordsvar.xy);
+ vec4 mediumblurred = texture2D(mblurredcolorbuffer, uvcoordsvar.xy);
+ vec4 smallblurred = small_sample_blur(colorbuffer, uvcoordsvar.xy, color_orig);
+ float depth = texture2D(depthbuffer, uvcoordsvar.xy).r;
+
+ float zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth)).r;
+ float coc_far = clamp(calculate_far_coc(zdepth), 0.0, 1.0);
+
+ /* calculate final coc here */
+ float coc = max(max(coc_far, mediumblurred.a), 0.0);
+
+ float width = 2.5;
+ float radius = 0.2;
+
+ factors.x = 1.0 - clamp(width * coc, 0.0, 1.0);
+ factors.y = 1.0 - clamp(abs(width * (coc - 2.0 * radius)), 0.0, 1.0);
+ factors.z = 1.0 - clamp(abs(width * (coc - 3.0 * radius)), 0.0, 1.0);
+ factors.w = 1.0 - clamp(abs(width * (coc - 4.0 * radius)), 0.0, 1.0);
+ /* blend! */
+ vec4 color = factors.x * color_orig + factors.y * smallblurred + factors.z * mediumblurred + factors.w * highblurred;
+
+ 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);
+}
+
+
+void main()
+{
+#ifdef FIRST_PASS
+ first_pass();
+#elif defined(SECOND_PASS)
+ second_pass();
+#elif defined(THIRD_PASS)
+ third_pass();
+#elif defined(FOURTH_PASS)
+ fourth_pass();
+#elif defined(FIFTH_PASS)
+ fifth_pass();
+#endif
+}
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
new file mode 100644
index 00000000000..e315d2fb97a
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_frag.glsl
@@ -0,0 +1,166 @@
+/* amount of offset to move one pixel left-right.
+ * In second pass some dimensions are zero to control verical/horizontal convolution */
+uniform vec2 invrendertargetdim;
+
+uniform ivec2 rendertargetdim;
+
+/* color buffer */
+uniform sampler2D colorbuffer;
+uniform sampler2D farbuffer;
+uniform sampler2D nearbuffer;
+
+/* depth buffer */
+uniform sampler2D depthbuffer;
+
+uniform sampler2D cocbuffer;
+
+/* this includes focal distance in x and aperture size in y */
+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;
+
+/* downsampling coordinates */
+varying vec2 downsample1;
+varying vec2 downsample2;
+varying vec2 downsample3;
+varying vec2 downsample4;
+
+#define M_PI 3.1415926535897932384626433832795
+
+/* calculate 4 samples at once */
+vec4 calculate_coc(in vec4 zdepth)
+{
+ vec4 coc = dof_params.x * (vec4(dof_params.y) / zdepth - vec4(1.0));
+
+ /* multiply by 1.0 / sensor size to get the normalized size */
+ return coc * dof_params.z;
+}
+
+#define THRESHOLD 0.0
+
+/* downsample the color buffer to half resolution */
+void downsample_pass()
+{
+ vec4 depth;
+ vec4 zdepth;
+ vec4 coc;
+ float far_coc, near_coc;
+
+ /* custom downsampling. We need to be careful to sample nearest here to avoid leaks */
+ vec4 color1 = texture2D(colorbuffer, downsample1);
+ vec4 color2 = texture2D(colorbuffer, downsample2);
+ vec4 color3 = texture2D(colorbuffer, downsample3);
+ vec4 color4 = texture2D(colorbuffer, downsample4);
+
+ depth.r = texture2D(depthbuffer, downsample1).r;
+ depth.g = texture2D(depthbuffer, downsample2).r;
+ depth.b = texture2D(depthbuffer, downsample3).r;
+ depth.a = texture2D(depthbuffer, downsample4).r;
+
+ zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), depth);
+ coc = calculate_coc(zdepth);
+ vec4 coc_far = -coc;
+
+ /* now we need to write the near-far fields premultiplied by the coc */
+ vec4 near_weights = vec4((coc.x >= THRESHOLD) ? 1.0 : 0.0, (coc.y >= THRESHOLD) ? 1.0 : 0.0,
+ (coc.z >= THRESHOLD) ? 1.0 : 0.0, (coc.w >= THRESHOLD) ? 1.0 : 0.0);
+ vec4 far_weights = vec4((coc_far.x >= THRESHOLD) ? 1.0 : 0.0, (coc_far.y >= THRESHOLD) ? 1.0 : 0.0,
+ (coc_far.z >= THRESHOLD) ? 1.0 : 0.0, (coc_far.w >= THRESHOLD) ? 1.0 : 0.0);
+
+ near_coc = max(max(max(coc.x, coc.y), max(coc.z, coc.w)), 0.0);
+ far_coc = max(max(max(coc_far.x, coc_far.y), max(coc_far.z, coc_far.w)), 0.0);
+
+ float norm_near = dot(near_weights, vec4(1.0));
+ 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 +
+ color4 * near_weights.w;
+ gl_FragData[1] = 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;
+ if (norm_far > 0.0)
+ gl_FragData[1] /= norm_far;
+ gl_FragData[2] = vec4(near_coc, far_coc, 0.0, 1.0);
+}
+
+/* accumulate color in the near/far blur buffers */
+void accumulate_pass(void) {
+ float theta = atan(particlecoord.y, particlecoord.x);
+ float r;
+
+ 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))));
+
+ if (dot(particlecoord, particlecoord) > r * r)
+ discard;
+
+ gl_FragData[0] = color;
+}
+#define MERGE_THRESHOLD 4.0
+
+/* combine the passes, */
+void final_pass(void) {
+ vec4 finalcolor;
+ float totalweight;
+ float depth = texture2D(depthbuffer, uvcoord).r;
+
+ vec4 zdepth = get_view_space_z_from_depth(vec4(viewvecs[0].z), vec4(viewvecs[1].z), vec4(depth));
+ float coc_near = calculate_coc(zdepth).r;
+ float coc_far = max(-coc_near, 0.0);
+ coc_near = max(coc_near, 0.0);
+
+ vec4 farcolor = texture2D(farbuffer, uvcoord);
+ float farweight = farcolor.a;
+ if (farweight > 0.0)
+ farcolor /= farweight;
+ vec4 nearcolor = texture2D(nearbuffer, uvcoord);
+
+ vec4 srccolor = texture2D(colorbuffer, uvcoord);
+
+ vec4 coc = texture2D(cocbuffer, uvcoord);
+
+ float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
+ finalcolor = mix(srccolor, farcolor, mixfac);
+
+ farweight = mix(1.0, farweight, mixfac);
+
+ float nearweight = nearcolor.a;
+ if (nearweight > 0.0) {
+ nearcolor /= nearweight;
+ }
+
+ if (coc_near > 1.0) {
+ nearweight = 1.0;
+ finalcolor = nearcolor;
+ }
+ else {
+ totalweight = nearweight + farweight;
+ finalcolor = mix(finalcolor, nearcolor, nearweight / totalweight);
+ }
+
+ gl_FragData[0] = finalcolor;
+}
+
+void main()
+{
+#ifdef FIRST_PASS
+ downsample_pass();
+#elif defined(SECOND_PASS)
+ accumulate_pass();
+#elif defined(THIRD_PASS)
+ final_pass();
+#endif
+}
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
new file mode 100644
index 00000000000..7918122a681
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_geo.glsl
@@ -0,0 +1,50 @@
+uniform ivec2 rendertargetdim;
+uniform sampler2D colorbuffer;
+
+uniform vec2 layerselection;
+
+uniform sampler2D cocbuffer;
+
+/* initial uv coordinate */
+varying in vec2 uvcoord[1];
+varying out vec2 particlecoord;
+varying out vec4 color;
+
+
+#define M_PI 3.1415926535897932384626433832795
+
+void main(void)
+{
+ vec4 coc = texture2DLod(cocbuffer, uvcoord[0], 0.0);
+
+ float offset_val = dot(coc.rg, layerselection);
+ if (offset_val < 1.0)
+ return;
+
+ vec4 colortex = texture2DLod(colorbuffer, uvcoord[0], 0.0);
+
+ /* find the area the pixel will cover and divide the color by it */
+ float alpha = 1.0 / (offset_val * offset_val * M_PI);
+ colortex *= alpha;
+ colortex.a = alpha;
+
+ vec2 offset_far = vec2(offset_val * 0.5) / vec2(rendertargetdim.x, rendertargetdim.y);
+
+ gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
+ color = colortex;
+ particlecoord = vec2(-1.0, -1.0);
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(-1.0, 1.0);
+ color = colortex;
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
+ particlecoord = vec2(1.0, -1.0);
+ color = colortex;
+ EmitVertex();
+ gl_Position = gl_PositionIn[0] + 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
new file mode 100644
index 00000000000..09a0c75facc
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_hq_vert.glsl
@@ -0,0 +1,58 @@
+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;
+
+/* downsampling coordinates */
+varying vec2 downsample1;
+varying vec2 downsample2;
+varying vec2 downsample3;
+varying vec2 downsample4;
+
+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;
+
+ gl_Position = gl_Vertex;
+}
+
+/* geometry shading pass, calculate a texture coordinate based on the indexed id */
+void vert_dof_coc_scatter_pass()
+{
+ vec2 pixel = vec2(rendertargetdim.x, rendertargetdim.y);
+ /* some math to get the target pixel */
+ int row = gl_InstanceID / rendertargetdim.x;
+ int column = gl_InstanceID % rendertargetdim.x;
+ uvcoord = (vec2(column, row) + vec2(0.5)) / pixel;
+
+ vec2 pos = uvcoord * 2.0 - vec2(1.0);
+ gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);
+
+// uvcoord = vec2(0.5, 0.5);
+// gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
+}
+
+void vert_dof_final()
+{
+ uvcoord = gl_MultiTexCoord0.xy;
+ gl_Position = gl_Vertex;
+}
+
+void main()
+{
+#if defined(FIRST_PASS)
+ vert_dof_downsample();
+#elif defined(SECOND_PASS)
+ vert_dof_coc_scatter_pass();
+#else
+ vert_dof_final();
+#endif
+} \ No newline at end of file
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
new file mode 100644
index 00000000000..a2ef990c4e8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_dof_vert.glsl
@@ -0,0 +1,68 @@
+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;
+
+varying vec2 depth_uv1;
+varying vec2 depth_uv2;
+varying vec2 depth_uv3;
+varying vec2 depth_uv4;
+
+//very simple shader for gull screen FX, just pass values on
+
+void vert_generic()
+{
+ uvcoordsvar = gl_MultiTexCoord0;
+ gl_Position = gl_Vertex;
+}
+
+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;
+
+ 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;
+
+ gl_Position = gl_Vertex;
+}
+
+void vert_dof_fourth_pass()
+{
+ vec4 halfpixel = vec4(-0.5, 0.5, -0.5, 0.5);
+ uvcoordsvar = gl_MultiTexCoord0.xxyy + halfpixel * vec4(invrendertargetdim.x,
+ invrendertargetdim.x, invrendertargetdim.y, invrendertargetdim.y);
+
+ gl_Position = gl_Vertex;
+}
+
+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;
+}
+
+void main()
+{
+#ifdef FIRST_PASS
+ vert_dof_first_pass();
+#elif defined(FOURTH_PASS)
+ vert_dof_fourth_pass();
+#elif defined(FIFTH_PASS)
+ vert_dof_fifth_pass();
+#else
+ vert_generic();
+#endif
+}
+
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
new file mode 100644
index 00000000000..1dc49b52be1
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_lib.glsl
@@ -0,0 +1,39 @@
+/* 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]);
+
+ return zview * (viewvec_origin + vec3(uvcoords, 0.0) * viewvec_diff);
+}
+
+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]));
+}
+
+#else
+/* orthographic camera code */
+
+vec3 get_view_space_from_depth(in vec2 uvcoords, in vec3 viewvec_origin, in vec3 viewvec_diff, in float depth)
+{
+ vec3 offset = vec3(uvcoords, depth);
+
+ return vec3(viewvec_origin + offset * viewvec_diff);
+}
+
+vec4 get_view_space_z_from_depth(in vec4 near, in vec4 range, in vec4 depth)
+{
+ return -(near + depth * range);
+}
+
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
new file mode 100644
index 00000000000..494a74dcdf8
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_ssao_frag.glsl
@@ -0,0 +1,94 @@
+// color buffer
+uniform sampler2D colorbuffer;
+
+// jitter texture for ssao
+uniform sampler2D jitter_tex;
+
+// concentric sample texture for ssao
+uniform sampler1D ssao_concentric_tex;
+
+// depth buffer
+uniform sampler2D depthbuffer;
+// coordinates on framebuffer in normalized (0.0-1.0) uv space
+varying vec4 uvcoordsvar;
+
+/* ssao_params.x : pixel scale for the ssao radious */
+/* ssao_params.y : factor for the ssao darkening */
+uniform vec4 ssao_params;
+uniform vec3 ssao_sample_params;
+uniform vec4 ssao_color;
+
+/* store the view space vectors for the corners of the view frustum here.
+ * It helps to quickly reconstruct view space vectors by using uv coordinates,
+ * see http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */
+uniform vec4 viewvecs[3];
+
+vec3 calculate_view_space_normal(in vec3 viewposition)
+{
+ vec3 normal = cross(normalize(dFdx(viewposition)),
+ ssao_params.w * normalize(dFdy(viewposition)));
+ normalize(normal);
+ return normal;
+}
+
+float calculate_ssao_factor(float depth)
+{
+ /* take the normalized ray direction here */
+ vec2 rotX = texture2D(jitter_tex, uvcoordsvar.xy * ssao_sample_params.yz).rg;
+ vec2 rotY = vec2(-rotX.y, rotX.x);
+
+ /* occlusion is zero in full depth */
+ if (depth == 1.0)
+ return 0.0;
+
+ vec3 position = get_view_space_from_depth(uvcoordsvar.xy, viewvecs[0].xyz, viewvecs[1].xyz, depth);
+ vec3 normal = calculate_view_space_normal(position);
+
+ // 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;
+ /* convert from -1.0...1.0 range to 0.0..1.0 for easy use with texture coordinates */
+ offset *= 0.5;
+
+ float factor = 0.0;
+ int x;
+ int num_samples = int(ssao_sample_params.x);
+
+ for (x = 0; x < num_samples; x++) {
+ vec2 dir_sample = texture1D(ssao_concentric_tex, (float(x) + 0.5) / ssao_sample_params.x).rg;
+
+ /* rotate with random direction to get jittered result */
+ vec2 dir_jittered = vec2(dot(dir_sample, rotX), dot(dir_sample, rotY));
+
+ vec2 uvcoords = uvcoordsvar.xy + dir_jittered * offset;
+
+ if (uvcoords.x > 1.0 || uvcoords.x < 0.0 || uvcoords.y > 1.0 || uvcoords.y < 0.0)
+ continue;
+
+ float depth_new = texture2D(depthbuffer, uvcoords).r;
+ if (depth_new != 1.0) {
+ vec3 pos_new = get_view_space_from_depth(uvcoords, viewvecs[0].xyz, viewvecs[1].xyz, depth_new);
+ vec3 dir = pos_new - position;
+ float len = length(dir);
+ float f = dot(dir, normal);
+
+ /* use minor bias here to avoid self shadowing */
+ if (f > 0.05 * len + 0.0001)
+ factor += f * 1.0/(len * (1.0 + len * len * ssao_params.z));
+ }
+ }
+
+ factor /= ssao_sample_params.x;
+
+ return clamp(factor * ssao_params.y, 0.0, 1.0);
+}
+
+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);
+}
diff --git a/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
new file mode 100644
index 00000000000..5194e414520
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_fx_vert.glsl
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 00000000000..a0ae96a1f72
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl
@@ -0,0 +1,100 @@
+uniform int PrimitiveIdBase;
+uniform int osd_active_uv_offset;
+
+varying vec3 varnormal;
+varying vec3 varposition;
+
+in block {
+ VertexData v;
+} inpt[4];
+
+uniform bool osd_flat_shading;
+uniform int osd_fvar_count;
+
+#define INTERP_FACE_VARYING_2(result, fvarOffset, tessCoord) \
+ { \
+ vec2 v[4]; \
+ int primOffset = (gl_PrimitiveID + PrimitiveIdBase) * 4; \
+ for (int i = 0; i < 4; ++i) { \
+ int index = (primOffset + i) * osd_fvar_count + fvarOffset; \
+ v[i] = vec2(texelFetch(FVarDataBuffer, index).s, \
+ texelFetch(FVarDataBuffer, index + 1).s); \
+ } \
+ result = mix(mix(v[0], v[1], tessCoord.s), \
+ mix(v[3], v[2], tessCoord.s), \
+ tessCoord.t); \
+ }
+
+uniform samplerBuffer FVarDataBuffer;
+
+out block {
+ VertexData v;
+} outpt;
+
+void set_mtface_vertex_attrs(vec2 st);
+
+void emit_flat(int index, vec3 normal)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = normal;
+
+ /* Compatibility */
+ varnormal = outpt.v.normal;
+ varposition = outpt.v.position.xyz;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ set_mtface_vertex_attrs(st);
+
+ gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+void emit_smooth(int index)
+{
+ outpt.v.position = inpt[index].v.position;
+ outpt.v.normal = inpt[index].v.normal;
+
+ /* Compatibility */
+ varnormal = outpt.v.normal;
+ varposition = outpt.v.position.xyz;
+
+ /* TODO(sergey): Only uniform subdivisions atm. */
+ vec2 quadst[4] = vec2[](vec2(0,0), vec2(1,0), vec2(1,1), vec2(0,1));
+ vec2 st = quadst[index];
+
+ INTERP_FACE_VARYING_2(outpt.v.uv, osd_active_uv_offset, st);
+
+ set_mtface_vertex_attrs(st);
+
+ gl_Position = gl_ProjectionMatrix * inpt[index].v.position;
+ EmitVertex();
+}
+
+void main()
+{
+ gl_PrimitiveID = gl_PrimitiveIDIn;
+
+ if (osd_flat_shading) {
+ vec3 A = (inpt[0].v.position - inpt[1].v.position).xyz;
+ vec3 B = (inpt[3].v.position - inpt[1].v.position).xyz;
+ vec3 flat_normal = normalize(cross(B, A));
+ emit_flat(0, flat_normal);
+ emit_flat(1, flat_normal);
+ emit_flat(3, flat_normal);
+ emit_flat(2, flat_normal);
+ }
+ else {
+ emit_smooth(0);
+ emit_smooth(1);
+ emit_smooth(3);
+ emit_smooth(2);
+ }
+ EndPrimitive();
+}
+
+void set_mtface_vertex_attrs(vec2 st) {
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 3ba36c11311..311fcb8ead2 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -149,10 +149,23 @@ void geom(vec3 co, vec3 nor, mat4 viewinvmat, vec3 attorco, vec2 attuv, vec4 att
uv_attribute(attuv, uv);
normal = -normalize(nor); /* blender render normal is negated */
vcol_attribute(attvcol, vcol);
+ srgb_to_linearrgb(vcol, vcol);
vcol_alpha = attvcol.a;
frontback = (gl_FrontFacing)? 1.0: 0.0;
}
+void particle_info(vec4 sprops, vec3 loc, vec3 vel, vec3 avel, out float index, out float age, out float life_time, out vec3 location, out float size, out vec3 velocity, out vec3 angular_velocity)
+{
+ index = sprops.x;
+ age = sprops.y;
+ life_time = sprops.z;
+ size = sprops.w;
+
+ location = loc;
+ velocity = vel;
+ angular_velocity = avel;
+}
+
void mapping(vec3 vec, mat4 mat, vec3 minvec, vec3 maxvec, float domin, float domax, out vec3 outvec)
{
outvec = (mat * vec4(vec, 1.0)).xyz;
@@ -169,9 +182,9 @@ void camera(vec3 co, out vec3 outview, out float outdepth, out float outdist)
outview = normalize(co);
}
-void lamp(vec4 col, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac)
+void lamp(vec4 col, float energy, vec3 lv, float dist, vec3 shadow, float visifac, out vec4 outcol, out vec3 outlv, out float outdist, out vec4 outshadow, out float outvisifac)
{
- outcol = col;
+ outcol = col * energy;
outlv = lv;
outdist = dist;
outshadow = vec4(shadow, 1.0);
@@ -297,6 +310,10 @@ void math_modulo(float val1, float val2, out float outval)
outval = 0.0;
else
outval = mod(val1, val2);
+
+ /* change sign to match C convention, mod in GLSL will take absolute for negative numbers,
+ * see https://www.opengl.org/sdk/docs/man/html/mod.xhtml */
+ outval = (val1 > 0.0) ? outval : -outval;
}
void math_abs(float val1, out float outval)
@@ -338,6 +355,7 @@ void vec_math_cross(vec3 v1, vec3 v2, out vec3 outvec, out float outval)
{
outvec = cross(v1, v2);
outval = length(outvec);
+ outvec /= outval;
}
void vec_math_normalize(vec3 v, out vec3 outvec, out float outval)
@@ -357,6 +375,12 @@ void normal(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
outdot = -dot(dir, nor);
}
+void normal_new_shading(vec3 dir, vec3 nor, out vec3 outnor, out float outdot)
+{
+ outnor = normalize(nor);
+ outdot = dot(normalize(dir), nor);
+}
+
void curves_vec(float fac, vec3 vec, sampler2D curvemap, out vec3 outvec)
{
outvec.x = texture2D(curvemap, vec2((vec.x + 1.0)*0.5, 0.0)).x;
@@ -687,22 +711,7 @@ void mix_linear(float fac, vec4 col1, vec4 col2, out vec4 outcol)
{
fac = clamp(fac, 0.0, 1.0);
- outcol = col1;
-
- if(col2.r > 0.5)
- outcol.r= col1.r + fac*(2.0*(col2.r - 0.5));
- else
- outcol.r= col1.r + fac*(2.0*(col2.r) - 1.0);
-
- if(col2.g > 0.5)
- outcol.g= col1.g + fac*(2.0*(col2.g - 0.5));
- else
- outcol.g= col1.g + fac*(2.0*(col2.g) - 1.0);
-
- if(col2.b > 0.5)
- outcol.b= col1.b + fac*(2.0*(col2.b - 0.5));
- else
- outcol.b= col1.b + fac*(2.0*(col2.b) - 1.0);
+ outcol = col1 + fac*(2.0*(col2 - vec4(0.5)));
}
void valtorgb(float fac, sampler2D colormap, out vec4 outcol, out float outalpha)
@@ -722,6 +731,16 @@ void invert(float fac, vec4 col, out vec4 outcol)
outcol.w = col.w;
}
+void clamp_vec3(vec3 vec, vec3 min, vec3 max, out vec3 out_vec)
+{
+ out_vec = clamp(vec, min, max);
+}
+
+void clamp_val(float value, float min, float max, out float out_value)
+{
+ out_value = clamp(value, min, max);
+}
+
void hue_sat(float hue, float sat, float value, float fac, vec4 col, out vec4 outcol)
{
vec4 hsv;
@@ -1507,9 +1526,9 @@ void mtex_nspace_world(mat4 viewmat, vec3 texnormal, out vec3 outnormal)
outnormal = normalize((viewmat*vec4(texnormal, 0.0)).xyz);
}
-void mtex_nspace_object(mat4 viewmat, mat4 obmat, vec3 texnormal, out vec3 outnormal)
+void mtex_nspace_object(vec3 texnormal, out vec3 outnormal)
{
- outnormal = normalize((viewmat*(obmat*vec4(texnormal, 0.0))).xyz);
+ outnormal = normalize(gl_NormalMatrix * texnormal);
}
void mtex_blend_normal(float norfac, vec3 normal, vec3 newnormal, out vec3 outnormal)
@@ -1925,6 +1944,17 @@ void shade_add_spec(float t, vec3 lampcol, vec3 speccol, out vec3 outcol)
outcol = t*lampcol*speccol;
}
+void alpha_spec_correction(vec3 spec, float spectra, float alpha, out float outalpha)
+{
+ if (spectra > 0.0) {
+ float t = clamp(max(max(spec.r, spec.g), spec.b) * spectra, 0.0, 1.0);
+ outalpha = (1.0 - t) * alpha + t;
+ }
+ else {
+ outalpha = alpha;
+ }
+}
+
void shade_add(vec4 col1, vec4 col2, out vec4 outcol)
{
outcol = col1 + col2;
@@ -1960,6 +1990,11 @@ void shade_mul_value(float fac, vec4 col, out vec4 outcol)
outcol = col*fac;
}
+void shade_mul_value_v3(float fac, vec3 col, out vec3 outcol)
+{
+ outcol = col*fac;
+}
+
void shade_obcolor(vec4 col, vec4 obcol, out vec4 outcol)
{
outcol = vec4(col.rgb*obcol.rgb, col.a);
@@ -2077,18 +2112,23 @@ void shade_exposure_correct(vec3 col, float linfac, float logfac, out vec3 outco
outcol = linfac*(1.0 - exp(col*logfac));
}
-void shade_mist_factor(vec3 co, float miststa, float mistdist, float misttype, float misi, out float outfac)
+void shade_mist_factor(vec3 co, float enable, float miststa, float mistdist, float misttype, float misi, out float outfac)
{
- float fac, zcor;
+ if(enable == 1.0) {
+ float fac, zcor;
- zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
-
- fac = clamp((zcor-miststa)/mistdist, 0.0, 1.0);
- if(misttype == 0.0) fac *= fac;
- else if(misttype == 1.0);
- else fac = sqrt(fac);
+ zcor = (gl_ProjectionMatrix[3][3] == 0.0)? length(co): -co[2];
+
+ fac = clamp((zcor - miststa) / mistdist, 0.0, 1.0);
+ if(misttype == 0.0) fac *= fac;
+ else if(misttype == 1.0);
+ else fac = sqrt(fac);
- outfac = 1.0 - (1.0-fac)*(1.0-misi);
+ outfac = 1.0 - (1.0 - fac) * (1.0 - misi);
+ }
+ else {
+ outfac = 0.0;
+ }
}
void shade_world_mix(vec3 hor, vec4 col, out vec4 outcol)
@@ -2223,6 +2263,16 @@ void node_bsdf_hair(vec4 color, float offset, float roughnessu, float roughnessv
result = color;
}
+void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out vec4 result)
+{
+ node_bsdf_diffuse(color, 0.0, N, result);
+}
+
+void node_ambient_occlusion(vec4 color, out vec4 result)
+{
+ result = color;
+}
+
/* emission */
void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
@@ -2230,6 +2280,22 @@ void node_emission(vec4 color, float strength, vec3 N, out vec4 result)
result = color*strength;
}
+/* background */
+
+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 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+ worldvec = (gl_ModelViewMatrixInverse * co).xyz;
+}
+
+void node_background(vec4 color, float strength, vec3 N, out vec4 result)
+{
+ result = color*strength;
+}
+
/* closures */
void node_mix_shader(float fac, vec4 shader1, vec4 shader2, out vec4 shader)
@@ -2259,10 +2325,12 @@ void node_layer_weight(float blend, vec3 N, vec3 I, out float fresnel, out float
{
/* fresnel */
float eta = max(1.0 - blend, 0.00001);
- fresnel = fresnel_dielectric(normalize(I), N, (gl_FrontFacing)? 1.0/eta : eta );
+ vec3 I_view = (gl_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 );
/* facing */
- facing = abs(dot(normalize(I), N));
+ facing = abs(dot(I_view, N));
if(blend != 0.5) {
blend = clamp(blend, 0.0, 0.99999);
blend = (blend < 0.5)? 2.0*blend: 0.5/(1.0 - blend);
@@ -2302,7 +2370,7 @@ void node_uvmap(vec3 attr_uv, out vec3 outvec)
void node_geometry(vec3 I, vec3 N, mat4 toworld,
out vec3 position, out vec3 normal, out vec3 tangent,
out vec3 true_normal, out vec3 incoming, out vec3 parametric,
- out float backfacing)
+ out float backfacing, out float pointiness)
{
position = (toworld*vec4(I, 1.0)).xyz;
normal = (toworld*vec4(N, 0.0)).xyz;
@@ -2315,20 +2383,21 @@ void node_geometry(vec3 I, vec3 N, mat4 toworld,
parametric = vec3(0.0);
backfacing = (gl_FrontFacing)? 0.0: 1.0;
+ pointiness = 0.0;
}
-void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
+void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
vec3 attr_orco, vec3 attr_uv,
out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
out vec3 camera, out vec3 window, out vec3 reflection)
{
- generated = mtex_2d_mapping(attr_orco);
+ generated = attr_orco * 0.5 + vec3(0.5);
normal = normalize((obinvmat*(viewinvmat*vec4(N, 0.0))).xyz);
uv = attr_uv;
object = (obinvmat*(viewinvmat*vec4(I, 1.0))).xyz;
- camera = I;
+ camera = vec3(I.xy, -I.z);
vec4 projvec = gl_ProjectionMatrix * vec4(I, 1.0);
- window = mtex_2d_mapping(projvec.xyz/projvec.w);
+ window = vec3(mtex_2d_mapping(projvec.xyz/projvec.w).xy * camerafac.xy + camerafac.zw, 0.0);
vec3 shade_I;
shade_view(I, shade_I);
@@ -2336,6 +2405,32 @@ void node_tex_coord(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat,
reflection = (viewinvmat*vec4(view_reflection, 0.0)).xyz;
}
+void node_tex_coord_background(vec3 I, vec3 N, mat4 viewinvmat, mat4 obinvmat, vec4 camerafac,
+ vec3 attr_orco, vec3 attr_uv,
+ out vec3 generated, out vec3 normal, out vec3 uv, out vec3 object,
+ out vec3 camera, out vec3 window, out vec3 reflection)
+{
+ vec4 v = (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 co = vec4(co_homogenous.xyz / co_homogenous.w, 0.0);
+
+ co = normalize(co);
+ vec3 coords = (gl_ModelViewMatrixInverse * co).xyz;
+
+ generated = coords;
+ normal = -coords;
+ uv = vec3(attr_uv.xy, 0.0);
+ object = coords;
+
+ camera = vec3(co.xy, -co.z);
+ window = (gl_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);
+
+ reflection = -coords;
+}
+
/* textures */
void node_tex_gradient(vec3 co, out vec4 color, out float fac)
@@ -2362,17 +2457,34 @@ void node_tex_clouds(vec3 co, float size, out vec4 color, out float fac)
fac = 1.0;
}
-void node_tex_environment(vec3 co, sampler2D ima, out vec4 color)
+void node_tex_environment_equirectangular(vec3 co, sampler2D ima, out vec4 color)
+{
+ vec3 nco = normalize(co);
+ float u = -atan(nco.y, nco.x)/(2.0*M_PI) + 0.5;
+ float v = atan(nco.z, hypot(nco.x, nco.y))/M_PI + 0.5;
+
+ color = texture2D(ima, vec2(u, v));
+}
+
+void node_tex_environment_mirror_ball(vec3 co, sampler2D ima, out vec4 color)
{
- float u = (atan(co.y, co.x) + M_PI)/(2.0*M_PI);
- float v = atan(co.z, hypot(co.x, co.y))/M_PI + 0.5;
+ vec3 nco = normalize(co);
+
+ nco.y -= 1.0;
+
+ float div = 2.0*sqrt(max(-0.5*nco.y, 0.0));
+ if(div > 0.0)
+ nco /= div;
+
+ float u = 0.5*(nco.x + 1.0);
+ float v = 0.5*(nco.z + 1.0);
color = texture2D(ima, vec2(u, v));
}
void node_tex_environment_empty(vec3 co, out vec4 color)
{
- color = vec4(0.0);
+ color = vec4(1.0, 0.0, 1.0, 1.0);
}
void node_tex_image(vec3 co, sampler2D ima, out vec4 color, out float alpha)
@@ -2480,6 +2592,11 @@ void node_output_material(vec4 surface, vec4 volume, float displacement, out vec
result = surface;
}
+void node_output_world(vec4 surface, vec4 volume, out vec4 result)
+{
+ result = surface;
+}
+
/* ********************** matcap style render ******************** */
void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out vec4 result)
@@ -2487,6 +2604,7 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v
vec3 normal;
vec2 tex;
+#ifndef USE_OPENSUBDIV
/* remap to 0.0 - 1.0 range. This is done because OpenGL 2.0 clamps colors
* between shader stages and we want the full range of the normal */
normal = vec3(2.0, 2.0, 2.0) * vec3(N.x, N.y, N.z) - vec3(1.0, 1.0, 1.0);
@@ -2494,6 +2612,10 @@ void material_preview_matcap(vec4 color, sampler2D ima, vec4 N, vec4 mask, out v
normal.z = 0.0;
}
normal = normalize(normal);
+#else
+ normal = inpt.v.normal;
+ mask = vec4(1.0, 1.0, 1.0, 1.0);
+#endif
tex.x = 0.5 + 0.49 * normal.x;
tex.y = 0.5 + 0.49 * normal.y;
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 978b6db1b9a..5f406c959f1 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
@@ -10,7 +10,7 @@ void main()
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, gl_TexCoord[0].st + vec2(3.0 * ScaleU.x, 3.0 * ScaleU.y ) ) * 0.015625;
gl_FragColor = color;
}
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
index b5d8dcc0f35..7e332706695 100644
--- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl
@@ -1,3 +1,11 @@
+#ifdef USE_OPENSUBDIV
+in vec3 normal;
+in vec4 position;
+
+out block {
+ VertexData v;
+} outpt;
+#endif
varying vec3 varposition;
varying vec3 varnormal;
@@ -8,10 +16,15 @@ varying float gl_ClipDistance[6];
void main()
{
- vec4 co = gl_ModelViewMatrix * gl_Vertex;
+#ifndef USE_OPENSUBDIV
+ vec4 position = gl_Vertex;
+ vec3 normal = gl_Normal;
+#endif
+
+ vec4 co = gl_ModelViewMatrix * position;
varposition = co.xyz;
- varnormal = normalize(gl_NormalMatrix * gl_Normal);
+ varnormal = normalize(gl_NormalMatrix * normal);
gl_Position = gl_ProjectionMatrix * co;
#ifdef CLIP_WORKAROUND
@@ -24,3 +37,7 @@ void main()
gl_ClipVertex = co;
#endif
+#ifdef USE_OPENSUBDIV
+ outpt.v.position = co;
+ outpt.v.normal = varnormal;
+#endif
diff --git a/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
new file mode 100644
index 00000000000..9dbcaeb7a32
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_vertex_world.glsl
@@ -0,0 +1,13 @@
+
+varying vec3 varposition;
+varying vec3 varnormal;
+
+void main()
+{
+ /* position does not need to be transformed, we already have it */
+ gl_Position = gl_Vertex;
+
+ varposition = gl_Vertex.xyz;
+
+ varnormal = normalize(-varposition);
+