我一直在阅读有关光线追踪和阴影的大量文章,但我的光线追踪图像看起来并不太好。我在谈论镜面高光附近非常明亮的绿色区域。结果绿色在这里最大化,看起来像。 如何调整颜色和/或阴影计算以使其看起来正确?
(别介意愚蠢的代码,我只是想先把原则弄清楚。)
以下是它的外观:
这里只是漫反射组件:
这是仅镜面反射分量:
编辑:将漫反射更改为颜色diffuseColor = ColorMake(0.0f,0.6f,0.0f); 然后图像看起来像这样:
Point lightPosition = PointMake(-100.0f, 100.0f, -100.0f);
Color diffuseColor = ColorMake(0.0f, 1.0f, 0.0f);
Color specularColor = ColorMake(1.0f, 1.0f, 1.0f);
Color pixelColor = ColorMake(0.0f, 0.0f, 0.0f);
// Trace...
// Diffuse
Point intersectionPosition = PointMake(x, y, z);
Vector intersectionNormal = VectorMake((x - xs) / rs, (y - ys) / rs, (z - zs) / rs);
Vector intersectionNormalN = VectorNormalize(intersectionNormal);
Vector lightVector = VectorSubtract(lightPosition, intersectionPosition);
VectorlightVectorN = VectorNormalize(lightVector);
float cosTheta = VectorDotProduct(intersectionNormalN, lightVectorN);
if (cosTheta < 0.0f)
{
cosTheta = 0.0f;
}
pixelColor = ColorMultScalar(diffuseColor, cosTheta);
// Specular
Vector incomVector = VectorSubtract(intersectionPosition, lightPosition);
Vector incomVectorN = VectorNormalize(incomVector);
float myDot = - VectorDotProduct(incomVectorN, intersectionNormalN);
float myLen = 2.0f * myDot;
Vector tempNormal = VectorMultScalar(intersectionNormalN, myLen);
Vector reflectVector = VectorAdd(tempNormal, incomVectorN);
Vector reflectVectorN = VectorNormalize(reflectVector);
float mySpec = MAX(-VectorDotProduct(reflectVectorN, incomVectorN), 0);
mySpec = powf(mySpec, 5);
specularColor = ColorMultScalar(specularColor, mySpec);
pixelColor = ColorAdd(pixelColor, specularColor);
pixelColor = ColorClamp(pixelColor);
[self putPixelatX:i andY:j andR:pixelColor.r andG:pixelColor.g andB:pixelColor.b];
答案 0 :(得分:7)
问题是,当您计算球体的漫反射颜色时,您已经拥有1个或非常接近1的小像素区域(在绿色通道中)。将“phong”组件(其中所有通道中的值接近1)相加,得到的像素区域> = 1.然后,当您将颜色值钳位为1时,该区域>&gt; = 1引人注目。
您可以使用图片编辑程序对此进行测试,并对两个图层(漫反射层上方的phong图层)进行“添加”叠加。这给出了您看到的结果 - 以及预期的结果。
您可以通过多种措施来避免此问题:
我的光线追踪实验可以追溯到几年前,但你可以试试这些。
更新1:
我注意到的一件事是,当你对输出图像进行伽马校正时 - 效果不太明显;) - 好吧,这有点不完整。
最终的解决方案是使用另一种着色模型:Wikipedia on Specular highlight。
更新2:
一个实际的解决方案是计算最终像素颜色的phong贡献(即你的变量mySpec
)。我的想法是只使用漫反射组件的一部分,其中镜面反射实际上不是0,也就是说,如果你有一些镜面反射组件,你实际上并没有看到漫反射组件太多(或根本没有)所以它可以是调整为:
float diffuseContrib = 1.f - mySpec;
这应该看起来不错,但我不确定正确实际上是如何:)。
但请注意;这假设您的镜面反射和漫反射组件在[0..1]范围内。
我的结果是这样的:
答案 1 :(得分:6)
这长期以来一直是&#34;镜面+漫反射+环境&#34;的问题。照明模型。也就是说,它是一个黑客,因此,无法保证正确性。
如果您首先热衷于巩固基础知识,请查看优秀的图书&#34;基于物理的光线跟踪&#34;作者:Matt Pharr和Greg Humphreys。
答案 2 :(得分:1)
您应该阅读Blinn/Phong model。这里有一些示例着色器片段代码。 基本上,您可以使用各自的角度缩放单个组件(环境,漫反射,镜面反射项)并将它们相加。
varying vec3 N;
varying vec3 v;
void main (void)
{
vec3 L = normalize(gl_LightSource[0].position.xyz - v);
vec3 E = normalize(-v); // we are in Eye Coordinates, so EyePos is (0,0,0)
vec3 R = normalize(-reflect(L,N));
//calculate Ambient Term:
vec4 Iamb = gl_FrontLightProduct[0].ambient;
//calculate Diffuse Term:
vec4 Idiff = gl_FrontLightProduct[0].diffuse * max(dot(N,L), 0.0);
Idiff = clamp(Idiff, 0.0, 1.0);
// calculate Specular Term:
vec4 Ispec = gl_FrontLightProduct[0].specular
* pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess);
Ispec = clamp(Ispec, 0.0, 1.0);
// write Total Color:
gl_FragColor = gl_FrontLightModelProduct.sceneColor + Iamb + Idiff + Ispec;
}
取自:http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php
答案 3 :(得分:1)
为什么不做(光+环境)*漫反射+镜面反射?即在将光照和阴影与漫反射相乘后添加镜面反射分量?这将给出明确的重点。