我为3D飞机追踪器添加了一个发光效果:
效果由THREE.ShaderMaterial
提供。该效果仅适用于某些PC。在其他PC中,效果不可见,但没有显示错误,其他一切都有效。我尝试过多台PC和操作系统,似乎是与硬件相关的问题,而不是操作系统问题。
glow
效果的代码如下所示:
private _createGlow(radius: number, segments: number) {
let material = new THREE.ShaderMaterial({
uniforms: {
"c": { type: "f", value: 0.01 },
"p": { type: "f", value: 6 },
glowColor: { type: "c", value: new THREE.Color(0x002296) },
viewVector: { type: "v3", value: this._camera.position }
},
vertexShader: `
uniform vec3 viewVector;
uniform float c;
uniform float p;
varying float intensity;
void main()
{
vec3 vNormal = normalize( normalMatrix * normal );
vec3 vNormel = normalize( normalMatrix * viewVector );
intensity = pow( c - dot(vNormal, vNormel), p );
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: `
uniform vec3 glowColor;
varying float intensity;
void main()
{
vec3 glow = glowColor * intensity;
gl_FragColor = vec4( glow, 1.0 );
}`,
side: THREE.FrontSide,
blending: THREE.AdditiveBlending,
transparent: true
});
let geometry = new THREE.SphereGeometry(radius, segments, segments);
let mesh = new THREE.Mesh(geometry, material);
mesh.scale.multiplyScalar(1.2);
return mesh;
}
场景创建的代码如下:
this._scene = new THREE.Scene();
this._scene.add(this._universe);
this._scene.add(this._glow);
this._scene.add(this._atmosphere1);
this._scene.add(this._atmosphere2);
this._scene.add(this._earth);
this._scene.add(this._light);
this._scene.add(new THREE.AmbientLight(0x333333, 0.9));
这是GPU驱动程序问题还是类似的问题?我该如何解决?谢谢!
答案 0 :(得分:2)
你的问题中有许多未知数。由于我们无法访问您已对代码进行过测试的所有系统,因此我们无法接受您的代码,并且可以解决问题。并给你一个工作片段。
然而,你可以做的是在进行3D编程时无处不在的东西,即差分调试 - 分而治之。
着色器至少使用过去10年制造的硬件支持的功能,因此我会更广泛地寻找问题。我乍一看怀疑有几个罪魁祸首:
normalMatrix
等)可能未正确初始化。在这种情况下,基本过程是从最基本的基本着色器开始,一直向上,直到找到导致错误行为的单个语句或表达式。
首先制作一个只输出白色(或glowColor
)的着色器并禁用剔除并测试它 - 你看到你的球体吗?
启用剔除 - 你看到了球体吗?
接下来调试法线向量 - 将法线传递给像素着色器并将它们作为片段颜色输出。您可以使用(n * 0.5) + 0.5
对其进行编码,以获得世界空间"法线贴图"对象。它看起来不错吗?
最后添加强度计算。它有用吗?嗯,它不应该,因为在这一点上,我们重建了整个发光效果,我们知道它并不总是有效。那么为什么它不起作用呢?
最后一个问题 - 如果GPU除以0会发生什么?
我猜你的代码无法正常工作的原因是pow( c - dot(vNormal, vNormel), p )
只要基数为负数就会返回NaN。不同的GPU可能有不同的方法来处理NaN,有些不太明显。
简而言之:你应该读完整件事。该方法比结果更有用。