【求助】自定义后效实现高斯模糊效果,编辑器预览正常模糊,浏览器预览没有模糊效果

  • Creator: 3.8.5
  • 浏览器:chrome
// Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.

CCEffect %{
  techniques:
  - passes:
    - vert: vs:vert        # 指定顶点着色器为 vs 文件中的 vert 函数
      frag: fs:frag        # 指定片段着色器为 fs 文件中的 frag 函数
      pass: post-process   # 指定该 Pass 为后处理 Pass
      rasterizerState:
        cullMode: none     # 关闭背面剔除
      depthStencilState:
        depthTest: false   # 关闭深度测试
        depthWrite: false  # 关闭深度写入
      blendState:
        targets:
        - blend: true      # 启用混合
          blendSrc: one    # 设置混合源因子为 1
          blendDst: one_minus_src_alpha # 设置混合目标因子为 1 - 源 alpha
          blendSrcAlpha: one # 设置 alpha 混合源因子为 1
          blendDstAlpha: zero # 设置 alpha 混合目标因子为 0
      properties:
        textureSize: { value: [0.0, 0.0], editor: { type: 'vec2', displayName: 'Texture Size' } } # 定义纹理尺寸属性
        blurRadius: { value: 1.0, editor: { type: 'float', displayName: 'Blur Radius' } } # 模糊半径
        kernelSize: { value: 5, editor: { type: 'int', displayName: 'Kernel Size', slide: true, range: [3, 11], step: 1  } } # 卷积核大小
}%

CCProgram vs %{
  precision highp float; // 使用高精度浮点数,避免精度损失

  #include <legacy/decode-standard> // 包含标准顶点输入解码库
  #include <builtin/uniforms/cc-global> // 包含全局 uniforms
  #include <common/common-define> // 包含通用定义

  out vec2 v_uv; // 输出 UV 坐标到片段着色器

  vec4 vert () {
    StandardVertInput In; // 定义标准顶点输入结构
    CCDecode(In); // 解码顶点输入数据(如顶点位置、UV 坐标等)

    // 处理裁剪和翻转逻辑,确保顶点位置正确
    CC_HANDLE_GET_CLIP_FLIP(In.position.xy);

    v_uv = a_texCoord; // 将 UV 坐标传递给片段着色器
    return In.position; // 返回顶点位置,传递给光栅化阶段
  }
}%

CCProgram fs %{
  precision highp float; // 使用高精度浮点数
  #include <cc-global> // 包含全局 uniforms(如视图矩阵、投影矩阵等)

  in vec2 v_uv; // 从顶点着色器传入的 UV 坐标
  
  #pragma rate inputTexture pass // 指明 inputTexture 是 Pass 级别的 uniform
  uniform sampler2D inputTexture; // 输入纹理(后处理的目标纹理)
  
  // 定义材质属性(从Effect文件中传入)
  uniform Constant {
    vec2 textureSize; // 纹理尺寸(用于标准化像素偏移)
    float blurRadius; // 模糊半径(控制模糊强度)
    int kernelSize; // 卷积核大小(控制模糊采样范围)
  };

  // 高斯核函数(用于计算权重)
  float gaussian(float x, float sigma) {
    sigma = max(sigma, 0.001); // 防止 sigma 为零(避免除以零错误)
    return exp(-(x * x) / (2.0 * sigma * sigma)) / (sqrt(6.28318) * sigma);
  }

  // 高斯模糊函数
  vec4 gaussianBlur() {
    vec2 texelSize = vec2(1.0) / textureSize; // 计算纹理像素大小(每个像素在 UV 坐标系中的跨度)
    highp vec4 result = vec4(0.0); // 初始化模糊结果
    highp float weightSum = 0.0; // 初始化权重总和
    const int MAX_KERNEL_HALF = 5; // 支持最大 kernelSize=11
    int halfSize = kernelSize / 2; // 计算卷积核的一半大小

    // 遍历卷积核(以当前像素为中心,遍历周围的像素)
    for (int i = -MAX_KERNEL_HALF; i <= MAX_KERNEL_HALF; i++) {
      for (int j = -MAX_KERNEL_HALF; j <= MAX_KERNEL_HALF; j++) {
        // 跳过超出实际 kernelSize 的像素
        if (abs(float(i)) > float(halfSize) || abs(float(j)) > float(halfSize)) {
          continue;
        }
        vec2 offset = vec2(float(i), float(j)) * texelSize * blurRadius; // 计算像素偏移
        float weight = gaussian(float(i), blurRadius) * gaussian(float(j), blurRadius); // 计算权重
        result += texture(inputTexture, v_uv + offset) * weight; // 加权累加采样结果
        weightSum += weight; // 累加权重
      }
    }

    // 归一化结果(确保权重和为 1)
    return (weightSum > 0.0) ? (result / weightSum) : texture(inputTexture, v_uv);
  }

  // 主片段着色器函数
  vec4 frag () {
    return gaussianBlur(); // 执行高斯模糊
  }
}%

建好了材质挂上上面的shader文件。

在场景中建立节点 GaussianBlur,上面挂cc.PostProcess和cc.BlitScreen,并挂上建好的材质。

摄像机设置好PostProcess。

项目设置也设置好。

场景编辑器里的摄像机预览有模糊效果。

但外部浏览器里没有模糊效果。

请教各位大能应该如何修改?

有点离谱。
我是相机预览没效果。浏览器有效果。

设置了项目设置的管线后有没有重开编辑器或Ctrl+R刷新编辑器,需要这些操作编辑器的相机才能正常预览。另外你的浏览器是怎么正常的,和我的代码和设置一样吗?

哦对。没有refresh。重启之后就有引擎内效果了。
我没用你的shader,我就放了个颜色变换到fragment shader。
你试试一个最简单的shader?比如uv在[0,0.5]区间就输出白色这种简单debug一下。
或着用一个系统内置的。

我写的另外一个描边的后效就正常,设置都一模一样,就这个高斯模糊不行,非常邪门。单颜色调试也能正常,猜可能是高斯模糊算法里面哪段浏览器不支持,调试了挺久,坐等有经验的大能解答。

:joy:
实在不行可以试试数值检测。

还是做等等党,先练习其他效果,也许就悟了 :sweat_smile:

1赞

楼主怎么解决的呢