threejs(11)-Proficient in shader programming (difficulty) 1

1. First introduction to shader language

GLSL stands for openGL Shading Language, which is a specific standard for shader programs, as you will see in the following chapters. There are other types of shaders depending on the hardware and operating system. Here we will use the openGL specification regulated by the Khronos Group. Understanding the history of OpenGL will help you understand most of its strange conventions, for which I recommend checking out: https://openglbook.com/chapter-0-preface-what-is-opengl.html

Insert image description here

import * as THREE from "three";

import {
    
     OrbitControls } from "three/examples/jsm/controls/OrbitControls";

// console.log(THREE);
// 初始化场景
const scene = new THREE.Scene();

// 创建透视相机
const camera = new THREE.PerspectiveCamera(
  90,
  window.innerHeight / window.innerHeight,
  0.1,
  1000
);
// 设置相机位置
// object3d具有position,属性是1个3维的向量
camera.position.set(0, 0, 2);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
//   更新摄像机的投影矩阵
camera.updateProjectionMatrix();
scene.add(camera);

// 加入辅助轴,帮助我们查看3维坐标轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

// 加载纹理

// const material = new THREE.MeshBasicMaterial({ color: "#00ff00" });
// 创建着色器材质
// vertexShader顶点着色器
//fragmentShader 片源着色器
const shaderMaterial = new THREE.ShaderMaterial({
    
    
  vertexShader: ` // vertexShader顶点着色器
        void main(){  // 投影矩阵(三维投影到二维,因为电脑屏幕是二维)<-视图矩阵<-模型矩阵
            gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ) ; //vec4 四个维度
        }
    `,
  fragmentShader: `//fragmentShader 片源着色器
        void main(){
            gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
        }
  `,
});

// 创建平面
const floor = new THREE.Mesh(
  new THREE.PlaneBufferGeometry(1, 1, 64, 64),
  shaderMaterial
);

console.log(floor);
scene.add(floor);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
    
     alpha: true });
// renderer.shadowMap.enabled = true;
// renderer.shadowMap.type = THREE.BasicShadowMap;
// renderer.shadowMap.type = THREE.VSMShadowMap;

// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);

// 监听屏幕大小改变的变化,设置渲染的尺寸
window.addEventListener("resize", () => {
    
    
  //   console.log("resize");
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight;
  //   更新摄像机的投影矩阵
  camera.updateProjectionMatrix();

  //   更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight);
  //   设置渲染器的像素比例
  renderer.setPixelRatio(window.devicePixelRatio);
});

// 将渲染器添加到body
document.body.appendChild(renderer.domElement);

// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼
controls.enableDamping = true;
// 设置自动旋转
// controls.autoRotate = true;

const clock = new THREE.Clock();
function animate(t) {
    
    
  const elapsedTime = clock.getElapsedTime();
  //   console.log(elapsedTime);
  requestAnimationFrame(animate);
  // 使用渲染器渲染相机看这个场景的内容渲染出来
  renderer.render(scene, camera);
}

animate();

2. Shader plug-in installation and file import development

When vscode installs the shader plug-in to write glsl files, it will highlight the
Insert image description here
01-shader/src/shader/basic/fragment.glsl
source shader

void main(){
    
     //vec4 四个维度
    gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}

01-shader/src/shader/basic/vertex.glsl
vertex shader

void main(){
    
     // 投影矩阵(三维投影到二维,因为电脑屏幕是二维)<-视图矩阵<-模型矩阵
    gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4( position, 1.0 ) ;
}
import * as THREE from "three";

import {
    
     OrbitControls } from "three/examples/jsm/controls/OrbitControls";

// 顶点着色器
import basicVertexShader from "../shader/basic/vertex.glsl";
// 片元着色器
import basicFragmentShader from "../shader/basic/fragment.glsl";

// 初始化场景
const scene = new THREE.Scene();

