Files
AnyImage/tests/anyimage/common/test_hdr_rgb_render.py
nan 489003c2cc Add new tests and functionality for image processing and geometry handling
- Introduced color_image.py for preparing standalone color images for tests.
- Added hdr_image.py to create HDR textures for testing.
- Implemented test_image_depth_panorama.py to evaluate panorama topology, UVs, and depth discontinuities.
- Created test_shadeless.py to validate the opacity and HDR color endpoints of the Shadeless group.
- Developed moge3_export.py for exporting dynamic MoGe-3 backbone and ONNX graphs.
- Added material.py to inherit material slots onto generated geometry.
- Built image_depth_panorama.py to construct a quad panorama with depth separation and sampling.
2026-09-10 14:42:17 +08:00

81 lines
3.6 KiB
Python

import bpy
import numpy as np
import pytest
from anyimage.common.hdr_image import HdrBackgroundInput
from anyimage.common.image import cleanup_image_input, image_rgba
from anyimage.common.image_target import ImageEditTarget
from tests.support.hdr_image import hdr_texture
from tests.support.image_texture import texture, texture_context
@pytest.mark.parametrize("use_alpha", [False, True])
def test_hdr_texture_rgb_remains_visible_independently_of_alpha(hdr_texture, tmp_path, use_alpha):
source = hdr_texture.image
source.pixels.foreach_set(np.tile([4, 2, 0.5, 1], 12).astype(np.float32))
alpha = np.tile([0, 0.25, 0.5, 1], (3, 1)).astype(np.float32)
path = tmp_path / "alpha.npy"
np.save(path, alpha)
snapshot = HdrBackgroundInput.prepare(source)
try:
result = snapshot.apply(ImageEditTarget.capture(texture_context(hdr_texture)), path)
finally:
cleanup_image_input(snapshot.path, True)
# A second removal must accept its own independent-channel result and keep RGB intact.
snapshot = HdrBackgroundInput.prepare(result)
try:
snapshot.apply(ImageEditTarget.capture(texture_context(hdr_texture)), path)
np.testing.assert_array_equal(image_rgba(result)[..., :3], np.tile([4, 2, 0.5], (3, 4, 1)))
finally:
cleanup_image_input(snapshot.path, True)
result.reload()
scene = bpy.context.scene
scene.render.engine = "CYCLES"
scene.cycles.device = "CPU"
scene.cycles.samples = 32
scene.cycles.use_denoising = False
scene.render.film_transparent = True
scene.render.resolution_x, scene.render.resolution_y = 64, 16
scene.render.resolution_percentage = 100
scene.render.image_settings.file_format = "OPEN_EXR"
scene.render.image_settings.color_mode = "RGBA"
scene.render.image_settings.color_depth = "32"
scene.render.filepath = str(tmp_path / "render.exr")
bpy.ops.object.camera_add(location=(0, 0, 5))
scene.camera = bpy.context.object
scene.camera.data.type = "ORTHO"
scene.camera.data.ortho_scale = 4
bpy.ops.mesh.primitive_plane_add(size=2)
bpy.context.object.scale = (2, 0.5, 1)
material = bpy.data.materials.new("HDR RGB validation")
material.use_nodes = True
nodes, links = material.node_tree.nodes, material.node_tree.links
nodes.clear()
image_node = nodes.new("ShaderNodeTexImage")
image_node.image = result
image_node.interpolation = "Closest"
emission = nodes.new("ShaderNodeEmission")
links.new(image_node.outputs["Color"], emission.inputs["Color"])
output = nodes.new("ShaderNodeOutputMaterial")
if use_alpha:
transparent = nodes.new("ShaderNodeBsdfTransparent")
mix = nodes.new("ShaderNodeMixShader")
links.new(image_node.outputs["Alpha"], mix.inputs[0])
links.new(transparent.outputs[0], mix.inputs[1])
links.new(emission.outputs[0], mix.inputs[2])
links.new(mix.outputs[0], output.inputs["Surface"])
else:
links.new(emission.outputs[0], output.inputs["Surface"])
bpy.context.object.data.materials.append(material)
bpy.ops.render.render(write_still=True)
rendered = bpy.data.images.load(scene.render.filepath, check_existing=False)
pixels = image_rgba(rendered)
for index, opacity in enumerate((0, 0.0625, 0.25, 1)):
patch = pixels[4:12, index * 16 + 4:index * 16 + 12]
expected_alpha = opacity if use_alpha else 1
np.testing.assert_allclose(patch[..., 3].mean(), expected_alpha, atol=0.035)
expected_rgb = patch[..., 3:4] * np.array([4, 2, 0.5])
np.testing.assert_allclose(patch[..., :3], expected_rgb, rtol=2e-5, atol=1e-6)