ThreeJS(13)-Shader-Sollwertmaterial

Fügen Sie hier eine Bildbeschreibung ein

Integrierte Variablen für Shader-Material

Die integrierten Variablen des Three.js-Shaders sind

  1. gl_PointSize: Steuert im Punkt-Rendering-Modus die Rendering-Pixelgröße des quadratischen Punktbereichs (beachten Sie, dass dies die Pixelgröße ist, nicht die three.js-Einheit, sodass beim Bewegen der Kamera die Größe des auf dem Bildschirm angezeigten Punkts erhalten bleibt unverändert)
  2. gl_Position: Steuert die Position ausgewählter Scheitelpunkte
  3. gl_FragColor: RGB-Farbwert des Fragments
  4. gl_FragCoord: Die Koordinaten des Fragments, ebenfalls in Pixel
  5. gl_PointCoord: Entspricht im Punkt-Rendering-Modus quadratischen Pixelkoordinaten

Sie erscheinen entweder einzeln oder in Gruppen im Shader und sind die Seele des Shaders. Lassen Sie uns über ihre Bedeutung bzw. Verwendung sprechen.

  1. gl_PointSize

Die integrierte Variable gl_PointSize ist vom Typ Float. Da der Scheitelpunkt im Punktrendering-Modus ein Punkt ist, können wir ihn theoretisch nicht sehen, daher wird er als Quadrat dargestellt, das der Kamera zugewandt ist. Die integrierte Variable gl_PointSize wird hauptsächlich verwendet, um die Pixelgröße der von den Scheitelpunkten gerenderten quadratischen Oberfläche festzulegen (der Standardwert ist 0).

void main() {
    
       gl_PointSize = 10.0}
  1. gl_Position

Die integrierte Variable gl_Position ist ein vec4-Typ, der die Scheitelpunktpositionskoordinaten darstellt, die letztendlich an den Fragment-Shader übergeben werden, um für die Fragmentierung verwendet zu werden. vec4(x,y,z,1.0), die ersten drei Parameter stellen den xyz-Koordinatenwert des Scheitelpunkts dar und der vierte Parameter ist eine Gleitkommazahl 1.0.

void main() {
    
         gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); }
  1. gl_FragColor

Die integrierte Variable gl_FragColor ist vom Typ vec4 und wird hauptsächlich zum Festlegen der Farbe des Fragmentpixels verwendet. Die ersten drei Parameter stellen den Farbwert des Fragmentpixels RGB dar, und der vierte Parameter
ist die Fragmentpixeltransparenz A. 1.0 bedeutet undurchsichtig , und 0,0 bedeutet völlig transparent. .

void main() {
    
         gl_FragColor = vec4(1.0,0.0,0.0,1.0); }
  1. gl_FragCoord

Die integrierte Variable gl_FragCoord ist vom Typ vec2 und stellt die Koordinaten aller von WebGL auf der Leinwand gerenderten Fragmente oder Pixel dar. Der Ursprung der Koordinaten ist die obere linke Ecke der Leinwand. Die x-Achse verläuft horizontal nach rechts , und das y ist vertikal nach unten. Die Einheit der gl_FragCoord-Koordinaten ist ein Pixel, und der Wert von gl_FragCoord ist vec2(x,y). Auf die vertikalen und horizontalen Koordinaten der Fragmentkoordinaten kann jeweils über gl_FragCoord.x und gl_FragCoord zugegriffen werden. j. Hier ist ein ausgeliehenes Bild.
Fügen Sie hier eine Bildbeschreibung ein
Geben wir ein Beispiel.

fragmentShader: `
    void main() {
    
    
        if(gl_FragCoord.x < 600.0) {
    
    
            gl_FragColor = vec4(1.0,0.0,0.0,1.0);
        } else {
    
    
            gl_FragColor = vec4(1.0,1.0,0.0,1.0);
        }
    }
`

Fügen Sie hier eine Bildbeschreibung ein
Hier werden 600 Pixel als Grenze verwendet. Der Teil, in dem der x-Wert kleiner als 600 Pixel ist, wird rot gerendert, und der Teil größer als 600 Pixel wird gelb gerendert.

  1. gl_PointCoord

Die integrierte Variable gl_PointCoord ist ebenfalls vom Typ vec2, die ebenfalls die Koordinaten des Pixels darstellt, aber im Gegensatz zu gl_FragCoord berechnet gl_FragCoord den x-Wert aus [0, Breite] und den y-Wert aus [0, Höhe] basierend auf dem Ganzen Leinwand. gl_PointCoord ist im Punktrenderingmodus wirksam und sein Bereich entspricht der kleinen quadratischen Oberfläche, ebenfalls von der oberen linken Ecke [0,0] bis zur unteren rechten Ecke [1,1].

  1. Integrierte variable Übungen

