--information:段階グラデーション v1.0 by teruyoshi -- Azuriteさんのグラデーション+(https://github.com/azurite581/AviUtl2-GradientPlus)を参考に作成しました --track@str:強さ,0,100,100,0.01 --track0:中心X,-5000,5000,0,0.01 --track1:中心Y,-5000,5000,0,0.01 --track@angle_deg:角度/内径,-3600,3600,0,0.01 --track@width:幅,0,2000,300,0.01 --select@shape:形状=0,線形=0,円形=1 --track@step:段階数,0,100,5,1 --track3:🕒️グラデ曲線0→100,0,100,0,0.01 --時間制御でグラデーションの遷移を制御する --color@rgb1:開始色,0xffffff --track@a1:開始色透明度,0,100,0,0.01 --color@rgb2:終了色,0x000000 --track@a2:終了色透明度,0,100,0,0.01 --select@colorSpace:色空間=0,RGB=0,HSL短経路=1,HSL長経路=2,HSL右回り=3,HSL左回り=4 --select@blendMode:合成モード=0,通常=0,加算=1,減算=2,乗算=3,スクリーン=4,オーバーレイ=5,比較(明)=6,比較(暗)=7,輝度=8,色差=9,陰影=10,明暗=11,差分=12,アルファ加算=13,アルファ最大値=14,アルファ減算=15,アルファ加算2=16 --check@clear:元オブジェクトをクリア,0 local MaxResolution = 100 -- グラデーションカーブの解像度 -- 重い場合はMaxResolutionを下げてください(下のシェーダー側のMaxResolutionも同じ値にしてください) local BM = {"none", "add", "sub", "mul", "screen", "overlay", "light", "dark", "brightness", "chroma", "shadow", "light_dark", "diff", "alpha_add", "alpha_max", "alpha_sub", "alpha_add2"} local num = obj.setanchor("track", 0, "line") for i = 0, num - 1 do cx = obj.getvalue(0) cy = obj.getvalue(1) end --[[pixelshader@stepGradient: static const uint MaxResolution = 100; // 上のLua側のMaxresolutionと同じ値にすること float4 rgb2hsl(float4 rgba) { float r = rgba.r; float g = rgba.g; float b = rgba.b; float maxc = max(r, max(g, b)); float minc = min(r, min(g, b)); float h = 0.0; float s = 0.0; float l = (maxc + minc) / 2.0; if (maxc != minc) { float delta = maxc - minc; if (l < 0.5) s = delta / (maxc + minc); else s = delta / (2.0 - maxc - minc); if (maxc == r) h = (g - b) / delta + (g < b ? 6.0 : 0.0); else if (maxc == g) h = (b - r) / delta + 2.0; else h = (r - g) / delta + 4.0; h /= 6.0; } return float4(h, s, l, rgba.w); } float4 hue2rgb(float hue){ float r = abs(hue * 6.0 - 3.0) - 1.0; float g = 2.0 - abs(hue * 6.0 - 2.0); float b = 2.0 - abs(hue * 6.0 - 4.0); return float4(r, g, b, 1.0); } float4 hsl2rgb(float4 hsla) { float r = abs(hsla.x * 6.0 - 3.0) -1.0; float g = 2.0 - abs(hsla.x * 6.0 - 2.0); float b = 2.0 - abs(hsla.x * 6.0 - 4.0); float C = (1.0 - abs(2.0 * hsla.z - 1.0)) * hsla.y; return float4((float3(r,g,b) - 0.5) * C + hsla.z, hsla.w); } float4 lerpRGB(float4 c1, float4 c2, float t, float step) { float stepT; if (step == 0) stepT = t; else stepT = floor(t * step) / (step + 1); if (stepT <= 1.0) return lerp(c1, c2, stepT); return lerp(c1, c2, stepT); } float4 lerpHSL_short(float4 c1, float4 c2, float t, float step) { float4 hsla1 = rgb2hsl(c1); float4 hsla2 = rgb2hsl(c2); float stepT; if (step == 0) stepT = t; else stepT = floor(t * step) / (step + 1); // 短経路補正 if (abs(hsla2.x - hsla1.x) > 0.5) { if (hsla1.x > hsla2.x) hsla2.x += 1.0; else hsla1.x += 1.0; } float4 hsla = lerp(hsla1, hsla2, stepT); if (hsla.x > 1.0) hsla.x -= 1.0; if (hsla.x < 0.0) hsla.x += 1.0; return hsl2rgb(hsla); } float4 lerpHSL_long(float4 c1, float4 c2, float t, float step) { float4 hsla1 = rgb2hsl(c1); float4 hsla2 = rgb2hsl(c2); float stepT; if (step == 0) stepT = t; else stepT = floor(t * step) / (step + 1); // 短経路補正 if (abs(hsla2.x - hsla1.x) < 0.5) { if (hsla1.x > hsla2.x) hsla2.x += 1.0; else hsla1.x += 1.0; } float4 hsla = lerp(hsla1, hsla2, stepT); if (hsla.x > 1.0) hsla.x -= 1.0; if (hsla.x < 0.0) hsla.x += 1.0; return hsl2rgb(hsla); } float4 lerpHSL_r(float4 c1, float4 c2, float t, float step) { float4 hsla1 = rgb2hsl(c1); float4 hsla2 = rgb2hsl(c2); float stepT; if (step == 0) stepT = t; else stepT = floor(t * step) / (step + 1); if (hsla2.x < hsla1.x) hsla2.x += 1.0; float4 hsla = lerp(hsla1, hsla2, stepT); if (hsla.x > 1.0) hsla.x -= 1.0; if (hsla.x < 0.0) hsla.x += 1.0; return hsl2rgb(hsla); } float4 lerpHSL_l(float4 c1, float4 c2, float t, float step) { float4 hsla1 = rgb2hsl(c1); float4 hsla2 = rgb2hsl(c2); float stepT; if (step == 0) stepT = t; else stepT = floor(t * step) / (step); if (hsla1.x > hsla2.x) hsla1.x -= 1.0; float4 hsla = lerp(hsla2, hsla1, stepT); if (hsla.x > 1.0) hsla.x -= 1.0; if (hsla.x < 0.0) hsla.x += 1.0; return hsl2rgb(hsla); } Texture2D tex : register(t0); cbuffer constant0 : register(b0) { float str; float2 center; float angle; float width; float3 rgb1; float a1; float3 rgb2; float a2; float colorSpace; float shape; float step; float gCurve[MaxResolution]; }; SamplerState samLinear : register(s0); struct PS_INPUT { float4 pos : SV_Position; float2 uv : TEXCOORD0; }; float4 stepGradient(PS_INPUT input) : SV_Target { float original_a = tex.Sample(samLinear, input.uv).a; // 元オブジェクトの透明度 float4 rgba1 = float4(rgb1 * original_a*a1, a1 * original_a); float4 rgba2 = float4(rgb2 * original_a*a2, a2 * original_a); float d; if (shape == 0) { // 線形 d = dot(input.pos.xy - center, float2(cos(angle), sin(angle))) + width/2.0 + width/step/2; } else { // 円形 d = (length(input.pos.xy - center) - angle)*2; // angleは円形の場合内径として流用 } if (step == 1) { // 段階数が1の場合は単純な2色塗り分け if (d < width ) return rgba1; else return rgba2; } if (d < 0 ) return rgba1; if (d > width ) return rgba2; float mapped_d = gCurve[floor((d)/width * MaxResolution)]; switch (colorSpace) { case 0: // RGB補間 return lerpRGB(rgba1, rgba2, mapped_d, step); case 1 : // HSL短経路補間 return lerpHSL_short(rgba1, rgba2, mapped_d, step); case 2 : // HSL長経路補間 return lerpHSL_long(rgba1, rgba2, mapped_d, step); case 3 : // HSL右回り補間 return lerpHSL_r(rgba1, rgba2, mapped_d, step); case 4 : // HSL左回り補間 return lerpHSL_l(rgba2, rgba1, mapped_d, step); default: return lerpRGB(rgba1, rgba2, mapped_d, step); } } ]] --グラデ曲線からグラデーションカーブの配列を作成 local gCurves = {} if obj.getoption("track_mode", "3") == 0 then -- 時間制御が設定されていない場合は直線移動とみなす for i = 0, MaxResolution*4 do gCurves[i] = i/(MaxResolution*4) end else for i = 0, MaxResolution*4 do gCurves[i] = obj.getvalue(3,(obj.totaltime-1/obj.framerate)*i/(MaxResolution*4))/100 end end obj.setoption("drawtarget", "tempbuffer", obj.w, obj.h) if clear == 0 then obj.draw() end local angle = math.rad(angle_deg) + math.pi/2 if shape == 0 then -- 線形グラデーション else -- 円形グラデーション angle = angle_deg/2 -- 円形の場合は角度を内径として流用 end -- 中心座標を補正 cx = cx + obj.w / 2 cy = cy + obj.h / 2 -- 色をrgbに分解 local r1 , g1, b1 = RGB(rgb1) local r2 , g2, b2 = RGB(rgb2) obj.pixelshader("stepGradient", "object", "object", { str/100.0, cx, cy, angle, width, r1/255.0, g1/255.0, b1/255.0, 1-a1/100.0, r2/255.0, g2/255.0, b2/255.0, 1-a2/100.0, colorSpace, shape, step, unpack(gCurves) }, "copy" ) obj.setoption("blend", BM[blendMode+1]) obj.draw(0,0,0,1.0,str/100.0) obj.setoption("blend", "none") obj.copybuffer("obj","tmp")