webGL: 曲師師AR項目總結

介紹

項目連接(須要網易新聞客戶端最新版)html

AR錄屏

前幾周作了一個AR小項目,主要功能就是展現模型動畫,想作一個分享,可是AR是基於APP的,不太好分享~。。腦袋疼~。。好在AR其實本質就是3d,就想着用webGL講講裏面的一些東西。c++

項目邏輯主要是 搜索平面-> 建立模型-> 模型操做(矩陣變換以及動畫播放)web

其中,建立模型和模型的縮放、位移、移動以及播放相應模型動畫這些不作解釋,徹底能夠用threejs、babylonjs去找對應API,這篇文章主要是講搜索平面所用到的材質是怎麼作的。typescript

平面提示材質

這裏的邏輯是捕捉到一個有效平面後出現一個具備延申效果的平面提示材質。windows

  • 平面捕捉使用的是AR SDK提供的api。

平面捕捉

材質製做思路:api

  • 建立地面Mesh -> 材質添加遮罩層處理 -> 材質添加白點素材,並作repeat處理 -> 傳入mesh座標用做白點素材的偏移量

  1. 建立地面mesh
//babylon.js
    this.tracking = BABYLON.Mesh.CreateGround('Ground', 1, 1, 1, this.scene);
複製代碼
  1. 自定義材質動畫

    因爲開發文檔沒有須要的材質因此我選擇自定義材質。ui

//shaderCode
    BABYLON.Effect.ShadersStore["trackingVertexShader"] = require('./tracking.vert');
    BABYLON.Effect.ShadersStore["trackingFragmentShader"] = require('./tracking.frag');
    this.tracking.material = new BABYLON.ShaderMaterial("trackingShader", this.scene, {
        vertex: "tracking",
        fragment: "tracking",
    },
    { 
        attributes: ["position", "normal", "uv"],
        uniforms: ["world", "worldView", "worldViewProjection", "view", "projection","uPosition","uTexture","uTime"]
        //uniform 我只用到了 uPosition,uTexture,uTime 分別是mesh的位置,白點素材和時間
    });
複製代碼
//頂點着色器
    precision highp float;
    attribute vec3 position;
    attribute vec2 uv;
    uniform mat4 worldViewProjection;
    varying vec2 vUv;
    void main(void) {
        vec3 _position = position*vec3(1.0,0.0,1.0);
        gl_Position = worldViewProjection * vec4(_position, 1.0);
        vUv = uv;
    }
複製代碼

其中頂點着色器沒啥說的,傳入的uniform都是傳給片元着色器的。this

//片元着色器
    precision highp float;
    varying vec2 vUv;
    uniform sampler2D uTexture; //白點素材
    uniform vec3 uPosition;     //當前mesh的位置
    uniform float uTime;        //時間
    void main(void) {
        float _distance = distance(vec2(0.5),vUv);
        //mask 第一步:半徑超過0.5的顏色丟棄;
        if(_distance<.5){
                //白點:基於mesh位置作偏移,能夠實現移動mesh時 白點相對於世界的位置不變。
                vec2 uv = vUv*5.+uPosition.xz*5.0/5.0;
                //白點:作repeat處理
                vec2 uv = mod(abs(uv),1.0);
                //這一段判斷不用在乎 我這個圖片不知道爲啥邊緣會有一條線。。
                if(uv.x>0.05&&uv.x<0.95&&uv.y>0.05&&uv.y<0.95){
                    vec4 color = texture2D(uTexture,uv);
                    //mask 第二步:作透明度漸變mesh;
                    gl_FragColor = color*vec4(vec3(1),1.0-pow(_distance*2.,2.));
                    if(gl_FragColor.a==0.0) discard;
                }else{
                    discard;
                }
        }else{
            discard;
        }
    }
複製代碼

剩下的就是傳入uniform數據就能夠了。spa

//uTexture
    const texture = new BABYLON.Texture(require('../assets/Artboard.png'), this.scene);
    texture.wrapU = BABYLON.Texture.MIRROR_ADDRESSMODE;
    texture.wrapV = BABYLON.Texture.MIRROR_ADDRESSMODE;
    (<BABYLON.ShaderMaterial>this.tracking.material).setTexture("uTexture", texture);
    //uPosition 
    //this.tracking.position -> BABYLON.Vector3
    (<BABYLON.ShaderMaterial>this.tracking.material).setVector3('uPosition',this.tracking.position);
複製代碼

效果以下(白點有延申效果且每一個白點相對於世界靜止的):

附加項

感受放在webGL不是很好看,哈哈哈,隨便改了改片元着色器,根據時間作了一個漣漪的效果。

//片元着色器
    precision highp float;
    varying vec2 vUv;
    uniform sampler2D uTexture;
    uniform vec3 uPosition;
    uniform float uTime;
    void main(void) {
        float _distance = distance(vec2(0.5),vUv);
        if(_distance<.5){
                //漣漪start
                vec2 offset = vec2(0);
                float ripple = mod(uTime/1000.,1.5)-_distance;
                if(abs(ripple)<.1){
                    offset=normalize(vUv-vec2(0.5))*-1.*(cos(ripple*31.42)+1.)/8.;
                }
                vec2 uv = mod(abs(vUv*5.+offset+uPosition.xz*5.0/5.0),1.0);
                //漣漪end
                if(uv.x>0.05&&uv.x<0.95&&uv.y>0.05&&uv.y<0.95){
                    vec4 color = texture2D(uTexture,uv);
                    gl_FragColor = color*vec4(vec3(1),1.0-pow(_distance*2.,2.));
                    if(gl_FragColor.a==0.0) discard;
                }else{
                    discard;
                }
        }else{
            discard;
        }
    }
複製代碼

漣漪效果以下:

demo link

ps:場景是本身實現的,以爲windows 10 3d查看器的場景挺好看的就仿照作了一個。哈哈。

相關文章
相關標籤/搜索