【问题标题】:Three.js render white part of plain geometryThree.js 渲染纯几何的白色部分
【发布时间】:2016-03-08 14:00:58
【问题描述】:

我正在尝试将 this plainGeometry 变成 this(某种面具)。

此代码有效:(总而言之,创建两种材质,将平面划分为段,并用MeshFaceMaterial为每个段确定它的材质)

   Button.onClick(function () {

            var obj = editor.selected;
            var material = obj.material;
            var tex = material.map;
            var objHeight = obj.geometry.parameters.height;
            var objWidth = obj.geometry.parameters.width;
            var texHeight = tex.image.height;
            var texWidth = tex.image.width;

            var geometry = new THREE.PlaneGeometry(objWidth, objHeight, objWidth, objHeight);

            var facesNum = objHeight * objWidth * 2;
            var facesX = objWidth * 2;
            var facesInX = texWidth * 2;

            var materials = [];
            materials.push(material);
            materials.push(new THREE.MeshBasicMaterial({ }));

            for (var i = 0; i < facesNum; i++) {
                if ((i % facesX >= objWidth - texWidth) &&
                    (i % facesX <= (facesInX + objWidth - texWidth - 1)) &&
                    (i <= (texHeight * objWidth * 2) - 1)) {
                    geometry.faces[i].materialIndex = 0;
                }
                else {
                    geometry.faces[i].materialIndex = 1;
                }
            }

            obj.geometry = geometry;
            obj.material = new THREE.MeshFaceMaterial(materials);

            editor.signals.materialChanged.dispatch(obj);


        });

但我想知道是否有更简单的方法。有什么建议吗?

【问题讨论】:

    标签: javascript three.js textures


    【解决方案1】:

    另一种方法是在纹理上使用 Alpha 通道。您可以使用 Gimp 或 Photoshop 完成此操作。

    然后,您复制网格并将其推到轴外一点点,并在材质上使用 polygonOffsetFactor。将背景材质应用到第一个网格,将带有 alpha 纹理的前景材质应用到第二个网格。 看到这个小提琴alphaTest。 (您可能需要禁用跨域访问安全性,以便纹理可以在此小提琴中加载,如果您使用 --disable-web-security 标志运行它,chrome 将允许这样做) 这种方法的优点是图像可以是任何形状和位置,并且不需要适合几何面。

    如果您使用的几何图形很复杂,另一种方法是使用 Three.DecalGeometry 切割出一个网格块,并使用材质上的 polygonOffsetFactor 将其移动一点。请参阅three.js decals example

    示例小提琴的来源如下:

    var renderer;
    var pointLight;
    var scene;
    var plane1;
    var plane2;
    
    function addPlane()
    {
       var material1 = new THREE.MeshPhongMaterial({ color: 0xFFFFFF });
       var material2;
       var loader = new THREE.TextureLoader();
       loader.load('http://i.imgur.com/ETdl4De.png',
         function ( texture ) {     
              var material2 = new THREE.MeshPhongMaterial({
          color: 0xFFFFFF,
          map: texture,
          alphaTest: 0.7,
          polygonOffset: true,
                polygonOffsetFactor: - 4,
         });
    
       var geometry1 = new THREE.PlaneGeometry(12, 12, 12, 12);
       var geometry2 = geometry1.clone();   
       plane1 = new THREE.Mesh(geometry1,material1);      
       plane2 = new THREE.Mesh(geometry2,material2);      
       scene.add(plane2);
       scene.add(plane1);
        }
    );
    
    }
    (function() {
    
        'use strict';
    
        scene = new THREE.Scene();
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.01, 10000);
    
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);                 
        document.body.appendChild(renderer.domElement);
    
            addPlane();
    
        camera.position.z = 52;
    
        pointLight = new THREE.DirectionalLight(0xffffff,1);
        pointLight.position.x = 11;
        pointLight.position.y = 5;
        pointLight.position.z = 25;
        scene.add(pointLight);
    
        var reqAnimFrame = window.requestAnimationFrame ||          window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame;
    
        var render = function() {
            reqAnimFrame(render);        
            renderer.render(scene, camera);
        };
        render();
    }());
    

    【讨论】:

    • 感谢您的详细解答!不幸的是,我正在寻找一种只包含一个网格的解决方案(比如将纹理本身渲染为白色)。
    • 据我了解,使用多个纹理来完成此操作的功能曾经有效,但已被删除,我认为它不再有效:​​(
    • 您熟悉将平面拆分为不等段的能力吗? (heightSegments 和 widthSegments 将平面分成相等的部分)
    • 我认为你想对不相等的段做些什么是可能的,但你可能不得不手动编码。 ThreeCSG 可能会有所帮助。祝你好运!
    • 最终我通过更改顶点位置来做到这一点。非常感谢!
    【解决方案2】:

    最终做到了:

    var obj = editor.selected;
    var tex = obj.material.map.;
    
    var materials = [];
    materials.push(new THREE.MeshBasicMaterial({ map: tex }));
    materials.push(new THREE.MeshBasicMaterial({}));
    
    var material = new THREE.MeshFaceMaterial(materials);
    
    var objHeight = obj.geometry.parameters.height;
    var objWidth = obj.geometry.parameters.width;
    var texHeight = tex.image.height;
    var texWidth = tex.image.width;
    
    tex.repeat = new THREE.Vector2(3, 3);
    tex.offset = new THREE.Vector2(0, 0);
    
    var geometry = new THREE.PlaneGeometry(objWidth, objHeight, 3, 3);
    
    var v = geometry.vertices;
    var facesNum = geometry.faces.length;
    
    v[1] = new THREE.Vector3(-texWidth / 2, objHeight / 2, 0);
    v[2] = new THREE.Vector3(texWidth / 2, objHeight / 2, 0);
    v[5] = new THREE.Vector3(-texWidth / 2, (objHeight / 2) - texHeight, 0);
    v[6] = new THREE.Vector3(texWidth / 2, (objHeight / 2) - texHeight, 0);
    
    v[9] = v[13];
    v[10] = v[14];
    v[4] = v[8] = v[12];
    v[7] = v[11] = v[15];
    
    for (var i = 0; i < facesNum; i++) {
        if (i !== 2 && i !== 3) geometry.faces[i].materialIndex = 1;
    }
    
    obj.material = material;
    obj.geometry = geometry;
    
    editor.signals.materialChanged.dispatch(obj);
    

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 1970-01-01
      • 2020-08-20
      • 1970-01-01
      • 1970-01-01
      • 2013-11-25
      • 2017-05-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多