Merge branch 'blender-v5.0-release'

This commit is contained in:
Jacques Lucke
2025-10-16 19:20:23 +02:00
22 changed files with 202 additions and 39 deletions

View File

@@ -12,7 +12,7 @@ IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('IMAGE')
shader = gpu.shader.from_builtin('IMAGE_SCENE_LINEAR_TO_REC709_SRGB')
batch = batch_for_shader(
shader, 'TRI_FAN',
{
@@ -45,7 +45,7 @@ IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('IMAGE')
shader = gpu.shader.from_builtin('IMAGE_SCENE_LINEAR_TO_REC709_SRGB')
batch = batch_for_shader(
shader, 'TRIS',
{

View File

@@ -58,7 +58,7 @@ def draw_circle_2d(position, color, radius, *, segments=None):
batch.draw(shader)
def draw_texture_2d(texture, position, width, height):
def draw_texture_2d(texture, position, width, height, is_scene_linear_with_rec709_srgb_target=False):
"""
Draw a 2d texture.
@@ -71,6 +71,13 @@ def draw_texture_2d(texture, position, width, height):
:type width: float
:arg height: Height of the image when drawn.
:type height: float
:arg is_scene_linear_with_rec709_srgb_target:
True if the `texture` is stored in scene linear color space and
the destination framebuffer uses the Rec.709 sRGB color space
(which is true when drawing textures acquired from :class:`bpy.types.Image` inside a
'PRE_VIEW', 'POST_VIEW' or 'POST_PIXEL' draw handler).
Otherwise the color space is assumed to match the one of the framebuffer. (default=False)
:type is_scene_linear_with_rec709_srgb_target: bool
"""
import gpu
from . batch import batch_for_shader
@@ -78,7 +85,8 @@ def draw_texture_2d(texture, position, width, height):
coords = ((0, 0), (1, 0), (1, 1), (0, 1))
indices = ((0, 1, 2), (2, 3, 0))
shader = gpu.shader.from_builtin('IMAGE')
shader = gpu.shader.from_builtin(
'IMAGE_SCENE_LINEAR_TO_REC709_SRGB' if is_scene_linear_with_rec709_srgb_target else 'IMAGE')
batch = batch_for_shader(
shader, 'TRIS',
{"pos": coords, "texCoord": coords},
@@ -89,7 +97,6 @@ def draw_texture_2d(texture, position, width, height):
gpu.matrix.translate(position)
gpu.matrix.scale((width, height))
shader = gpu.shader.from_builtin('IMAGE')
shader.uniform_sampler("image", texture)
batch.draw(shader)

View File

@@ -415,7 +415,10 @@ class OBJECT_PT_visibility(ObjectButtonsPanel, Panel):
layout = self.layout
ob = context.object
layout.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
col = layout.column()
col.prop(ob, "hide_select", text="Selectable", toggle=False, invert_checkbox=True)
col.prop(ob, "hide_surface_pick", text="Surface Picking", toggle=False, invert_checkbox=True)
layout.separator()
col = layout.column(heading="Show In")
col.prop(ob, "hide_viewport", text="Viewports", toggle=False, invert_checkbox=True)

View File

@@ -574,7 +574,7 @@ static void pack_linked_id(Main &bmain,
std::nullopt,
nullptr,
LIB_ID_COPY_DEFAULT | LIB_ID_COPY_ID_NEW_SET |
LIB_ID_COPY_NO_ANIMDATA);
LIB_ID_COPY_NO_ANIMDATA | LIB_ID_COPY_ASSET_METADATA);
id_us_min(packed_id);
copied_id_process(linked_id, packed_id);

View File

@@ -1089,6 +1089,10 @@ bool Instance::object_needs_prepass(const ObjectRef &ob_ref, bool in_paint_mode)
}
if (resources.is_selection() || state.is_depth_only_drawing) {
if (ob_ref.object->visibility_flag & OB_HIDE_SURFACE_PICK) {
/* Special flag to avoid surfaces to contribute to depth picking and selection. */
return false;
}
/* Selection and depth picking always need a prepass.
* Note that depth writing and depth test might be disable for certain selection mode. */
return true;

View File

@@ -2043,9 +2043,6 @@ void DRW_draw_depth_loop(Depsgraph *depsgraph,
if (use_only_selected && !(ob.base_flag & BASE_SELECTED)) {
return false;
}
if ((ob.base_flag & BASE_SELECTABLE) == 0) {
return false;
}
return true;
};

View File

@@ -580,6 +580,11 @@ static eSnapMode raycast_obj_fn(SnapObjectContext *sctx,
{
bool retval = false;
if (ob_eval->visibility_flag & OB_HIDE_SURFACE_PICK) {
/* Do not snap it surface picking is disabled. */
return SCE_SNAP_TO_NONE;
}
if (ob_data == nullptr) {
if ((sctx->runtime.occlusion_test_edit == SNAP_OCCLUSION_AS_SEEM) &&
ELEM(ob_eval->dt, OB_BOUNDBOX, OB_WIRE))

View File

@@ -376,8 +376,9 @@ enum GPUUniformBuiltin {
GPU_UNIFORM_RESOURCE_CHUNK, /* int resourceChunk */
GPU_UNIFORM_RESOURCE_ID, /* int resourceId */
GPU_UNIFORM_SRGB_TRANSFORM, /* bool srgbTarget */
GPU_UNIFORM_SCENE_LINEAR_XFORM, /* float3x3 gpu_scene_linear_to_xyz */
};
#define GPU_NUM_UNIFORMS (GPU_UNIFORM_SRGB_TRANSFORM + 1)
#define GPU_NUM_UNIFORMS (GPU_UNIFORM_SCENE_LINEAR_XFORM + 1)
/**
* TODO: To be moved as private API. Not really used outside of gpu_matrix.cc and doesn't really

View File

@@ -136,7 +136,9 @@ enum GPUBuiltinShader {
GPU_SHADER_3D_POINT_UNIFORM_COLOR,
/**
* Draw a texture in 3D. Take a 3D position and a 2D texture coordinate for each vertex.
* Draw a sRGB color space texture in 3D.
* Texture color space is assumed to match the framebuffer.
* Take a 3D position and a 2D texture coordinate for each vertex.
*
* \param image: uniform sampler2D
* \param texCoord: in vec2
@@ -144,6 +146,17 @@ enum GPUBuiltinShader {
*/
GPU_SHADER_3D_IMAGE,
/**
* Draw a scene linear color space texture in 3D.
* Texture value is transformed to the Rec.709 sRGB color space.
* Take a 3D position and a 2D texture coordinate for each vertex.
*
* \param image: uniform sampler2D
* \param texCoord: in vec2
* \param pos: in vec3
*/
GPU_SHADER_3D_IMAGE_SCENE_LINEAR_TO_REC709_SRGB,
/**
* Draw a sRGB color space (with Rec.709 primaries) texture in 3D.
* Take a 3D position and color for each vertex with linear interpolation in window space.
*
* \param color: uniform vec4
@@ -152,8 +165,19 @@ enum GPUBuiltinShader {
* \param pos: in vec3
*/
GPU_SHADER_3D_IMAGE_COLOR,
/**
* Draw a scene linear color space texture in 3D.
* Texture value is transformed to the Rec.709 sRGB color space.
* Take a 3D position and color for each vertex with linear interpolation in window space.
*
* \param color: uniform vec4
* \param image: uniform sampler2D
* \param texCoord: in vec2
* \param pos: in vec3
*/
GPU_SHADER_3D_IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB,
};
#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_IMAGE_COLOR + 1)
#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB + 1)
/** Support multiple configurations. */
enum GPUShaderConfig {

View File

@@ -6,9 +6,10 @@
* \ingroup gpu
*/
#include "BLI_colorspace.hh"
#include "BLI_math_matrix.h"
#include "BLI_math_matrix_types.hh"
#include "BLI_string.h"
#include "BLI_time.h"
#include "GPU_capabilities.hh"
#include "GPU_debug.hh"
@@ -265,6 +266,9 @@ void GPU_shader_bind(blender::gpu::Shader *gpu_shader,
shader->bind(constants_state);
GPU_matrix_bind(gpu_shader);
Shader::set_srgb_uniform(ctx, gpu_shader);
/* Blender working color space do not change during the drawing of the frame.
* So we can just set the uniform once. */
Shader::set_scene_linear_to_xyz_uniform(gpu_shader);
}
else {
if (constants_state) {
@@ -634,6 +638,15 @@ void Shader::set_srgb_uniform(Context *ctx, blender::gpu::Shader *shader)
ctx->shader_builtin_srgb_is_dirty = false;
}
void Shader::set_scene_linear_to_xyz_uniform(blender::gpu::Shader *shader)
{
int32_t loc = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_SCENE_LINEAR_XFORM);
if (loc != -1) {
GPU_shader_uniform_float_ex(
shader, loc, 9, 1, blender::colorspace::scene_linear_to_rec709.ptr()[0]);
}
}
void Shader::set_framebuffer_srgb_target(int use_srgb_to_linear)
{
Context *ctx = Context::get();

View File

@@ -35,8 +35,12 @@ static const char *builtin_shader_create_info_name(GPUBuiltinShader shader)
return "gpu_shader_simple_lighting";
case GPU_SHADER_3D_IMAGE:
return "gpu_shader_3D_image";
case GPU_SHADER_3D_IMAGE_SCENE_LINEAR_TO_REC709_SRGB:
return "gpu_shader_3D_image_scene_linear";
case GPU_SHADER_3D_IMAGE_COLOR:
return "gpu_shader_3D_image_color";
case GPU_SHADER_3D_IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB:
return "gpu_shader_3D_image_color_scene_linear";
case GPU_SHADER_2D_CHECKER:
return "gpu_shader_2D_checker";
case GPU_SHADER_2D_DIAG_STRIPES:

View File

@@ -220,6 +220,8 @@ inline const char *ShaderInterface::builtin_uniform_name(GPUUniformBuiltin u)
return "drw_ResourceID";
case GPU_UNIFORM_SRGB_TRANSFORM:
return "srgbTarget";
case GPU_UNIFORM_SCENE_LINEAR_XFORM:
return "gpu_scene_linear_to_rec709";
default:
return nullptr;

View File

@@ -115,6 +115,7 @@ class Shader {
return parent_shader_;
}
static void set_scene_linear_to_xyz_uniform(gpu::Shader *shader);
static void set_srgb_uniform(Context *ctx, gpu::Shader *shader);
static void set_framebuffer_srgb_target(int use_srgb_to_linear);

View File

@@ -2,6 +2,10 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/**
*/
#pragma once
#include "infos/gpu_srgb_to_framebuffer_space_infos.hh"
@@ -11,20 +15,66 @@ SHADER_LIBRARY_CREATE_INFO(gpu_srgb_to_framebuffer_space)
/* Undefine the macro that avoids compilation errors. */
#undef blender_srgb_to_framebuffer_space
/* Raw python shaders don't have create infos and thus don't generate the needed `srgbTarget`
* uniform automatically. For API compatibility, we sill define this loose uniform, but it will
* not be parsed by the Metal or Vulkan backend. */
#ifdef GPU_RAW_PYTHON_SHADER
uniform bool srgbTarget = false;
#endif
float4 blender_srgb_to_framebuffer_space(float4 in_color)
/**
* Input is Rec.709 sRGB.
* Output is Rec.709 linear if hardware will add a Linear to sRGB comversion, noop otherwise.
* NOTE: Old naming convention, but avoids breaking compatibility for python shaders.
*
* As per GPU API design, all framebuffers with SRGBA_8_8_8_8 attachments will always enable SRGB
* rendering. In this mode the shader output is expected to be in a linear color space. This allows
* to do the blending stage with linear values (more correct) and then store the result in 8bpc
* keeping accurate colors.
*
* To ensure consistent result (blending excluded) between a framebuffer using SRGBA_8_8_8_8 and
* one using RGBA_8_8_8_8, we need to do the sRGB > linear conversion to counteract the hardware
* encoding during framebuffer output.
*
* For reference: https://wikis.khronos.org/opengl/framebuffer#Colorspace
*/
float4 blender_srgb_to_framebuffer_space(float4 srgb_color)
{
if (srgbTarget) {
float3 c = max(in_color.rgb, float3(0.0f));
/**
* IMPORTANT: srgbTarget denote that the output is expected to be in __linear__ space.
* https://wikis.khronos.org/opengl/framebuffer#Colorspace
*/
if (!srgbTarget) {
/* Input should already be in sRGB. */
return srgb_color;
}
/* Note that this is simply counteracting the hardware Linear > sRGB conversion. */
float3 c = max(srgb_color.rgb, float3(0.0f));
float3 c1 = c * (1.0f / 12.92f);
float3 c2 = pow((c + 0.055f) * (1.0f / 1.055f), float3(2.4f));
in_color.rgb = mix(c1, c2, step(float3(0.04045f), c));
}
return in_color;
float4 linear_color;
linear_color.rgb = mix(c1, c2, step(float3(0.04045f), c));
linear_color.a = srgb_color.a;
return linear_color;
}
/**
* Input is Rec.709 sRGB.
* Output is Rec.709 linear if hardware will add a Linear to sRGB comversion, noop otherwise.
*/
float4 blender_rec709_srgb_to_output_space(float4 srgb_color)
{
return blender_srgb_to_framebuffer_space(srgb_color);
}
/* Input is Blender Scene Linear. Output is Rec.709 sRGB. */
float4 blender_scene_linear_to_rec709_srgb(float3x3 scene_linear_to_rec709,
float4 scene_linear_color)
{
float3 rec709_linear = scene_linear_to_rec709 * scene_linear_color.rgb;
/* TODO(fclem): For wide gamut (extended sRGB), we need to encode negative values in a certain
* way here. */
/* Linear to sRGB transform. */
float3 c = max(rec709_linear, float3(0.0f));
float3 c1 = c * 12.92f;
float3 c2 = 1.055f * pow(c, float3(1.0f / 2.4f)) - 0.055f;
float4 srgb_color;
srgb_color.rgb = mix(c1, c2, step(float3(0.0031308f), c));
srgb_color.a = scene_linear_color.a;
return srgb_color;
}

View File

@@ -2,14 +2,17 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/gpu_shader_2D_image_rect_color_infos.hh"
#include "infos/gpu_shader_3D_image_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(gpu_shader_2D_image_rect_color)
FRAGMENT_SHADER_CREATE_INFO(gpu_shader_3D_image_color_scene_linear)
#include "gpu_shader_colorspace_lib.glsl"
void main()
{
fragColor = texture(image, texCoord_interp) * color;
fragColor = blender_srgb_to_framebuffer_space(fragColor);
#ifdef BLENDER_SCENE_LINEAR_TO_REC709
fragColor = blender_scene_linear_to_rec709_srgb(gpu_scene_linear_to_rec709, fragColor);
#endif
fragColor = blender_rec709_srgb_to_output_space(fragColor);
}

View File

@@ -2,14 +2,17 @@
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "infos/gpu_shader_2D_image_infos.hh"
#include "infos/gpu_shader_3D_image_infos.hh"
FRAGMENT_SHADER_CREATE_INFO(gpu_shader_2D_image_common)
FRAGMENT_SHADER_CREATE_INFO(gpu_shader_3D_image)
#include "gpu_shader_colorspace_lib.glsl"
void main()
{
fragColor = texture(image, texCoord_interp);
fragColor = blender_srgb_to_framebuffer_space(fragColor);
#ifdef BLENDER_SCENE_LINEAR_TO_REC709
fragColor = blender_scene_linear_to_rec709_srgb(gpu_scene_linear_to_rec709, fragColor);
#endif
fragColor = blender_rec709_srgb_to_output_space(fragColor);
}

View File

@@ -28,6 +28,7 @@ PUSH_CONSTANT(float4, rect_geom)
SAMPLER(0, sampler2D, image)
VERTEX_SOURCE("gpu_shader_2D_image_rect_vert.glsl")
FRAGMENT_SOURCE("gpu_shader_image_color_frag.glsl")
COMPILATION_CONSTANT(bool, is_scene_linear_image, false)
ADDITIONAL_INFO(gpu_srgb_to_framebuffer_space)
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()

View File

@@ -31,12 +31,31 @@ GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(gpu_shader_3D_image)
ADDITIONAL_INFO(gpu_shader_3D_image_common)
COMPILATION_CONSTANT(bool, is_scene_linear_image, false)
FRAGMENT_SOURCE("gpu_shader_image_frag.glsl")
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(gpu_shader_3D_image_scene_linear)
ADDITIONAL_INFO(gpu_shader_3D_image_common)
ADDITIONAL_INFO(gpu_scene_linear_to_rec709_space)
COMPILATION_CONSTANT(bool, is_scene_linear_image, true)
FRAGMENT_SOURCE("gpu_shader_image_frag.glsl")
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(gpu_shader_3D_image_color)
ADDITIONAL_INFO(gpu_shader_3D_image_common)
COMPILATION_CONSTANT(bool, is_scene_linear_image, false)
PUSH_CONSTANT(float4, color)
FRAGMENT_SOURCE("gpu_shader_image_color_frag.glsl")
DO_STATIC_COMPILATION()
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(gpu_shader_3D_image_color_scene_linear)
ADDITIONAL_INFO(gpu_shader_3D_image_common)
ADDITIONAL_INFO(gpu_scene_linear_to_rec709_space)
COMPILATION_CONSTANT(bool, is_scene_linear_image, true)
PUSH_CONSTANT(float4, color)
FRAGMENT_SOURCE("gpu_shader_image_color_frag.glsl")
DO_STATIC_COMPILATION()

View File

@@ -19,3 +19,8 @@ GPU_SHADER_CREATE_INFO(gpu_srgb_to_framebuffer_space)
PUSH_CONSTANT(bool, srgbTarget)
DEFINE("blender_srgb_to_framebuffer_space(a) a")
GPU_SHADER_CREATE_END()
GPU_SHADER_CREATE_INFO(gpu_scene_linear_to_rec709_space)
PUSH_CONSTANT(float3x3, gpu_scene_linear_to_rec709)
DEFINE("BLENDER_SCENE_LINEAR_TO_REC709")
GPU_SHADER_CREATE_END()

View File

@@ -690,6 +690,7 @@ enum {
OB_HIDE_PROBE_VOLUME = 1 << 11,
OB_HIDE_PROBE_CUBEMAP = 1 << 12,
OB_HIDE_PROBE_PLANAR = 1 << 13,
OB_HIDE_SURFACE_PICK = 1 << 14,
};
/** #Object.shapeflag */

View File

@@ -2840,6 +2840,15 @@ static void rna_def_object_visibility(StructRNA *srna)
prop, "Disable in Planar Light Probes", "Globally disable in planar light probes");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw");
prop = RNA_def_property(srna, "hide_surface_pick", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "visibility_flag", OB_HIDE_SURFACE_PICK);
RNA_def_property_ui_text(
prop,
"Disable in Surface Picking",
"Disable surface influence during selection, snapping and depth-picking operators. "
"Usually used to avoid semi-transparent objects to affect scene navigation");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Object_internal_update_draw");
/* Instancer options. */
prop = RNA_def_property(srna, "show_instancer_for_render", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "duplicator_visibility_flag", OB_DUPLI_FLAG_RENDER);

View File

@@ -42,9 +42,17 @@
"``IMAGE``\n" \
" :Attributes: vec3 pos, vec2 texCoord\n" \
" :Uniforms: sampler2D image\n" \
"``IMAGE_SCENE_LINEAR_TO_REC709_SRGB``\n" \
" :Attributes: vec3 pos, vec2 texCoord\n" \
" :Uniforms: sampler2D image\n" \
" :Note: Expect texture to be in scene linear color space\n" \
"``IMAGE_COLOR``\n" \
" :Attributes: vec3 pos, vec2 texCoord\n" \
" :Uniforms: sampler2D image, vec4 color\n" \
"``IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB``\n" \
" :Attributes: vec3 pos, vec2 texCoord\n" \
" :Uniforms: sampler2D image, vec4 color\n" \
" :Note: Expect texture to be in scene linear color space\n" \
"``SMOOTH_COLOR``\n" \
" :Attributes: vec3 pos, vec4 color\n" \
" :Uniforms: none\n" \
@@ -70,7 +78,10 @@
static const PyC_StringEnumItems pygpu_shader_builtin_items[] = {
{GPU_SHADER_3D_FLAT_COLOR, "FLAT_COLOR"},
{GPU_SHADER_3D_IMAGE, "IMAGE"},
{GPU_SHADER_3D_IMAGE_SCENE_LINEAR_TO_REC709_SRGB, "IMAGE_SCENE_LINEAR_TO_REC709_SRGB"},
{GPU_SHADER_3D_IMAGE_COLOR, "IMAGE_COLOR"},
{GPU_SHADER_3D_IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB,
"IMAGE_COLOR_SCENE_LINEAR_TO_REC709_SRGB"},
{GPU_SHADER_3D_SMOOTH_COLOR, "SMOOTH_COLOR"},
{GPU_SHADER_3D_UNIFORM_COLOR, "UNIFORM_COLOR"},
{GPU_SHADER_3D_POLYLINE_FLAT_COLOR, "POLYLINE_FLAT_COLOR"},