求助:Shader做的激光,黑色背景怎么去掉?

  • Creator 版本:2.3.4

  • 目标平台:Google Chrome 浏览器

  • 参考: glow line1,做的激光效果

  • 问题:Shader 做的激光,怎么只保留激光的效果,黑色部分怎么去掉?

  • 效果图

  • .effect 代码

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.  

CCEffect %{

techniques:

 - passes:

     - vert: vs

       frag: fs

       blendState:

         targets:

           - blend: true

       rasterizerState:

         cullMode: none

       properties:

         texture: { value: white }

         alphaThreshold: { value: 0.5 }

}%

CCProgram vs %{

precision highp float;

#include <cc-global>

#include <cc-local>

in vec3 a_position;

in vec4 a_color;

out vec4 v_color;

#if USE_TEXTURE

 in vec2 a_uv0;

 out vec2 v_uv0;

#endif

void main() {

 vec4 pos = vec4(a_position, 1);



 #if CC_USE_MODEL

   pos = cc_matViewProj * cc_matWorld * pos;

 #else

   pos = cc_matViewProj * pos;

 #endif



 #if USE_TEXTURE

   v_uv0 = a_uv0;

 #endif



 v_color = a_color;



 gl_Position = pos;

}

}%

CCProgram fs %{

precision highp float;

#include <alpha-test>

#include <texture>

#include <cc-global>

in vec4 v_color;

#if USE_TEXTURE

 in vec2 v_uv0;

 uniform sampler2D texture;

#endif

//羽化范围(越小越窄,越大羽化越明显)                    

float featherRange = 1.0;

//泛光强度(控制外围发光的亮度)                    

float glowIntensity = 1.0;

//核心强度(控制激光核心亮度)                    

float coreIntensity = 0.05;

//扭曲强度(越大扭曲越明显)              

float twistStrength = 0.0025;

//扭曲频率(越大波纹越密)              

float twistFrequency = 8.0;

//扭曲流动速度(越大动得越快)              

float twistSpeed = 20.0;

//convert HSV to RGB                                                                                                                          

vec3 hsv2rgb(vec3 c)

{

 vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);

 vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);

 return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);

}

void main() {

 vec4 o = vec4(0.0);

 float iTime = cc_time.x;



 vec2 fragPos = v_uv0;

 fragPos.x -= 0.5;

 //基于y轴和时间的正弦扰动,模拟纵向流动扭曲

 float twistOffset = sin(fragPos.y * twistFrequency + iTime * twistSpeed) * twistStrength;        

 fragPos.x += twistOffset;    

 fragPos.y += sin(fragPos.x * twistFrequency * 0.5 + iTime * twistSpeed * 0.8) * twistStrength * 0.5;



 //蓝色色相,保留原有动态流动效果                                        

 float blueHue = 0.6 + sin(fragPos.y * 2.0 + iTime * 5.0) * 0.01;

 float saturation = 1.0;

 float value = 0.3;



 vec3 baseColor = hsv2rgb(vec3(blueHue, saturation, value));



 //计算距离(x方向的偏移,决定激光的横向范围)                      

 float dist = abs(fragPos.x);



 //羽化处理:平滑衰减,实现边缘柔和过渡                      

 // smoothstep(a, b, x):x<a返回0,x>b返回1,中间平滑插值                      

 float featherSmooth = 1.0 - smoothstep(0.0, featherRange, dist);              

 float coreStrength = coreIntensity / (dist + 0.01);

 coreStrength *= featherSmooth; // 羽化衰减



 //泛光发光层:高斯衰减模拟辉光(外围弱光)                      

 float glowStrength = glowIntensity * exp(-dist * 8.0);

 glowStrength *= featherSmooth;

                

 float totalStrength = coreStrength + glowStrength;

          

 vec3 finalColor = baseColor * totalStrength;              

 float luminance = dot(finalColor, vec3(0.299, 0.587, 0.114));

 finalColor += luminance * 0.5;



 float finalAlpha = clamp(totalStrength, 0.05, 1.0);

 o.rgb = finalColor * finalAlpha;

 o.a = finalAlpha;

              

 gl_FragColor = o;

}

}%

有没有大佬懂的,还有参考 simple laser effect for game 这个

换一下叠加模式就行

shader新手,不太懂

换叠加模式后,颜色都成白的了
image

只有在黑背景上的效果才正确

参考这个帖子 或者问AI Blend 混合

o.a = finalAlpha;

// ===================== 新增:黑色区域过滤逻辑 =====================

float rgbSum = dot(o.rgb, vec3(1.0));

o.a = o.a * step(0.7, rgbSum);

o.rgb = o.rgb * step(0.7, rgbSum);
// =================================================================

gl_FragColor = o;

