Files
test2/source/blender/draw/engines/overlay/overlay_facing.hh
Clément Foucault 5bd572d4fd Cleanup: Overlay: Remove _next in overlay filename
These are not needed anymore since the legacy codebase
is gone.
2025-04-16 20:51:24 +02:00

113 lines
3.3 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup overlay
*/
#pragma once
#include "BKE_paint.hh"
#include "draw_sculpt.hh"
#include "overlay_base.hh"
namespace blender::draw::overlay {
/**
* Draw a specific color for front and back-faces on surfaces.
* Can be toggle in (Viewport Overlays > Geometry > Face Orientation)
*/
class Facing : Overlay {
private:
PassMain ps_ = {"Facing"};
public:
void begin_sync(Resources &res, const State &state) final
{
enabled_ = state.v3d && state.show_face_orientation() && !state.xray_enabled &&
!res.is_selection() && !state.is_depth_only_drawing;
if (!enabled_) {
/* Not used. But release the data. */
ps_.init();
return;
}
const View3DShading &shading = state.v3d->shading;
const bool is_solid_viewport = shading.type == OB_SOLID;
bool use_cull = (is_solid_viewport && (shading.flag & V3D_SHADING_BACKFACE_CULLING));
DRWState backface_cull_state = use_cull ? DRW_STATE_CULL_BACK : DRWState(0);
/* Use the Depth Equal test in solid mode to ensure transparent textures display correctly.
* (See #128113). And the Depth-Less test in other modes (E.g. EEVEE) to ensure the overlay
* displays correctly (See # 114000). */
DRWState depth_compare_state = is_solid_viewport ? DRW_STATE_DEPTH_EQUAL :
DRW_STATE_DEPTH_LESS_EQUAL;
ps_.init();
ps_.state_set(DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | depth_compare_state |
backface_cull_state,
state.clipping_plane_count);
ps_.shader_set(res.shaders->facing.get());
ps_.bind_ubo(OVERLAY_GLOBALS_SLOT, &res.globals_buf);
ps_.bind_ubo(DRW_CLIPPING_UBO_SLOT, &res.clip_planes_buf);
}
void object_sync(Manager &manager,
const ObjectRef &ob_ref,
Resources & /*res*/,
const State &state) final
{
if (!enabled_) {
return;
}
const bool renderable = DRW_object_is_renderable(ob_ref.object);
const bool draw_surface = (ob_ref.object->dt >= OB_WIRE) &&
(renderable || (ob_ref.object->dt == OB_WIRE));
const bool draw_facing = draw_surface && (ob_ref.object->dt >= OB_SOLID);
if (!draw_facing) {
return;
}
const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob_ref.object, state.rv3d) &&
!state.is_image_render;
if (use_sculpt_pbvh) {
ResourceHandle handle = manager.resource_handle_for_sculpt(ob_ref);
for (SculptBatch &batch : sculpt_batches_get(ob_ref.object, SCULPT_BATCH_DEFAULT)) {
ps_.draw(batch.batch, handle);
}
}
else {
blender::gpu::Batch *geom = DRW_cache_object_surface_get(ob_ref.object);
if (geom) {
ps_.draw(geom, manager.unique_handle(ob_ref));
}
}
}
void pre_draw(Manager &manager, View &view) final
{
if (!enabled_) {
return;
}
manager.generate_commands(ps_, view);
}
void draw(Framebuffer &framebuffer, Manager &manager, View &view) final
{
if (!enabled_) {
return;
}
GPU_framebuffer_bind(framebuffer);
manager.submit_only(ps_, view);
}
};
} // namespace blender::draw::overlay