Blender V4.5
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,
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(
106}
107
108void SceneResources::init(const SceneState &scene_state, const DRWContext *ctx)
109{
110 const View3DShading &shading = scene_state.shading;
111
112 world_buf.viewport_size = ctx->viewport_size_get();
113 world_buf.viewport_size_inv = 1.0f / world_buf.viewport_size;
114 world_buf.xray_alpha = shading.xray_alpha;
115 world_buf.background_color = scene_state.background_color;
116 world_buf.object_outline_color = float4(float3(shading.object_outline_color), 1.0f);
117 world_buf.ui_scale = ctx->is_image_render() ? 1.0f : U.pixelsize;
118 world_buf.matcap_orientation = (shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0;
119
120 StudioLight *studio_light = nullptr;
121 if (U.edit_studio_light) {
122 studio_light = BKE_studiolight_studio_edit_get();
123 }
124 else {
125 if (shading.light == V3D_LIGHTING_MATCAP) {
126 studio_light = BKE_studiolight_find(shading.matcap, STUDIOLIGHT_TYPE_MATCAP);
127 if (studio_light && studio_light->name != current_matcap) {
128 if (get_matcap_tx(matcap_tx, *studio_light)) {
129 current_matcap = studio_light->name;
130 }
131 }
132 }
133 /* If matcaps are missing, use this as fallback. */
134 if (studio_light == nullptr) {
136 }
137 }
138 if (!matcap_tx.is_valid()) {
140 }
141
142 float4x4 world_shading_rotation = float4x4::identity();
143 if (shading.flag & V3D_SHADING_WORLD_ORIENTATION) {
144 world_shading_rotation = get_world_shading_rotation_matrix(shading.studiolight_rot_z);
145 }
146
147 for (int i = 0; i < 4; i++) {
148 SolidLight *sl = (studio_light) ? &studio_light->light[i] : nullptr;
149 world_buf.lights[i] = get_light_data_from_studio_solidlight(sl, world_shading_rotation);
150 }
151
152 if (studio_light != nullptr) {
153 world_buf.ambient_color = float4(float3(studio_light->light_ambient), 0.0f);
154 world_buf.use_specular = shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT &&
156 }
157 else {
158 world_buf.ambient_color = float4(1.0f, 1.0f, 1.0f, 0.0f);
159 world_buf.use_specular = false;
160 }
161
162 /* TODO(@pragma37): volumes_do */
163
164 cavity.init(scene_state, *this);
165
166 if (scene_state.draw_dof && !jitter_tx.is_valid()) {
167 /* We don't care about total_samples in this case */
169 }
170
171 world_buf.push_update();
172
173 for (int i : IndexRange(6)) {
174 if (i < scene_state.clip_planes.size()) {
175 clip_planes_buf[i] = scene_state.clip_planes[i];
176 }
177 else {
179 }
180 }
181
182 clip_planes_buf.push_update();
183
184 missing_tx.ensure_2d(
185 GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(1.0f, 0.0f, 1.0f, 1.0f));
186 missing_texture.gpu.texture = &missing_tx;
187 missing_texture.name = "Missing Texture";
188
189 dummy_texture_tx.ensure_2d(
190 GPU_RGBA8, int2(1), GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
191 dummy_tile_array_tx.ensure_2d_array(
192 GPU_RGBA8, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
193 dummy_tile_data_tx.ensure_1d_array(
194 GPU_RGBA8, 1, 1, GPU_TEXTURE_USAGE_SHADER_READ, float4(0.0f, 0.0f, 0.0f, 0.0f));
195
196 if (volume_cube_batch == nullptr) {
198 }
199}
200
201} // 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
@ GPU_RGBA16F
@ GPU_RGBA8
#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