// 创建透视相机
const camera = new THREE.PerspectiveCamera(
  90,
  window.innerHeight / window.innerHeight,
  0.1,
  1000
);
// 设置相机位置
// object3d具有position,属性是1个3维的向量
camera.position.set(0, 0, 2);
// 更新摄像头
camera.aspect = window.innerWidth / window.innerHeight;
//   更新摄像机的投影矩阵
camera.updateProjectionMatrix();
scene.add(camera);

// 加入辅助轴,帮助我们查看3维坐标轴
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

// const material = new THREE.MeshBasicMaterial({ color: "#00ff00" });
// 创建着色器材质
const shaderMaterial = new THREE.ShaderMaterial({
    
    
  vertexShader: basicVertexShader,
  fragmentShader: basicFragmentShader,
});

// 创建平面
const floor = new THREE.Mesh(
  new THREE.PlaneBufferGeometry(1, 1, 64, 64),
  shaderMaterial
);

console.log(floor);
scene.add(floor);

// 初始化渲染器
const renderer = new THREE.WebGLRenderer({
    
     alpha: true });
// renderer.shadowMap.enabled = true;
// renderer.shadowMap.type = THREE.BasicShadowMap;
// renderer.shadowMap.type = THREE.VSMShadowMap;

// 设置渲染尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);

// 监听屏幕大小改变的变化,设置渲染的尺寸
window.addEventListener("resize", () => {
    
    
  //   console.log("resize");
  // 更新摄像头
  camera.aspect = window.innerWidth / window.innerHeight;
  //   更新摄像机的投影矩阵
  camera.updateProjectionMatrix();

  //   更新渲染器
  renderer.setSize(window.innerWidth, window.innerHeight);
  //   设置渲染器的像素比例
  renderer.setPixelRatio(window.devicePixelRatio);
});

// 将渲染器添加到body
document.body.appendChild(renderer.domElement);

// 初始化控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼
controls.enableDamping = true;
// 设置自动旋转
// controls.autoRotate = true;

function animate(t) {
    
    
  requestAnimationFrame(animate);
  // 使用渲染器渲染相机看这个场景的内容渲染出来
  renderer.render(scene, camera);
}

animate();

3. Understand the original shader material rawShaderMaterial and attribute_uniform_varying variables

1. What is a shader material?

ShaderMaterial is a small program written in GLSL and runs on the GPU. It can provide effects beyond materials, and can also combine many objects into a single Geometry or BufferGeometry to improve performance.

RawShaderMaterial This class works similarly to ShaderMaterial, except that the definitions of built-in uniforms and attributes are not automatically added to the GLSL shader code.

2. Variables of shader materials

Each shader material can specify two different types of shaders, which are vertex shaders and fragment shaders.
● The vertex shader runs first; it receives attributes, calculates/manipulates the position of each individual vertex, and passes other data (varyings) to the fragment shader.
● Runs after the fragment (or pixel) shader; it sets the color of each individual "fragment" (pixel) rendered to the screen.
There are three types of variables in shaders: uniforms, attributes, and varyings
Uniforms are variables that have the same value for all vertices . For example, light, fog, and shadow maps are data stored in uniforms. Uniforms can be accessed through vertex shaders and fragment shaders.
Attributes Variables associated with each vertex . For example, vertex positions, normals, and vertex colors are all data stored in attributes. attributes are only accessible in vertex shaders.
Varyings are variables passed from the vertex shader to the fragment shader . For each fragment, each varying value will be a smooth interpolation of adjacent vertex values.
Note: Internally within a shader, uniforms and attributes are like constants; you can only modify their values ​​via buffers using JavaScript code.

3. Use of shader materials

As mentioned above, each shader material can specify two different types of shaders. However, if we do not specify these two shaders and use them directly, no error will be reported, because ShaderMaterial has defined the default vertex shader and fragment shader. processor, their code is like this.

