Three.js envmaps和顶点动画

时间:2015-12-10 15:08:49

标签: javascript three.js shader

我正在使用JavaScript编写第一步并使用Three.js进行编码。

我正在学习如何使用着色器,而且我有一周时间没有使用顶点动画。

这是我的顶点着色器:

uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;

varying float vReflectionFactor;
varying vec3 vReflect;

void main() {
  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

  vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );

  vec3 I = worldPosition.xyz - cameraPosition;

  vReflect = reflect( I, worldNormal );
  vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );

  gl_Position = projectionMatrix * mvPosition;
}

这个是片段着色器:

uniform vec3 color;
uniform samplerCube envMap;

varying vec3 vReflect;
varying float vReflectionFactor;

void main() {
  vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
  gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}

然后我向我的属性声明了一个变量,向我的制服宣布了另一个变量,将它分配给几何体,但是当我加载网站时,我什么都没看到。 JavaScript控制台告诉我,在这一行uniforms.amplitude.value = Math.sin(frame);中没有定义制服。

你有一些推荐吗?你知道我能做些什么吗?

我在这里提供完整的代码,希望它可以提供帮助:

<script id="vertexShader" type="x-shader/x-vertex">

uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;

varying float vReflectionFactor;
varying vec3 vReflect;

void main() {
  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

  vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );

  vec3 I = worldPosition.xyz - cameraPosition;

  vReflect = reflect( I, worldNormal );
  vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );

  gl_Position = projectionMatrix * mvPosition;
}
  </script>

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

uniform vec3 color;
uniform samplerCube envMap;

varying vec3 vReflect;
varying float vReflectionFactor;

void main() {
  vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
  gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}
  </script>

  <script>

  var camera, scene, renderer;
  var mesh, material, controls, sky;
  init();
  animate();

  function init(){
    renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setClearColor(0xfffff, 0);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 2000);
    camera.position.z = 400;
    //controls = new THREE.TrackballControls( camera );

    scene = new THREE.Scene();
    var numberOfImages = 46, images = [];
            for (var i = 1; i <= numberOfImages; i++) {
              images.push('sources/instagram2/image' + i + ".jpg");
            }

    var urls = images.sort(function(){return .6 - Math.random()}).slice(0,6);
    var textureCube = THREE.ImageUtils.loadTextureCube( urls );
    // Skybox
    var skyshader = THREE.ShaderLib[ "cube" ];
    skyshader.uniforms[ "tCube" ].value = textureCube;

    var skymaterial = new THREE.ShaderMaterial( {

      fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
      vertexShader: document.getElementById( 'vertexShader' ).textContent,
      uniforms: skyshader.uniforms,
      depthWrite: false,
      side: THREE.BackSide

    } );

    sky = new THREE.Mesh( new THREE.BoxGeometry( 1500, 1500, 1500 ), skymaterial );
    sky.visible = false;
    scene.add( sky );

    var attributes = {
        displacement: {
        type: 'f', // a float
        value: [] // an empty array
        }
    };

    var uniforms = {
        color: {
          type: "c",
          value: new THREE.Color(0x000000),
        },
        envMap: {
          type: "t",
          value: textureCube
        },
        fresnelBias: {
          type: "f",
          value: 0.1
        },
        fresnelScale: {
          type: "f",
          value: 1.0
        },
        fresnelPower: {
          type: 'f',
          value: 2.0
        },
        amplitude: {
          type: 'f',
          value: 0
        }
    };
    var vertexShader = document.getElementById('vertexShader').text;
    var fragmentShader = document.getElementById('fragmentShader').text;
    material = new THREE.ShaderMaterial(
        {
          uniforms : uniforms,
          vertexShader : vertexShader,
          fragmentShader : fragmentShader,
        });


    var loader = new THREE.BinaryLoader();
    loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {

    mesh = new THREE.Mesh(geometry, material);
    mesh.scale.set( 300, 300, 300 );

    var vertices = mesh.geometry.vertices;
    var values = attributes.displacement.value
    for(var v = 0; v < vertices.length; v++) {
    values.push(Math.random() * 10);
    }

    scene.add(mesh);

    } );



    var light = new THREE.AmbientLight( 0x404040 ); // soft white light
    scene.add( light );

    var directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(1, 1, 1).normalize();
    scene.add(directionalLight);

    window.addEventListener('resize', onWindowResize, false);

  }

  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }

  var frame = 0;

  function animate() {

    uniforms.amplitude.value = Math.sin(frame);
    frame += 0.01;

    requestAnimationFrame(animate);
    //controls.update();
    //mesh.rotation.x += 0.005;
    //mesh.rotation.y += 0.005;
    renderer.render(scene, camera);
    stats.update();
  }

