実験: ワイヤーフレームの色を変更してみる
はじめに
今回は、Blenderのワイヤーフレームの色をHackして変更してみます。 GLSL(OpenGL Shading Language)の知識が役に立ちました。
使用したコード
master (2.93.0)を使用しました。 https://developer.blender.org/rBd447bd3e4a9a793364b5f4951ad280fe0293d79e
ワイヤーフレームが描画される仕組み
頂点シェーダとフラグメントシェーダでモデルのワイヤーフレームが描画されます。
頂点シェーダで定義されているfinalColor
にワイヤーフレームの色がセットされて、フラグメントシェーダでfinalColor
を参照して最終的な色(fragColor
)にセットされます。
source/blender/draw/engines/overlay/shaders/wireframe_vert.glsl
out vec4 finalColor; [...] void main() { [...] vec3 rim_col, wire_col; if (isObjectColor || isRandomColor) { wire_object_color_get(rim_col, wire_col); } else { wire_color_get(rim_col, wire_col); } facing = clamp(abs(facing), 0.0, 1.0); /* Do interpolation in a non-linear space to have a better visual result. */ rim_col = pow(rim_col, vec3(1.0 / 2.2)); wire_col = pow(wire_col, vec3(1.0 / 2.2)); vec3 final_front_col = mix(rim_col, wire_col, 0.35); finalColor.rgb = mix(rim_col, final_front_col, facing); finalColor.rgb = pow(finalColor.rgb, vec3(2.2)); finalColor.a = wireOpacity; finalColor.rgb *= wireOpacity; }
source/blender/draw/engines/overlay/shaders/wireframe_frag.glsl
in vec4 finalColor;
[...]
void main()
{
[...]
fragColor = finalColor;
ちなみに、wireframe_vert.glsl
やwireframe_frag.glsl
はビルド時に、const char[]
型のdatatoc_wireframe_vert_glsl
とdatatoc_wireframe_frag_glsl
にそれぞれ変換されるようです。
そして、OVERLAY_shader_wireframe()
でシェーダープログラムとしてロードされます。
source/blender/draw/engines/overlay/overlay_shader.c
GPUShader *OVERLAY_shader_wireframe(bool custom_bias) { const DRWContextState *draw_ctx = DRW_context_state_get(); const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg]; OVERLAY_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg]; if (!sh_data->wireframe[custom_bias]) { sh_data->wireframe[custom_bias] = GPU_shader_create_from_arrays({ .vert = (const char *[]){sh_cfg->lib, datatoc_common_view_lib_glsl, datatoc_common_globals_lib_glsl, datatoc_gpu_shader_common_obinfos_lib_glsl, datatoc_wireframe_vert_glsl, NULL}, .frag = (const char *[]){datatoc_common_view_lib_glsl, datatoc_common_globals_lib_glsl, datatoc_wireframe_frag_glsl, NULL}, .defs = (const char *[]){sh_cfg->def, custom_bias ? "#define CUSTOM_DEPTH_BIAS\n" : NULL, NULL}, }); } return sh_data->wireframe[custom_bias]; }
ワイヤーフレームの色をセットしている場所の特定
wire_color_get()
を見ると、colorWire
という変数が見つかりました。この変数にワイヤーフレームの色がセットされていそうです。
void wire_color_get(out vec3 rim_col, out vec3 wire_col) { [...] else if (is_selected && useColoring) { if (isTransform) { rim_col = colorTransform.rgb; } else if (is_active) { rim_col = colorActive.rgb; } else { rim_col = colorSelect.rgb; } wire_col = colorWire.rgb; } else { rim_col = colorWire.rgb; wire_col = colorBackground.rgb; } }
colorWire
をgrepしてみると、以下のuniform変数として定義されていることが分かりました。
source/blender/draw/intern/shaders/common_globals_lib.glsl
/* keep in sync with GlobalsUboStorage */
layout(std140) uniform globalsBlock
{
vec4 colorWire;
vec4 colorWireEdit;
vec4 colorActive;
vec4 colorSelect;
[...]
もう少し探索を進めると、uniform変数にセットしていそうなコードが見つかりました。
UI_GetThemeColor4fv(TH_WIRE, gb->colorWire);
にbreak pointをセットしてみます。
デバッガで確認すると、初回実行時には、ゼロ初期化されていて、DRW_globals_update(void)
の呼び出し後は、
gb->colorWire
に(0, 0, 0, 1)がセットされました。
source/blender/draw/intern/draw_common.c
void DRW_globals_update(void) { GlobalsUboStorage *gb = &G_draw.block; UI_GetThemeColor4fv(TH_WIRE, gb->colorWire); UI_GetThemeColor4fv(TH_WIRE_EDIT, gb->colorWireEdit); UI_GetThemeColor4fv(TH_ACTIVE, gb->colorActive); UI_GetThemeColor4fv(TH_SELECT, gb->colorSelect); [...]
コードの修正
colorWire
は、float[4]
でそれぞれの要素はRGBAに対応しているようです。
そこで、rgba = (1, 0, 0, 1)
、つまり赤をセットしてみます。
diff --git a/source/blender/draw/intern/draw_common.c b/source/blender/draw/intern/draw_common.c index 132b5274517..db7501e6a94 100644 --- a/source/blender/draw/intern/draw_common.c +++ b/source/blender/draw/intern/draw_common.c @@ -53,7 +53,12 @@ void DRW_globals_update(void) { GlobalsUboStorage *gb = &G_draw.block; - UI_GetThemeColor4fv(TH_WIRE, gb->colorWire); + gb->colorWire[0] = 1.0; + gb->colorWire[1] = 0.0; + gb->colorWire[2] = 0.0; + gb->colorWire[3] = 1.0; + + //UI_GetThemeColor4fv(TH_WIRE, gb->colorWire); UI_GetThemeColor4fv(TH_WIRE_EDIT, gb->colorWireEdit); UI_GetThemeColor4fv(TH_ACTIVE, gb->colorActive); UI_GetThemeColor4fv(TH_SELECT, gb->colorSelect);
ビルドと実行結果
ビルドして実行し、ワイヤーフレームで表示すると無事ワイヤーフレームの色が赤くなりました。
関連情報
ワイヤーフレームの不透明度をUIから変更できるようにする修正