Blender  V3.3
workbench_effect_cavity.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. */
3 
15 #include "DRW_render.h"
16 
17 #include "BLI_rand.h"
18 
19 #include "../eevee/eevee_lut.h" /* TODO: find somewhere to share blue noise Table. */
20 
21 #include "workbench_engine.h"
22 #include "workbench_private.h"
23 
24 #define JITTER_TEX_SIZE 64
25 #define CAVITY_MAX_SAMPLES 512
26 
27 /* Using Hammersley distribution */
28 static float *create_disk_samples(int num_samples, int num_iterations)
29 {
30  BLI_assert(num_samples * num_iterations <= CAVITY_MAX_SAMPLES);
31  const int total_samples = num_samples * num_iterations;
32  const float num_samples_inv = 1.0f / num_samples;
33  /* vec4 to ensure memory alignment. */
34  float(*texels)[4] = MEM_callocN(sizeof(float[4]) * CAVITY_MAX_SAMPLES, __func__);
35  for (int i = 0; i < total_samples; i++) {
36  float it_add = (i / num_samples) * 0.499f;
37  float r = fmodf((i + 0.5f + it_add) * num_samples_inv, 1.0f);
38  double dphi;
39  BLI_hammersley_1d(i, &dphi);
40 
41  float phi = (float)dphi * 2.0f * M_PI + it_add;
42  texels[i][0] = cosf(phi);
43  texels[i][1] = sinf(phi);
44  /* This deliberately distribute more samples
45  * at the center of the disk (and thus the shadow). */
46  texels[i][2] = r;
47  }
48 
49  return (float *)texels;
50 }
51 
53 {
54  float jitter[64 * 64][4];
55  const float num_samples_inv = 1.0f / num_samples;
56 
57  for (int i = 0; i < 64 * 64; i++) {
58  float phi = blue_noise[i][0] * 2.0f * M_PI;
59  /* This rotate the sample per pixels */
60  jitter[i][0] = cosf(phi);
61  jitter[i][1] = sinf(phi);
62  /* This offset the sample along its direction axis (reduce banding) */
63  float bn = blue_noise[i][1] - 0.5f;
64  CLAMP(bn, -0.499f, 0.499f); /* fix fireflies */
65  jitter[i][2] = bn * num_samples_inv;
66  jitter[i][3] = blue_noise[i][1];
67  }
68 
70 
71  return DRW_texture_create_2d(64, 64, GPU_RGBA16F, DRW_TEX_WRAP, &jitter[0][0]);
72 }
73 
75  const Scene *scene)
76 {
79 }
80 
82 {
83  View3DShading *shading = &wpd->shading;
84  const DRWContextState *draw_ctx = DRW_context_state_get();
85  Scene *scene = draw_ctx->scene;
86 
87  if (CAVITY_ENABLED(wpd)) {
88  int cavity_sample_count_single_iteration = scene->display.matcap_ssao_samples;
89  int cavity_sample_count_total = workbench_cavity_total_sample_count(wpd, scene);
90  const int max_iter_count = cavity_sample_count_total / cavity_sample_count_single_iteration;
91 
92  int sample = wpd->taa_sample % max_iter_count;
93  wd->cavity_sample_start = cavity_sample_count_single_iteration * sample;
94  wd->cavity_sample_end = cavity_sample_count_single_iteration * (sample + 1);
95 
97  wd->cavity_jitter_scale = 1.0f / 64.0f;
98 
103 
104  wd->curvature_ridge = 0.5f / max_ff(square_f(shading->curvature_ridge_factor), 1e-4f);
105  wd->curvature_valley = 0.7f / max_ff(square_f(shading->curvature_valley_factor), 1e-4f);
106  }
107 }
108 
110 {
111  const DRWContextState *draw_ctx = DRW_context_state_get();
112  Scene *scene = draw_ctx->scene;
113 
114  int cavity_sample_count_single_iteration = scene->display.matcap_ssao_samples;
115  int cavity_sample_count = workbench_cavity_total_sample_count(wpd, scene);
116  const int max_iter_count = max_ii(1, cavity_sample_count / cavity_sample_count_single_iteration);
117 
118  if (wpd->vldata->cavity_sample_count != cavity_sample_count) {
121  }
122 
123  if (wpd->vldata->cavity_sample_ubo == NULL) {
124  float *samples = create_disk_samples(cavity_sample_count_single_iteration, max_iter_count);
125  wpd->vldata->cavity_jitter_tx = create_jitter_texture(cavity_sample_count);
126  /* NOTE: Uniform buffer needs to always be filled to be valid. */
128  sizeof(float[4]) * CAVITY_MAX_SAMPLES, samples, "wb_CavitySamples");
129  wpd->vldata->cavity_sample_count = cavity_sample_count;
130  MEM_freeN(samples);
131  }
132 }
133 
135 {
136  WORKBENCH_PassList *psl = data->psl;
137  WORKBENCH_PrivateData *wpd = data->stl->wpd;
139  struct GPUShader *sh;
140  DRWShadingGroup *grp;
141 
142  if (CAVITY_ENABLED(wpd)) {
144 
147 
149 
150  grp = DRW_shgroup_create(sh, psl->cavity_ps);
151  DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
152  DRW_shgroup_uniform_block(grp, "world_data", wpd->world_ubo);
153 
154  if (SSAO_ENABLED(wpd)) {
155  DRW_shgroup_uniform_block(grp, "samples_coords", wpd->vldata->cavity_sample_ubo);
156  DRW_shgroup_uniform_texture(grp, "depthBuffer", dtxl->depth);
157  DRW_shgroup_uniform_texture(grp, "cavityJitter", wpd->vldata->cavity_jitter_tx);
158  }
159  if (CURVATURE_ENABLED(wpd)) {
160  DRW_shgroup_uniform_texture(grp, "objectIdBuffer", wpd->object_id_tx);
161  }
163  }
164  else {
165  psl->cavity_ps = NULL;
166  }
167 }
typedef float(TangentPoint)[2]
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_INLINE
MINLINE float max_ff(float a, float b)
MINLINE int min_ii(int a, int b)
MINLINE int max_ii(int a, int b)
MINLINE float square_f(float a)
#define M_PI
Definition: BLI_math_base.h:20
Random number functions.
void BLI_hammersley_1d(unsigned int n, double *r)
Definition: rand.cc:353
#define UNUSED_VARS(...)
@ DRW_TEX_WRAP
Definition: DRW_render.h:141
@ DRW_STATE_WRITE_COLOR
Definition: DRW_render.h:303
@ DRW_STATE_BLEND_MUL
Definition: DRW_render.h:333
#define DRW_UBO_FREE_SAFE(ubo)
Definition: DRW_render.h:191
#define DRW_PASS_CREATE(pass, state)
Definition: DRW_render.h:690
#define DRW_shgroup_uniform_block(shgroup, name, ubo)
Definition: DRW_render.h:651
#define DRW_TEXTURE_FREE_SAFE(tex)
Definition: DRW_render.h:183
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
struct GPUShader GPUShader
Definition: GPU_shader.h:20
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
GPUUniformBuf * GPU_uniformbuf_create_ex(size_t size, const void *data, const char *name)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
Scene scene
const DRWContextState * DRW_context_state_get(void)
DefaultTextureList * DRW_viewport_texture_list_get(void)
Definition: draw_manager.c:638
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
void DRW_shgroup_call_procedural_triangles(DRWShadingGroup *shgroup, Object *ob, uint tri_count)
DRWShadingGroup * DRW_shgroup_create(struct GPUShader *shader, DRWPass *pass)
GPUTexture * DRW_texture_create_2d(int w, int h, eGPUTextureFormat format, DRWTextureFlag flags, const float *fpixels)
depth_tx normal_tx diffuse_light_tx specular_light_tx volume_light_tx environment_tx ambient_occlusion_tx aov_value_tx in_weight_img GPU_RGBA16F
const float blue_noise[64 *64][4]
Definition: eevee_lut.c:3491
const float btdf_split_sum_ggx[16][64 *64 *2]
Definition: eevee_lut.c:6569
const float bsdf_split_sum_ggx[64 *64 *2]
Definition: eevee_lut.c:5542
const float ltc_mag_ggx[64 *64 *2]
Definition: eevee_lut.c:2061
const float ltc_disk_integral[64 *64]
Definition: eevee_lut.c:2975
const float ltc_mat_ggx[64 *64 *4]
Definition: eevee_lut.c:10
const int state
ccl_gpu_kernel_postfix ccl_global float int int int int sh
ccl_gpu_kernel_postfix ccl_global float int int int int ccl_global const float int int int int int int int int int int int int num_samples
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fmodf(x, y)
Definition: metal/compat.h:230
struct Scene * scene
Definition: DRW_render.h:979
struct GPUTexture * depth
float matcap_ssao_distance
float matcap_ssao_attenuation
struct SceneDisplay display
float curvature_ridge_factor
float cavity_valley_factor
float curvature_valley_factor
struct DRWPass * cavity_ps
struct GPUUniformBuf * world_ubo
struct GPUTexture * object_id_tx
struct GPUTexture * normal_buffer_tx
struct WORKBENCH_ViewLayerData * vldata
struct GPUUniformBuf * cavity_sample_ubo
struct GPUTexture * cavity_jitter_tx
void workbench_cavity_data_update(WORKBENCH_PrivateData *wpd, WORKBENCH_UBO_World *wd)
void workbench_cavity_samples_ubo_ensure(WORKBENCH_PrivateData *wpd)
BLI_INLINE int workbench_cavity_total_sample_count(const WORKBENCH_PrivateData *wpd, const Scene *scene)
void workbench_cavity_cache_init(WORKBENCH_Data *data)
static float * create_disk_samples(int num_samples, int num_iterations)
static struct GPUTexture * create_jitter_texture(int num_samples)
#define CAVITY_MAX_SAMPLES
#define CURVATURE_ENABLED(wpd)
GPUShader * workbench_shader_cavity_get(bool cavity, bool curvature)
#define CAVITY_ENABLED(wpd)
#define SSAO_ENABLED(wpd)