Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/engines/workbench/workbench_resources.cc
- This file was added.
| /* SPDX-License-Identifier: GPL-2.0-or-later */ | |||||
| #include "../eevee/eevee_lut.h" /* TODO: find somewhere to share blue noise Table. */ | |||||
| #include "BKE_studiolight.h" | |||||
| #include "IMB_imbuf_types.h" | |||||
| #include "workbench_private.hh" | |||||
| namespace blender::workbench { | |||||
| bool get_matcap_tx(Texture &matcap_tx, const StudioLight &studio_light) | |||||
| { | |||||
| ImBuf *matcap_diffuse = studio_light.matcap_diffuse.ibuf; | |||||
| ImBuf *matcap_specular = studio_light.matcap_specular.ibuf; | |||||
| if (matcap_diffuse && matcap_diffuse->rect_float) { | |||||
| int layers = 1; | |||||
| float *buffer = matcap_diffuse->rect_float; | |||||
| Vector<float> combined_buffer = {}; | |||||
HooglyBoogly: This initialization is unnecessary, `Vector` will be default initialized either way | |||||
Not Done Inline ActionsI have the habit of always explicitly initializing local variables. pragma37: I have the habit of always explicitly initializing local variables.
There are other places… | |||||
Not Done Inline ActionsIt's not a big deal I guess, but I think it's better to remove it, since it implies Vector doesn't do that itself. HooglyBoogly: It's not a big deal I guess, but I think it's better to remove it, since it implies `Vector`… | |||||
| if (matcap_specular && matcap_specular->rect_float) { | |||||
| int size = matcap_diffuse->x * matcap_diffuse->y * 4; | |||||
| combined_buffer.extend(matcap_diffuse->rect_float, size); | |||||
| combined_buffer.extend(matcap_specular->rect_float, size); | |||||
| buffer = combined_buffer.begin(); | |||||
| layers++; | |||||
| } | |||||
| matcap_tx = Texture(studio_light.name, | |||||
| GPU_RGBA16F, | |||||
| GPU_TEXTURE_USAGE_SHADER_READ, | |||||
| int2(matcap_diffuse->x, matcap_diffuse->y), | |||||
| layers, | |||||
| buffer); | |||||
| return true; | |||||
| } | |||||
| return false; | |||||
| } | |||||
| float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z) | |||||
| { | |||||
| /* TODO(Miguel Pozo) C++ API ? */ | |||||
| float V[4][4], R[4][4]; | |||||
| DRW_view_viewmat_get(nullptr, V, false); | |||||
| axis_angle_to_mat4_single(R, 'Z', -studiolight_rot_z); | |||||
| mul_m4_m4m4(R, V, R); | |||||
| swap_v3_v3(R[2], R[1]); | |||||
| negate_v3(R[2]); | |||||
| return float4x4(R); | |||||
Not Done Inline ActionsCan use new matrix API. Also can use float3x3 and finaly convert to float4x4 by just using functional cast. fclem: Can use new matrix API. Also can use `float3x3` and finaly convert to `float4x4` by just using… | |||||
| } | |||||
| LightData get_light_data_from_studio_solidlight(const SolidLight *sl, | |||||
| float4x4 world_shading_rotation) | |||||
| { | |||||
| LightData light = {}; | |||||
| if (sl && sl->flag) { | |||||
| float3 direction = world_shading_rotation.ref_3x3() * float3(sl->vec); | |||||
| light.direction = float4(direction, 0.0f); | |||||
| /* We should pre-divide the power by PI but that makes the lights really dim. */ | |||||
| light.specular_color = float4(float3(sl->spec), 0.0f); | |||||
| light.diffuse_color_wrap = float4(float3(sl->col), sl->smooth); | |||||
| } | |||||
| else { | |||||
| light.direction = float4(1.0f, 0.0f, 0.0f, 0.0f); | |||||
| light.specular_color = float4(0.0f); | |||||
| light.diffuse_color_wrap = float4(0.0f); | |||||
| } | |||||
| return light; | |||||
| } | |||||
| void SceneResources::load_jitter_tx(int total_samples) | |||||
| { | |||||
| const int texel_count = jitter_tx_size * jitter_tx_size; | |||||
| static float4 jitter[texel_count]; | |||||
| const float total_samples_inv = 1.0f / total_samples; | |||||
| /* Create blue noise jitter texture */ | |||||
| for (int i = 0; i < texel_count; i++) { | |||||
| float phi = blue_noise[i][0] * 2.0f * M_PI; | |||||
| /* This rotate the sample per pixels */ | |||||
| jitter[i].x = math::cos(phi); | |||||
| jitter[i].y = math::sin(phi); | |||||
| /* This offset the sample along its direction axis (reduce banding) */ | |||||
| float bn = blue_noise[i][1] - 0.5f; | |||||
| bn = clamp_f(bn, -0.499f, 0.499f); /* fix fireflies */ | |||||
| jitter[i].z = bn * total_samples_inv; | |||||
| jitter[i].w = blue_noise[i][1]; | |||||
| } | |||||
| jitter_tx.free(); | |||||
| jitter_tx.ensure_2d(GPU_RGBA16F, int2(jitter_tx_size), GPU_TEXTURE_USAGE_SHADER_READ, jitter[0]); | |||||
| } | |||||
| void SceneResources::init(const SceneState &scene_state) | |||||
| { | |||||
| const View3DShading &shading = scene_state.shading; | |||||
| world_buf.viewport_size = DRW_viewport_size_get(); | |||||
| world_buf.viewport_size_inv = DRW_viewport_invert_size_get(); | |||||
| world_buf.xray_alpha = shading.xray_alpha; | |||||
| world_buf.background_color = scene_state.background_color; | |||||
| world_buf.object_outline_color = float4(float3(shading.object_outline_color), 1.0f); | |||||
| world_buf.ui_scale = DRW_state_is_image_render() ? 1.0f : G_draw.block.size_pixel; | |||||
| world_buf.matcap_orientation = (shading.flag & V3D_SHADING_MATCAP_FLIP_X) != 0; | |||||
| StudioLight *studio_light = nullptr; | |||||
| if (U.edit_studio_light) { | |||||
| studio_light = BKE_studiolight_studio_edit_get(); | |||||
| } | |||||
| else { | |||||
| if (shading.light == V3D_LIGHTING_MATCAP) { | |||||
| studio_light = BKE_studiolight_find(shading.matcap, STUDIOLIGHT_TYPE_MATCAP); | |||||
| if (studio_light && studio_light->name != current_matcap) { | |||||
| if (get_matcap_tx(matcap_tx, *studio_light)) { | |||||
| current_matcap = studio_light->name; | |||||
| } | |||||
| } | |||||
| } | |||||
| /* If matcaps are missing, use this as fallback. */ | |||||
| if (studio_light == nullptr) { | |||||
| studio_light = BKE_studiolight_find(shading.studio_light, STUDIOLIGHT_TYPE_STUDIO); | |||||
| } | |||||
| } | |||||
| if (!matcap_tx.is_valid()) { | |||||
| matcap_tx.ensure_2d_array(GPU_RGBA16F, int2(1), 1, GPU_TEXTURE_USAGE_SHADER_READ); | |||||
| } | |||||
| float4x4 world_shading_rotation = float4x4::identity(); | |||||
| if (shading.flag & V3D_SHADING_WORLD_ORIENTATION) { | |||||
| world_shading_rotation = get_world_shading_rotation_matrix(shading.studiolight_rot_z); | |||||
| } | |||||
| for (int i = 0; i < 4; i++) { | |||||
| SolidLight *sl = (studio_light) ? &studio_light->light[i] : nullptr; | |||||
| world_buf.lights[i] = get_light_data_from_studio_solidlight(sl, world_shading_rotation); | |||||
| } | |||||
| if (studio_light != nullptr) { | |||||
| world_buf.ambient_color = float4(float3(studio_light->light_ambient), 0.0f); | |||||
| world_buf.use_specular = shading.flag & V3D_SHADING_SPECULAR_HIGHLIGHT && | |||||
| studio_light->flag & STUDIOLIGHT_SPECULAR_HIGHLIGHT_PASS; | |||||
| } | |||||
| else { | |||||
| world_buf.ambient_color = float4(1.0f, 1.0f, 1.0f, 0.0f); | |||||
| world_buf.use_specular = false; | |||||
| } | |||||
| /* TODO(Miguel Pozo) volumes_do */ | |||||
| cavity.init(scene_state, *this); | |||||
| if (scene_state.draw_dof && !jitter_tx.is_valid()) { | |||||
| /* We don't care about total_samples in this case */ | |||||
| load_jitter_tx(1); | |||||
| } | |||||
| world_buf.push_update(); | |||||
| for (int i : IndexRange(6)) { | |||||
| if (i < scene_state.clip_planes.size()) { | |||||
| clip_planes_buf[i] = scene_state.clip_planes[i]; | |||||
| } | |||||
| else { | |||||
| clip_planes_buf[i] = float4(0); | |||||
| } | |||||
| } | |||||
| clip_planes_buf.push_update(); | |||||
| } | |||||
| } // namespace blender::workbench | |||||
This initialization is unnecessary, Vector will be default initialized either way