1

I am currently learning OpenGL and stumbled across this tutorial: http://patriciogonzalezvivo.com/2015/thebookofshaders/03/

I tried to use the snipped in webgl in order to further understand the mechanism but somehow it doesnt work and I am honestly not sure why. I am sure there must be some syntax error but what could it be? If not then how can I make this work?

To be honest im trying to understand how to implement u_time. I thought the GPU automatically has an in built timer which causes the color transition animation.

// set the scene size
var WIDTH = 400,
    HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
    ASPECT = WIDTH / HEIGHT,
    NEAR = 0.1,
    FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.Camera(  VIEW_ANGLE,
                              ASPECT,
                              NEAR,
                              FAR  );
var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

// create the sphere's material
var shaderMaterial = new THREE.MeshShaderMaterial({
  vertexShader:   $('#vertexshader').text(),
  fragmentShader: $('#fragmentshader').text()
});

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
  new THREE.Sphere(radius, segments, rings),
  shaderMaterial);

// add the sphere to the scene
scene.addChild(sphere);

// draw!
renderer.render(scene, camera);
<div id="container"></div>

<script type="x-shader/x-vertex" id="vertexshader">
// switch on high precision floats
#ifdef GL_ES
precision highp float;
#endif

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

<script type="x-shader/x-fragment" id="fragmentshader">

uniform float u_time;

void main() {
  gl_FragColor = vec4(sin(u_time),0.0,0.0,1.0);
}

</script>
<script src="https://aerotwist.com/static/tutorials/an-introduction-to-shaders-part-1/demo/js/Three.js"></script>
<script src="https://code.jquery.com/jquery-2.2.4.js"></script>

4
  • Where are you declaring projectionMatrix, modelViewMatrix and position ? projectionMatrix and modelViewMatrix should be declared as uniforms ; position as attribute, plus you should send them to the gpu. If this is not your problem, then you should clarify what is not working I guess. Commented May 23, 2016 at 19:40
  • BTW, I do not know THREE.js, but I don't see where you send the u_time uniform as well. Commented May 23, 2016 at 19:41
  • @Zouch I was following the tutorial. I assume I have to somehow bind the u_time in javascript code. Create a timer of some sort. Commented May 23, 2016 at 19:51
  • Three.js declares and updates the projectionMatrix, modelViewMatrix, position attributes automatically. Commented May 23, 2016 at 20:41

1 Answer 1

4

You were right that you need to bind/update the value in javascript. To do that, you need to do two things:

  1. Declare the u_time uniform ( including the type and initial value ) that is in the shader when you create the shader material.

    var shaderMaterial = new THREE.MeshShaderMaterial({
      uniforms: { // <- This is an object with your uniforms as keys
        u_time: { type: "f", value: 0 }
      },
      vertexShader:   $('#vertexshader').text(),
      fragmentShader: $('#fragmentshader').text()
    });
    
  2. You need to have a render loop where you continuously update the uniform's value. Here is a basic example of a render loop which uses requestAnimationFrame() to call itself once the browser is ready to render another frame:

    function draw () {
      requestAnimationFrame(draw);
    
      // Update shader's time
      sphere.materials[0].uniforms.u_time.value += 0.01;
    
      // draw!
      renderer.render(scene, camera);
    }
    
    draw();
    

    Note that you update uniforms.u_time.value not uniforms.u_time. This is because a uniform holds both it's type and it's current value.

Working jsFiddle with changes

Also know that you are using a very old version of three.js in your fiddle. Version r40 is from 2011 and we are up to r76 currently. There are some niceties in recent versions that make this simpler.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.