此问题已在此处有答案:
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;
}
型
1条答案
按热度按时间nzk0hqpo1#
我在这个答案的帮助下解决了它:https://stackoverflow.com/a/35742512/18092120
显然,光线开始时离表面太近了,所以我所要做的就是在反射光线的方向上偏移一点。