利用shader绘制一个带经纬度的球体

引子: 这是曾经的一道webgl面试题。

出处

利用shader绘制一个带经纬度的球体

最终效果:
在这里插入图片描述

代码

1、创建几何球体

这部分很基础,很快带过然后进入shader
App.js

class App {
  ...
  addObj() {
    // 几何球体
    const geometry = new THREE.SphereBufferGeometry(30, 64, 64);

    // 材质
    var material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });

    // 网格
    var mesh = new THREE.Mesh(geometry, material);
    mesh.name = "spare"
    this.scene.add(mesh);
  }
}

创建一个球体:
在这里插入图片描述

2、使用着色器材质

这个也是基础工作。
App.js

import { fragmentShader } from './glsl.fragmentShader.js'
import { vertexShader } from './glsl.vertexShader.js'
class App {
  addObj() {
    ...
    // 材质
    var material = new THREE.ShaderMaterial({
      uniforms: this.uniforms,
      vertexShader: vertexShader,
      fragmentShader: fragmentShader
    });
    ...
  }
}

glsl.vertexShader.js

export let vertexShader = `
// 这里使用 uv,将传给片元着色器使用。
varying vec2 vUv;
void main() {
  vUv = uv;
  gl_Position = projectionMatrix * modelViewMatrix * vec(position, 1.0);
}
`

glsl.fragmentShader.js, 这里先设置为白色。

export let fragmentShader = `
varying vec2 vUv;
void main() {
  gl_FragColor = vec4(1.);
}
`

在这里插入图片描述

3、绘制网格

重点终于来了!

1)感受一下uv
export let fragmentShader = `
varying vec2 vUv;
void main() {
  gl_FragColor = vec4(vec3(vUv.x), 1.0);
}
`

uv.x 范围是从0~1,那么体现在球体的x方向,颜色就是从黑色到白色。uv.y同理。
在这里插入图片描述

2)绘制一条线

根据uv坐标的特性,对uv坐标进行不同处理,那么就可以绘制线了。

export let fragmentShader = `
varying vec2 vUv;
void main() {
  float lineWidth = 0.01;
  if(vUv.x<lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

在这里插入图片描述

3) 绘制多条线

uv坐标有超出重复的特性,比如说:

默认uv的坐标范围是0~1,如果超出1,就会重复贴图。

varying vec2 vUv;
void main() {
  // 线的数量
  float lineNumber = 5.0;
  // 线的宽度
  float lineWidth = 0.01;

  // 取uv.x 的小数部分
  float x = fract(vUv.x * lineNumber);
  if(x<lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

这样就会出现多条线:
在这里插入图片描述

4、绘制经纬线

有了前面的基础,那么经纬线就很好绘制了。

varying vec2 vUv;
void main() {
  float lineNumber = 20.0;
  float lineWidth = 0.01;
  float x = fract(vUv.x * lineNumber);
  float y = fract(vUv.y * lineNumber);
  if(x<lineWidth || y <lineWidth) {
    gl_FragColor = vec4(vec3(0.0), 1.0);
  } else {
    gl_FragColor = vec4(1.);
  }
}
`

最终效果:
在这里插入图片描述

<全文结束, 多多点赞会变好看, 多多评论会变有钱>

发布了74 篇原创文章 · 获赞 6 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_21476953/article/details/103729700