//顶点着色器代码
void main() {
    
    
    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
//片元着色器代码
void main() {
    
    
    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}

The projectionMatrix, modelViewMatrix and position here are all variables set by three for us and can be used directly. We have already mentioned the first two variables before, and position is the coordinate value of each vertex. When the shader code is executed, gl_Position and gl_FragColor will be executed in a loop to set the vertex position and color interpolation. And what we finally need to set is gl_Position and gl_FragColor. Without going into too much detail, let’s look at a small example below.

var geom = new THREE.SphereGeometry(10, 30, 20);
var mate = new THREE.ShaderMaterial({
    
    
    vertexShader: `
    varying vec3 vNormal;
    void main() {
    
    
                //将attributes的normal通过varying赋值给了向量vNormal
        vNormal = normal;
                //projectionMatrix是投影变换矩阵 modelViewMatrix是相机坐标系的变换矩阵 最后我们将y值乘以1.4得到了一个形如鸡蛋的几何体
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position.x, position.y * 1.4, position.z, 1.0 );
    }
    `,
    fragmentShader: `
        //片元着色器同样需要定义varying vec3 vNormal;
    varying vec3 vNormal;
    void main() {
    
    
                //vNormal是一个已经归一化的三维向量
        float pr = (vNormal.x + 1.0) / 2.0; //pr红色通道值范围为0~1
        float pg = (vNormal.y + 1.0) / 2.0; //pg绿色通道值范围为0~1
        float pb = (vNormal.z + 1.0) / 2.0; //pb蓝色通道值范围为0~1
        gl_FragColor=vec4(pr, pg, pb, 1.0); //最后设置顶点颜色,点与点之间会自动插值
    }
    `
})
var mesh = new THREE.Mesh(geom, mate);
scene.add(mesh)

Insert image description here
In this article, we simply operate the vertex shader and fragment shader to draw a colorful egg, but this is just a static shader.
Insert image description here
In the vertex shader, extract the model coordinates separately:

vec4 modelPosition = modelMatrix * vec4(position, 1.0);  
gl_Position = projectionMatrix * viewMatrix * modelPosition;

modelPosition is what we call model coordinates, that is, the right-handed coordinate system. Note that it is different from the spatial rectangular coordinate system. (pictures from the Internet)

Right-handed coordinate system
Insert image description here
Space rectangular coordinate system

Insert image description here
Process the xyz coordinates of the model and modify the vertex shader. For each point vertex:

  • The XY coordinates move overall by 1.0 units
  • The Z coordinate is sinusoidally distributed along with its X coordinate
void main() {
    
    
	v_uv = uv; // uv坐标信息
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    modelPosition.x += 1.0;
    modelPosition.y += 1.0;
    modelPosition.z += 0.1 * sin(modelPosition.x * 10.0);
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

In order to improve efficiency, threejs only renders one side by default. You need to set side:THREE.DoubleSide.

const shaderMaterial = new THREE.RawShaderMaterial({
    
    
  // 投影矩阵 * 视图矩阵 * 模型矩阵 * 顶点坐标
  vertexShader: vertexShader,
  fragmentShader: fragmentShader,
  side:THREE.DoubleSide
})

The effect is as expected:
Insert image description here
the fragment shader of the model is processed again, and the color is set according to the size of the Z coordinate:

  • Setting varying float f_height in the vertex shader is used to transfer the Z coordinate of the model to the fragment shader.
  • The fragment shader declares arying float f_height to receive information from the vertex shader, accept it in the main function, and assign this value to the first bit in rgba

Vertex shader:

attribute vec3 position;
attribute vec2 uv;

uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

varying vec2 v_uv;
varying float f_height;// 传递Z

precision lowp float;

void main() {
    
    
	// v_uv = uv; // uv坐标信息
    vec4 modelPosition = modelMatrix * vec4(position, 1.0);
    modelPosition.x += 1.0;
    modelPosition.y += 1.0;
    modelPosition.z += 0.1 * sin(modelPosition.x * 10.0); 
  f_height = modelPosition.z // 放入传递的数据
    gl_Position = projectionMatrix * viewMatrix * modelPosition;
}

Fragment shader:

// varying vec2 v_uv;
varying float f_height; // 传递来的Z坐标
precision lowp float;

void main() {
    
    
  float height = f_height + 1.0;  // 创建变量接收数据
  // gl_FragColor = vec4(v_uv, 0.0, 1.0); 
  gl_FragColor = vec4(height * 1.0, 0.0, 0.0, 1.0);
}

The R value at the crest is very high, while the Z coordinate at the trough is 0, which is close to pure black.
Insert image description here

4. Unform transfer time variables to create animations and sample textures through uv

const texture = textureLoader.load("./texture/ca.jpeg");
const rawShaderMaterial = new THREE.RawShaderMaterial({
    
    
  vertexShader: basicVertexShader,
  fragmentShader: basicFragmentShader,
  //   wireframe: true,
  side: THREE.DoubleSide,
  uniforms: {
    
     // 传入时间
    uTime: {
    
    
      value: 0,
    },
    uTexture: {
    
    
      value: texture,
    },
  },
});
function animate(t) {
    
    
  const elapsedTime = clock.getElapsedTime();
  //   console.log(elapsedTime);
  rawShaderMaterial.uniforms.uTime.value = elapsedTime; // 改变时间
  requestAnimationFrame(animate);
  // 使用渲染器渲染相机看这个场景的内容渲染出来
  renderer.render(scene, camera);
}

01-shader/src/shader/raw/vertex.glsl
uTime time is passed in

precision lowp float;
attribute vec3 position;
attribute vec2 uv;


uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;

// 获取时间
uniform float uTime;


varying vec2 vUv;

// highp  -2^16 - 2^16
// mediump -2^10 - 2^10
// lowp -2^8 - 2^8

varying float vElevation;


void main(){
    
    
    vUv = uv;
    vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
    // modelPosition.x += 1.0;
    // modelPosition.z += 1.0;

    // modelPosition.z += modelPosition.x;

    modelPosition.z = sin((modelPosition.x+uTime) * 10.0)*0.05 ;
    modelPosition.z += sin((modelPosition.y+uTime)  * 10.0)*0.05 ;
    vElevation = modelPosition.z;

    gl_Position = projectionMatrix * viewMatrix * modelPosition ;
}

01-shader/src/shader/raw/fragment.glsl

precision lowp float;
varying vec2 vUv;
varying float vElevation;

uniform sampler2D uTexture; 


void main(){
    
    
    // gl_FragColor = vec4(vUv, 0.0, 1.0);
    // float height = vElevation + 0.05 * 10.0;
    // gl_FragColor = vec4(1.0*height,0.0, 0.0, 1.0);

    // 根据UV,取出对应的颜色
    float height = vElevation + 0.05 * 20.0;
    vec4 textureColor = texture2D(uTexture,vUv);
    textureColor.rgb*=height;
    gl_FragColor = textureColor;
}

Insert image description here

5. Shaders to write various types of patterns 1

glsl built-in functions

When we start to learn three.js shader materials, we often have no idea where to start. The shaders we have written so hard will also be at a loss due to inexplicable errors. The reason is that shader materials involve another language - GLSL. Only by understanding this language can we better write shader materials and make good use of our GPU. This article talks about glsl built-in functions.

1. Functions related to angles
function parameter describe
sin(x) radian sine function
cos(x) radian cosine function
so(x) radian tangent function
asin(x) radian arcsine function
acos(x) radian arc cosine function
time(x) radian arctangent function
radians(x) radian Convert angles to radians
degrees(x) radian Convert radians to degrees
2. Mathematical functions

This type of operation mainly involves operations on exponential logarithmic power functions.

function describe
pow(x,y) x to the power of y. If x is less than 0, the result is undefined. Likewise, if x=0 and y<=0, the result is undefined.
exp(x) e to the power x
log(x) Calculate the value of y such that x equals e raised to the power of y. If the value of x is less than 0, the result is undefined.
exp2(x) Calculate 2 raised to the power x
log2(x) Calculate the value of y such that x equals 2 raised to the y power. If the value of x is less than 0, the result is undefined.
sqrt(x) Calculate the square root of x. If x is less than 0, the result is undefined.
inversesqrt(x) Computes the value of one of the square roots of x. If x is less than or equal to 0, the result is undefined.
3. Commonly used functions

Here are commonly used functions, which are very similar to the built-in functions in js and need to be remembered.

function describe
abs(x) Returns the absolute value of x
sign(x) If x>0, return 1.0; if x=0, return 0; if x<0, return -1.0
floor(x) Returns the largest integer value less than or equal to x
ceil(x) Returns the smallest integer value greater than or equal to x
fract(x) Returns x-floor(x), which returns the decimal part of x
mod(x) Returns the modulus of x and y
min(x) Returns the smaller value of x and y.
max(x) Returns the larger value of x and y.
clamp(x, minVal, maxVal) Clamp the x value between minVal and maxVal, which means that when x < minVal, return minVal, when x > maxVal, return maxVal, when x is between minVal and maxVal, return x
mix(x, y, a) Returns a linear mixture of x and y, such as: x*(1−a)+y*a
step(edge, x) If x < edge, return 0.0, otherwise return 1.0
smoothstep(edge0, edge1, x) If x <= edge0, return 0.0; if x >= edge1, return 1.0; if edge0 < x < edge1, perform a smooth Hermitian difference between 0 and 1. If edge0 >= edge1, the result is undefined.
4. Geometric functions

This is a function related to length, distance, vector, etc.

function describe
length(x) Returns the length of vector x
distance(p0,p1) Calculate the distance between vectors p0, p1
dot Dot product between vectors x, y
cross(x, y) Cross product between vectors x, y
normalize(x) Normalize a vector, returning a vector with the same direction as x but length 1
faceforward(N, I, Nref) If the dot product of Nref and I is less than 0, return N; otherwise, return -N;
reflect(I, N) Return reflection vector
refract(I, N, eta) Returns the refraction vector

These are the commonly used functions. We also need to practice repeatedly in practice before we can use it skillfully.

Random numbers
https://thebookofshaders.com/10/?lan=ch

Insert image description here

02-three_shader graphics/src/shaders/
deep/vertex.glsl vertex shader

varying vec2 vUv;
// highp -2^16-2^16
// mediump = -2^10-2^10
// lowp -2^8-2^8
precision lowp float;
void main(){
    
    
    vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
    vUv=uv; // uv自动获取,相当于(0,0)、(1,0)、(1,1)、(0,1) 四点坐标
    gl_Position =  projectionMatrix * viewMatrix * modelPosition;
}

// uv is automatically obtained, equivalent to (0,0), (1,0), (1,1), (0,1) four-point coordinates Insert image description here
02-three_shader graphics/src/shaders/deep/fragment.glsl

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	 // 1通过顶点对应的uv,决定每一个像素在uv图像的位置,通过这个位置x,y决定颜色
	 // rgba(0,0,0,1)、rgba(1,0,0,1)、rgba(1,1,0,1)、rgba(0,1,0,1)
     gl_FragColor =vec4(vUv,0,1) ;
}

Insert image description here

to the first deformation

Insert image description here

02-three_shader graphics/src/shaders/deep/fragment.glsl

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	 // 1通过顶点对应的uv,决定每一个像素在uv图像的位置,通过这个位置x,y决定颜色
	 // rgba(0,0,1,1)、rgba(1,0,1,1)、rgba(1,1,1,1)、rgba(0,1,1,1)
     gl_FragColor =vec4(vUv,1,1) ;
}

