gpt4 book ai didi

three.js - 每个实例具有唯一纹理的 InstancedMesh

转载 作者:行者123 更新时间:2023-12-04 12:23:06 24 4
gpt4 key购买 nike

我正在寻找一种方法来绘制具有独特纹理的多个对象。我遇到了这个 old question关于 instancedMesh,有人获得了多个具有不同纹理的实例,但在桌面上,纹理有奇怪的伪影。最初我认为那个演示一定有问题,但对我来说一切都很好,我也尝试使用混合函数代替条件,但纹理仍然有伪影。
我一直在寻找不同的方法来绘制多个独特的几何图形,因此合并几何图形不是一种选择,但我得到的大多数结果都是针对具有合并几何图形的多个对象。如果有人可以提供一些指导,那就太好了。

    var camera, scene, renderer, stats;

var mesh;
var amount = parseInt( window.location.search.substr( 1 ) ) || 10;
var count = Math.pow( amount, 3 );

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2( 1, 1 );

var rotationTheta = 0.1;
var rotationMatrix = new THREE.Matrix4().makeRotationY( rotationTheta );
var instanceMatrix = new THREE.Matrix4();
var matrix = new THREE.Matrix4();

init();
animate();

function init() {

camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.set( amount, amount, amount );
camera.lookAt( 0, 0, 0 );

scene = new THREE.Scene();

var light = new THREE.HemisphereLight( 0xffffff, 0x000088 );
light.position.set( - 1, 1.5, 1 );
scene.add( light );

var light = new THREE.HemisphereLight( 0xffffff, 0x880000, 0.5 );
light.position.set( - 1, - 1.5, - 1 );
scene.add( light );

var geometry = new THREE.BoxBufferGeometry( .5, .5, .5, 1, 1, 1 );

var material = [
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/square-outline-textured.png' ) } ),
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/golfball.jpg' ) } ),
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/metal.jpg' ) } ),
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/roughness_map.jpg' ) } ),
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/tri_pattern.jpg' ) } ),
new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/water.jpg' ) } ),
];

material.forEach((m,side)=>{
if ( side!=2 ) return;

m.onBeforeCompile = ( shader ) => {

shader.uniforms.textures = { 'type': 'tv', value: [
new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/crate.gif' ),
new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/equirectangular.png' ),
new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/colors.png' )
] };


shader.vertexShader = shader.vertexShader.replace(
'#define STANDARD',
`#define STANDARD
varying vec3 vTint;
varying float vTextureIndex;`
).replace(
'#include <common>',
`#include <common>
attribute vec3 tint;
attribute float textureIndex;`
).replace(
'#include <project_vertex>',
`#include <project_vertex>
vTint = tint;
vTextureIndex=textureIndex;`
);

shader.fragmentShader = shader.fragmentShader.replace(
'#define STANDARD',
`#define STANDARD
uniform sampler2D textures[3];
varying vec3 vTint;
varying float vTextureIndex;`
)
.replace(
'#include <fog_fragment>',
`#include <fog_fragment>
int texIdx = int(vTextureIndex);
vec4 col;
if (texIdx == 0) {
col = texture2D(textures[0], vUv );
} else if ( texIdx==1) {
col = texture2D(textures[1], vUv );
} else if ( texIdx==2) {
col = texture2D(textures[2], vUv );
}

gl_FragColor = col;
// gl_FragColor.rgb *= vTint;`

)
;
}
});

mesh = new THREE.InstancedMesh( geometry, material, count );

var i = 0;
var offset = ( amount - 1 ) / 2;

var transform = new THREE.Object3D();
var textures = [];

for ( var x = 0; x < amount; x ++ ) {

for ( var y = 0; y < amount; y ++ ) {

for ( var z = 0; z < amount; z ++ ) {

transform.position.set( offset - x, offset - y, offset - z );
transform.updateMatrix();

mesh.setMatrixAt( i ++, transform.matrix );


textures.push(Math.random()<0.3 ? 0 : (Math.random()<0.5 ? 1 : 2));
}

}

}

geometry.setAttribute( 'textureIndex',
new THREE.InstancedBufferAttribute( new Float32Array(textures), 1 ) );

scene.add( mesh );


renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

new THREE.OrbitControls( camera, renderer.domElement );

stats = new Stats();
document.body.appendChild( stats.dom );

window.addEventListener( 'resize', onWindowResize, false );
document.addEventListener( 'mousemove', onMouseMove, false );

}

