opengl 光线跟踪器非常嘈杂[重复]

mdfafbf1  于 2023-08-04  发布在  其他
关注(0)|答案(1)|浏览(110)

此问题已在此处有答案

Ray tracer reflections grainy(1个答案)
24天前关闭
所以,我正在实现一个光线跟踪器。它在计算着色器内部运行,该计算着色器将结果写入纹理。渲染器使用完美反射,即没有随机性。因此,理想情况下,不应该有噪声源。然而,渲染的图像实际上非常嘈杂。我不知道为什么会这样。
着色器代码:
光线-球体相交:

HitInfo testSphereIntersect(vec3 rayOrigin, vec3 rayDir, Sphere s) {
  HitInfo h;
  h.didHit = true;

  vec3 translatedRayOrig = rayOrigin - s.position.xyz;

  float a = dot(rayDir, rayDir);
  float b = dot(translatedRayOrig, rayDir) * 2;
  float c = dot(translatedRayOrig, translatedRayOrig) - (s.radius * s.radius);

  float discriminant = (b * b) - (4 * a * c);

  if (discriminant < 0) {
    h.didHit = false;
    return h;
  }

  float t_0 = (-b - sqrt(discriminant)) / (2 * a);
  float t_1 = (-b + sqrt(discriminant)) / (2 * a);

  if (t_0 < 0 && t_1 < 0) {
    h.didHit = false;
    return h;
  }

  h.rayT = t_0 >= 0 ? t_0 : t_1;
  h.position = rayOrigin + rayDir * h.rayT;
  h.normal = normalize(h.position - s.position.xyz);

  return h;
}

字符串
trace函数:

vec4 trace(vec3 rayDir, vec4 bgColour){

  vec3 rayOrigin = cameraPos;

  vec3 colour = vec3(0, 0, 0);

  HitInfo hit;
  uint sphereIndex;

  Material mat;
  float mult = 1.0f;

  for (int i = 0; i <= maxBounces; i++){
    
    hit = closestHIt(sphereIndex, rayDir, rayOrigin);
    if (!hit.didHit){
      
      colour +=  bgColour.xyz * mult;
      break;
    }

    vec3 lightDir = normalize(vec3(-1, -1, -1));
    float intensity = max(dot(hit.normal, -lightDir), 0);

    mat = materials[spheres[sphereIndex].materialID];

    vec3 sphereCol = mat.kd.xyz;
    sphereCol *= intensity;
    colour += sphereCol * mult;

    rayOrigin = hit.position;
    rayDir = normalize(reflect(rayDir, hit.normal));

    mult *= 0.7f;
  }

  return vec4(colour, 1);
}


这会找到关闭的命中:

HitInfo closestHIt(out uint index, vec3 rayDir, vec3 rayOrigin){

  HitInfo minHit;
  minHit.rayT = 1.0 / 0.0;
  minHit.didHit = false;

  uint minIndex = -1;
  
  for (int i = 0; i < spheres.length(); i++){

    HitInfo h = testSphereIntersect(rayOrigin, rayDir, spheres[i]);
    if (!h.didHit)
      continue;

    

    if (h.rayT < minHit.rayT){
      minHit = h;
      minIndex = i;
      minHit.didHit = true;
    }
  }
  
  index = minIndex;
  return minHit;
}


下面是光线生成代码:

vec3 getRayDir(float fov /* in degrees */, float aspectRatio) {
  vec2 texelCoord = gl_GlobalInvocationID.xy;
  vec2 ndc = vec2((texelCoord.x + 0.5) / (resolution[0]),
                  (texelCoord.y + 0.5) / (resolution[1]));

  vec2 pixelCamera;
  pixelCamera.x = ((2 * ndc.x) - 1) * aspectRatio * tan(radians(fov / 2));
  pixelCamera.y = ((2 * ndc.y) - 1) * tan(radians(fov / 2));

  vec3 rayDir = normalize((lookAt * vec4(pixelCamera, -1.0f, 0)).xyz);

  return rayDir;
}

nzk0hqpo

nzk0hqpo1#

我在这个答案的帮助下解决了它:https://stackoverflow.com/a/35742512/18092120
显然,光线开始时离表面太近了,所以我所要做的就是在反射光线的方向上偏移一点。

相关问题