From d8a9ea4996cf091611d00daa8852e09ae60152c5 Mon Sep 17 00:00:00 2001 From: micheus Date: Thu, 13 Nov 2025 17:11:24 -0300 Subject: [PATCH 1/2] Added an option to apply ambient occlusion (AO) blending with vertex colors To enable a different action via the application menu, the CTRL modifier key was used to trigger a secondary option for the AO command. This is a useful feature for those who paint vertex objects for use in games. NOTE: Added an option to apply AO blending with vertex colors. Thanks to boggers and DevEarley for the suggestion --- plugins_src/commands/wpc_ambocc.erl | 25 ++++++++++++++-------- src/wings_color.erl | 32 ++++++++++++++++++++++++++++- src/wings_va.erl | 16 ++++++++++++++- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/plugins_src/commands/wpc_ambocc.erl b/plugins_src/commands/wpc_ambocc.erl index a0fe2e9e7..59eeb880f 100644 --- a/plugins_src/commands/wpc_ambocc.erl +++ b/plugins_src/commands/wpc_ambocc.erl @@ -19,6 +19,7 @@ -export([init/0,menu/2,command/2]). -define(NEED_OPENGL, 1). +-define(NEED_ESDL, 1). -include_lib("wings/src/wings.hrl"). -include_lib("wings/e3d/e3d_image.hrl"). @@ -27,11 +28,14 @@ init() -> menu({tools}, Menu) -> Menu ++ [separator,{?__(1,"Ambient Occlusion"),ambient_occlusion, - ?__(2,"Add Ambient-Occlusion vertex colors via OpenGL")}]; + ?__(2,"Add Ambient-Occlusion vertex colors via OpenGL") ++ + " " ++ wings_s:key(ctrl) ++ " " ++ + ?__(3,"Blend to current vertex colors")}]; menu(_, Menu) -> Menu. command({tools,ambient_occlusion}, St0) -> - St = ambient_occlusion(St0), + Mix = wings_io:is_modkey_pressed(?CTRL_BITS), + St = ambient_occlusion(St0, Mix), create_ambient_light(St); command(_Cmd, _) -> next. @@ -40,7 +44,7 @@ command(_Cmd, _) -> next. -define(SAMPLE_SZ, 64). -define(NUM_SAMPLES, (?TEX_SZ div ?SAMPLE_SZ)). -ambient_occlusion(St) -> +ambient_occlusion(St, Mix) -> StartTime = os:timestamp(), gl:pushAttrib(?GL_ALL_ATTRIB_BITS), setup_gl(), @@ -48,7 +52,7 @@ ambient_occlusion(St) -> DrawFun = make_disp_list(St), AO = AO_0#ao{df=DrawFun}, #st{shapes=Shapes} = St, - ProcessObject = fun(_,We) -> process_obj(We, AO) end, + ProcessObject = fun(_,We) -> process_obj(We, AO, Mix) end, Shapes2 = ?SLOW(gb_trees:map(ProcessObject, Shapes)), St2 = St#st{shapes=Shapes2}, cleanup(AO), @@ -81,16 +85,16 @@ setup_shaders() -> cleanup(#ao{cleanup_fbo=Fbo}) -> wings_gl:delete_fbo(Fbo). -process_obj(We, _) when ?IS_NOT_VISIBLE(We#we.perm) -> +process_obj(We, _, _) when ?IS_NOT_VISIBLE(We#we.perm) -> We; -process_obj(We, _) when ?IS_NOT_SELECTABLE(We#we.perm) -> +process_obj(We, _, _) when ?IS_NOT_SELECTABLE(We#we.perm) -> We; -process_obj(We, _) when ?IS_ANY_LIGHT(We) -> +process_obj(We, _, _) when ?IS_ANY_LIGHT(We) -> case We#we.name =/= ambient() of true -> We#we{perm=?PERM_HIDDEN_BIT}; false -> We end; -process_obj(We0, AO) -> +process_obj(We0, AO, Mix) -> #we{es=Etab,vp=Vtab,name=Name} = We0, io:fwrite(?__(1,"Processing: ~s\n"), [Name]), gl:clear(?GL_COLOR_BUFFER_BIT bor ?GL_DEPTH_BUFFER_BIT), @@ -98,7 +102,10 @@ process_obj(We0, AO) -> SetColor = fun(Edge, #edge{vs=Va,ve=Vb}, W) -> Color1 = array:get(Va, VertexColors), Color2 = array:get(Vb, VertexColors), - wings_va:set_edge_color(Edge, Color1, Color2, W) + case Mix of + false -> wings_va:set_edge_color(Edge, Color1, Color2, W); + true -> wings_va:blend_edge_color(Edge, Color1, Color2, W) + end end, array:sparse_foldl(SetColor, We0, Etab). diff --git a/src/wings_color.erl b/src/wings_color.erl index 19ce3c353..cad5f9a0e 100644 --- a/src/wings_color.erl +++ b/src/wings_color.erl @@ -18,7 +18,7 @@ rgba_to_rgb/1, rgb3bv/1, rgb4bv/1, rgb3fv/1, rgb4fv/1, srgb_to_linear/1, hsb_to_rgb/3, lab_to_rgb/3, cmyk_to_rgb/4, - def_palette/0 + def_palette/0, blend/2 ]). -include("wings.hrl"). @@ -487,3 +487,33 @@ get_palette(_, _) -> []. %% Sto = gb_trees:update(val, V, Sto6), %% {store,Sto}; %% eyepicker_update(_, _) -> void. + +blend({R0,G0,B0}, ColorToBlend) -> + {R,G,B,_} = blend_0({R0,G0,B0,1}, tuple_to_list(ColorToBlend)), + {R,G,B}; +blend(Color, ColorToBlend) -> + blend_0(Color, tuple_to_list(ColorToBlend)). + +blend_0({R,G,B,A}, [Gr0,Gr0,Gr0|_]) when is_integer(R) -> + {Gr,_,_} = rgb3bv({Gr0,Gr0,Gr0}), + Factor = Gr / 255, + {round(R * Factor), + round(G * Factor), + round(B * Factor), + A}; +blend_0({R,G,B,A}, [Rb0,Gb0,Bb0|_]) when is_integer(R) -> + {Rb,Gb,Bb} = rgb3bv({Rb0,Gb0,Bb0}), + {(R + Rb) div 2, + (G + Gb) div 2, + (B + Bb) div 2, + A}; +blend_0({R,G,B,A}, [Gr,Gr,Gr|_]) -> + {R * Gr, + G * Gr, + B * Gr, + A}; +blend_0({R,G,B,A}, [Rb,Gb,Bb|_]) -> + {(R + Rb) / 2, + (G + Gb) / 2, + (B + Bb) / 2, + A}. diff --git a/src/wings_va.erl b/src/wings_va.erl index 1790fa691..423538463 100644 --- a/src/wings_va.erl +++ b/src/wings_va.erl @@ -17,7 +17,7 @@ face_mixed_attrs/2, all/2,edge_attrs/3,edge_attrs/4,set_edge_attrs/4,set_both_edge_attrs/4, set_edge_attrs/2,set_edge_uvs/2,set_edge_colors/2,del_edge_attrs/2, - set_edge_color/4, + set_edge_color/4,blend_edge_color/4, vtx_attrs/2,vtx_attrs/3,attr/2,new_attr/2,average_attrs/1,average_attrs/2, set_vtx_face_uvs/4, remove/2,remove/3,renumber/2,merge/2,gc/1,any_update/2]). @@ -305,6 +305,13 @@ set_edge_color(Edge, LeftCol, RightCol, #we{lv=Lva0,rv=Rva0}=We) -> Rva = set_color(Edge, RightCol, Rva0), We#we{lv=Lva,rv=Rva}. +%% mix_edge_color(Edge, LeftColor, RightColor, We0) -> We +%% Blend the current vertex colors and the new color to the edge. +blend_edge_color(Edge, LeftCol, RightCol, #we{lv=Lva0,rv=Rva0}=We) -> + Lva = blend_color(Edge, LeftCol, Lva0), + Rva = blend_color(Edge, RightCol, Rva0), + We#we{lv=Lva,rv=Rva}. + %% del_edge_attrs(Edge, We0) -> We. %% Delete all vertex attributes for the given edge. %% Should only be use when an edge has been removed. @@ -803,6 +810,13 @@ set_uv(Edge, UV, Tab) -> end, aset(Edge, Attr, Tab). +blend_color(Edge, Color, Tab) -> + case aget(Edge, Tab) of + none -> aset(Edge, [Color|none], Tab); + [Color|_] -> Tab; + [OldColor|UV] -> aset(Edge, [wings_color:blend(OldColor,Color)|UV], Tab) + end. + mix(_, none, _) -> none; mix(_, [_|_], none) -> none; mix(W, [Col1|UV1], [Col2|UV2]) -> From 837a4768d8d28c417914c19c8f2c917059d65c4d Mon Sep 17 00:00:00 2001 From: micheus Date: Tue, 16 Dec 2025 19:47:15 -0300 Subject: [PATCH 2/2] - Worked on Copilot suggestions --- src/wings_va.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wings_va.erl b/src/wings_va.erl index 423538463..fb897aa85 100644 --- a/src/wings_va.erl +++ b/src/wings_va.erl @@ -305,7 +305,7 @@ set_edge_color(Edge, LeftCol, RightCol, #we{lv=Lva0,rv=Rva0}=We) -> Rva = set_color(Edge, RightCol, Rva0), We#we{lv=Lva,rv=Rva}. -%% mix_edge_color(Edge, LeftColor, RightColor, We0) -> We +%% blend_edge_color(Edge, LeftColor, RightColor, We0) -> We %% Blend the current vertex colors and the new color to the edge. blend_edge_color(Edge, LeftCol, RightCol, #we{lv=Lva0,rv=Rva0}=We) -> Lva = blend_color(Edge, LeftCol, Lva0),