Use UV to achieve gradient effect, from left to right

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
     gl_FragColor =vec4(vUv.x,vUv.x,vUv.x,1) ;
}

Use UV to achieve gradient effect, from bottom to top

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = vUv.y;
    gl_FragColor =vec4(strength,strength,strength,1);
}

Use UV to achieve gradient effect, from top to bottom

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = 1.0 - vUv.y;
    gl_FragColor =vec4(strength,strength,strength,1);
}

Use mold taking to achieve repeated effects

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = mod(vUv.y * 10.0 , 1.0) ; // 取模 0.1,0.2,0.3....->0.1,0.2,0.3....
    gl_FragColor =vec4(strength,strength,strength,1);
}

Use step(edge, x) if x < edge, return 0.0, otherwise return 1.0

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength =  mod(vUv.y * 10.0 , 1.0);
	strength = step(0.5,strength);
    gl_FragColor =vec4(strength,strength,strength,1);
}

stripes addition

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = step(0.8, mod(vUv.x * 10.0 , 1.0)) ;
	strength += step(0.8, mod(vUv.y * 10.0 , 1.0)) ;
    gl_FragColor =vec4(strength,strength,strength,1);
}

multiply stripes

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = step(0.8, mod(vUv.x * 10.0 , 1.0)) ;
	strength *= step(0.8, mod(vUv.y * 10.0 , 1.0)) ;
    gl_FragColor =vec4(strength,strength,strength,1);
}

