This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/draw/engines/workbench/workbench_resources.cc
Clément Foucault b0b9e746fa BLI: Use BLI_math_matrix_type.hh instead of BLI_math_float4x4.hh
Straightforward port. I took the oportunity to remove some C vector
functions (ex: copy_v2_v2).

This makes some changes to DRWView to accomodate the alignement
requirements of the float4x4 type.
2023-02-06 21:25:45 +01:00

175 lines
5.9 KiB
C++

/* 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 {
static bool get_matcap_tx(Texture &matcap_tx, StudioLight &studio_light)
{
BKE_studiolight_ensure_flag(&studio_light,
STUDIOLIGHT_MATCAP_DIFFUSE_GPUTEXTURE |
STUDIOLIGHT_MATCAP_SPECULAR_GPUTEXTURE);
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 = {};
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;
}
static float4x4 get_world_shading_rotation_matrix(float studiolight_rot_z)
{
/* TODO(@pragma37): 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);
}
static LightData get_light_data_from_studio_solidlight(const SolidLight *sl,
float4x4 world_shading_rotation)
{
LightData light = {};
if (sl && sl->flag) {
float3 direction = math::transform_direction(world_shading_rotation, 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(@pragma37): 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