Three.js中文网 Three.js中文网
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
首页
免费视频
系统课 (opens new window)
  • Three.js基础课程
  • Vue3+Threejs 3D可视化
  • Threejs进阶课程
  • 展厅3D预览漫游
  • Threejs Shader
  • Blender建模基础
  • Three.js基础课程(旧版本) (opens new window)
  • 文章
WebGPU教程
  • WebGL教程
  • WebGL教程(旧版本) (opens new window)
3D案例
  • 本站部署(打开快) (opens new window)
  • 原英文官网文档 (opens new window)
Web3D系统课程视频
  • 1.threejs Shader基础语法

  • 2.onBeforeCompile修改材质

    • 1. threejs材质的shader代码
    • 2. onBeforeCompile修改材质shader
    • 3. 修改材质shader(彩色图变灰度图)
    • 4. 顶点位置插值(设置片元颜色)
      • 5. 顶点位置插值(设置片元颜色)2
      • 6. 模型扫光效果(顶点位置插值)
      • 7. 模型扫光效果(颜色渐变)
    • Threejs Shader教程
    • 2.onBeforeCompile修改材质
    郭隆邦
    2023-10-28
    目录

    4. 顶点位置插值(设置片元颜色)

    # 顶点位置插值(设置片元颜色)

    这节课讲解一个onBeforeCompile修改材质shader的案例,具体就是对顶点的位置坐标xyz进行插值计算,然后根据片元对应的顶点插值坐标,设置片元颜色。

    顶点插值这个知识点其实在前面1.9. 顶点位置插值(实现渐变色) (opens new window)讲解过,可以去回顾下。

    # 任务:在网格y方向增加一条光带

    # 修改顶点着色器:增加顶点位置插值计算代码

    你可以通过浏览器控制台log打印,查看顶点着色器代码。

    material.onBeforeCompile = function (shader) {
      console.log('vertexShader', shader.vertexShader);
    };
    
    // 浏览器控制台打印顶点着色器代码(提醒不同版本不一定相同)
    #include <common>
    ...
    void main(){
      ...
      #include <fog_vertex>
    } 
    

    这时候你可以思考一个问题,怎么给顶点着色器代码main函数之前插入一行插值计算的相关代码varying vec3 vPosition;

    #include <common>
    ...
    varying vec3 vPosition;//表示顶点位置插值后的坐标
    void main(){
      ...
      #include <fog_vertex>
    } 
    

    .replace()查询关键词void main() {进行如下替换。

    material.onBeforeCompile = function (shader) {
      shader.vertexShader = shader.vertexShader.replace(
        'void main() {',
        `
        varying vec3 vPosition;//顶点位置插值后的坐标
        void main(){
        `
      );
    };
    

    在main函数里面,增加顶点位置插值计算的代码。 position表示几何体的顶点位置坐标,modelMatrix表示网格模型的旋转缩放平移。

    material.onBeforeCompile = function (shader) {
      shader.vertexShader = shader.vertexShader.replace(
        'void main() {',
        `
        varying vec3 vPosition;//顶点位置插值后的坐标
        void main(){
          // 顶点位置坐标模型矩阵变换后,进行插值计算
          vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
        `
      );
    };
    

    # 片元着色器增加varying vec3 vPosition;

    查看片元着色器代码,在main函数前面增加代码varying vec3 vPosition;,与上面顶点着色器代码思路相似。

    material.onBeforeCompile = function (shader) {
      console.log('fragmentShader', shader.fragmentShader);
    };
    

    片元着色器增加varying vec3 vPosition;,获取顶点位置插值之后的坐标值vPosition。

    shader.fragmentShader = shader.fragmentShader.replace(
      'void main() {',
      `
      varying vec3 vPosition;
      void main() {
      `
    );
    

    # 根据片元对应顶点位置设置片元颜色

    回顾下前面shader知识点,大家都知道,网格模型Mesh经过图元装配和光栅化以后,会生成一个一个的片元,这些片元会构成Mesh的3D轮廓。

    同时顶点位置数据插值计算之后,会生成每个片元对应的xyz坐标。这时候我们就可以跟片元的坐标vPosition控制自身的颜色值。

    // 顶点着色器
    varying vec3 vPosition;//顶点位置插值后的坐标
    void main(){
      // 顶点位置坐标模型矩阵变换后,进行插值计算
      vPosition = vec3(modelMatrix * vec4( position, 1.0 ));
    }
    // 片元着色器
    varying vec3 vPosition;//顶点位置插值后的坐标
    void main(){
      // 根据y坐标控制片元颜色
      if(vPosition.y > 20.0 && vPosition.y < 21.0 ){
        gl_FragColor = vec4(1.0,1.0,0.0,1.0);
      }
    }
    

    # 修改片元着色器字符串

    浏览器控制打印的片元着色器代码,复制main函数里面最后一行代码(提醒:不同版本可能不同,以你自己版本为准)

    material.onBeforeCompile = function (shader) {
      console.log('fragmentShader', shader.fragmentShader);
    };
    

    网格材质shader代码中gl_FragColor已经有默认设置的颜色,我们可以在片元着色器主函数main里面最后一行增加下面代码,在网格模型上生成一条光带。

    shader.fragmentShader = shader.fragmentShader.replace(
        '#include <dithering_fragment>',
        `
        #include <dithering_fragment>
        if(vPosition.y > 20.0 && vPosition.y < 21.0 ){
            gl_FragColor = vec4(1.0,1.0,0.0,1.0);
        }
        `
      );
    

    # 多条光带

    网格模型上面等间距设置多条光带。

    shader.fragmentShader = shader.fragmentShader.replace(
      '#include <dithering_fragment>',
      `
      #include <dithering_fragment>
      float y0 = 0.0;
      for (int i = 0; i < 4; i++) {
        y0 += 20.0;
        if(vPosition.y > y0 && vPosition.y < y0+1.0 ){
          gl_FragColor = vec4(1.0,1.0,0.0,1.0);
        }
      }
      `
    );
    

    # 总结

    静态不动的模型,使用最方便

    运动的

    3. 修改材质shader(彩色图变灰度图)
    5. 顶点位置插值(设置片元颜色)2

    ← 3. 修改材质shader(彩色图变灰度图) 5. 顶点位置插值(设置片元颜色)2→

    Theme by Vdoing | Copyright © 2016-2025 豫ICP备16004767号-2
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式