2016-05-23 2 views
-1

я в настоящее время обучения OpenGL и наткнулся на этом уроке: http://patriciogonzalezvivo.com/2015/thebookofshaders/03/Анимационные пользовательские шейдеры в WebGL/three.js

Я пытался использовать пропущено в WebGL для того, чтобы глубже понять механизм, но почему-то не работает и Я честно не знаю, почему. Я уверен, что должна быть какая-то синтаксическая ошибка, но что это может быть? Если нет, то как я могу это сделать?

Чтобы быть честным, я пытаюсь понять, как реализовать u_time. Я думал, что у GPU автоматически есть встроенный таймер, который вызывает анимацию перехода цвета.

// 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>

+0

Где вы объявляете projectionMatrix, modelViewMatrix и позицию? projectionMatrix и modelViewMatrix должны быть объявлены как униформы; позицию как атрибут, плюс вы должны отправить их в gpu. Если это не ваша проблема, вы должны уточнить, что не работает, я думаю. – Zouch

+0

BTW, я не знаю THREE.js, но я не вижу, куда вы отправляете форму u_time. – Zouch

+0

@Zouch Я следил за учебником. Я предполагаю, что мне нужно каким-то образом привязать u_time к javascript-коду. Создайте таймер какого-то типа. – Asperger

ответ

3

Вы были правы, что вам нужно, чтобы связать/обновить значение в JavaScript. Чтобы сделать это, вам нужно сделать две вещи:

  1. Объявите u_time форму (включая type и начальное value), который находится в затенении при создании шейдера материала.

    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. Вы должны иметь цикл рендеринга, где вы постоянно обновлять равномерная-х value. Вот основной пример визуализации цикла, который использует requestAnimationFrame() называть себя, как только браузер готов предоставить другой кадр:

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

    Обратите внимание, что при обновлении uniforms.u_time.value не uniforms.u_time. Это связано с тем, что в одной и той же форме равно type, и она текущая value.

Working jsFiddle with changes

знает также, что вы используете очень старую версию three.js в своей скрипке. Версия r40 - с 2011 года, и сейчас мы работаем до r76. В последних версиях есть несколько тонкостей, которые делают это проще.

Смежные вопросы