정점 색상 그라디언트가 선형이 아닙니다.

Aug 21 2020

정점 채색을 통해 기본 큐브를 페인팅하고 있습니다. 하단 4 개의 정점을 (0.25, 0.25, 0.25)로, 상단 4 개의 정점을 (0.75, 0.75, 0.75)로 칠합니다.

VERTEX PAINT 모드 (단축키 S 를 사용 하여 색상을 얻음) 에서 결과를 검사 할 때 큐브의 바닥은 실제로 (0.25, 0.25, 0.25)이고 위쪽은 (0.75, 0.75, 0.75)입니다.

그러나 정육면체의 중간 점은 (0.5, 0.5, 0.5)가 아니라 ~ (0.56, 0.56, 0.56)입니다. 어쨌든 그라디언트는 선형이 아닙니다. sRGB 대 선형의 문제라고 생각하지 않습니다. 그렇지 않으면 아래쪽 및 위쪽 값도 잘못 될 것이기 때문에 그 사이의 값일뿐입니다. 그렇다면 여기서 문제는 무엇입니까? 선형 그래디언트가 정말 필요합니다.

편집하다. 관련 문제 :https://developer.blender.org/T71835 이것은 정점 색상이 저장되는 방법과 관련이 있음을 나타냅니다 (8 비트 sRGB).

이 문제를 재현하는 코드 :

"""Script that checks vertex color interpolation error on the default cube.

run command: `blender --python gradient_error.py` (opens blender)
"""

import bpy

# Set up scene
sce = bpy.context.scene

# Select cube
scene = bpy.context.scene
for ob in scene.objects:
    ob.select_set(False)
    if ob.name == 'Cube':
        ob.select_set(True)
obj = bpy.context.view_layer.objects.active

# Get cube data
mesh = obj.data
vert_list = mesh.vertices

# Get the color map
if mesh.vertex_colors:
    color_map = mesh.vertex_colors.active
else:
    color_map = mesh.vertex_colors.new()

# apply colors
i = 0
for poly in mesh.polygons:
    for idx in poly.loop_indices: #vertices
        loop = mesh.loops[idx]
        v = vert_list[loop.vertex_index]
    
        z_coord = v.co.z

        # Paint bottom 4 vertices 0.25, top 4 vertices 0.75.
        if z_coord < 0:
            color_map.data[i].color = (0.25, 0.25, 0.25, 0)
        else:
            color_map.data[i].color = (0.75, 0.75, 0.75, 0)
        i += 1

# Give it this new material
mat = bpy.data.materials.new('vcolor_material')

# Deactivate shadows
mat.shadow_method = 'NONE'

# Apply material
mesh.materials.append(mat)

# Set Flat lighting and show Vertex Coloring
my_areas = bpy.context.workspace.screens[0].areas
my_shading = 'WIREFRAME'
for area in my_areas:
    for space in area.spaces:
        if space.type == 'VIEW_3D':
            space.shading.light = "FLAT"
            space.shading.color_type = "VERTEX"

bpy.ops.object.mode_set(mode='VERTEX_PAINT')

print("\nRan succesfully.\n")

답변

5 RichSedman Aug 25 2020 at 16:03

그래디언트는 선형이지만 예상하는 색상 공간이 아닙니다. 다음과 같이 증명됩니다.

여기서 Attribute 노드는 셰이더에서 Vertex Color (Col)를 사용할 수 있도록합니다. 이것은 별도의 RGB 구성 요소로 분할되고 생성 된 'X'좌표 (정육면체의 왼쪽에서 0.0에서 오른쪽에서 1.0까지 실행)와 비교됩니다.

그라디언트는 선형이지만 끝 점이 예상과 다릅니다 (즉, 파란색 세로 격자 선은 X = 0.5이고 그라디언트 선은 아래쪽에서 약 0.05에서 위쪽에서 약 0.525까지 이어집니다). 이것은 sRGB 색 공간 변환 때문입니다.

0.25 및 0.75의 값은 sRGB에서 '진정한'밝기로 변환 할 때 약 0.05 및 0.525의 '절대'값과 관련됩니다. sRGB 색 공간은 밝기의 0 비트 정수 표현을 최대한 활용하기위한 것입니다. 가능한 한 시각적으로 다양합니다. 따라서 범위의 시작 / 끝에있는 값과 인간의 눈에 화면에 표시 될 때 눈에 띄는 것에 맞게 압축 / 확장됩니다.

보다 https://en.wikipedia.org/wiki/SRGB 다음 그래프의 빨간색 선을 확인하십시오.

그래프의 하단과 오른쪽에있는 축 값을 사용하면 x 축의 0.75가 '강도'에서 약 0.5로 변환되는 것을 볼 수 있습니다. Python 코드는 sRGB 값 0.75를 적용하고 약 0.525의 '강도'를 생성합니다. 상한을 위해. 마찬가지로 낮은 0.25는 그래프 하단에서 훨씬 더 작은 '강도'값으로 변환됩니다. 그 '강도'는 원래 sRGB 값이 아닌 결과 정점 색상 그라디언트를 생성하기 위해 선형 보간되는 것입니다.

1 uvnoob Aug 25 2020 at 13:32

그레이 스케일 데이터 만 셰이더 노드에서 사용해야하는 경우 추악한 해결 방법이 있습니다. 대신 알파 채널을 사용하세요. 스크립트에서 알파 값을 각각 0.25와 0.75로 설정하고 greater than 0.5노드를 사용 하여 알파 채널이 보간 된 선형임을 시각적으로 확인했습니다.

UV와 같은 다른 속성도 사용할 수 있습니다.

원뿔형 설명이 저를 넘어서는 것이 두렵지 만 여기에 문제를 설명하는 스레드가 있습니다. 해결 방법은 연결된 답변을 기반으로합니다.

https://github.com/KhronosGroup/glTF-Blender-IO/issues/542#issuecomment-569361267