为什么在此代码中激光没有从球体反射出来? (GLSL,three.js)

时间:2019-02-13 09:27:40

标签: graphics three.js glsl collision-detection transformation

这是我正在测试我的glsl代码的场景。A laser beam and a mirror ball白线是我根据three.js中基本CylinderGeometry的缩放和转换绘制的激光束。灰球是“镜子球”。我可以在镜子球的任何方向移动,如果球和激光相交,我想做的是使激光从球反射。但是,根据我的glsl代码,它永远不会发生。

首先,这就是我形成球和激光的几何形状的方式。

var mirrorBallPosition = {  type: 'v3',  value: new THREE.Vector3(0.0, 3.0, -2.0)};
var laserMaterial = new THREE.ShaderMaterial({
  uniforms: {
    offset: {type: 'v3', value: new THREE.Vector3(-0.15, 2.42, -0.64)},
    mirrorBallPosition: mirrorBallPosition
    }
})
var mirrorBallMaterial = new THREE.ShaderMaterial({
  uniforms:{
    mirrorBallPosition: mirrorBallPosition
  }
});
// LOAD SHADERS
var shaderFiles = [
  'glsl/laser.vs.glsl',
  'glsl/laser.fs.glsl',
  'glsl/mirrorBall.vs.glsl',
  'glsl/mirrorBall.fs.glsl'
];
new THREE.SourceLoader().load(shaderFiles, function(shaders) {
  laserMaterial.vertexShader = shaders['glsl/laser.vs.glsl'];
  laserMaterial.fragmentShader = shaders['glsl/laser.fs.glsl'];
  mirrorBallMaterial.vertexShader = shaders['glsl/mirrorBall.vs.glsl'];
  mirrorBallMaterial.fragmentShader = shaders['glsl/mirrorBall.fs.glsl'];
})
laser = {}
//Laser geometry
laser.laserGeometry = new THREE.CylinderGeometry(0.02, 0.02, 1, 16);
for (let i = 0; i < laser.laserGeometry.vertices.length; ++i)
  laser.laserGeometry.vertices[i].y += 0.5;
laser.leftLaser = new THREE.Mesh(laser.laserGeometry, leftLaserMaterial);
laser.rightLaser = new THREE.Mesh(laser.laserGeometry, rightLaserMaterial);
scenes[Part.LASERS].add(laser.leftLaser);
scenes[Part.LASERS].add(laser.rightLaser);

laser.mirrorBallGeometry = new THREE.SphereGeometry(1,32,32);
laser.mirrorBall = new THREE.Mesh(laser.mirrorBallGeometry, mirrorBallMaterial);
scenes[Part.LASERS].add(laser.mirrorBall);
...
// SETUP UPDATE CALL-BACK
function update() {
  checkKeyboard();
  requestAnimationFrame(update);
  renderer.render(scenes[Part.LASERS], cameras[Part.LASERS]);
}
update();

这是我的激光器的顶点着色器代码。

