Search code examples
graphicsthree.jsglslshaderaframe

Implementing a gradient shader in three.js


I am trying to learn about shaders using three.js. What I am trying to do is create a shader that generates gradients to texture planets with. Right now I am just trying to generate one gradient to make sure it works. However, when I apply the shader it only renders one of the colors, and does not create the gradient effect I'm looking for. I can't seem to find where I'm going wrong with my code.

I'm using the Book of Shaders as the basis for my code. Specifically, I was looking at this example, trying to replicate the background color.

Here is my shader code:

  <section id="fragmentshader">
      #ifdef GL_ES
      precision mediump float;
      #endif

      // #define PI 3.14159265359

      uniform vec2 u_resolution;
      // uniform vec2 u_mouse;
      // uniform float u_time;

      vec3 colorA = vec3(0.500,0.141,0.912);
      vec3 colorB = vec3(1.000,0.833,0.224);



      void main() {
          vec2 st = gl_FragCoord.xy/u_resolution.xy;
          vec3 color = vec3(0.0);

          color = mix( colorA,
                 colorB,
                 st.y);

          gl_FragColor = vec4(color,1.0);
      }
    </section>
    <section id="vertexshader">

      void main() {
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    </section>

and my three.js code inside an a-frame component:

    var uniforms = {
      u_resolution: { type: "v2", value: new THREE.Vector2() },
    };

    var fShader = $('#fragmentshader');
    var vShader = $('#vertexshader');


    var geometry = new THREE.SphereGeometry(getRandomInt(100, 250), 20, 20);

    // var material = new THREE.MeshBasicMaterial( {wireframe: true });
    var material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: vShader.text(),
      fragmentShader: fShader.text()

    });

    var sphere = new THREE.Mesh(geometry, material);

This is what my spheres currently look like


Solution

  • var camera, scene, renderer, mesh, material;
    init();
    animate();
    
    function init() {
        // Renderer.
        renderer = new THREE.WebGLRenderer();
        //renderer.setPixelRatio(window.devicePixelRatio);
        renderer.setSize(window.innerWidth, window.innerHeight);
        // Add renderer to page
        document.body.appendChild(renderer.domElement);
    
        // Create camera.
        camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 400;
    
        // Create scene.
        scene = new THREE.Scene();
        
        var uniforms = {
          "color1" : {
            type : "c",
            value : new THREE.Color(0xffffff)
          },
          "color2" : {
            type : "c",
            value : new THREE.Color(0x000000)
          },
        };
        
        var fShader = document.getElementById('fragmentShader').text;
        var vShader = document.getElementById('vertexShader').text;
    
        // Create material
        var material = new THREE.ShaderMaterial({
          uniforms: uniforms,
          vertexShader: vShader,
          fragmentShader: fShader
        });
    
        // Create cube and add to scene.
        var geometry = new THREE.BoxGeometry(200, 200, 200);
        mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);
    
        // Create ambient light and add to scene.
        var light = new THREE.AmbientLight(0x404040); // soft white light
        scene.add(light);
    
        // Create directional light and add to scene.
        var directionalLight = new THREE.DirectionalLight(0xffffff);
        directionalLight.position.set(1, 1, 1).normalize();
        scene.add(directionalLight);
    
        // Add listener for window resize.
        window.addEventListener('resize', onWindowResize, false);
    
    }
    
    function animate() {
        requestAnimationFrame(animate);
        mesh.rotation.x += 0.005;
        mesh.rotation.y += 0.01;
        renderer.render(scene, camera);
    }
    
    function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();
        renderer.setSize(window.innerWidth, window.innerHeight);
    }
    <script src="https://rawgit.com/mrdoob/three.js/r86/build/three.min.js"></script>
    
    <script id="vertexShader" type="x-shader/x-vertex">
      varying vec2 vUv;
      void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
      }
    </script>
    
    <script id="fragmentShader" type="x-shader/x-fragment">
      uniform vec3 color1;
      uniform vec3 color2;
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(mix(color1, color2, vUv.y),1.0);
      }
    </script>