function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();

renderer.setSize( window.innerWidth, window.innerHeight );

}

function onMouseMove( event ) {

event.preventDefault();

mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

}

function animate() {

requestAnimationFrame( animate );

render();

}

function render() {

raycaster.setFromCamera( mouse, camera );

var intersection = raycaster.intersectObject( mesh );
// console.log('intersection', intersection.length);
if ( intersection.length > 0 ) {

mesh.getMatrixAt( intersection[ 0 ].instanceId, instanceMatrix );
matrix.multiplyMatrices( instanceMatrix, rotationMatrix );

mesh.setMatrixAt( intersection[ 0 ].instanceId, matrix );
mesh.instanceMatrix.needsUpdate = true;

}

renderer.render( scene, camera );

stats.update();

}
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

最佳答案

我相信您的问题来自转换 floatint ,然后使用它来创建分支。此错误仅出现在少数 GPU 中,而不是所有 GPU 中。我通过保持 vTextureIndex 让它开始工作如 float ,如果 textureIndex 对所有 3 个纹理进行采样并将每个纹理乘以 1匹配,或者如果 textureIndex 乘以 0不匹配。
我基本上替换了这些行:

int texIdx = int(vTextureIndex);
vec4 col;
if (texIdx == 0) {
col = texture2D(textures[0], vUv );
} else if ( texIdx==1) {
col = texture2D(textures[1], vUv );
} else if ( texIdx==2) {
col = texture2D(textures[2], vUv );
}
用这种方法:
float x = vTextureIndex;
vec4 col;
col = texture2D(textures[0], vUv ) * step(-0.1, x) * step(x, 0.1);
col += texture2D(textures[1], vUv ) * step(0.9, x) * step(x, 1.1);
col += texture2D(textures[2], vUv ) * step(1.9, x) * step(x, 2.1);
  • textureIndex为 0,第一个纹理乘以 1,其他纹理乘以 0
  • textureIndex为 1,第二个纹理乘以 1,其他纹理乘以 0
  • textureIndex为 2,第三个纹理乘以 1,其他纹理乘以 0

  • enter image description here

    var camera, scene, renderer, stats;

    var mesh;
    var amount = parseInt( window.location.search.substr( 1 ) ) || 10;
    var count = Math.pow( amount, 3 );

    var raycaster = new THREE.Raycaster();
    var mouse = new THREE.Vector2( 1, 1 );

    var rotationTheta = 0.1;
    var rotationMatrix = new THREE.Matrix4().makeRotationY( rotationTheta );
    var instanceMatrix = new THREE.Matrix4();
    var matrix = new THREE.Matrix4();

    init();
    animate();

    function init() {

    camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 10000 );
    camera.position.set( amount, amount, amount );
    camera.lookAt( 0, 0, 0 );

    scene = new THREE.Scene();

    var light = new THREE.HemisphereLight( 0xffffff, 0x000088 );
    light.position.set( - 1, 1.5, 1 );
    scene.add( light );

    var light = new THREE.HemisphereLight( 0xffffff, 0x880000, 0.5 );
    light.position.set( - 1, - 1.5, - 1 );
    scene.add( light );

    var geometry = new THREE.BoxBufferGeometry( .5, .5, .5, 1, 1, 1 );

    var material = [
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/square-outline-textured.png' ) } ),
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/golfball.jpg' ) } ),
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/metal.jpg' ) } ),
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/roughness_map.jpg' ) } ),
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/tri_pattern.jpg' ) } ),
    new THREE.MeshStandardMaterial( { map: new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/water.jpg' ) } ),
    ];

    material.forEach((m,side)=>{
    if ( side!=2 ) return;

    m.onBeforeCompile = ( shader ) => {

    shader.uniforms.textures = { 'type': 'tv', value: [
    new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/crate.gif' ),
    new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/equirectangular.png' ),
    new THREE.TextureLoader().load( 'https://threejs.org/examples/textures/colors.png' )
    ] };


    shader.vertexShader = shader.vertexShader.replace(
    '#define STANDARD',
    `#define STANDARD
    varying vec3 vTint;
    varying float vTextureIndex;`
    ).replace(
    '#include <common>',
    `#include <common>
    attribute vec3 tint;
    attribute float textureIndex;`
    ).replace(
    '#include <project_vertex>',
    `#include <project_vertex>
    vTint = tint;
    vTextureIndex=textureIndex;`
    );

    shader.fragmentShader = shader.fragmentShader.replace(
    '#define STANDARD',
    `#define STANDARD
    uniform sampler2D textures[3];
    varying vec3 vTint;
    varying float vTextureIndex;`
    )
    .replace(
    '#include <fog_fragment>',
    `#include <fog_fragment>
    float x = vTextureIndex;
    vec4 col;
    col = texture2D(textures[0], vUv ) * step(-0.1, x) * step(x, 0.1);
    col += texture2D(textures[1], vUv ) * step(0.9, x) * step(x, 1.1);
    col += texture2D(textures[2], vUv ) * step(1.9, x) * step(x, 2.1);

    gl_FragColor = col;
    `

    )
    ;
    }
    });

    mesh = new THREE.InstancedMesh( geometry, material, count );

    var i = 0;
    var offset = ( amount - 1 ) / 2;

    var transform = new THREE.Object3D();
    var textures = [];

    for ( var x = 0; x < amount; x ++ ) {

    for ( var y = 0; y < amount; y ++ ) {

    for ( var z = 0; z < amount; z ++ ) {

    transform.position.set( offset - x, offset - y, offset - z );
    transform.updateMatrix();

    mesh.setMatrixAt( i ++, transform.matrix );


    textures.push(Math.random()<0.3 ? 0 : (Math.random()<0.5 ? 1 : 2));
    }

    }

    }

    geometry.setAttribute( 'textureIndex',
    new THREE.InstancedBufferAttribute( new Float32Array(textures), 1 ) );

    scene.add( mesh );


    renderer = new THREE.WebGLRenderer( { antialias: false } );
    renderer.setPixelRatio( window.devicePixelRatio );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

    new THREE.OrbitControls( camera, renderer.domElement );

    stats = new Stats();
    document.body.appendChild( stats.dom );

    window.addEventListener( 'resize', onWindowResize, false );
    document.addEventListener( 'mousemove', onMouseMove, false );

    }

    function onWindowResize() {

    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize( window.innerWidth, window.innerHeight );

    }

    function onMouseMove( event ) {

    event.preventDefault();

    mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
    mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;

    }

    function animate() {

    requestAnimationFrame( animate );

    render();

    }

    function render() {

    raycaster.setFromCamera( mouse, camera );

    var intersection = raycaster.intersectObject( mesh );
    // console.log('intersection', intersection.length);
    if ( intersection.length > 0 ) {

    mesh.getMatrixAt( intersection[ 0 ].instanceId, instanceMatrix );
    matrix.multiplyMatrices( instanceMatrix, rotationMatrix );

    mesh.setMatrixAt( intersection[ 0 ].instanceId, matrix );
    mesh.instanceMatrix.needsUpdate = true;

    }

    renderer.render( scene, camera );

    stats.update();

    }
    <script src="https://threejs.org/build/three.js"></script>
    <script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
    <script src="https://threejs.org/examples/js/libs/dat.gui.min.js"></script>
    <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

    关于three.js - 每个实例具有唯一纹理的 InstancedMesh,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65974267/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com