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>
相关推荐
天宇&嘘月2 小时前
web第三次作业
前端·javascript·css
小王不会写code2 小时前
axios
前端·javascript·axios
luckyext3 小时前
HBuilderX中,VUE生成随机数字,vue调用随机数函数
前端·javascript·vue.js·微信小程序·小程序
小小码农(找工作版)3 小时前
JavaScript 前端面试 4(作用域链、this)
前端·javascript·面试
鱼樱前端5 小时前
深入JavaScript引擎与模块加载机制:从V8原理到模块化实战
前端·javascript
yangjiajia1234565 小时前
vue3 ref和reactive的区别
前端·javascript·vue.js
sda423423424236 小时前
8.【线性代数】——求解Ax=b
线性代数·ax=b
诚信爱国敬业友善6 小时前
Vue 基础二(进阶使用)
前端·javascript·vue.js
なし.6 小时前
【Web前端开发精品课 HTML CSS JavaScript基础教程】第二十四章课后题答案
前端·javascript·css·html