2017-05-07 248 views
1

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

我的Vertex Shader代碼:

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; 
} 

我的片段着色器代碼:

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 
} 

再次,如果頂點顏色設置我檢查,然後將它傳遞給片段着色器,然後套每點。

由於某些原因,每個點設置顏色時,頂點都是白色的(截圖:The white pixels should be green/red)。我遠離WebGL的高級用戶,任何幫助,將不勝感激。我做錯了什麼,我不知道?

回答

1

您創建自定義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

+0

我做了修改,但我得到了相同的結果。 即使在之前,#ifdef代碼部分也能正常工作。只是顏色總是白色的。出於某種原因,它被錯誤地傳遞給碎片着色器。 – bmakan

+0

歡迎使用stackoverflow。你設置'geometry.colors'意味着你正在使用'Geometry'而不是'BufferGeometry',在這種情況下這個答案是正確的。如果您使用'BufferGeometry',則需要設置屬性。無論如何,您可以自由提供自己的答案以作進一步澄清,但最好接受幫助您的人的答案。 – WestLangley

0

OK,我想我想通了,因爲它的工作現在。

我不得不設置顏色爲幾何屬性:

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提供的建議,併除去vertexColors: THREE.VertexColors,部分從材料定義並設置限定,以及:

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

然後在我的頂點着色器我說:

attributes vec3 colors; 

獲取從JavaScript傳遞的顏色。其餘的都是一樣的,我只是使用與上面發佈的問題相同的代碼將顏色傳遞給片段着色器。