顶点颜色正在变为白色

时间:2017-05-07 09:59:06

标签: javascript three.js shader

我正在使用THREE.js积分,有时我需要它们具有不同的每点颜色。有时,我也在修改他们的alpha值,所以我必须编写自己的着色器程序。

在JavaScript中,我有以下代码:

let materials;
if (pointCloudData.colors !== undefined) {
    geometry.colors = pointCloudData.colors.map(hexColor => new THREE.Color(hexColor));
    // If the point cloud has color for each point...
    materials = new THREE.ShaderMaterial({
        vertexColors: THREE.VertexColors,
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        transparent: true,
    });
} else {
    // Set color for the whole cloud
    materials = new THREE.ShaderMaterial({
        uniforms: {
            unicolor: { value: pointCloudData.color },
        },
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        transparent: true,
    });
}

const pointCloud = new THREE.Points(geometry, materials);

我基本上将网格颜色设置为均匀值,除非我已经定义了每个点颜色 - 然后我将vertexColors设置为几何。我还检查了存储在geometry.colors中的值,它们是范围[0,1]中的正确RGB值。

我的顶点着色器代码:

attribute float size;
attribute float alpha;

varying float vAlpha;
varying vec3 vColor;
void main() {
    vAlpha = alpha;

    #ifdef USE_COLOR
        vColor = color;
    #endif

    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_PointSize = size * ( 300.0 / -mvPosition.z );
    gl_Position = projectionMatrix * mvPosition;
}

我的Fragment着色器代码:

uniform vec3 unicolor;

varying vec3 vColor;
varying float vAlpha;
void main() {
    #ifdef USE_COLOR
        gl_FragColor = vec4(vColor, vAlpha);
    #else
        gl_FragColor = vec4(unicolor, vAlpha);
    #endif
}

同样,我正在检查是否设置了vertexColor,然后将其传递给片段着色器,然后设置每点。

出于某种原因,在设置每点颜色时顶点都是白色的(屏幕截图:The white pixels should be green/red)。我远非WebGL的高级用户,任何帮助将不胜感激。我做错了,我不知道吗?

2 个答案:

答案 0 :(得分:2)

您正在创建自定义ShaderMaterial并在片段着色器中使用此模式:

#ifdef USE_COLOR
    vColor = color;
#endif

因此,您需要指定material.defines,如此:

var defines = {};
defines[ "USE_COLOR" ] = "";

// points material
var shaderMaterial = new THREE.ShaderMaterial( {

    defines:        defines,
    uniforms:       uniforms,
    vertexShader:   document.getElementById( 'vertexshader' ).textContent,
    fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
    transparent:    true

} );

您无需设置vertexColors: THREE.VertexColors。这只是内置材质使用的一个标志,用于提醒渲染器为您设置defines

three.js r.85

答案 1 :(得分:1)

好吧,我想我已经弄明白了,因为它现在正在运作。

我必须将颜色设置为几何属性:

const colors = new Float32Array(n * 3);
for (let i = 0; i < n; i += 1) {
    new THREE.Color(pointCloudData.colors[i]).toArray(colors, i * 3);
}
geometry.addAttribute('colors', new THREE.BufferAttribute(colors, 1));

我还使用了WestLangley提供的建议,并从Material定义中删除了vertexColors: THREE.VertexColors,部分并设置了定义:

materials = new THREE.ShaderMaterial({
    defines: {
        USE_COLOR: '',
    },
    vertexShader: document.getElementById('vertexshader').textContent,
    fragmentShader: document.getElementById('fragmentshader').textContent,
    transparent: true,
});

然后在我的Vertex着色器中添加了:

attributes vec3 colors;

获取从JavaScript传递的颜色。其余的是相同的,我只是使用与上面发布的问题相同的代码将颜色传递给片段着色器。