更新

我在全局范围内添加了uniforms变量,现在控制台没有显示任何问题,但我看不到顶点动画:

<script id="vertexShader" type="x-shader/x-vertex">

uniform float fresnelBias;
uniform float amplitude;
uniform float fresnelScale;
uniform float fresnelPower;
attribute float displacement;

varying float vReflectionFactor;
varying vec3 vReflect;

void main() {

  vec3 newPosition = position + normal * vec3(displacement * amplitude);

  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  vec4 worldPosition = modelMatrix * vec4( position, 1.0 );

  vec3 worldNormal = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );

  vec3 I = worldPosition.xyz - cameraPosition;

  vReflect = reflect( I, worldNormal );
  vReflectionFactor = fresnelBias + fresnelScale * pow( 1.0 + dot( normalize( I ), worldNormal ), fresnelPower );

  gl_Position = projectionMatrix * mvPosition;
}
  </script>

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

uniform vec3 color;
uniform samplerCube envMap;

varying vec3 vReflect;
varying float vReflectionFactor;

void main() {
  vec4 envColor = textureCube( envMap, vec3( -vReflect.x, vReflect.yz ) );
  gl_FragColor = vec4(mix(color, envColor.xyz, vec3(clamp( vReflectionFactor, 0.0, 1.0 ))), 1.0);
}
  </script>

  <script>

  var camera, scene, renderer;
  var mesh, material, controls, sky;

    renderer = new THREE.WebGLRenderer({ alpha: true });
    renderer.setClearColor(0xfffff, 0);
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 2000);
    camera.position.z = 400;


    scene = new THREE.Scene();
    var numberOfImages = 46, images = [];
            for (var i = 1; i <= numberOfImages; i++) {
              images.push('sources/instagram2/image' + i + ".jpg");
            }

    var urls = images.sort(function(){return .6 - Math.random()}).slice(0,6);
    var textureCube = THREE.ImageUtils.loadTextureCube( urls );

    var skyshader = THREE.ShaderLib[ "cube" ];
    skyshader.uniforms[ "tCube" ].value = textureCube;

    var skymaterial = new THREE.ShaderMaterial( {

      fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
      vertexShader: document.getElementById( 'vertexShader' ).textContent,
      uniforms: skyshader.uniforms,
      depthWrite: false,
      side: THREE.BackSide

    } );

    sky = new THREE.Mesh( new THREE.BoxGeometry( 1500, 1500, 1500 ), skymaterial );
    sky.visible = false;
    scene.add( sky );

    var attributes = {
        displacement: {
        type: 'f', 
        value: [] 
        }
    };

    var uniforms = {
        color: {
          type: "c",
          value: new THREE.Color(0x000000),
        },
        envMap: {
          type: "t",
          value: textureCube
        },
        fresnelBias: {
          type: "f",
          value: 0.1
        },
        fresnelScale: {
          type: "f",
          value: 1.0
        },
        fresnelPower: {
          type: 'f',
          value: 2.0
        },
        amplitude: {
          type: 'f',
          value: 0
        }
    };
    var vertexShader = document.getElementById('vertexShader').text;
    var fragmentShader = document.getElementById('fragmentShader').text;
    material = new THREE.ShaderMaterial(
        {
          uniforms : uniforms,
          vertexShader : vertexShader,
          fragmentShader : fragmentShader,
        });


    var loader = new THREE.BinaryLoader();
    loader.load( "sources/obj/mmlogo/mm_logo.js", function ( geometry ) {

    mesh = new THREE.Mesh(geometry, material);
    mesh.scale.set( 100, 100, 100 );

    var vertices = mesh.geometry.vertices;
    var values = attributes.displacement.value
    for(var v = 0; v < vertices.length; v++) {
    values.push(Math.random() * 30);
    }

    scene.add(mesh);

    } );



    var light = new THREE.AmbientLight( 0x404040 );
    scene.add( light );

    var directionalLight = new THREE.DirectionalLight(0xffffff);
    directionalLight.position.set(1, 1, 1).normalize();
    scene.add(directionalLight);

    window.addEventListener('resize', onWindowResize, false);



  function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }

  var frame = 0;

  function animate() {

    uniforms.amplitude.value = Math.sin(frame);
    frame += 0.1;

    requestAnimationFrame(animate);
    //controls.update();
    //mesh.rotation.x += 0.005;
    //mesh.rotation.y += 0.005;
    renderer.render(scene, camera);
  }

  animate();

  </script>

你有什么结果吗?

1 个答案:

答案 0 :(得分:0)

您已在uniforms函数中定义了init()变量,因此它的范围在该函数范围内,无法在animate()函数中访问。
uniforms变量添加到全局范围,您应该没问题。