You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Three.js中修改自定义Shader的Uniform变量值?

Custom Shader for Vertex Value Contour Mapping in Three.js

Hey there! I've built a custom shader that visualizes vertex-assigned values using contour mapping—great for showcasing elevation data, heatmaps, or any per-vertex attribute you want to highlight with clear contour lines. Here's a complete, functional example (I filled in the truncated parts of your original code to make it work end-to-end):

<html lang="en">
<head>
    <title>Face Contour Example</title>
    <style>
        body { margin: 0; }
        canvas { display: block; }
    </style>
</head>
<body>
    <script src="three.min.js"></script>
    <script src="OrbitControls.js"></script>
    <script src="SubdivisionModifier.js"></script>
    <script>
        // Basic scene setup
        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);

        // Add orbit controls for easy interaction
        const controls = new THREE.OrbitControls(camera, renderer.domElement);
        camera.position.z = 5;

        // Create a sample geometry (sphere works well for testing contours)
        const geometry = new THREE.SphereGeometry(2, 32, 32);
        
        // Assign random per-vertex values (replace this with your actual dataset)
        geometry.setAttribute('customValue', new THREE.Float32BufferAttribute(
            geometry.attributes.position.array.map(() => Math.random()),
            1
        ));

        // Custom Shader Material with contour logic
        const shaderMaterial = new THREE.ShaderMaterial({
            vertexShader: `
                attribute float customValue;
                varying float vCustomValue;

                void main() {
                    vCustomValue = customValue;
                    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
                }
            `,
            fragmentShader: `
                varying float vCustomValue;
                uniform float contourStep;

                void main() {
                    // Calculate contour bands and detect line positions
                    float band = floor(vCustomValue / contourStep);
                    float isContour = step(0.95, fract(vCustomValue / contourStep));

                    // Create a color gradient + dark contour lines
                    vec3 baseColor = mix(vec3(0.2, 0.6, 1.0), vec3(1.0, 0.8, 0.2), vCustomValue);
                    vec3 finalColor = mix(baseColor, vec3(0.0), isContour);

                    gl_FragColor = vec4(finalColor, 1.0);
                }
            `,
            uniforms: {
                contourStep: { value: 0.1 } // Adjust this to control how dense contours are
            }
        });

        // Apply subdivision to make contours smoother on low-poly geometry
        const subdivider = new THREE.SubdivisionModifier(2);
        subdivider.modify(geometry);

        // Create mesh and add to scene
        const mesh = new THREE.Mesh(geometry, shaderMaterial);
        scene.add(mesh);

        // Animation loop
        function animate() {
            requestAnimationFrame(animate);
            controls.update();
            renderer.render(scene, camera);
        }
        animate();

        // Handle window resize
        window.addEventListener('resize', () => {
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(window.innerWidth, window.innerHeight);
        });
    </script>
</body>
</html>

Core Features to Note:

  • Per-Vertex Data Integration: The shader uses a custom customValue attribute—swap out the random values with your own dataset (like elevation, temperature, or simulation data).
  • Adjustable Contour Density: Tweak the contourStep uniform to make contour lines more or less frequent.
  • Smooth Contours: The SubdivisionModifier refines geometry to avoid jagged lines on low-poly meshes.
  • Color Gradient: The base color transitions based on vertex values, making it easy to see value ranges at a glance.

Quick Breakdown of the Shader Logic:

  1. Vertex Shader: Simply passes the per-vertex customValue to the fragment shader as a varying variable.
  2. Fragment Shader:
    • Splits vertex values into bands using contourStep.
    • Uses fract() and step() to detect fragments that fall on contour line edges.
    • Mixes a gradient base color with black to draw sharp contour lines.

Feel free to tweak color palettes, contour line thickness, or step size to fit your specific use case!

内容的提问来源于stack exchange,提问作者Three Percent Games

火山引擎 最新活动