FuRegisterClass("GPUSampleFuse", CT_SourceTool, { REGS_Category = "Fuses\\Examples", REGS_OpIconString = "GFu", REGS_OpDescription = "GPU Sample Fuse", REG_NoObjMatCtrls = true, REG_NoMotionBlurCtrls = true, REG_Source_GlobalCtrls = true, REG_Source_SizeCtrls = true, REG_Source_AspectCtrls = true, REG_Source_DepthCtrls = true, }) -- Description of kernel parameters GradientParams = [[ float col[4]; int dstsize[2]; ]] CircleParams = [[ float amp; float damp; float freq; float phase; float center[2]; int srcsize[2]; int compOrder; ]] -- Source of kernel GradientSource = [[ __KERNEL__ void GradientKernel(__CONSTANTREF__ GradientParams *params, __TEXTURE2D_WRITE__ dst) { DEFINE_KERNEL_ITERATORS_XY(x, y) if (x < params->dstsize[0] && y < params->dstsize[1]) { float2 pos = to_float2(x, y) / to_float2(params->dstsize[0] - 1, params->dstsize[1] - 1); float4 col = to_float4_v(params->col); col *= to_float4(pos.x, pos.y, 0.0f, 1.0f); _tex2DVec4Write(dst, x, y, col); } } ]] CircleSource = [[ #define _length(a,b) _sqrtf(((a).x-(b).x)*((a).x-(b).x) + ((a).y-(b).y)*((a).y-(b).y)) __KERNEL__ void CircleKernel(__CONSTANTREF__ CircleParams *params, __TEXTURE2D__ src, __TEXTURE2D_WRITE__ dst) { DEFINE_KERNEL_ITERATORS_XY(x, y) if (x < params->srcsize[0] && y < params->srcsize[1]) { float2 pos = to_float2(x, y) / to_float2(params->srcsize[0] - 1, params->srcsize[1] - 1); float2 center = to_float2_v(params->center); float d = _length(pos, center); float vl = fmax(params->amp - params->damp * d, 0.0f); vl = 1.0f + sin(d * params->freq + params->phase) * vl; float2 frompos = vl * (pos - center) + center; float4 col = _tex2DVecN(src, frompos.x, frompos.y, params->compOrder); _tex2DVec4Write(dst, x, y, col); } } ]] function Create() InCenter = self:AddInput("Center", "Center", { LINKID_DataType = "Point", INPID_InputControl = "OffsetControl", INPID_PreviewControl = "CrosshairControl", }) InAmplitude = self:AddInput("Amplitude", "Amplitude", { LINKID_DataType = "Number", INPID_InputControl = "SliderControl", INP_Default = 0.5, }) InDamping = self:AddInput("Damping", "Damping", { LINKID_DataType = "Number", INPID_InputControl = "SliderControl", INP_Default = 0.0, }) InFrequency = self:AddInput("Frequency", "Frequency", { LINKID_DataType = "Number", INPID_InputControl = "SliderControl", INP_Default = 0.0, INP_MaxScale = 100.0 }) InPhase = self:AddInput("Phase", "Phase", { LINKID_DataType = "Number", INPID_InputControl = "ScrewControl", INP_Default = 0.0, INP_MaxScale = 10.0, }) end function Process(req) local center = InCenter:GetValue(req) local amp = InAmplitude:GetValue(req).Value local damp = InDamping:GetValue(req).Value local freq = InFrequency:GetValue(req).Value local phase = InPhase:GetValue(req).Value local realwidth = Width local realheight = Height -- We'll handle proxy ourselves Width = Width / Scale Height = Height / Scale Scale = 1 local imgattrs = { IMG_Document = self.Comp, IMG_Width = Width, IMG_Height = Height, IMG_XScale = XAspect, IMG_YScale = YAspect, IMAT_OriginalWidth = realwidth, IMAT_OriginalHeight = realheight, IMG_Quality = not req:IsQuick(), IMG_MotionBlurQuality = not req:IsNoMotionBlur(), } if not req:IsStampOnly() then imgattrs.IMG_ProxyScale = 1 end if SourceDepth == 0 then imgattrs.IMG_Depth = SourceDepth end local img = Image(imgattrs) local out local success = false if img then local node = DVIPComputeNode(req, "GradientKernel", GradientSource, "GradientParams", GradientParams) if node then -- create image local params = node:GetParamBlock(GradientParams) params.col[0] = 1.0 params.col[1] = 1.0 params.col[2] = 1.0 params.col[3] = 1.0 params.dstsize[0] = img.DataWindow:Width() params.dstsize[1] = img.DataWindow:Height() node:SetParamBlock(params) node:AddOutput("dst", img) success = node:RunSession(req) end if success then out = Image({IMG_Like = img}) local node = DVIPComputeNode(req, "CircleKernel", CircleSource, "CircleParams", CircleParams) if node then local params = node:GetParamBlock(CircleParams) params.amp = amp params.damp = damp params.freq = freq params.phase = phase params.center[0] = center.X params.center[1] = center.Y params.compOrder = 15 params.srcsize[0] = out.DataWindow:Width() params.srcsize[1] = out.DataWindow:Height() node:SetParamBlock(params) node:AddSampler("RowSampler", TEX_FILTER_MODE_LINEAR, TEX_ADDRESS_MODE_CLAMP, TEX_NORMALIZED_COORDS_TRUE) node:AddInput("src", img) node:AddOutput("dst", out) success = node:RunSession(req) else out = nil end end end OutImage:Set(req, out) end