- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试用 C++ 编写光线追踪器,但到目前为止的结果与我预期的不一样,所以我猜光照方程式中存在错误。这是我到目前为止所得到的:
Picture of my result. In the upper line what I've got, in the bottom line what I would like to get
我正在使用 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->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;
}
现在我的问题是:
如何进一步添加反射和折射?我知道我必须递归调用该函数,但首先我必须计算什么以及以何种方式计算?我尝试使用此代码在灯光的 for 循环中进行反射,但在某些无限递归测试中它不起作用:
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_surfaces(Scene* scene, ray3f ray) {
auto intersection = intersection3f();
float currentDistance = INFINITY;
float t;
// foreach surface
for (Surface* surface : scene->surfaces) {
// if it is a quad
if (surface->isquad) {
/// compute ray intersection (and ray parameter), continue if not hit
auto normal = transform_normal(scene->camera->frame, surface->frame.z);
if (dot(ray.d, normal) == 0) {
continue;
}
t = dot(surface->frame.o - ray.e, normal)/dot(ray.d,normal);
// check if computed param is within ray.tmin and ray.tmax
if (t < ray.tmin or t > ray.tmax) continue;
// check if this is the closest intersection, continue if not
auto p = ray.eval(t);//Intersection point
if (dist(ray.e, p) >= currentDistance) {
continue;
}
currentDistance = dist(ray.e, p);
// if hit, set intersection record values
intersection.ray_t = t;
intersection.pos = p;
intersection.norm = normalize(ray.e - p);
intersection.mat = surface->mat;
intersection.hit = true;
}
// if it is a sphere
else {
// compute ray intersection (and ray parameter), continue if not hit
auto a = lengthSqr(ray.d);
auto b = 2 * dot(ray.d, ray.e - surface->frame.o);
auto c = lengthSqr(ray.e - surface->frame.o) - surface->radius*surface->radius;
auto det = b*b - 4 * a*c;
if (det < 0) {
continue;
}
float t1 = (-b - sqrt(det)) / (2 * a);
float t2 = (-b + sqrt(det)) / (2 * a);
// check if computed param is within ray.tmin and ray.tmax
if (t1 >= ray.tmin && t1 <= ray.tmax) t = t1;
else if (t2 >= ray.tmin && t2 <= ray.tmax) t = t2;
else continue;
auto p = ray.eval(t); //Intersection point
// check if this is the closest intersection, continue if not
if (dist(ray.e, p) > currentDistance) {
continue;
}
currentDistance = dist(ray.e, p);
// if hit, set intersection record values
intersection.ray_t = t;
intersection.pos = p;
intersection.norm = normalize(ray.e - p);
intersection.mat = surface->mat;
intersection.hit = true;
intersection.ray_t = 2;
}
}
return intersection;
}
提前致谢。
最佳答案
关于 phong 着色模型:它是描述光在表面上的散射的模型。因此,每个表面都有不同的属性,这些属性由环境系数、漫反射系数和镜面反射系数表示。根据您拥有的表面,它们会有所不同(例如玻璃、木材……)
表面的环境颜色就像对象具有的最小颜色,即使它被另一个对象遮挡也是如此。基本上每个对象都有一种颜色,由 float (0 - 1) 或整数 (0 - 255) 表示。要应用 phong 模型的第一部分,您假设对象被遮蔽,因为光线不会到达对象的每一英寸。要应用环境光着色,您只需将环境系数(它是一个表面属性,通常在 0 到 1 之间)乘以对象的颜色。
现在我们需要检查对象是否被遮蔽。如果物体没有被遮蔽(并且只有这样),您需要应用 phong 模型的其他两个部分,因为它们仅在物体被光线照射时才相关。
漫射系数是光散射程度的量度。镜面反射分量是反光度的量度。有一些近似公式可以有效地计算这两个系数。
我添加了一段代码摘录来指导您。我删掉了很多计算交点和反射光线的代码。我留下了评论以明确步骤。
从您的屏幕截图来看,您似乎忘记了添加镜面反射组件。
如果您还没有听说过 http://scratchapixel.com ,那么你一定要检查一下。当我编写我的 raytracer 时,它对我有很大的帮助。注意:我不是专家,但我自己在空闲时间用 C++ 编写了一个 raytracer,所以我尝试分享我的经验,因为我遇到了与您的屏幕截图中相同的问题。
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;
很抱歉这个问题的简短回答,但时间不早了,我也变得懒惰了。当我有更多时间时,我会再次入住。我希望我能帮上一点忙。
关于c++ - 光线追踪 - 光照方程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33054399/
我正在开发一个网站,在不使用任何第三方 API 的情况下使用 Firebase 云消息传递(Chrome 和 Firefox 浏览器)向我的订阅者发送推送通知。推送通知发送工作正常,但我不知道“如何跟
我在尝试追踪此 OutOfMemoryError 时遇到了非常糟糕的时间,非常感谢您的帮助。我的应用程序分为架构部分和一个模块,该模块公开一些基本的 REST WS 以及 Hibernate 进行的数
在 Android 操作系统源代码中(路径:/drivers/staging/android/binder_trace.h),我们有一个名为 binder_trace.h 的文件,并且在 /drive
我正在查看我的 CakePHP 应用程序的 error.log,并看到我定期收到此类信息: 2011-07-28 14:49:39 Warning: Warning (2): Missing argu
我收到了有关我的应用程序中内存泄漏的报告,但我无法准确追踪到底发生了什么。我有一个功能可以取出旧 View 并交换新 View 。我没有使用 NavControllers 或任何 @propertie
这是真气! >_< 我编写了一个庞大而复杂的 Haskell 库。我写了一个小测试程序,到目前为止,我已经花了大约 8 个小时试图弄清楚为什么它一直在我身上崩溃。有时 GHC 会提示“奇怪的封闭类型”
是否有系统的方法来调试导致组件在 React 中重新渲染的原因?我放置了一个简单的 console.log() 来查看它渲染了多少次,但我很难弄清楚是什么导致组件渲染多次,即在我的情况下(4 次)。是
我已经升级到 Django 1.4,现在当我运行我的开发服务器时,我收到以下警告: /home/flc/venvs/myprj/lib/python2.6/site-packages/django/v
我有一个 Web 应用程序在某处存在内存泄漏,但我无法检测到它。我已经尝试过 Chrome 开发者工具,通常效果很好,但我无法追踪负责的代码行。 Chrome 工具给了我太多信息,我无法将内存中的对象
直接从标记调用函数的好处之一是更容易跟踪所调用的内容。我想知道是否有浏览器插件或其他东西支持附加(绑定(bind))到元素的每个事件的“Goto javascript 源函数”。理想情况下,这会将我带
我在工作中使用 darcs 已经一年多了,但我一直在问自己同样的问题: 跟踪导致两个补丁之间依赖的代码行/文件/代码更改的最佳方法是什么?目前我的做法如下: 我使用 darcs changes -i
我知道以前有人问过此类问题,但我无法解决我的疑问。我有一个简单的黑白棋引擎(实际上它玩得很好),它使用下面的类来获得最佳棋步: import java.util.*; import java.util
上下文:我们正在构建用于快速交付 WPF 应用程序的框架。该框架使用 Autofac 作为 IoC 容器,还使用 Prism v1 中的区域。我们正在使用 Microsoft 的并行扩展来安排任务
有什么追踪东西的技巧吗?技术?任何可用于检查函数 x 的调用者的工具(调用堆栈的某些部分显示为 ??? 或被跳过)。 --track-origins=yes 是否会使速度变慢(当我尝试这样做时,我使用
我有一个基于 KnockoutJS 2.2.1 创建的 jQuery 网格插件。到目前为止它进展顺利,但是当插件在一个元素上初始化时,'computed' loadGrid 方法调用 3 次。 为了说
我是这种开发的新手。我正在尝试创建一个涉及 GPS 跟踪的 android 应用程序。我正在使用 Nutiteq,因为我必须使用 openstreetmap 作为默认 map 。请帮助我。 最佳答案
我希望用户能够通过我的应用程序之一跟踪他们的 friend 。该应用程序适用于音乐节。 我一直在想办法做到这一点: 让用户为设备设置昵称(与 UDID 关联),并让用户通过昵称将彼此添加到“好友列表”
有没有办法找到所有者或域名示例,如果我给谷歌的IP,我的工具发现谷歌的IP,这应该以编程方式完成地址最喜欢的编程语言将是VC++其他语言也不是问题 最佳答案 您正在寻找的关键字似乎是WHOIS 通常可
我的 VC++ 项目中有几个包含大量类的 map ,其中一些默认可构造,另一些则不能。尝试构建时,出现“没有合适的默认构造函数可用”错误。问题是错误被列为发生在 map.cpp 的第 173 行,这是
我平均工作(约 20k 行代码,Objective-C 与 C++ 混合),我正在努力寻找 EXC_BAD_ACCESS 错误。 我已经尝试了所有常见的技术(比如启用 NSZombie、guard e
我是一名优秀的程序员,十分优秀!