Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

3D音效演示(WebGL+AudioAPI)

  之前有介绍过关于3D音效的用法,但只是非常简单的描述,而且给出的例子也很不直观。现在我们结合WebGL来实现个真正的3D效果+3D音效。下面的例子可以使用键盘的W、S、A、D按键来控制摄像机移动,越接近立方体就可以听见越大的声音。
<base href="http://www.web-tinker.com/files/" />
<script src="SimpleWebGL.2.0.js"></script>
<script src="SimpleWebGL.Matrix.1.0.js"></script>
<canvas width="600" height="400" id="canvas"></canvas>
<script type="text/glsl" id="vs">
attribute vec3 position;
attribute vec3 normal;
uniform mat4 mMatrix;
uniform mat4 vMatrix;
uniform mat4 pMatrix;
uniform vec3 lDirection;
varying float diffuse;
void main(){
  gl_Position=pMatrix*vMatrix*mMatrix*vec4(position,1.0);
  vec3 tNormal=normalize(mMatrix*vec4(normal,0.0)).xyz;
  diffuse=max(-dot(tNormal,normalize(lDirection)),0.2);
}
</script>
<script type="text/glsl" id="fs">
varying lowp float diffuse;
void main(){
  gl_FragColor=vec4(vec3(diffuse),1);
}
</script>
<script>
//初始化AudioContext
var AudioContext=AudioContext||webkitAudioContext;
var context=new AudioContext;
//创建节点
var oscillator=context.createOscillator();
var panner=context.createPanner();
//配置节点
oscillator.frequency.value=100;
//连接节点
oscillator.connect(panner);
panner.connect(context.destination);
//3D场景
new SimpleWebGL(canvas).namespace(function(
  Program,VertexShader,FragmentShader,ArrayBuffer,Matrix
){
  //立方体参数
  var cube={
    position:new ArrayBuffer([
      -1,-1,-1, 1,-1,-1, 1,1,-1, -1,-1,-1, -1,1,-1, 1,1,-1,
      -1,-1,1,  1,-1,1,  1,1,1,  -1,-1,1,  -1,1,1,  1,1,1,
      -1,-1,-1, -1,1,-1, -1,1,1, -1,-1,-1, -1,-1,1, -1,1,1,
      1,-1,-1,  1,1,-1,  1,1,1,  1,-1,-1,  1,-1,1,  1,1,1,
      -1,-1,-1, 1,-1,-1, 1,-1,1, -1,-1,-1, -1,-1,1, 1,-1,1,
      -1,1,-1,  1,1,-1,  1,1,1,  -1,1,-1,  -1,1,1,  1,1,1,
    ]),normal:new ArrayBuffer([
      0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1, 0,0,-1,
      0,0,1,  0,0,1,  0,0,1,  0,0,1,  0,0,1,  0,0,1,
      -1,0,0, -1,0,0, -1,0,0, -1,0,0, -1,0,0, -1,0,0,
      1,0,0,  1,0,0,  1,0,0,  1,0,0,  1,0,0,  1,0,0,
      0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0, 0,-1,0,
      0,1,0,  0,1,0,  0,1,0,  0,1,0,  0,1,0,  0,1,0,
    ]),mMatrix:Matrix.model([0,0,0])
  };
  //着色器初始化
  var vMatrix=Matrix.view([0,0,12]);
  var program=new Program(
    new FragmentShader(fs),new VertexShader(vs)
  ).link().use().data({
    lDirection:[-0.5,-1,-1],
    pMatrix:Matrix.projection(40,canvas.width/canvas.height,0.1,1000),
  }).data(cube);
  //初始化声音位置
  context.listener.setPosition(vMatrix[12],vMatrix[13],vMatrix[14]);
  (function(){
    var s=new Matrix([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,-1,0]);
    s.multiply(vMatrix);
    context.listener.setOrientation(s[12],s[13],s[14],0,1,0);
  })();
  //播放帧
  this.setting("DEPTH_TEST","LESS").color(0,0,0,1).play(function(i){
    //绘制
    this.clear("COLOR");
    program.data({
      mMatrix:cube.mMatrix.yaw(0.5).pitch(0.5).roll(0.5),
      vMatrix:vMatrix
    }).draw(36);
    //响应键盘操作
    if(keys[W])vMatrix.multiply(Matrix.view([0,0,-0.3]));
    if(keys[S])vMatrix.multiply(Matrix.view([0,0,0.3]));
    if(keys[A])vMatrix.yaw(-0.5);
    if(keys[D])vMatrix.yaw(0.5);
    //响应3D音效
    if(keys[W]||keys[S])
      context.listener.setPosition(vMatrix[12],vMatrix[13],vMatrix[14]);
    if(keys[A]||keys[D]){
      var s=new Matrix([1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,-1,0]);
      s.multiply(vMatrix);
      context.listener.setOrientation(s[12],s[13],s[14],0,1,0);
    };
  });
  //键盘操作
  var keys=[],W=87,S=83,A=65,D=68;
  document.addEventListener("keydown",function(e){
    keys[e.keyCode]=true;
  });
  document.addEventListener("keyup",function(e){
    keys[e.keyCode]=false;
  });
});
//播放声音
oscillator.start(0);
</script>
网名:
54.198.108.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^