Vue2+ThreeJS工程无痛搭建指南

工程初始化流程

全局安装vue-cli
npm install -g vue-cli
进入目录-初始化项目
vue init webpack my-project
进入项目
cd my-project
安装工程核心包(Three JS)
npm install three

核心功能实现与避坑

fbx载入功能代码实现
     //模型初始化
        initModelFbx() {
            console.log('模型加载');

            let loader = new FBXLoader();

            loader.load(modelPath, function (object) {
     
                var mat = modelMat;
                console.log(object);
                showModel = object;
                showModel.position.set(0, -30, 0);
                // geometry.center(); //居中显示
                showModel.children[1].material =  mat;
                //获取原生shader代码
                let fragStr=THREE.ShaderLib["basic"].fragmentShader;
                let VertStr=THREE.ShaderLib["basic"].vertexShader;
                console.log(fragStr);
                console.log(VertStr);
                // showModel.children[1].material=mat;
                
                //添加骨骼辅助
                // let meshHelper = new THREE.SkeletonHelper(showModel);
                // scene.add(meshHelper);
                scene.add(showModel);
                console.log(showModel);
                console.log(showModel.children[1]);
            });

        },
fbx载入可能出现THREE.FBXLoader: Cannot find the version number for the file given错误,解决办法为,移动文件到static目录下,具体操作见文章(【Vue2+ThreeJS踩坑记录(一)】
本地文件载入功能
//本地文件读取
        load(name) {
            let xhr = new XMLHttpRequest(),
                okStatus = document.location.protocol === "file:" ? 0 : 200;
            xhr.open('GET', name, false);
            xhr.overrideMimeType("text/html;charset=utf-8");//默认为utf-8
            xhr.send(null);
            return xhr.status === okStatus ? xhr.responseText : null;
        },
shader代码
顶点着色器代码
#include <common>
#include <skinning_pars_vertex>
varying vec3 vNormal;
varying vec2 vUv;
varying vec3 objectPos;
void main() {
	#include <morphcolor_vertex>
	#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )
		#include <beginnormal_vertex>
		#include <morphnormal_vertex>
		#include <skinbase_vertex>
		#include <skinnormal_vertex>
		#include <defaultnormal_vertex>
	#endif
	#include <begin_vertex>
	#include <skinning_vertex>
	#include <project_vertex>
	#include <worldpos_vertex>
    vNormal=normal;
    vUv = uv;
    objectPos= position;
}
片段着色器代码

#include <common>

uniform vec3 diffuse;
uniform float opacity;
uniform mat4 modelMatrix;
uniform vec3 color;
uniform vec3 lightPosition;
uniform vec3 _mainColor;
uniform sampler2D _mainTex;
uniform sampler2D _normalTex;
uniform vec2 tilling;
uniform  float _roughness;
uniform  float _roughnessContrast;
uniform  float _roughnessInit;
uniform  float _roughnessMin;
uniform  float _roughnessMax;
varying vec3 objectPos;
varying vec3 vNormal;
varying vec2 vUv;

vec3 ACETompping(vec3 x)
{
    float a=2.51;
    float b=.03;
    float c=2.43;
    float d=.59;
    float e=.14;
    return saturate((x*(a*x+b))/(x*(c*x+d)+e));
}
vec4 lerp(vec4 a,vec4 b,vec4 w)
{
    return a+w*(b-a);
    
}
float lerpFloat(float a,float b,float w)
{
    return a+w*(b-a);
    
}
mat3 cotangent_frame(vec3 N,vec3 p,vec2 uv)
{
   
    vec3 dp1=dFdx(p);
    vec3 dp2=dFdy(p);
    vec2 duv1=dFdx(uv);
    vec2 duv2=dFdy(uv);
    
    
    vec3 dp2perp=cross(dp2,N);
    vec3 dp1perp=cross(N,dp1);
    vec3 T=dp2perp*duv1.x+dp1perp*duv2.x;
    vec3 B=dp2perp*duv1.y+dp1perp*duv2.y;
    
   
    float invmax=inversesqrt(max(dot(T,T),dot(B,B)));
    return mat3(T*invmax,B*invmax,N);
}
vec3 ComputeNormal(vec3 nornal,vec3 viewDir,vec2 uv,sampler2D normalMap)
{
 
    vec3 map=texture2D(normalMap,uv).xyz;
    
    map=map*255./127.-128./127.;
    
    mat3 TBN=cotangent_frame(nornal,-viewDir,uv);
    return normalize(TBN*map);
    return(texture2D(normalMap,vUv).rgb-.5)*2.;
}
void main() {
	
    vec3 worldNormal = normalize( vec3( modelMatrix * vec4( vNormal, 0.0 ) ) );
     vec3 worldPosition=(modelMatrix*vec4(objectPos,1.0)).xyz;//获取世界坐标
	
     vec3 vDir=normalize(cameraPosition-worldPosition);
    vec3 nDir=ComputeNormal(worldNormal,vDir,vUv*tilling,_normalTex);
    vec3 lDir = normalize( lightPosition - worldPosition );
    //向量操作
    
    vec3 rvDir=reflect(-vDir,nDir);
    float NdotV=dot(nDir,vDir);
    float NdotL=dot(nDir,lDir);
    //贴图操作
 
    
    vec3 mainTex=texture2D(_mainTex,vUv).xyz;
    vec3 roughnessTex=vec3(1.0,1.0,1.0);
    vec3 _roughnessContrasts=vec3(_roughnessContrast,_roughnessContrast,_roughnessContrast);
    
    //粗糙度
    float finalRoughness=saturate(pow(roughnessTex,_roughnessContrasts)*_roughnessInit).x;
    finalRoughness=lerpFloat(_roughnessMin,_roughnessMax,finalRoughness);
    finalRoughness=finalRoughness*(1.7-.7*finalRoughness);
    finalRoughness=finalRoughness*6.;
    
    //漫反射模型(兰伯特)
    vec3 lambert=vec3(max(0.0,NdotL),max(0.0,NdotL),max(0.0,NdotL));

    
    //最终颜色
    vec3 finalColor=(lambert.xyz*_mainColor);
    vec3 finalColor_liner=pow(finalColor,vec3(2.2,2.2,2.2));
    finalColor=ACETompping(finalColor_liner);
    vec3 finalColor_gamma=pow(finalColor,vec3(1./2.2,1./2.2,1./2.2));
    
    gl_FragColor=vec4(finalColor_gamma,1);
	
}
这里注意一下,如果不使用#inlcude引用库,可能会导致fbx模型动画无效。具体情况见此文章链接(【Vue2+ThreeJS踩坑记录(二)】fbx蒙皮网格模型挂载ShaderMaterial材质之后,挂载动画无效的解决办法】
材质初始化
 initMat() {
            fragShaderStr = this.load(shaderPath + `.frag`);
            vertexShaderStr = this.load(shaderPath + `.vert`);

            modelMat = new THREE.ShaderMaterial({
                uniforms: {
                    _mainColor: { value: new THREE.Vector3(1.0, 1.0, 1.0) },
                    lightPosition: { value: new THREE.Vector3(0, -10, 0) },
                    tilling: { value: new THREE.Vector2(1, 1) },
                    _normalTex: { value: new THREE.TextureLoader().load("static/texture/Naria/Naria_N.tga") },
                    _roughness: { value: 1.0 },
                    _roughnessContrast: { value: 1.06 },
                    _roughnessInit: { value: 1.92 },
                    _roughnessMin: { value: 0.0 },
                    _roughnessMax: { value: 0.7 }
                },
                //236,65,65
                vertexShader: vertexShaderStr,
                fragmentShader: fragShaderStr,


            });
        },
载入并播放fbx动画
    //载入模型动画
        initModelAnim() {
            console.log('动画加载');

            let loader = new FBXLoader();

            loader.load(animationPath, function (object) {

                //创建动画混合器,并指定模型,混合器会自动根据指定模型寻找骨骼,并绑定
                let mixer = new THREE.AnimationMixer(showModel);
                //添加至动画混合器数组
                animationMixers.push(mixer);
                //挂载动画
                showModel.animations.push(object.animations[0]);
                //获取动画片
                let action = mixer.clipAction(showModel.animations[0]);
                //播放动画片
                action.play();
            });
        },

更新动画混合器
 if (animationMixers.length > 0) {
     //遍历并更新所有动画混合器
     animationMixers[0].update(clock.getDelta());
}
工程打包
工程打包之前建议按这篇文章配置(【Vue2+ThreeJS踩坑记录(三)】Vue2打包项目之后,运行本地项目为空白页解决办法

配置完之后使用如下命名打包

npm run build
案例代码链接
工程链接
DEMO链接(大小为8mb,用的是GitHubPage,可能加载要几分钟)
最终效果图

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue2.0是一种用于构建用户界面的前端框架,而Three.js是一个用于创建3D图形的JavaScript库。两者可以很好地结合在一起,以实现更丰富和交互性更高的用户界面。 在使用Vue2.0和Three.js时,我们可以通过指令绑定和组件化的方式实现与Three.js的集成。比如,我们可以创建一个Vue组件,在该组件中引入Three.js的库文件,并通过Vue的生命周期钩子,在组件的mounted函数中初始化Three.js场景、相机、渲染器等。 在Vue中,我们可以通过数据绑定和计算属性的方式来修改和控制Three.js中的对象属性和动画。例如,可以通过绑定Vue的数据属性来控制Three.js中的物体位置、大小、颜色等属性。同时,Vue的计算属性可以用于实时计算和更新物体的属性,比如根据用户的输入来调整物体的大小或者旋转的角度。 另外,Vue的事件系统也能与Three.js结合使用,通过监听Vue的事件,我们可以在特定的Vue方法中触发Three.js中的动作和逻辑。比如,在用户点击某个按钮时,可以在Vue方法中调用Three.js的方法来执行3D场景中的动画效果或其他操作。 总之,Vue2.0和Three.js的结合可以让我们更方便地创建复杂的3D交互界面。通过Vue的数据绑定、计算属性、事件系统等特性,我们能够更灵活地控制和操作Three.js中的对象和动画,从而实现更丰富和交互性更高的用户界面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值