Godot图片投影shader

前言:

原理是获取图像的A通道进行膨胀+高斯模糊+uv移动旋转

这个例子没写很好随便写的,将就着用

代码:

shader_type canvas_item;

uniform vec2 offset;
uniform float rotation;

uniform int blursize;
uniform float shadow_size;

float normpdf(in float x, in float sigma){
    return 0.39894*exp(-.5*x*x/(sigma*sigma))/sigma;
}

vec4 gaussian_blur(sampler2D src, vec2 size, vec2 uv, int m_size){
    vec4 cc = texture(src, uv);
    vec3 c = cc.rgb;
    int k_size = (m_size-1)/2;
    float sigma = 7.;
    vec3 final_color = vec3(0.);
    float z = 0.;
    for(int i=-k_size;i<=k_size;i++){
        float n = normpdf(float(i), sigma);
        z+=n;
        for(int j=-k_size;j<=k_size;j++){
            final_color+=n*n*texture(src,uv+size*vec2(float(i),float(j))).rgb;
        }
    }
    return vec4(final_color/z/z,1.);
}

void fragment() {
    // 获取当前像素的坐标
    vec2 uv = UV;

    // 获取原始图像的Alpha通道值
    vec4 originalTex = textureLod(TEXTURE, uv, 0.0);
    float alpha = originalTex.a;

    // 计算投影坐标
    vec2 projectedUV = vec2(uv.x + offset.x, uv.y + offset.y);
    projectedUV = vec2(
        cos(rotation) * (projectedUV.x - uv.x) - sin(rotation) * (projectedUV.y - uv.y) + uv.x,
        sin(rotation) * (projectedUV.x - uv.x) + cos(rotation) * (projectedUV.y - uv.y) + uv.y
    );

    // 获取投影位置的纹理采样值
    //vec4 projectedTex = textureLod(TEXTURE, projectedUV, 0.0);
	vec4 projectedTex = gaussian_blur(TEXTURE ,TEXTURE_PIXEL_SIZE ,projectedUV , blursize);

    // 使用原始图像的Alpha通道值创建投影形状
    vec4 projection = vec4(0.0, 0.0, 0.0, projectedTex.r * shadow_size);

    // 将当前像素的颜色设置为原始图像和投影形状的混合
	//COLOR = max(projection, originalTex);
	
	COLOR = originalTex;
	if (COLOR.a <= 0.5){
		COLOR.a = COLOR.a + projection.a;
		COLOR.rgb = projection.rgb
	}
		
	//COLOR = projection;
}

 左图是原图,右图是shader的效果

其实有点像PS的混合选项,网上也有大佬写过原理的文章。

因为shader无法栅格化,所以有需求的话可以加入opencv对图像进行处理。

参考资料:

【PS算法理论探讨二】 Photoshop中图层样式之 投影样式 算法原理初探讨。 - Imageshop - 博客园 (cnblogs.com)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值