网站备案服务,对于给不良网站发律师函如何做,学校网站设计制作目的,滁州建设管理网站着色器代码解析 大家好#xff01;我是 [数擎AI]#xff0c;一位热爱探索新技术的前端开发者#xff0c;在这里分享前端和Web3D、AI技术的干货与实战经验。如果你对技术有热情#xff0c;欢迎关注我的文章#xff0c;我们一起成长、进步#xff01; 开发领域#xff1a;…着色器代码解析 大家好我是 [数擎AI]一位热爱探索新技术的前端开发者在这里分享前端和Web3D、AI技术的干货与实战经验。如果你对技术有热情欢迎关注我的文章我们一起成长、进步 开发领域前端开发 | AI 应用 | Web3D | 元宇宙 技术栈JavaScript、React、ThreeJs、WebGL、Go 经验经验6 年 前端开发经验专注于图形渲染和 AI 技术 经验经验演示地址 开源项目AI智简未来、晓智元宇宙、数字孪生引擎 源码地址 提供的 GLSL 着色器代码通过光线行进算法Ray Marching生成一个动态的三维场景。以下是代码的核心功能概述
1. 平滑联合Smooth Union
opSmoothUnion 函数用于平滑地融合两个几何体使它们看起来像一个整体。 公式如下
float opSmoothUnion( float d1, float d2, float k ) {float h clamp( 0.5 0.5*(d2-d1)/k, 0.0, 1.0 );return mix( d2, d1, h ) - k*h*(1.0-h);
}
其中
d1 和 2 表示两个几何体的距离场值。k控制平滑程度的参数。mix 函数用于插值clamp 函数限制范围。
2. 符号距离函数SDF
sdSphere 函数定义了一个点到球体表面的距离
float sdSphere( vec3 p, float s ) {return length(p) - s;
}输入 p 是点的三维坐标s 是球体的半径。返回值为点到球表面的最短距离。
3. 场景组合
map 函数动态地组合多个球体通过时间参数让它们产生动画
float map(vec3 p) {float d 2.0;for (int i 0; i 16; i) {float fi float(i);float time iTime * (fract(fi * 412.531 0.513) - 0.5) * 2.0;d opSmoothUnion(sdSphere(p sin(time fi * vec3(52.5126, 64.62744, 632.25)) * vec3(2.0, 2.0, 0.8),mix(0.5, 1.0, fract(fi * 412.531 0.5124))),d,0.4);}return d;
}
通过循环生成 16 个动态移动的球体并用 opSmoothUnion 进行平滑组合。球体的位置随时间iTime变化实现动画效果。
4. 光线行进
在 mainImage 中实现了光线行进算法通过迭代寻找光线与几何体的交点
vec3 rayOri vec3(...); // 光线起点
vec3 rayDir vec3(0.0, 0.0, -1.0); // 光线方向
for (int i 0; i 64; i) { p rayOri rayDir * depth; float dist map(p); depth dist; if (dist 1e-6) break;
}
depth 表示光线当前行进的深度。map§ 计算光线与场景的最近距离。
完整代码
import * as THREE from three;
import React, { useEffect, useRef } from react;const CineShader: React.FC () {const cineShaderRef useRefany();useEffect(() {// 初始化场景、相机和渲染器const scene new THREE.Scene();const camera new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000,);const renderer new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 设置相机位置camera.position.z 5;// 创建自定义 ShaderMaterialconst shaderMaterial new THREE.ShaderMaterial({uniforms: {iResolution: {value: new THREE.Vector2(window.innerWidth, window.innerHeight),},iTime: { value: 0.0 },},vertexShader: varying vec2 vUv;void main() {vUv uv;gl_Position projectionMatrix * modelViewMatrix * vec4(position, 1.0);},fragmentShader: uniform vec2 iResolution;uniform float iTime;varying vec2 vUv;// 平滑联合float opSmoothUnion(float d1, float d2, float k) {float h clamp(0.5 0.5 * (d2 - d1) / k, 0.0, 1.0);return mix(d2, d1, h) - k * h * (1.0 - h);}// 球体 SDFfloat sdSphere(vec3 p, float s) {return length(p) - s;}// 场景组合float map(vec3 p) {float d 2.0;for (int i 0; i 16; i) {float fi float(i);float time iTime * (fract(fi * 412.531 0.513) - 0.5) * 2.0;d opSmoothUnion(sdSphere(p sin(time fi * vec3(52.5126, 64.62744, 632.25)) * vec3(2.0, 2.0, 0.8), mix(0.5, 1.0, fract(fi * 412.531 0.5124))),d,0.4);}return d;}// 计算法线vec3 calcNormal(vec3 p) {const float h 1e-5;const vec2 k vec2(1, -1);return normalize(k.xyy * map(p k.xyy * h) k.yyx * map(p k.yyx * h) k.yxy * map(p k.yxy * h) k.xxx * map(p k.xxx * h));}void main() {vec2 uv gl_FragCoord.xy / iResolution;uv uv * 2.0 - 1.0; // 将坐标转换为 [-1, 1]// 设置光线起点和方向vec3 rayOri vec3(uv * vec2(iResolution.x / iResolution.y, 1.0) * 6.0, 3.0);vec3 rayDir vec3(0.0, 0.0, -1.0);// 光线行进float depth 0.0;vec3 p;for (int i 0; i 64; i) {p rayOri rayDir * depth;float dist map(p);depth dist;if (dist 1e-6) {break;}}depth min(6.0, depth); // 限制最大深度// 计算颜色vec3 n calcNormal(p);float b max(0.0, dot(n, vec3(0.577))); // 简单光照vec3 col (0.5 0.5 * cos((b iTime * 3.0) uv.xyx * 2.0 vec3(0, 2, 4))) * (0.85 b * 0.35);col * exp(-depth * 0.15); // 添加深度雾效gl_FragColor vec4(col, 1.0);},});// 创建平面并添加到场景const geometry new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);const plane new THREE.Mesh(geometry, shaderMaterial);scene.add(plane);// 动画渲染循环function animate() {requestAnimationFrame(animate);// 更新时间shaderMaterial.uniforms.iTime.value 0.1;renderer.render(scene, camera);}animate();// 响应窗口大小调整window.addEventListener(resize, () {renderer.setSize(window.innerWidth, window.innerHeight);shaderMaterial.uniforms.iResolution.value.set(window.innerWidth,window.innerHeight,);camera.aspect window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();});}, []);return div ref{cineShaderRef}/;
};export default CineShader;
关注我们