在当前的激光 Shader 片元着色器末尾添加过滤逻辑,通过判断 RGB 颜色值总和是否低于指定阈值,将接近黑色的区域直接设为透明,以此消除 Shader 输出的黑色边缘,让激光效果更干净。

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.  

CCEffect %{
techniques:
  - passes:
      - vert: vs

        frag: fs

        blendState:
          targets:
            - blend: true

        rasterizerState:
          cullMode: none

        properties:
          texture: { value: white }

          alphaThreshold: { value: 0.5 }

}%

CCProgram vs %{

precision highp float;

#include <cc-global>

#include <cc-local>

in vec3 a_position;

in vec4 a_color;

out vec4 v_color;

#if USE_TEXTURE
  
  in vec2 a_uv0;
  
  out vec2 v_uv0;
  
#endif

void main() {
  
  vec4 pos = vec4(a_position, 1);
  
  #if CC_USE_MODEL
    
    pos = cc_matViewProj * cc_matWorld * pos;
    
  #else
    
    pos = cc_matViewProj * pos;
    
  #endif
  
  #if USE_TEXTURE
    
    v_uv0 = a_uv0;
    
  #endif
  
  v_color = a_color;
  
  gl_Position = pos;
  
}

}%

CCProgram fs %{

precision highp float;

#include <alpha-test>

#include <texture>

#include <cc-global>

in vec4 v_color;

#if USE_TEXTURE
  
  in vec2 v_uv0;
  
  uniform sampler2D texture;
  
#endif

//羽化范围(越小越窄,越大羽化越明显)                    

float featherRange = 1.0;

//泛光强度(控制外围发光的亮度)                    

float glowIntensity = 1.0;

//核心强度(控制激光核心亮度)                    

float coreIntensity = 0.05;

//扭曲强度(越大扭曲越明显)              

float twistStrength = 0.0025;

//扭曲频率(越大波纹越密)              

float twistFrequency = 8.0;

//扭曲流动速度(越大动得越快)              

float twistSpeed = 20.0;

//convert HSV to RGB                                                                                                                          

vec3 hsv2rgb(vec3 c)

{
  
  vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
  
  vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
  
  return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
  
}

void main() {
  
  vec4 o = vec4(0.0);
  
  float iTime = cc_time.x;
  
  vec2 fragPos = v_uv0;
  
  fragPos.x -= 0.5;
  
  //基于y轴和时间的正弦扰动,模拟纵向流动扭曲
  
  float twistOffset = sin(fragPos.y * twistFrequency + iTime * twistSpeed) * twistStrength;
  
  fragPos.x += twistOffset;
  
  fragPos.y += sin(fragPos.x * twistFrequency * 0.5 + iTime * twistSpeed * 0.8) * twistStrength * 0.5;
  
  //蓝色色相,保留原有动态流动效果                                        
  
  float blueHue = 0.6 + sin(fragPos.y * 2.0 + iTime * 5.0) * 0.01;
  
  float saturation = 1.0;
  
  float value = 0.3;
  
  vec3 baseColor = hsv2rgb(vec3(blueHue, saturation, value));
  
  //计算距离(x方向的偏移,决定激光的横向范围)                      
  
  float dist = abs(fragPos.x);
  
  //羽化处理:平滑衰减,实现边缘柔和过渡                      
  
  // smoothstep(a, b, x):x<a返回0,x>b返回1,中间平滑插值                      
  
  float featherSmooth = 1.0 - smoothstep(0.0, featherRange, dist);
  
  float coreStrength = coreIntensity / (dist + 0.01);
  
  coreStrength *= featherSmooth; // 羽化衰减
  
  //泛光发光层:高斯衰减模拟辉光(外围弱光)                      
  
  float glowStrength = glowIntensity * exp(-dist * 8.0);
  
  glowStrength *= featherSmooth;
  
  float totalStrength = coreStrength + glowStrength;
  
  vec3 finalColor = baseColor * totalStrength;
  
  float luminance = dot(finalColor, vec3(0.299, 0.587, 0.114));
  
  finalColor += luminance * 0.5;
  
  float finalAlpha = clamp(totalStrength, 0.05, 1.0);
  
  o.rgb = finalColor * finalAlpha;
  
  o.a = finalAlpha;
  
  // ===================== 新增:黑色区域过滤逻辑 =====================
  // 计算RGB通道的总和(黑色区域总和接近0)
  float rgbSum = dot(o.rgb, vec3(1.0));
  // 使用step函数过滤:rgbSum < 阈值0.7时,alpha设为0;否则保留原alpha
  // step(a, x):x < a 返回0,x >= a 返回1
  o.a = o.a * step(0.7, rgbSum);
  // 同步将RGB设为0(可选,避免透明区域残留极淡颜色)
  o.rgb = o.rgb * step(0.7, rgbSum);
  // =================================================================
  
  gl_FragColor = o;
  
}

}%