block graphics

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = step(0.2, mod(vUv.x * 10.0 , 1.0)) ;
	strength *= step(0.2, mod(vUv.y * 10.0 , 1.0)) ;
    gl_FragColor =vec4(strength,strength,strength,1);
}

Use absolute values

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = abs(vUv.x - 0.5) ;
    gl_FragColor =vec4(strength,strength,strength,1);
}

6. Shader preparation of various types of patterns 2

Take the minimum of 2 values

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength =min(abs(vUv.x - 0.5), abs(vUv.y - 0.5))  ;
    gl_FragColor =vec4(strength,strength,strength,1);
}

step

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength =step(0.2,max(abs(vUv.x - 0.5), abs(vUv.y - 0.5)));
    gl_FragColor =vec4(strength,strength,strength,1);
}

Use rounding to achieve stripe gradient

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = floor(vUv.y*10.0)/10.0;
    gl_FragColor =vec4(strength,strength,strength,1);
}

Multiply stripes to achieve gradient lattice

Insert image description here

precision lowp float;
varying vec2 vUv;
void main(){
    
    
	float strength = floor(vUv.x*10.0)/10.0*floor(vUv.y*10.0)/10.0;
    gl_FragColor =vec4(strength,strength,strength,1);
}

random effects

Insert image description here

