Blender V5.0
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/eevee_lut.hh" /* TODO: find somewhere to share blue noise Table. */
6
7#include "BKE_studiolight.h"
8
9#include "BLI_math_matrix.h"
10#include "BLI_math_rotation.h"
11#include "BLI_math_vector.h"
12
13#include "GPU_batch_utils.hh"
14#include "IMB_imbuf_types.hh"
15
16#include "draw_common_c.hh"
17#include "workbench_private.hh"
18
19namespace blender::workbench {
20
21static bool get_matcap_tx(Texture &matcap_tx, StudioLight &studio_light)
22{
23 BKE_studiolight_ensure_flag(&studio_light,
26 ImBuf *matcap_diffuse = studio_light.matcap_diffuse.ibuf;
27 ImBuf *matcap_specular = studio_light.matcap_specular.ibuf;
28 if (matcap_diffuse && matcap_diffuse->float_buffer.data) {
29 int layers = 1;
30 float *buffer = matcap_diffuse->float_buffer.data;
31 Vector<float> combined_buffer;
32
33 if (matcap_specular && matcap_specular->float_buffer.data) {
34 int size = matcap_diffuse->x * matcap_diffuse->y * 4;
35 combined_buffer.extend(matcap_diffuse->float_buffer.data, size);
36 combined_buffer.extend(matcap_specular->float_buffer.data, size);
37 buffer = combined_buffer.begin();
38 layers++;
39 }
40
41 matcap_tx = Texture(studio_light.name,
42 gpu::TextureFormat::SFLOAT_16_16_16_16,
44 int2(matcap_diffuse->x, matcap_diffuse->y),
45 layers,
46 buffer);
47 return true;
48 }
49 return false;
50}
51
52static float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z)
53{
55 float R[4][4];
56 axis_angle_to_mat4_single(R, 'Z', -studiolight_rot_z);
57 mul_m4_m4m4(R, V.ptr(), R);
58 swap_v3_v3(R[2], R[1]);
59 negate_v3(R[2]);
60 return float4x4(R);
61}
62
64 const float4x4 &world_shading_rotation)
65{
66 LightData light = {};
67 if (sl && sl->flag) {
68 float3 direction = math::transform_direction(world_shading_rotation, float3(sl->vec));
69 light.direction = float4(direction, 0.0f);
70 /* We should pre-divide the power by PI but that makes the lights really dim. */
71 light.specular_color = float4(float3(sl->spec), 0.0f);
72 light.diffuse_color_wrap = float4(float3(sl->col), sl->smooth);
73 }
74 else {
75 light.direction = float4(1.0f, 0.0f, 0.0f, 0.0f);
76 light.specular_color = float4(0.0f);
77 light.diffuse_color_wrap = float4(0.0f);
78 }
79 return light;
80}
81
82void SceneResources::load_jitter_tx(int total_samples)
83{
85
86 const float total_samples_inv = 1.0f / total_samples;
87
88 /* Create blue noise jitter texture */
89 for (int x = 0; x < 64; x++) {
90 for (int y = 0; y < 64; y++) {
91 float phi = eevee::lut::blue_noise[y][x][0] * 2.0f * M_PI;
92 /* This rotate the sample per pixels */
93 jitter[y][x].x = math::cos(phi);
94 jitter[y][x].y = math::sin(phi);
95 /* This offset the sample along its direction axis (reduce banding) */
96 float bn = eevee::lut::blue_noise[y][x][1] - 0.5f;
97 bn = clamp_f(bn, -0.499f, 0.499f); /* fix fireflies */
98 jitter[y][x].z = bn * total_samples_inv;
99 jitter[y][x].w = eevee::lut::blue_noise[y][x][1];
100 }
101 }
102
103 jitter_tx.free();
104 jitter_tx.ensure_2d(gpu::TextureFormat::SFLOAT_16_16_16_16,
107 jitter[0][0]);
108}
109
110void SceneResources::init(const SceneState &scene_state, const DRWContext *ctx)
111{
112 const View3DShading &shading = scene_state.shading;
113
114 world_buf.viewport_size = ctx->viewport_size_get();
115 world_buf.viewport_size_inv = 1.0f / world_buf.viewport_size;
116 world_buf.xray_alpha = shading.xray_alpha;
117 world_buf.background_color = scene_state.background_color;
118 world_buf.object_outline_color = float4(float3(shading.object_outline_color), 1.0f);
119 world_buf.ui_scale = ctx->is_image_render() ? 1.0f : U.pixelsize;
120 world_buf.matcap_orientation = (shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
121
122 StudioLight *studio_light = nullptr;
123 if (U.edit_studio_light) {
124 studio_light = BKE_studiolight_studio_edit_get();
125 }
126 else {
127 if (shading.light == V3D_LIGHTING_MATCAP) {
128 studio_light = BKE_studiolight_find(shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
129 if (studio_light && studio_light->name != current_matcap) {
130 if (get_matcap_tx(matcap_tx, *studio_light)) {
131 current_matcap = studio_light->name;
132 }
133 }
134 }
135 /* If matcaps are missing, use this as fallback. */
136 if (studio_light == nullptr) {
138 }
139 }
140 if (!matcap_tx.is_valid()) {
141 matcap_tx.ensure_2d_array(
142 gpu::TextureFormat::SFLOAT_16_16_16_16, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_READ);
143 }
144
145 float4x4 world_shading_rotation = float4x4::identity();
146 if (shading.flag & V3D_SHADING_WORLD_ORIENTATION) {
147 world_shading_rotation = get_world_shading_rotation_matrix(shading.studiolight_rot_z);
148 }
149
150 for (int i = 0; i < 4; i++) {
151 SolidLight *sl = (studio_light) ? &studio_light->light[i] : nullptr;
152 world_buf.lights[i] = get_light_data_from_studio_solidlight(sl, world_shading_rotation);
153 }
154
155 if (studio_light != nullptr) {
156 world_buf.ambient_color = float4(float3(studio_light->light_ambient), 0.0f);
157 world_buf.use_specular = shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT &&
159 }
160 else {
161 world_buf.ambient_color = float4(1.0f, 1.0f, 1.0f, 0.0f);
162 world_buf.use_specular = false;
163 }
164
165 /* TODO(@pragma37): volumes_do */
166
167 cavity.init(scene_state, *this);
168
169 if (scene_state.draw_dof && !jitter_tx.is_valid()) {
170 /* We don't care about total_samples in this case */
172 }
173
174 world_buf.push_update();
175
176 for (int i : IndexRange(6)) {
177 if (i < scene_state.clip_planes.size()) {
178 clip_planes_buf[i] = scene_state.clip_planes[i];
179 }
180 else {
182 }
183 }
184
185 clip_planes_buf.push_update();
186
187 missing_tx.ensure_2d(gpu::TextureFormat::UNORM_8_8_8_8,
188 int2(1),
190 float4(1.0f, 0.0f, 1.0f, 1.0f));
191 missing_texture.gpu.texture = &missing_tx;
192 missing_texture.name = "Missing Texture";
193
194 dummy_texture_tx.ensure_2d(gpu::TextureFormat::UNORM_8_8_8_8,
195 int2(1),
197 float4(0.0f, 0.0f, 0.0f, 0.0f));
198 dummy_tile_array_tx.ensure_2d_array(gpu::TextureFormat::UNORM_8_8_8_8,
199 int2(1),
200 1,
202 float4(0.0f, 0.0f, 0.0f, 0.0f));
203 dummy_tile_data_tx.ensure_1d_array(gpu::TextureFormat::UNORM_8_8_8_8,
204 1,
205 1,
207 float4(0.0f, 0.0f, 0.0f, 0.0f));
208
209 if (volume_cube_batch == nullptr) {
211 }
212}
213
214} // 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
blender::gpu::Batch * GPU_batch_unit_cube() ATTR_WARN_UNUSED_RESULT
@ GPU_TEXTURE_USAGE_SHADER_READ
#define U
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void extend(Span< T > array)
const float4x4 & viewmat(int view_id=0) const
Definition draw_view.hh:136
static View & default_get()
Definition draw_view.cc:317
#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
bool is_image_render() const
blender::float2 viewport_size_get() const
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]
UniformBuffer< WorldData > world_buf
void init(const SceneState &scene_state, const DRWContext *ctx)
UniformArrayBuffer< float4, 6 > clip_planes_buf
i
Definition text_draw.cc:230
CCL_NAMESPACE_BEGIN struct Window V