光线追踪-照明方程 我试图在C++中写一个光线跟踪器,但是到目前为止的结果并不像我所期望的那样,所以我猜想光照方程式中有一个错误。 到目前为止,我得到的是:
我使用的是Blinn(-Phong)模型,并假设所有灯光都是点光源。这是我的代码:光线追踪-照明方程 我试图在C++中写一个光线跟踪器,但是到目前为止的结果并不像我所期望的那样,所以我猜想光照方程式中有一个错误。 到目前为止,我得到的是:,c++,graphics,3d,raytracing,lighting,C++,Graphics,3d,Raytracing,Lighting,我使用的是Blinn(-Phong)模型,并假设所有灯光都是点光源。这是我的代码: vec3f raytrace_ray(Scene* scene, ray3f ray) { // get scene intersection auto intersection = intersect_surfaces(scene, ray); // if not hit, return background if (!intersection.hit) { return scene->back
vec3f raytrace_ray(Scene* scene, ray3f ray) {
// get scene intersection
auto intersection = intersect_surfaces(scene, ray);
// if not hit, return background
if (!intersection.hit) {
return scene->background;
}
// accumulate color starting with ambient
vec3f c = zero3f;
c += scene->ambient*intersection.mat->kd;
//Add emission
c += intersection.mat->ke;
// foreach light
for (Light* light : scene->lights) {
// compute light response
auto lightRadiance = light->intensity / distSqr(light->frame.o, intersection.pos);
if(lightRadiance == zero3f) continue;
// compute light direction
auto l = normalize(light->frame.o - intersection.pos);
auto v = normalize(intersection.pos - ray.e);
auto h = normalize(l+v); //bisector
auto n = intersection.mat->n;
auto normal = intersection.norm;
// compute the material response (brdf*cos)
auto brdf = intersection.mat->ks*pow(max(0.0f, dot(normal,h)), intersection.mat->n);
// check for shadows and accumulate if needed
auto shadowRay = ray3f(intersection.pos, l, 0.001f, length(light->frame.o - intersection.pos));
float visibleTerm;
auto shadowIntersect = intersect_surfaces(scene, shadowRay);
if (shadowIntersect.hit) {
visibleTerm = 0;
}
else {
visibleTerm = 1;
}
//Accumulate
c += lightRadiance*visibleTerm*(intersection.mat->kd + brdf)*abs(dot(normal, l));
}
// if the material has reflections
// create the reflection ray
// accumulate the reflected light (recursive call) scaled by the material reflection
// return the accumulated color∫
return c;
}
现在我的问题是:
ray3f reflectionRay = ray3f(intersection.pos, -l + 2 * dot(l, normal)*normal);
c += intersection.mat->kr*raytrace_ray(scene, reflectionRay);
auto normal = transform_normal_inverse(scene->camera->frame, surface->frame.z);
但是我只得到了飞机的另一个倾斜度,而没有解决第二次测试。这是我的交点代码(我只使用了四边形和球体):
intersection3f intersect_曲面(场景*场景,光线3f){
自动相交=相交3f();
浮动电流距离=无穷大;
浮动t;
//前刀面
用于(曲面*曲面:场景->曲面){
//如果它是四边形
如果(曲面->isquad){
///计算光线交点(和光线参数),如果未命中,则继续
自动法线=变换_法线(场景->摄影机->帧、曲面->帧.z);
if(点(光线d,法线)==0){
继续;
}
t=点(表面->帧.o-射线e,法线)/点(射线d,法线);
//检查计算的参数是否在ray.tmin和ray.tmax范围内
如果(tray.tmax)继续;
//检查这是否是最近的交叉口,如果不是,继续
自动p=ray.eval(t);//交点
if(距离(光线e,p)>=当前距离){
继续;
}
当前距离=距离(光线e,p);
//如果命中,则设置交叉点记录值
交叉点.ray_t=t;
交叉点位置=p;
交叉点.norm=规格化(光线.e-p);
intersection.mat=曲面->垫;
intersection.hit=true;
}
//如果它是一个球体
否则{
//计算光线交点(和光线参数),如果未命中,则继续
自动a=长度SQR(射线d);
自动b=2*dot(ray.d,ray.e-surface->frame.o);
自动c=长度SQR(光线.e-表面->帧.o-表面->半径*表面->半径;
自动检测=b*b-4*a*c;
如果(det<0){
继续;
}
浮点数t1=(-b-sqrt(det))/(2*a);
浮点数t2=(-b+sqrt(det))/(2*a);
//检查计算的参数是否在ray.tmin和ray.tmax范围内
如果(t1>=ray.tmin&&t1=ray.tmin&&t2当前距离){
继续;
}
当前距离=距离(光线e,p);
//如果命中,则设置交叉点记录值
交叉点.ray_t=t;
交叉点位置=p;
交叉点.norm=规格化(光线.e-p);
intersection.mat=曲面->垫;
intersection.hit=true;
交点.ray_t=2;
}
}
折返交叉口;
}
提前感谢。关于phong着色模型:它是一个描述光在表面上散射的模型。 因此,每个曲面都有不同的属性,这些属性由环境、漫反射和镜面反射系数表示。 根据您拥有的表面,它们会有所不同(如玻璃、木材等) 表面的环境色类似于对象的最小颜色,即使它被另一个对象遮挡。 基本上,每个对象都有一种颜色,由float(0-1)或int(0-255)表示。 若要应用phong模型的第一部分,假设对象已被遮挡,因为灯光不会到达对象的每一寸。 要应用环境光着色,只需将环境光系数(它是一个曲面属性,通常介于0和1之间)与对象的颜色相乘即可 现在我们需要检查对象是否有阴影。如果对象未被遮挡(并且仅在此时),则需要应用phong模型的其他两个部分,因为它们仅在对象被灯光照射时才相关 漫反射系数是衡量光线散射程度的指标。镜面反射成分是衡量反光度的指标。 有一些近似公式可以有效地计算这两个系数 我从代码中添加了一个摘录来指导您。我截取了很多计算交点和反射光线的代码。 我留下评论是为了让步骤更清楚 从屏幕截图的外观来看,似乎您忘记添加镜面反射组件 如果你还没有听说过,那么你一定要去看看。当我写我的光线跟踪器时,这对我是一个很大的帮助。 注:我不是专家,但我自己写了一个在RayTraceC++在我的空闲时间,所以我试图分享我的经验,因为我遇到了同样的问题,张贴在您的截图。
double ka = 0.1; //ambient coefficient
double kd; //diffuse coefficient
double ks; //specular coefficient
/****** First handle ambient shading ******/
Colour ambient = ka * objectColor; //ambient component
Colour diffuse, specular; // automatically set to 0
double brightness;
localColour = ambient; //localColour is the current colour of the object
/************ Next check wether the object is in shadow or light
* do this by casting a ray from the obj and
* check if there is an intersection with another obj ******/
for(int i = 0; i < objSize; i++)
{//iterate over all lights
if(dynamic_cast<Light *>(objects[i])) //if object is a light
{
//for each light
//create a Ray to light
//its origin is the intersection point
//its direction is the position of the light - intersection
//check for an intersection with a light
//if there is no intersection then we don't need to apply the specular and the diffuse components
if(t_light < 0) //no intersect, which is quite impossible
continue;
//then we check if that Ray intersects one object that is not a light
//we compute the distance to the object and compare it
//to the light distance, for each light seperately
//if it is smaller we know the light is behind the object
//--> shadowed by this light
//we know if inersection is shadowed or not
if(!shadowed)// if obj is not shadowed
{
//-------> //The important part. Adding the diffuse and the specular components.
rRefl = objects[index_nearObj]->calcReflectingRay(rShadow, intersect, normal); //reflected ray from light source, for ks
kd = maximum(0.0, (normal|rShadow.getDirection())); // calculate the diffuse coefficient
//the max of 0 and the cosine of the angle between the direction of the light source and
//the surface normal at the intersection point
ks = pow(maximum(0.0, (r.getDirection()|rRefl.getDirection())), objects[index_nearObj]->getShiny()); //calc the specular component
//the cosine of the angle between the incoming ray and the reflected ray to the power of a material property
diffuse = kd * objectColor; //diffuse colour
specular = ks * objects[i]->getColor(); //specular colour
brightness = 1 /(1 + t_light * DISTANCE_DEPENDENCY_LIGHT);
//Determines the brightness by how far the light source is apart from the object
// 1/(1 + distance to light * parameter)... change the parameter to have a stronger or weaker distance dependency
localColour += brightness * (diffuse + specular); //ADD the diffuse and the specular components to the object
}
}
}
double ka=0.1//环境系数
双kd//扩散系数
双ks//镜面反射系数
/******第一个处理环境光着色******/
环境颜色=ka*对象颜色//环境分量
颜色漫反射、镜面反射;//自动设置为0
双亮度;
本地颜色=环境颜色//LocalColor是对象的当前颜色
/************接下来检查对象是否处于阴影或灯光中
*通过从obj投射光线和
*检查是否与另一个obj相交******/
for(int i=0;i double ka = 0.1; //ambient coefficient
double kd; //diffuse coefficient
double ks; //specular coefficient
/****** First handle ambient shading ******/
Colour ambient = ka * objectColor; //ambient component
Colour diffuse, specular; // automatically set to 0
double brightness;
localColour = ambient; //localColour is the current colour of the object
/************ Next check wether the object is in shadow or light
* do this by casting a ray from the obj and
* check if there is an intersection with another obj ******/
for(int i = 0; i < objSize; i++)
{//iterate over all lights
if(dynamic_cast<Light *>(objects[i])) //if object is a light
{
//for each light
//create a Ray to light
//its origin is the intersection point
//its direction is the position of the light - intersection
//check for an intersection with a light
//if there is no intersection then we don't need to apply the specular and the diffuse components
if(t_light < 0) //no intersect, which is quite impossible
continue;
//then we check if that Ray intersects one object that is not a light
//we compute the distance to the object and compare it
//to the light distance, for each light seperately
//if it is smaller we know the light is behind the object
//--> shadowed by this light
//we know if inersection is shadowed or not
if(!shadowed)// if obj is not shadowed
{
//-------> //The important part. Adding the diffuse and the specular components.
rRefl = objects[index_nearObj]->calcReflectingRay(rShadow, intersect, normal); //reflected ray from light source, for ks
kd = maximum(0.0, (normal|rShadow.getDirection())); // calculate the diffuse coefficient
//the max of 0 and the cosine of the angle between the direction of the light source and
//the surface normal at the intersection point
ks = pow(maximum(0.0, (r.getDirection()|rRefl.getDirection())), objects[index_nearObj]->getShiny()); //calc the specular component
//the cosine of the angle between the incoming ray and the reflected ray to the power of a material property
diffuse = kd * objectColor; //diffuse colour
specular = ks * objects[i]->getColor(); //specular colour
brightness = 1 /(1 + t_light * DISTANCE_DEPENDENCY_LIGHT);
//Determines the brightness by how far the light source is apart from the object
// 1/(1 + distance to light * parameter)... change the parameter to have a stronger or weaker distance dependency
localColour += brightness * (diffuse + specular); //ADD the diffuse and the specular components to the object
}
}
}
Ray rRefl, rRefr; //reflected and refracted Ray
Colour reflectionColour = finalColour, refractionColour = finalColour; //reflected and refrated objects colour;
//initialize them to the background colour
//if there is no intersection of the reflected ray,
//then the backgroundcolour should be returned
double reflectance = 0, transmittance = 0;
//check if obj is reflective, and calc reflection
if(object->isReflective && depth < MAX_TRACE_DEPTH)
{
//handle reflection
rRefl = object->calcReflectingRay(r, intersect, normal);
if(REFL_COLOUR_ADD)//if the reflected colour is added to the object's colour
{
reflectionColour = raytrace(rRefl, depth + 1);//trace the reflected ray
reflectance = 1;
}
else objectColor = raytrace(rRefl, depth + 1);//otherwise set the object's clolour to the reflected colour(eg: Glass)
}
if(object->isRefractive() && depth < MAX_TRACE_DEPTH)
{
//handle transmission
rRefr = object->calcRefractingRay(r, intersect, normal, reflectance, transmittance);
if(rRefr.getDirection() != NullVector) // ignore total inner refl
refractionColour = raytrace(rRefr, depth + 1);//trace the refracted ray
}
//then calculate light ,shading and colour with the phong illumination model
//in the end add the reflected and refracted colours
finalColour = phongColour + transmittance * refractionColour + reflectance * reflectionColour;//Add phong, refraction and reflection
//if transmittance is 0 the object will not let light pass through, if reflectance is 0 the object will not reflect
return finalColour;