当前位置: 首页 > news >正文

现代郑州网站建设自贡建设能源开发有限公司网站

现代郑州网站建设,自贡建设能源开发有限公司网站,一个企业网站如何能放到互联网上 vps,wordpress所有缩略图模型材质属性丢失 上一篇博客我们学习了用着色器给模型添加光带扫描效果,今天来学习给导入的模型添加光带扫描效果,目标是给如下图的立筒仓加光带扫描。 首先我们试试原来的方法还是否有效。 import * as THREE from three;// 引入gltf模型加载库GLTFL…

模型材质属性丢失

上一篇博客我们学习了用着色器给模型添加光带扫描效果,今天来学习给导入的模型添加光带扫描效果,目标是给如下图的立筒仓加光带扫描。

首先我们试试原来的方法还是否有效。

import * as THREE from 'three';// 引入gltf模型加载库GLTFLoader.js
import {GLTFLoader
} from 'three/addons/loaders/GLTFLoader.js';export const model = new THREE.Group();
const loader = new GLTFLoader();const vertexShader = `
varying vec2 vPosition;
void main() {vPosition = position; // 将UV坐标传递给片元着色器gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;const fragmentShader = `
varying vec2 vPosition;void main() {if(vPosition.y > 10 && vPosition.y < 11){gl_FragColor = vec4(0.0,1.0,1.0,1.0);}}
`;// 以下代码是使用着色器材料进行颜色设置
export const material = new THREE.ShaderMaterial({//顶点着色器对象vertexShadervertexShader: vertexShader,// 片元着色器对象fragmentShaderfragmentShader: fragmentShader,
});loader.load('models/粮仓.glb', function (gltf) {let parentObj = gltf.scene.getObjectByName("立筒仓");parentObj.traverse(function (obj) {if (obj.isMesh) {console.log(obj.material);obj.material = material;}});model.add(gltf.scene);
});

运行结果,模型没法显示了。

因为模型贴图了,得用uv而不是position了,uv只包含xy两个数据项,范围是0~1.

const vertexShader = `
varying vec2 vUv;
void main() {vUv = uv; // 将UV坐标传递给片元着色器gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;const fragmentShader = `
varying vec2 vUv;void main() {if(vUv.y > 0.5 && vUv.y < 0.6){gl_FragColor = vec4(1.0,1.0,0.0,1.0);}}
`;

运行后可以看到模型和光带了,但模型变成了白色,这是因为我们直接把模型本身的材质硬生生换成了ShaderMaterial,原本材质的属性就都丢失了。

 onBeforeCompile的用法

是时候让onBeforeCompile出马了,这个方法在保留模型本身材质的前提下,对材质进行修改。

ShaderLib下,打开一个mesh材质的js文件看看顶点着色器和片元着色器的代码,它们都有void main()方法,我们主要是要修改这里。

修改顶点着色器

在片元着色器里,要在main的前面加varying vec2 vUv; 

在main的里面加

vUv = uv; // 将UV坐标传递给片元着色器

gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

使用replace方法对顶点着色器字符串进行修改,需要注意replace第二个参数里的main方法,不需要加},因为我们只是在main方法里插入

vUv = uv; // 将UV坐标传递给片元着色器

gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);

这些代码,main方法里面还有很多内置代码,main方法并没有在这里结束。

顶点着色器比较容易修改,内容不多。

shader.vertexShader = shader.vertexShader.replace(`void main() {`,`varying vec2 vUv;void main() {vUv = uv; // 将UV坐标传递给片元着色器gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);`);

修改片元着色器

片元着色器的修改相对来说要复杂一点,片元着色器里的varying vec2 vUv;跟刚才一样,加在main方法的前面即可。

shader.fragmentShader = shader.fragmentShader.replace(`void main() {`,`varying vec2 vUv;void main() {`);

后面的条件判断等代码,必须要加到片元着色器main方法最后一行代码的后面,比如这里最后一行代码是#include <dithering_fragment>,不同版本的threejs,不同材质,main方法最后一行代码不同,一定打印出来看看。console.log(shader.fragmentShader);

现在我们确定了main方法最后一行是#include <dithering_fragment>,还是使用replace往它后面插入if判断这些代码。片元着色器用了两次replace。

shader.fragmentShader = shader.fragmentShader.replace(`#include <dithering_fragment>`,`#include <dithering_fragment>if(vUv.y > 0.5 && vUv.y < 0.6){gl_FragColor = vec4(1.0,1.0,0.0,1.0);}`);

如果片元着色器第二次replace的内容太多,可以放在一个js文件里,引入。

fragment_shader.js

需要特别注意,fragment_shader.js文件开头必须跟刚才main方法最后一行相同,也就是还得带着#include <dithering_fragment>这句话,不然就相当于这句话被去掉了,代码就不完整了。

export default /* glsl */
`
#include <dithering_fragment>
// 整体设置渐变半透明色
gl_FragColor = vec4(mix(vec3(1.0, 1.0, 1.0),vec3(1.0, 0.0, 1.0),vPosition.z/20.0),0.5);// gl_FragColor = vec4(1.0,0.0,0.0,0.5);// 符合vPosition.y > y0 && vPosition.y < y0+1.0条件的设置其他颜色,形成光带
float y0 = 0.0;
for(int i=0;i<4;i++){y0 +=4.0;if(vPosition.z > y0 && vPosition.z < y0+1.0){gl_FragColor = vec4(1.0,1.0,0.0, 1.0);}
}`;
import fragment_shader from './fragment_shader.js'
shader.fragmentShader = shader.fragmentShader.replace('#include <dithering_fragment>', fragment_shader);

认识uv坐标

运行之后,光带有了,但是方向跟我们预期的不同,我们预期水平光带,结果变成了垂直的。

在blender里选中模型,打开uv编辑,可以下载该模型使用的贴图。

把贴图放到uv坐标里,是这样了。u就相当于x轴,v就相当于y轴,对照下图来看,光带应该从左到右移动,需要处理的是y轴数值,而不是x轴。

shader.fragmentShader = shader.fragmentShader.replace(`#include <dithering_fragment>`,`#include <dithering_fragment>if(vUv.x > 0.5 && vUv.x < 0.55){gl_FragColor = vec4(1.0,1.0,0.0,1.0);}`);

 现在光带方向正常了,要让它动起来,上一篇博客已经写过了,要使用uniforms传值,onBeforeCompile方法里的shader是内部对象,另外定义一个外部变量将它传出去,然后在渲染函数中改变它,但是,马上就报错了,说找不到uniforms属性,这里又是一个注意点,onBeforeCompile内部的shader在第一次render执行的时候,还没有值,所以取不到uniforms,render运行多次后,shader才有值。为了确保取到值,要加非空判断。

export let materialShader = null;
shader.uniforms.x = {value:0.0};
materialShader = shader; //将内部的shader传递到外部
function render() {renderer.render(scene, camera);// materialShader刚开始没有值,随着render的运行几次后才有,所以要加if判断,否则会报错if(materialShader){materialShader.uniforms.x.value += 0.01;if(materialShader.uniforms.x.value > 1.0){materialShader.uniforms.x.value = 0.0;}}requestAnimationFrame(render);
}

光带到顶部,会改变方向,这个问题我们上一篇博客也遇到过类似情况,将扫描范围缩小一点就可以了,比如materialShader.uniforms.x.value > 1.0的时候,重置到0。

图片尺寸是512*512,光带扫到了顶部,其实对应图片右边的两个白色圆片,假如只需要扫描左边的部分,用截图工具测量一下长度是372,372/512约等于0.72,修改materialShader.uniforms.x.value > 0.7,重置到0,光带就不会扫到顶部了。把光带变成多表彩色的,上一篇博客里讲过了方法。

完整代码:

import * as THREE from 'three';// 引入gltf模型加载库GLTFLoader.js
import {GLTFLoader
} from 'three/addons/loaders/GLTFLoader.js';export const model = new THREE.Group();
const loader = new GLTFLoader();
export let materialShader = null;
loader.load('models/粮仓.glb', function (gltf) {let parentObj = gltf.scene.getObjectByName("立筒仓");parentObj.traverse(function (obj) {if (obj.isMesh) {    obj.material.onBeforeCompile = function (shader) {console.log(shader.fragmentShader);shader.vertexShader = shader.vertexShader.replace(`void main() {`,`varying vec2 vUv;void main() {vUv = uv; // 将UV坐标传递给片元着色器gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);`);shader.fragmentShader = shader.fragmentShader.replace(`void main() {`,`varying vec2 vUv;uniform float x;void main() {`);shader.fragmentShader = shader.fragmentShader.replace(`#include <dithering_fragment>`,`#include <dithering_fragment>if(vUv.x > x && vUv.x < x+0.02){gl_FragColor = vec4(1.0,1.0,0.0,1.0);}`);shader.uniforms.x = {value:0.0};materialShader = shader; //将内部的shader传递到外部}}});model.add(gltf.scene);
});

// 渲染循环
function render() {renderer.render(scene, camera);// materialShader刚开始没有值,随着render的运行几次后才有,所以要加if判断,否则会报错if(materialShader){materialShader.uniforms.x.value += 0.01;if(materialShader.uniforms.x.value > 1.0){materialShader.uniforms.x.value = 0.0;}}requestAnimationFrame(render);
}

http://www.dtcms.com/a/552585.html

相关文章:

  • 海南景区网站建设方案wordpress 文章连续
  • 网站建设怎么添加背景音乐有空间域名服务器怎么做网站
  • 广东模板网站建设报价企业网站的建设怎么收费
  • 站长工具域名电商网站成品案例
  • 冬创网站建设培训中心批量 发布 wordpress
  • 网站制作应用网站制作系统哪个好
  • 有关网站建设的外文文献沈阳单页网站制作
  • 网页设计与制作题库及答案360搜索引擎优化
  • 咖啡厅网站开发目标手机版wordpress怎么用
  • 桂阳网站设计盖县网站开发
  • 做网站负责人风险广州seo优化推广
  • 施坦威网站关于我们太阳能灯网站建设
  • 网站建设时间安排表网站备案后有什么好处
  • 微信做引流网站南宁网站建设蓝云
  • 网站基本模块软件开发培训机构怎么鉴定好坏
  • 常州网站排名优化桐城市美丽乡村建设专题网站
  • 如何用魔方网表做门户网站国家企业信用公示官方
  • 深圳罗湖做网站公司哪家好局域网网页制作
  • 免费的黄金网站有哪些如何做网站需求表格清单
  • 哪些网站上可以做租车免费营销型wordpress模板
  • 网站建设平台设备溧阳市建设网站
  • 使用flask做前后端分离的网站欧美网站建设风格特点
  • 茶叶 企业 网站建设眉山 网站开发
  • 档案网站建设外包公司做网页引用别的网站的视频
  • 石家庄网站建设seo公司医院网站建设与维护题库
  • 深圳服装外贸网站建设丘里奇网站排名
  • 华邦网站惠州网站建设价格
  • 网站可以增加关键词吗电子商务网站运营流程
  • 微信链接的微网站怎么做dw怎么建设网站
  • 电销如何介绍网站建设东西湖区城乡建设局网站