#version 300 es
uniform vec3 offset;
uniform vec3 mirrorBallPosition;
void main(){
  vec3 targetPosition = vec3(0.0, 0.3, -5.0);
  vec3 laserStart = offset + vec3(0.0,1.0,0.0);
  laserStart.y = offset.y;
  mat4 T = mat4(1.0);
  T[3].xyz = laserStart;
  mat4 S = mat4(1.0);
  S[1][1] = length(laserStart-targetPosition);

  // Roll the laser horizontally
  mat4 Rx = mat4(1.0);
  Rx[1][1] = 0.0;
  Rx[1][2] = -1.0;
  Rx[2][1] = 1.0;
  Rx[2][2] = 0.0;

  vec3 laserDirection = targetPosition - laserStart;
  vec3 laserDirectionZX = laserDirection;
  laserDirectionZX.y = 0.0;
  laserDirection = normalize(laserDirection);
  laserDirectionZX = normalize(laserDirectionZX);

  mat4 Rz = mat4(1.0);
  vec3 minusZ = vec3(0.0,0.0,-1.0);
  float cosBeta = dot(minusZ, laserDirectionZX);
  float sinBeta = sqrt(1.0-(cosBeta * cosBeta));
  float flag = 1.0;
  float relativeXCoordinate = laserStart.x-targetPosition.x;
  if(relativeXCoordinate < 0.0){
    flag = -1.0;
  }
  Rz[0][0] = cosBeta;
  Rz[1][0] = -sinBeta * flag;
  Rz[0][1] = sinBeta * flag;
  Rz[1][1] = cosBeta;

  // Roll the laser vertically
  mat4 Rx_2 = mat4(1.0);
  float cosAlpha = dot(laserDirection, laserDirectionZX);
  float sinAlpha = sqrt(1.0-(cosAlpha * cosAlpha));
  Rx_2[1][1] = cosAlpha;
  Rx_2[2][1] = sinAlpha;
  Rx_2[1][2] = -sinAlpha;
  Rx_2[2][2] = cosAlpha;

    //Now this is the reflection part.
    //Got all of these equations here(URL below)
    //https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection
  float r = 0.3;  //sphere size
  float temp = dot(laserDirection,laserStart-mirrorBallPosition);
  float temp2 = length(laserStart-mirrorBallPosition);
  float insideSQRT = (temp * temp) - (temp2*temp2-r*r);
  // I calculate the world position with this transformation.
  vec3 fragmentWorldPos = vec3(T * Rx * Rz * Rx_2 * S * vec4(position, 1.0));

  if(length(fragmentWorldPos-mirrorBallPosition)<r){    //This is when the laser should reflect.
    float d = -temp - sqrt(insideSQRT);
    vec3 closestIntersect = (laserStart+(d*laserDirection));
    vec3 fromCenterToIntersect = closestIntersect - mirrorBallPosition;
    fromCenterToIntersect = normalize(fromCenterToIntersect);
    vec3 lightComingIn = closestIntersect-laserStart;
    vec3 reflectDir = reflect(lightComingIn, fromCenterToIntersect);
    reflectDir = normalize(reflectDir);
    float distance = length(fragmentWorldPos-closestIntersect);
    vec3 updatedWorldPosition = closestIntersect + (reflectDir * distance);
    gl_Position = projectionMatrix * viewMatrix * vec4(updatedWorldPosition,1.0);
  }
  else{ // This is when the laser should not reflect.
    gl_Position = projectionMatrix * viewMatrix * vec4(fragmentWorldPos, 1.0);
  }

}

这是一个很长的代码,但是唯一相关的部分应该是最后一部分的if-else语句。

  float r = 0.3;  //sphere size
  float temp = dot(laserDirection,laserStart-mirrorBallPosition);
  float temp2 = length(laserStart-mirrorBallPosition);
  float insideSQRT = (temp * temp) - (temp2*temp2-r*r);
  vec3 fragmentWorldPos = vec3(T * Rx * Rz * Rx_2 * S * vec4(position, 1.0));

  if(length(fragmentWorldPos-mirrorBallPosition)<r){    //This is when the laser should reflect.
    float d = -temp - sqrt(insideSQRT);
    vec3 closestIntersect = (laserStart+(d*laserDirection));
    vec3 fromCenterToIntersect = closestIntersect - mirrorBallPosition;
    fromCenterToIntersect = normalize(fromCenterToIntersect);
    vec3 lightComingIn = closestIntersect-laserStart;
    vec3 reflectDir = reflect(lightComingIn, fromCenterToIntersect);
    reflectDir = normalize(reflectDir);
    float distance = length(fragmentWorldPos-closestIntersect);
    vec3 updatedWorldPosition = closestIntersect + (reflectDir * distance);
    gl_Position = projectionMatrix * viewMatrix * vec4(updatedWorldPosition,1.0);
  }
  else{ // This is when the laser should not reflect.
    gl_Position = projectionMatrix * viewMatrix * vec4(fragmentWorldPos, 1.0);
  }

似乎从未执行过if {}部分,而仅执行过else {}部分,这意味着直线和球体永远不会被视为相交。如果我移动球体与线相交,结果将是这样。

When the sphere and the line intersects

如果我移动照相机以查看球的内部,则球内的激光部分仍然存在,这意味着if语句无法正确运行。

我从这里的所有https://en.wikipedia.org/wiki/Line%E2%80%93sphere_intersection中得到了所有方程式,并且我仔细检查了代码是否正确实现了方程式。为什么会发生这种情况?

0 个答案:

没有答案