precision lowp float;
varying vec2 vUv;
// 随机函数
float random (vec2 st) {
    
    
    return fract(sin(dot(st.xy,vec2(12.9898,78.233)))*43758.5453123);
}
strength = random(vec2(strength,strength));
gl_FragColor =vec4(strength,strength,strength,1);

Returns the vector length based on length

Insert image description here

precision lowp float;
varying vec2 vUv;
float strength = length(vUv);
gl_FragColor =vec4(strength,strength,strength,1);

Distance between 2 vectors according to distance technique

Insert image description here

Insert image description here

precision lowp float;
varying vec2 vUv;
float strength =1.0 - distance(vUv,vec2(0.5,0.5));
gl_FragColor =vec4(strength,strength,strength,1);

According to division, realize stars

Insert image description here

precision lowp float;
varying vec2 vUv;
float strength =0.15 / distance(vUv,vec2(0.5,0.5)) - 1.0;
gl_FragColor =vec4(strength,strength,strength,1);

crossed stars

Insert image description here

precision lowp float;
varying vec2 vUv;
float  strength = 0.15 / distance(vec2(vUv.x,(vUv.y-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
strength += 0.15 / distance(vec2(vUv.y,(vUv.x-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
gl_FragColor =vec4(strength,strength,strength,strength);

spin dart, spin uv

Insert image description here

Mathematics School->3.14

precision lowp float;
varying vec2 vUv;
// 旋转函数
vec2 rotate(vec2 uv, float rotation, vec2 mid)
{
    
    
    return vec2(
      cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
      cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
    );
}

vec2 rotateUv = rotate(vUv,3.14*0.25,vec2(0.5));
vec2 rotateUv = rotate(vUv,-uTime*5.0,vec2(0.5));
float  strength = 0.15 / distance(vec2(rotateUv.x,(rotateUv.y-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
strength += 0.15 / distance(vec2(rotateUv.y,(rotateUv.x-0.5)*5.0+0.5),vec2(0.5,0.5)) - 1.0;
gl_FragColor =vec4(strength,strength,strength,strength);

Guess you like

Origin blog.csdn.net/woyebuzhidao321/article/details/134166086