Wir haben grob über die fünf integrierten Variablen gesprochen. Lassen Sie uns anhand eines kleinen Falls die anderen vier außer gl_FragCoord ausprobieren. Erstes Bild,

Fügen Sie hier eine Bildbeschreibung ein

var planeGeom = new THREE.PlaneGeometry(1000, 1000, 100, 100);
uniforms = {
    
    
    time: {
    
    
        value: 0
    }
}
var planeMate = new THREE.ShaderMaterial({
    
    
    transparent: true,
    side: THREE.DoubleSide,
    uniforms: uniforms,
    vertexShader: `
                uniform float time;
        void main() {
    
    
            float y = sin(position.x / 50.0 + time) * 10.0 + sin(position.y / 50.0 + time) * 10.0;
            vec3 newPosition = vec3(position.x, position.y, y * 2.0 );
            gl_PointSize = (y + 20.0) / 4.0;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
        }
    `,
    fragmentShader: `
        void main() {
    
    
            float r = distance(gl_PointCoord, vec2(0.5, 0.5));
            if(r < 0.5) {
    
    
                gl_FragColor = vec4(0.0,1.0,1.0,1.0);
            }
        }
    `
})
var planeMesh = new THREE.Points(planeGeom, planeMate);
planeMesh.rotation.x = - Math.PI / 2;
scene.add(planeMesh);

Fallnebel

Fügen Sie hier eine Bildbeschreibung ein
src/main/main.js

import * as THREE from "three";

import {
    
     OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import fragmentShader from "../shader/basic/fragmentShader.glsl";
import vertexShader from "../shader/basic/vertexShader.glsl";
// 目标:打造一个旋转的银河系
// 初始化场景
const scene = new THREE.Scene();

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

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

// 导入纹理
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load('textures/particles/10.png');
const texture1 = textureLoader.load('textures/particles/9.png');
const texture2 = textureLoader.load('textures/particles/11.png');

let geometry=null;
let  points=null;

// 设置星系的参数
const params = {
    
    
  count: 1000,
  size: 0.1,
  radius: 5,
  branches: 4,
  spin: 0.5,
  color: "#ff6030",
  outColor: "#1b3984",
};

// GalaxyColor
let galaxyColor = new THREE.Color(params.color);
let outGalaxyColor = new THREE.Color(params.outColor);
let material;
const generateGalaxy = () => {
    
    
  // 如果已经存在这些顶点,那么先释放内存,在删除顶点数据
  if (points !== null) {
    
    
    geometry.dispose();
    material.dispose();
    scene.remove(points);
  }
  // 生成顶点几何
  geometry = new THREE.BufferGeometry();
  //   随机生成位置
  const positions = new Float32Array(params.count * 3);
  const colors = new Float32Array(params.count * 3);

  const scales = new Float32Array(params.count);

  //图案属性
  const imgIndex = new Float32Array(params.count)

  //   循环生成点
  for (let i = 0; i < params.count; i++) {
    
    
    const current = i * 3;

    // 计算分支的角度 = (计算当前的点在第几个分支)*(2*Math.PI/多少个分支)
    const branchAngel =
      (i % params.branches) * ((2 * Math.PI) / params.branches);

    const radius = Math.random() * params.radius;
    // 距离圆心越远,旋转的度数就越大
    // const spinAngle = radius * params.spin;

    // 随机设置x/y/z偏移值
    const randomX =
      Math.pow(Math.random() * 2 - 1, 3) * 0.5 * (params.radius - radius) * 0.3;
    const randomY =
      Math.pow(Math.random() * 2 - 1, 3) * 0.5 * (params.radius - radius) * 0.3;
    const randomZ =
      Math.pow(Math.random() * 2 - 1, 3) * 0.5 * (params.radius - radius) * 0.3;

    // 设置当前点x值坐标
    positions[current] = Math.cos(branchAngel) * radius + randomX;
    // 设置当前点y值坐标
    positions[current + 1] = randomY;
    // 设置当前点z值坐标
    positions[current + 2] = Math.sin(branchAngel) * radius + randomZ;

    const mixColor = galaxyColor.clone();
    mixColor.lerp(outGalaxyColor, radius / params.radius);

    //   设置颜色
    colors[current] = mixColor.r;
    colors[current + 1] = mixColor.g;
    colors[current + 2] = mixColor.b;



    // 顶点的大小
    scales[current] = Math.random();

    // 根据索引值设置不同的图案;
    imgIndex[current] = i%3 ;
  }
  geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
  geometry.setAttribute("aScale", new THREE.BufferAttribute(scales, 1));
  geometry.setAttribute("imgIndex", new THREE.BufferAttribute(imgIndex, 1));
  //   设置点的着色器材质
  material = new THREE.ShaderMaterial({
    
    
    vertexShader: vertexShader,
    fragmentShader: fragmentShader,
    
    transparent: true,
    vertexColors: true,
    blending: THREE.AdditiveBlending,
    depthWrite: false,
    uniforms: {
    
    
      uTime: {
    
    
        value: 0,
      },
      uTexture:{
    
    
        value:texture
      },
      uTexture1:{
    
    
        value:texture1
      },
      uTexture2:{
    
    
        value:texture2
      },
      uTime:{
    
    
        value:0
      },
      uColor:{
    
    
        value:galaxyColor
      }

    },
  });

  //   生成点
  points = new THREE.Points(geometry, material);
  scene.add(points);
  console.log(points);
  //   console.log(123);
};

generateGalaxy()



// 初始化渲染器
const renderer = new THREE.WebGLRenderer();
renderer.shadowMap.enabled = true;

// 设置渲染尺寸大小
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) {
    
    
  //   controls.update();
  const elapsedTime = clock.getElapsedTime();
  material.uniforms.uTime.value = elapsedTime;
  requestAnimationFrame(animate);
  // 使用渲染器渲染相机看这个场景的内容渲染出来
  renderer.render(scene, camera);
}

