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>
相关推荐
呆呆的小草33 分钟前
Cesium距离测量、角度测量、面积测量
开发语言·前端·javascript
WHOAMI_老猫37 分钟前
xss注入遇到转义,html编码绕过了解一哈
javascript·web安全·渗透测试·xss·漏洞原理
小前端大牛马2 小时前
react中hook和高阶组件的选型
前端·javascript·vue.js
刺客-Andy2 小时前
React第六十二节 Router中 createStaticRouter 的使用详解
前端·javascript·react.js
秋田君3 小时前
深入理解JavaScript设计模式之策略模式
javascript·设计模式·策略模式
平行云4 小时前
LarkXR 赋能AI x XR数字供应链:引领智能设计、数字孪生与零售新未来
人工智能·webrtc·xr·云渲染·虚幻引擎·云展厅
菜鸡爱上编程5 小时前
React16,17,18,19更新对比
前端·javascript·reactjs·react
我命由我123455 小时前
VSCode - VSCode 转换英文字母的大小写
开发语言·javascript·ide·vscode·编辑器·html·软件工具
陈龙龙的陈龙龙5 小时前
uniapp 金额处理组件
前端·javascript·uni-app
我命由我123455 小时前
VSCode - VSCode 让未被编辑的标签页不被自动关闭
前端·javascript·ide·vscode·编辑器·html·js