Blender V4.3
workbench_resources.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "../eevee_next/eevee_lut.hh" /* TODO: find somewhere to share blue noise Table. */
6#include "BKE_studiolight.h"
7#include "BLI_math_rotation.h"
8#include "IMB_imbuf_types.hh"
9
10#include "workbench_private.hh"
11
12namespace blender::workbench {
13
14static bool get_matcap_tx(Texture &matcap_tx, StudioLight &studio_light)
15{
16 BKE_studiolight_ensure_flag(&studio_light,
19 ImBuf *matcap_diffuse = studio_light.matcap_diffuse.ibuf;
20 ImBuf *matcap_specular = studio_light.matcap_specular.ibuf;
21 if (matcap_diffuse && matcap_diffuse->float_buffer.data) {
22 int layers = 1;
23 float *buffer = matcap_diffuse->float_buffer.data;
24 Vector<float> combined_buffer;
25
26 if (matcap_specular && matcap_specular->float_buffer.data) {
27 int size = matcap_diffuse->x * matcap_diffuse->y * 4;
28 combined_buffer.extend(matcap_diffuse->float_buffer.data, size);
29 combined_buffer.extend(matcap_specular->float_buffer.data, size);
30 buffer = combined_buffer.begin();
31 layers++;
32 }
33
34 matcap_tx = Texture(studio_light.name,
37 int2(matcap_diffuse->x, matcap_diffuse->y),
38 layers,
39 buffer);
40 return true;
41 }
42 return false;
43}
44
45static float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z)
46{
47 /* TODO(@pragma37): C++ API? */
48 float V[4][4], R[4][4];
49 DRW_view_viewmat_get(nullptr, V, false);
50 axis_angle_to_mat4_single(R, 'Z', -studiolight_rot_z);
51 mul_m4_m4m4(R, V, R);
52 swap_v3_v3(R[2], R[1]);
53 negate_v3(R[2]);
54 return float4x4(R);
55}
56
58 const float4x4 &world_shading_rotation)
59{
60 LightData light = {};
61 if (sl && sl->flag) {
62 float3 direction = math::transform_direction(world_shading_rotation, float3(sl->vec));
63 light.direction = float4(direction, 0.0f);
64 /* We should pre-divide the power by PI but that makes the lights really dim. */
65 light.specular_color = float4(float3(sl->spec), 0.0f);
66 light.diffuse_color_wrap = float4(float3(sl->col), sl->smooth);
67 }
68 else {
69 light.direction = float4(1.0f, 0.0f, 0.0f, 0.0f);
70 light.specular_color = float4(0.0f);
71 light.diffuse_color_wrap = float4(0.0f);
72 }
73 return light;
74}
75
76void SceneResources::load_jitter_tx(int total_samples)
77{
79
80 const float total_samples_inv = 1.0f / total_samples;
81
82 /* Create blue noise jitter texture */
83 for (int x = 0; x < 64; x++) {
84 for (int y = 0; y < 64; y++) {
85 float phi = eevee::lut::blue_noise[y][x][0] * 2.0f * M_PI;
86 /* This rotate the sample per pixels */
87 jitter[y][x].x = math::cos(phi);
88 jitter[y][x].y = math::sin(phi);
89 /* This offset the sample along its direction axis (reduce banding) */
90 float bn = eevee::lut::blue_noise[y][x][1] - 0.5f;
91 bn = clamp_f(bn, -0.499f, 0.499f); /* fix fireflies */
92 jitter[y][x].z = bn * total_samples_inv;
93 jitter[y][x].w = eevee::lut::blue_noise[y][x][1];
94 }
95 }
96
97 jitter_tx.free();
98 jitter_tx.ensure_2d(
100}
101
102void SceneResources::init(const SceneState &scene_state)
103{
104 const View3DShading &shading = scene_state.shading;
105
106 world_buf.viewport_size = DRW_viewport_size_get();
107 world_buf.viewport_size_inv = DRW_viewport_invert_size_get();
108 world_buf.xray_alpha = shading.xray_alpha;
109 world_buf.background_color = scene_state.background_color;
110 world_buf.object_outline_color = float4(float3(shading.object_outline_color), 1.0f);
111 world_buf.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.size_pixel;
112 world_buf.matcap_orientation = (shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
113
114 StudioLight *studio_light = nullptr;
115 if (U.edit_studio_light) {
116 studio_light = BKE_studiolight_studio_edit_get();
117 }
118 else {
119 if (shading.light == V3D_LIGHTING_MATCAP) {
120 studio_light = BKE_studiolight_find(shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
121 if (studio_light && studio_light->name != current_matcap) {
122 if (get_matcap_tx(matcap_tx, *studio_light)) {
123 current_matcap = studio_light->name;
124 }
125 }
126 }
127 /* If matcaps are missing, use this as fallback. */
128 if (studio_light == nullptr) {
130 }
131 }
132 if (!matcap_tx.is_valid()) {
134 }
135
136 float4x4 world_shading_rotation = float4x4::identity();
137 if (shading.flag & V3D_SHADING_WORLD_ORIENTATION) {
138 world_shading_rotation = get_world_shading_rotation_matrix(shading.studiolight_rot_z);
139 }
140
141 for (int i = 0; i < 4; i++) {
142 SolidLight *sl = (studio_light) ? &studio_light->light[i] : nullptr;
143 world_buf.lights[i] = get_light_data_from_studio_solidlight(sl, world_shading_rotation);
144 }
145
146 if (studio_light != nullptr) {
147 world_buf.ambient_color = float4(float3(studio_light->light_ambient), 0.0f);
148 world_buf.use_specular = shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT &&
150 }
151 else {
152 world_buf.ambient_color = float4(1.0f, 1.0f, 1.0f, 0.0f);
153 world_buf.use_specular = false;
154 }
155
156 /* TODO(@pragma37): volumes_do */
157
158 cavity.init(scene_state, *this);
159
160 if (scene_state.draw_dof && !jitter_tx.is_valid()) {
161 /* We don't care about total_samples in this case */
163 }
164
165 world_buf.push_update();
166
167 for (int i : IndexRange(6)) {
168 if (i < scene_state.clip_planes.size()) {
169 clip_planes_buf[i] = scene_state.clip_planes[i];
170 }
171 else {
172 clip_planes_buf[i] = float4(0);
173 }
174 }
175
176 clip_planes_buf.push_update();
177
178 missing_tx.ensure_2d(
179 GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(1.0f, 0.0f, 1.0f, 1.0f));
180 missing_texture.gpu.texture = missing_tx;
181 missing_texture.name = "Missing Texture";
182
183 dummy_texture_tx.ensure_2d(
184 GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
185 dummy_tile_array_tx.ensure_2d_array(
186 GPU_RGBA8, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
187 dummy_tile_data_tx.ensure_1d_array(
188 GPU_RGBA8, 1, 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
189}
190
191} // namespace blender::workbench
@ STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE
@ STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE
@ STUDIOLIGHT_TYPE_MATCAP
@ STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS
@ STUDIOLIGHT_TYPE_STUDIO
struct StudioLight * BKE_studiolight_find(const char *name, int flag)
void BKE_studiolight_ensure_flag(StudioLight *sl, int flag)
StudioLight * BKE_studiolight_studio_edit_get(void)
MINLINE float clamp_f(float value, float min, float max)
#define M_PI
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void axis_angle_to_mat4_single(float R[4][4], char axis, float angle)
MINLINE void negate_v3(float r[3])
MINLINE void swap_v3_v3(float a[3], float b[3])
@ V3D_LIGHTING_MATCAP
@ V3D_SHADING_SPECULAR_HIGHLIGHT
@ V3D_SHADING_WORLD_ORIENTATION
@ V3D_SHADING_MATCAP_FLIP_X
@ GPU_TEXTURE_USAGE_SHADER_READ
Contains defines and structs used throughout the imbuf module.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Texture
#define U
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void extend(Span< T > array)
DRW_Global G_draw
const float * DRW_viewport_invert_size_get()
const float * DRW_viewport_size_get()
bool DRW_state_is_image_render()
void DRW_view_viewmat_get(const DRWView *view, float mat[4][4], bool inverse)
RAYTRACE_GROUP_SIZE additional_info("eevee_shared", "eevee_gbuffer_data", "eevee_global_ubo", "eevee_sampling_data", "eevee_utility_texture", "eevee_hiz_data", "draw_view") .specialization_constant(Type RAYTRACE_GROUP_SIZE in_sh_0_tx in_sh_2_tx screen_normal_tx GPU_RGBA8
#define R
const float blue_noise[64][64][4]
T cos(const AngleRadianBase< T > &a)
T sin(const AngleRadianBase< T > &a)
VecBase< T, 3 > transform_direction(const MatBase< T, 3, 3 > &mat, const VecBase< T, 3 > &direction)
static bool get_matcap_tx(Texture &matcap_tx, StudioLight &studio_light)
static LightData get_light_data_from_studio_solidlight(const SolidLight *sl, const float4x4 &world_shading_rotation)
static float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z)
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
ImBufFloatBuffer float_buffer
struct ImBuf * ibuf
StudioLightImage matcap_specular
SolidLight light[STUDIOLIGHT_MAX_LIGHT]
char name[FILE_MAXFILE]
StudioLightImage matcap_diffuse
float light_ambient[3]
float object_outline_color[3]
char studio_light[256]
void init(const SceneState &scene_state)
UniformBuffer< WorldData > world_buf
UniformArrayBuffer< float4, 6 > clip_planes_buf
CCL_NAMESPACE_BEGIN struct Window V