xr-frame 通过shader去除视频背景色,加载透明视频

目录

前言

实现思路

[获取 XR 框架系统:](#获取 XR 框架系统:)

注册自定义效果

创建效果对象

渲染通道配置

着色器代码

顶点着色器

片元着色器(颜色分量g达到条件的片元将被透透明)

[effect-removeBlack 完整代码](#effect-removeBlack 完整代码)

wxml中使用


前言

实现了一个用于注册自定义效果(Effect)的 代码,用于 xr-frame框架中。这个效果的核心功能是去除场景中的黑色部分,或者说是对视频纹理进行处理

实现思路

获取 XR 框架系统

javascript 复制代码
const xrFrameSystem = wx.getXrFrameSystem();

这里通过 wx.getXrFrameSystem() 获取了 XR 框架系统对象 xrFrameSystem,它提供了对 XR 场景的管理和操作接口。

注册自定义效果

javascript 复制代码
xrFrameSystem.registerEffect('removeBlack', scene => {
  // 自定义效果的实现
});

使用 xrFrameSystem.registerEffect 方法注册了一个名为 'removeBlack' 的自定义效果。这个效果会在指定的场景中生效。

创建效果对象

javascript 复制代码
scene.createEffect({
  name: "removeBlack",
  images: [{
    key: 'u_videoMap',
    default: 'white',
    macro: 'WX_USE_VIDEOMAP'
  }],
  defaultRenderQueue: 2000,
  passes: [{}],
  shaders: [/* GLSL 代码 */]
});
  • name: "removeBlack":效果的名称,标识这个效果。
  • images:定义了效果中使用的纹理图像。
    • key: 'u_videoMap':纹理的键名,用于在 GLSL 代码中引用。
    • default: 'white':默认的纹理颜色为白色。
    • macro: 'WX_USE_VIDEOMAP':定义了一个宏,用于在 GLSL 代码中条件编译。
  • defaultRenderQueue: 2000:设置渲染队列的优先级,值越大越靠后渲染。
  • passes:定义渲染效果的各个渲染通道。
  • shaders:包含顶点和片段着色器的 GLSL 代码。

渲染通道配置

javascript 复制代码
passes: [{
  "renderStates": {
    cullOn: false,
    blendOn: true,
    blendSrc: xrFrameSystem.EBlendFactor.SRC_ALPHA,
    blendDst: xrFrameSystem.EBlendFactor.ONE_MINUS_SRC_ALPHA,
    cullFace: xrFrameSystem.ECullMode.BACK,
  },
  lightMode: "ForwardBase",
  useMaterialRenderStates: true,
  shaders: [0, 1]
}]
  • renderStates:定义了渲染状态。
    • cullOn: false:关闭剔除。
    • blendOn: true:启用混合。
    • blendSrc: xrFrameSystem.EBlendFactor.SRC_ALPHA:设置混合源因子为源 alpha。
    • blendDst: xrFrameSystem.EBlendFactor.ONE_MINUS_SRC_ALPHA:设置混合目标因子为 1 减去源 alpha。
    • cullFace: xrFrameSystem.ECullMode.BACK:剔除背面。
  • lightMode: "ForwardBase":设置光照模式为前向基础光照。
  • useMaterialRenderStates: true:使用材质的渲染状态。
  • shaders: [0, 1]:指定使用的着色器,分别是顶点着色器和片段着色器。

着色器代码

顶点着色器

javascript 复制代码
#version 100

uniform highp mat4 u_view;
uniform highp mat4 u_viewInverse;
uniform highp mat4 u_vp;
uniform highp mat4 u_projection;
uniform highp mat4 u_world;

attribute vec3 a_position;
attribute highp vec2 a_texCoord;

varying highp vec2 v_UV;

void main()
{
  v_UV = a_texCoord;
  vec4 worldPosition = u_world * vec4(a_position, 1.0);
  gl_Position = u_projection * u_view * worldPosition;
}
  • u_view, u_viewInverse, u_vp, u_projection, u_world:这些是 MVP(模型-视图-投影)矩阵,负责将顶点从局部坐标转换到屏幕坐标。
  • a_position:顶点位置。
  • a_texCoord:纹理坐标。
  • v_UV:将纹理坐标传递给片段着色器。
  • worldPosition:将顶点转换到世界坐标系。
  • gl_Position:最终的裁剪空间坐标。

片元着色器(颜色分量g达到条件的片元将被透透明)

javascript 复制代码
#version 100

precision mediump float;
precision highp int;
varying highp vec2 v_UV;

#ifdef WX_USE_VIDEOMAP
  uniform sampler2D u_videoMap;
#endif

void main()
{
#ifdef WX_USE_VIDEOMAP
  vec4 baseColor = texture2D(u_videoMap, v_UV);
#else
  vec4 baseColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif
  float rgbSum = baseColor.r + baseColor.g + baseColor.b;
  // 设定阈值避免异常情况
  if (baseColor.g < 1.1) {
    gl_FragData[0] = vec4(1.0, 1.0, 1.0, 0.0);
  } else {
    gl_FragData[0] = vec4(baseColor.rgb, 1.0);
  }
}
  • v_UV:从顶点着色器传递过来的纹理坐标。
  • u_videoMap:视频纹理。
  • baseColor:从视频纹理中采样的颜色。
  • rgbSum:计算颜色的 RGB 分量之和。
  • if (baseColor.g < 1.1):通过阈值判断是否为黑色,如果绿色分量小于 1.1(接近黑色),则输出 (1.0, 1.0, 1.0, 0.0),即白色且透明;否则输出原始颜色。

effect-removeBlack 完整代码

javascript 复制代码
const xrFrameSystem = wx.getXrFrameSystem();

xrFrameSystem.registerEffect('removeBlack', scene => scene.createEffect({
  name: "removeBlack",
  images: [{
    key: 'u_videoMap',
    default: 'white',
    macro: 'WX_USE_VIDEOMAP'
  }],
  defaultRenderQueue: 2000,
  passes: [{
    "renderStates": {
      cullOn: false,
      blendOn: true,
      blendSrc: xrFrameSystem.EBlendFactor.SRC_ALPHA,
      blendDst: xrFrameSystem.EBlendFactor.ONE_MINUS_SRC_ALPHA,
      cullFace: xrFrameSystem.ECullMode.BACK,
    },
    lightMode: "ForwardBase",
    useMaterialRenderStates: true,
    shaders: [0, 1]
  }],
  shaders: [
    `#version 100

uniform highp mat4 u_view;
uniform highp mat4 u_viewInverse;
uniform highp mat4 u_vp;
uniform highp mat4 u_projection;
uniform highp mat4 u_world;

attribute vec3 a_position;
attribute highp vec2 a_texCoord;

varying highp vec2 v_UV;

void main()
{
  v_UV = a_texCoord;
  vec4 worldPosition = u_world * vec4(a_position, 1.0);
  gl_Position = u_projection * u_view * worldPosition;
  }`,
    `#version 100

precision mediump float;
precision highp int;
varying highp vec2 v_UV;

#ifdef WX_USE_VIDEOMAP
  uniform sampler2D u_videoMap;
#endif

void main()
{
#ifdef WX_USE_VIDEOMAP
  vec4 baseColor = texture2D(u_videoMap, v_UV);
#else
  vec4 baseColor = vec4(1.0, 1.0, 1.0, 1.0);
#endif
  float rgbSum = baseColor.r + baseColor.g + baseColor.b;
  // 设定阈值避免异常情况
  if (baseColor.g < 1.1) {
    gl_FragData[0] = vec4(1.0, 1.0, 1.0, 0.0);
  } else {
    gl_FragData[0] = vec4(baseColor.rgb, 1.0);
  }
}
`],
}));

wxml中使用

在js中引用 import '../../utils/effect-removeBlack.js';,并如下使用

html 复制代码
    <xr-asset-load type="video-texture" asset-id="xianhe" src="http://njyjxr.oss-cn-shanghai.aliyuncs.com/zhanghai/Chizhou/feiheback.mp4" options="autoPlay:true,loop:true" />
    <xr-asset-material asset-id="xianhe-mat" effect="removeBlack" />



    <xr-mesh id="xianhe" position="-8 12 2.1" rotation="90 100 0" scale="30 1 21.2" material="xianhe-mat" geometry="plane" uniforms="u_videoMap: video-xianhe" states="renderQueue:2500"></xr-mesh>
相关推荐
酒尘&6 小时前
JS数组不止Array!索引集合类全面解析
开发语言·前端·javascript·学习·js
BoBoZz197 小时前
ParametricObjectsDemo多种参数曲面展示及面上部分点法线展示
python·vtk·图形渲染·图形处理
深海潜水员8 小时前
OpenGL 学习笔记 第一章:绘制一个窗口
c++·笔记·学习·图形渲染·opengl
用户47949283569158 小时前
"讲讲原型链" —— 面试官最爱问的 JavaScript 基础
前端·javascript·面试
用户47949283569158 小时前
2025 年 TC39 都在忙什么?Import Bytes、Iterator Chunking 来了
前端·javascript·面试
大怪v9 小时前
【Virtual World 04】我们的目标,无限宇宙!!
前端·javascript·代码规范
蓝瑟12 小时前
告别重复造轮子!业务组件多场景复用实战指南
前端·javascript·设计模式
渴望成为python大神的前端小菜鸟13 小时前
浏览器及其他 面试题
前端·javascript·ajax·面试题·浏览器
1024肥宅13 小时前
手写 new 操作符和 instanceof:深入理解 JavaScript 对象创建与原型链检测
前端·javascript·ecmascript 6
soda_yo13 小时前
浅拷贝与深拷贝: 克隆一只哈基米
前端·javascript·面试