Three.js - Using multiple textures in a single PointCloud

三世轮回 提交于 2019-11-30 15:37:45

Also you can cast vTexIndex to int.

int textureIndex = int(vTexIndex + 0.5);

if (textureIndex == 0) {
    finalColor = texture2D(textures[0], gl_PointCoord);
} else if (textureIndex == 1) {
    finalColor = texture2D(textures[1], gl_PointCoord);
} else if (textureIndex == 2) {
    finalColor = texture2D(textures[2], gl_PointCoord);
}

Thanks for replying to your own question. You helped me get started on a similar feature I was working.

I thought this might be helpful to someone else so I'm replying here.

I've created a fiddle that does what you're doing, but dynamically. You can add as many textures to the textures array and they will be dynamically added to the nodes. This was tricky to do in glsl, and required some hacky javascript templating.

To do this, I just created 2 methods that return the vertex and fragment shader to the shader material:

Fragment Shader Method:

World.prototype.getFragmentShader = function(numTextures){
var fragShader =  `uniform sampler2D textures[${numTextures}];

varying vec3 vColor;
varying float vTexIndex;

void main() {
    vec4 startColor = vec4(vColor, 1.0);
    vec4 finalColor;

    `;
  for(var i = 0; i < numTextures; i++){
    if(i == 0){ 
      fragShader += `if (vTexIndex < ${i}.5) {
        finalColor = texture2D(textures[${i}], gl_PointCoord);
        }
      `
    }
    else{
      fragShader += `else if (vTexIndex < ${i}.5) {
        finalColor = texture2D(textures[${i}], gl_PointCoord);
        }
      `
    }
  }
fragShader += `gl_FragColor = startColor * finalColor;
}`;

console.log('frag shader: ', fragShader)
return fragShader;
}

Vertex Shader:

World.prototype.getVertexShader = function(){

let vertexShader = `attribute vec3 color;
attribute float texIndex;

varying vec3 vColor;
varying float vTexIndex;

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

    vColor = color;
    vTexIndex = texIndex;

    gl_PointSize = 50.0;
    gl_Position = projectionMatrix * mvPosition;
}`;

return vertexShader;
}

You can see a live demo here: http://jsfiddle.net/jigglebilly/drmvz5co/

The new version of Three.js doesn't support attributes in ShaderMaterial. We'll have to delete attributes: attributes in new THREE.ShaderMaterial and use geometry.addAttribute instead. Here's the code to define texIndex:

var vIndex = new Float32Array( vertices.length );
for ( var i = 0, l = vertices.length; i < l; i ++ ) {
        vIndex[i] = Math.random()*getTextures().length;
}
geometry.addAttribute( 'texIndex', new THREE.BufferAttribute( vIndex, 1 ) );
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!