【问题标题】:Three.js envmaps and vertex animationThree.js envmaps 和顶点动画
【发布时间】:2015-12-11 19:05:56
【问题描述】:

我正在使用 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>

你有什么建议吗?

【问题讨论】:

    标签: javascript three.js shader


    【解决方案1】:

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

    【讨论】:

    • 谢谢@2pha。顺便说一句,我在网上找到了你的实验 blog.2pha.com/experimenting-threejs-shaders-and-shadermaterial,它们真的很有帮助。
    • 我将更新我的问题以显示没有任何控制台错误的代码。现在我可以看到我的模型,但它不会制作顶点动画。你有意见吗?
    • 制作一个 jsfiddle 以便更容易为您提供帮助
    • 我尝试制作一个 jsfiddle,但无法正确加载。我暂时在s000.tinyupload.com/?file_id=75645787875067994787 加载它。我希望你能看看并给我一些建议。
    • 看看HERE 在 jsfiddle 中实现three.js。使用最基本的代码来演示您的问题,并使用球体或盒子作为您的网格,而不是尝试加载一个。人们不会下载您的文件,因为这样做不值得。如果你需要帮助,你必须让人们更容易提供帮助。
    猜你喜欢
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-02
    • 2018-06-01
    • 2020-06-25
    相关资源
    最近更新 更多