animate();

src/shader/basic/fragmentShader.glsl



varying vec2 vUv;

uniform sampler2D uTexture;
uniform sampler2D uTexture1;
uniform sampler2D uTexture2;
varying float vImgIndex;
varying vec3 vColor;
void main(){
    
    
    
    // gl_FragColor = vec4(gl_PointCoord,0.0,1.0);

    // 设置渐变圆
    // float strength = distance(gl_PointCoord,vec2(0.5)); // 点到中心距离
    // strength*=2.0;
    // strength = 1.0-strength;
    // gl_FragColor = vec4(strength);

    // 圆形点
    // float strength = 1.0-distance(gl_PointCoord,vec2(0.5));
    // strength = step(0.5,strength);
    // gl_FragColor = vec4(strength);

    // 根据纹理设置图案
    // vec4 textureColor = texture2D(uTexture,gl_PointCoord);
    // gl_FragColor = vec4(textureColor.rgb,textureColor.r) ;
    vec4 textureColor;
    if(vImgIndex==0.0){
    
    
       textureColor = texture2D(uTexture,gl_PointCoord);
    }else if(vImgIndex==1.0){
    
    
       textureColor = texture2D(uTexture1,gl_PointCoord);
    }else{
    
    
       textureColor = texture2D(uTexture2,gl_PointCoord);
    }
    

    gl_FragColor = vec4(vColor,textureColor.r) ;
    

}

src/shader/basic/vertexShader.glsl


varying vec2 vUv;

attribute float imgIndex;
attribute float aScale;
varying float vImgIndex;

uniform float uTime;

varying vec3 vColor;
void main(){
    
    
    vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
    

    // 获取定点的角度
    float angle = atan(modelPosition.x,modelPosition.z);
    // 获取顶点到中心的距离
    float distanceToCenter = length(modelPosition.xz);
    // 根据顶点到中心的距离,设置旋转偏移度数
    float angleOffset = 1.0/distanceToCenter*uTime;
    // 目前旋转的度数
    angle+=angleOffset;

    modelPosition.x = cos(angle)*distanceToCenter;
    modelPosition.z = sin(angle)*distanceToCenter;

    vec4 viewPosition = viewMatrix*modelPosition;
    gl_Position =  projectionMatrix * viewPosition;

    // 设置点的大小
    // gl_PointSize = 100.0; // 点的大小
    // 根据viewPosition的z坐标决定是否原理摄像机
    gl_PointSize =200.0/-viewPosition.z*aScale; // 点的大小
    vUv = uv;
    vImgIndex=imgIndex;
    vColor = color;
}

Supongo que te gusta

Origin blog.csdn.net/woyebuzhidao321/article/details/134386276
Recomendado
Clasificación