我有一个顶部开口的圆柱体,其材料在 Three.JS 场景中是双面的。
我想要实现的是圆柱体正面有一种颜色,圆柱体内部有另一种颜色。
为了实现此功能,我创建了一个扩展
THREE.MeshStandardMaterial
的新材质类,并且我正在修改 onBeforeCompile
钩子中的顶点和片段着色器。
在片段着色器中的
main
方法的末尾,我有这个:
gl_FragColor = vec4(faceNormal.rgb, sampledDiffuseColor.w);
if(gl_FrontFacing == false) {
gl_FragColor = vec4(0.0,0.0,0.0, sampledDiffuseColor.w);
}
但无论出于何种原因,我无法真正弄清楚,
gl_FrontFacing
始终设置为true。
据我所知,这不是我正在设置或修改的内容,而是 webGL 为我设置的内容。但对于所有内面来说不应该都是假的吗?
或者我在这里做错了什么?
为了自己简化,我更新了
onBeforeCompile
钩子
onBeforeCompile(shader: any) {
shader.vertexShader = /* glsl */ `
void main() {
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
shader.fragmentShader = /* glsl */`
void main() {
gl_FragColor = gl_FrontFacing ? vec4(1.0, 0.0, 0.0, 1.0) : vec4(0.0, 0.0, 1.0, 1.0);
}
`;
}
好吧,我知道是什么原因导致它总是一样的。 我正在使用
transparent: true
创建材质。如果我切换它,它就会正确地找出里面的东西和不里面的东西。
问题是我也确实需要透明功能
这是一个完整的示例,具有透明真实且非工作内部颜色
<!DOCTYPE html>
<head>
<title> SimpleDoubleSide(gl_FrontFacing) </title>
<meta charset="utf-8" />
</head>
<body> </body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.160.0/three.js"></script>
<script>
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 60, 1, 0.01, 1000 );
camera.position.set( 1, 2, 3 );
camera.lookAt(0,0,0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
const container = document.createElement( 'div' );
document.body.appendChild( container );
container.appendChild( renderer.domElement );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setClearColor( 0xdedede, 1 );
const shMaterial = new THREE.MeshBasicMaterial( { side: THREE.DoubleSide, transparent: true } );
shMaterial.onBeforeCompile = shader => {
shader.vertexShader =
`
attribute vec2 backUV;
varying vec2 vBackUV;
` + shader.vertexShader;
shader.vertexShader = shader.vertexShader.replace(
`#include <fog_vertex>`,
`#include <fog_vertex>
vBackUV = backUV;
`
);
shader.fragmentShader =
`
uniform sampler2D backTexture;
varying vec2 vBackUV;
` + shader.fragmentShader;
shader.fragmentShader = shader.fragmentShader.replace(
`#include <map_fragment>`,
`#include <map_fragment>
diffuseColor = gl_FrontFacing ? vec4(0.0,0.0,0.0,1.0) : vec4(1.0,1.0,1.0,1.0); //texture2D( map, vUv ) : texture2D( backTexture, vBackUV );
`
);
};
const cylGeom = new THREE.CylinderGeometry( 0.5, 0.4, 1, 36, 8, true );
const cylinder = new THREE.Mesh( cylGeom, shMaterial );
scene.add( cylinder );
render();
function render( ) {
renderer.render( scene, camera );
requestAnimationFrame( render );
}
</script>
</html>
在这个github问题中找到了解决方案大纲