当前位置: 首页 > news >正文

泛解析对网站的影响深圳住房和建设局网站轮候大厅

泛解析对网站的影响,深圳住房和建设局网站轮候大厅,苏州公司注册地址,佛山网站建设首选首先#xff0c;让我们获取一个表面法线#xff0c;以便进行着色。这是一个垂直于交点处表面的向量。在我们的代码中#xff0c;我们需要做一个重要的设计决定#xff1a;法线向量是否为任意长度#xff0c;还是将其归一化为单位长度。 诱人的是#xff0c;如果不…        首先让我们获取一个表面法线以便进行着色。这是一个垂直于交点处表面的向量。在我们的代码中我们需要做一个重要的设计决定法线向量是否为任意长度还是将其归一化为单位长度。         诱人的是如果不需要法线向量具有单位长度可以跳过涉及归一化向量的昂贵平方根操作。然而在实践中有三个重要观察结果。首先如果以后需要单位长度的法线向量那么最好一次性完成它而不是为了每个需要单位长度的位置而一次又一次地进行“以防万一”。其次在几个地方我们确实需要单位长度的法线向量。第三如果你需要法线向量具有单位长度那么通常可以通过对特定几何类的构造函数或hit()函数进行理解来有效地生成该向量。例如球体的法线可以通过除以球体半径而完全避免使用平方根来制作单位长度。 鉴于所有这些情况我们将采用所有法线向量都具有单位长度的策略。 对于一个球体而言外向法线是指击中点减去中心点的方向 在球表面上这意味着从球中心指向您的矢量是笔直向上的。现在让我们将其加入代码中并进行着色。我们还没有任何灯光之类的东西所以让我们用颜色映射来可视化法线。一种常见的技巧是将法线的每个分量映射到0到1的区间并将(x,y,z)映射为(red,green,blue)。对于法线我们需要击中点而不仅仅是确定是否击中这是我们目前正在计算的。场景中只有一个球体并且它直接位于相机前方所以我们暂时不用担心t的负值。我们只假设最近的击中点最小的t就是我们想要的。通过对代码进行这些更改我们可以计算并可视化法线n double hit_sphere(const point3 center, double radius, const ray r) { vec3 oc r.origin() - center; auto a dot(r.direction(), r.direction()); auto b 2.0 * dot(oc, r.direction()); auto c dot(oc, oc) - radius*radius; auto discriminant b*b - 4*a*c;if(discriminant 0){return -1.0; } else { return (-b - sqrt(discriminant) ) / (2.0*a); } } color ray_color(const ray r) { Auto t hit_sphere(point3(0,0,-1), 0.5, r); if(t0.0){ vec3 N unit_vector(r.at(t) - vec3(0,0,-1)); return 0.5*color(N.x()1, N.y()1, N.z()1); }vec3 unit_direction unit_vector(r.direction()); auto a 0.5*(unit_direction.y() 1.0); return (1.0-a)*color(1.0, 1.0, 1.0) a*color(0.5, 0.7, 1.0); } 这就是生成的图片   6.2  简化光线与球体相交代码 让我们重新来看一下光线和球体的函数 double hit_sphere(const point3 center, double radius, const ray r) { vec3 oc r.origin() - center; auto a dot(r.direction(), r.direction()); auto b 2.0 * dot(oc, r.direction()); auto c dot(oc, oc) - radius*radius; auto discriminant b*b - 4*a*c; if (discriminant 0) {return -1.0; } else {return (-b - sqrt(discriminant) ) / (2.0*a);} } 光线和球体相交的代码之前 首先回想一下一个向量与自身的点积等于该向量的长度的平方。 其次注意到方程中的b有一个因子为2。考虑一下如果b2h时二次方程会发生什么变化。 我们现在可以将球体相交的代码简化为以下形式 double hit_sphere(const point3 center, double radius, const ray r) { vec3 oc r.origin() - center; auto a r.direction().length_squared(); auto half_b dot(oc, r.direction()); auto c oc.length_squared() - radius*radius; auto discriminant half_b*half_b - a*c; if (discriminant 0) {return -1.0;} else {return (-half_b - sqrt(discriminant) ) / a; } } 6.3  An Abstraction for Hittable Objects 现在多个球体怎么办虽然使用球体数组的方式很诱人但一个非常简洁的解决方案是为光线可能碰到的任何物体创建一个抽象类并将球体和球体列表都视为可击中的物体。关于该抽象类应该被称为什么有点困扰——如果不考虑面向对象编程称之为对象会很好。通常会使用表面Surface一词但它的弱点可能在于我们可能需要处理体积如雾、云等。hittable强调了将它们统一起来的成员函数。我对这些名称都不太满意但我们将采用hittable。 这个hittable抽象类将具有一个接受光线作为参数的hit函数。大多数光线追踪器发现给hit添加一个有效的命中区间tmin至tmax很方便因此只有当tminttmax时命中才会计数。对于初始光线这个区间是正数t但正如我们将看到的将tmin与tmax定义为区间可以简化我们的代码。一个设计问题是是否在命中物体时计算法线。随着搜索的进行我们可能会命中更近的物体而我们只需要最近物体的法线。我将选择简单的解决方案计算一些我将存储在某个结构中的相关信息。以下是这个抽象类的实现 #ifndef HITTABLE_H #define HITTABLE_H#include ray.hclass hit_record { public: point3 p; vec3 normal; double t; };class hittable { public: virtual ~hittable() default; virtual bool hit(const ray r, double ray_tmin, double ray_tmax, hit_record rec) const 0; };#endif 这是球体的实现代码 #ifndef SPHERE_H #define SPHERE_H #include hittable.h #include vec3.hclass sphere : public hittable { public: sphere(point3 _center, double _radius) : center(_center), radius(_radius) {} bool hit(const ray r, double ray_tmin, double ray_tmax, hit_record rec) const override {vec3 oc r.origin() - center;auto a r.direction().length_squared();auto half_b dot(oc, r.direction());auto c oc.length_squared() - radius*radius;auto discriminant half_b*half_b - a*c;if (discriminant 0) return false;auto sqrtd sqrt(discriminant);// Find the nearest root that lies in the acceptable range.auto root (-half_b - sqrtd) / a;if (root ray_tmin || ray_tmax root) {root (-half_b sqrtd) / a;if (root ray_tmin || ray_tmax root)return false; } rec.t root;rec.p r.at(rec.t);rec.normal (rec.p - center) / radius;return true;} private: point3 center; double radius; };#endif Listing 16: [sphere.h] The sphere class   6.4 正面面片与背面面片的区别     关于法线的第二个设计决定是它们是否应该始终指向外部。目前找到的法线始终指向从中心到交点的方向法线指向外部。如果射线从外部与球体相交法线则指向与射线相反的方向。如果射线从内部与球体相交法线始终指向外部则指向与射线相同的方向。或者我们可以让法线始终指向与射线相反的方向。如果射线在球体外部法线将指向外部但如果射线在球体内部法线将指向内部。    图7球体表面法线的可能方向   我们需要从这些可能性中选择一个因为最终我们希望确定射线是从表面的哪一侧射出的。这对于在每一侧上都以不同方式渲染的对象非常重要例如双面纸上的文本或者内外部分明确的玻璃球。 如果我们决定法线始终指向外部那么在给射线上色时我们需要确定射线所在的一侧。我们可以通过将射线与法线进行比较来找到答案。如果射线和法线方向相同射线在物体内部如果射线和法线方向相反射线在物体外部。这可以通过计算这两个向量的点积来确定如果它们的点积为正数那么射线在球体内部。 if (dot(ray_direction, outward_normal) 0.0) { // ray is inside the sphere ...}else { // ray is outside the sphere ...} 如果我们决定法线始终指向逆向的射线我们将无法使用点积来确定射线在表面的哪一侧。相反我们需要存储这个信息 bool front_face; if (dot(ray_direction, outward_normal) 0.0) { // ray is inside the sphere normal -outward_normal; front_face false; } else {// ray is outside the spherenormal outward_normal;front_face true; } 我们可以设置让法线始终从表面“向外”指向或者始终指向入射射线的反方向。这个决定取决于您是想在几何相交时确定表面的哪一侧还是在着色时确定。在本书中我们有比几何类型更多的材质类型所以我们将选择较少的工作量并将确定放在几何时间。这只是一种偏好问题在文献中会看到两种实现方式。 我们在hit_record类中添加了front_face布尔变量。我们还将添加一个函数来解决这个计算set_face_normal()。为了方便起见我们假设传递给新的set_face_normal()函数的向量长度为单位长度。我们可以显式地对参数进行归一化但如果几何代码这样做效率更高因为当您对特定几何有更多了解时通常更容易处理。 class hit_record { public: point3 p; vec3 normal; double t;bool front_face;void set_face_normal(const ray r, const vec3 outward_normal) {// Sets the hit record normal vector.// NOTE: the parameter outward_normal is assumed to have unit length.front_face dot(r.direction(), outward_normal) 0;normal front_face ? outward_normal : -outward_normal; } }; Listing 19: [hittable.h] Adding front-face tracking to hit_record 然后我们将表面边界确定添加到该类中 class sphere : public hittable {public: ...bool hit(const ray r, double ray_tmin, double ray_tmax, hit_record rec) const {...rec.t root;rec.p r.at(rec.t);vec3 outward_normal (rec.p - center) / radius;rec.set_face_normal(r, outward_normal);return true; }... }; Listing 20: [sphere.h] The sphere class with normal determination   6.5 hittable_list 我们有一个名为hittable的通用对象光线可以与其相交。现在我们添加一个类用于存储一系列hittable对象的列表 #ifndef HITTABLE_LIST_H #define HITTABLE_LIST_H#include hittable.h #include memory #include vectorusing std::shared_ptr; using std::make_shared;class hittable_list : public hittable {public: std::vectorshared_ptrhittable objects;hittable_list() { } hittable_list(shared_ptrhittable object) { add(object); }void clear() { objects.clear(); }void add(shared_ptrhittable object) {objects.push_back(object); }bool hit(const ray r, double ray_tmin, double ray_tmax, hit_record rec) const override {hit_record temp_rec;bool hit_anything false;auto closest_so_far ray_tmax;for (const auto object : objects) {if (object-hit(r, ray_tmin, closest_so_far, temp_rec)){hit_anything true;closest_so_far temp_rec.t;rec temp_rec;}}return hit_anything; } }; #endif Listing 21: [hittable_list.h] The hittable_list class   6.6 一些C的新特性    hittable_list 类的代码使用了两个C特性如果你平时不是C程序员可能会遇到困扰vector和shared_ptr。 shared_ptrtype是指向已分配类型的指针具有引用计数语义。每次将其值赋给另一个共享指针通常是简单赋值引用计数就会递增。当共享指针超出范围例如在块或函数的结尾处引用计数就会递减。一旦计数降至零对象就会被安全地删除。 通常共享指针首先使用新分配的对象进行初始化类似于下面的示例 shared_ptrdouble double_ptr make_shareddouble(0.37); shared_ptrvec3 vec3_ptr make_sharedvec3(1.414214, 2.718281, 1.618034); shared_ptrsphere sphere_ptr make_sharedsphere(point3(0,0,0), 1.0); make_sharedthing(thing_constructor_params ...) 分配一个新的 thing 类型的实例使用构造函数参数。它返回一个 shared_ptrthing。 由于类型可以通过 make_sharedtype(...) 的返回类型自动推断出来上述代码可以更简洁地使用 C 的 auto 类型推导器表示如下 auto double_ptr make_shareddouble(0.37); auto vec3_ptr make_sharedvec3(1.414214, 2.718281, 1.618034); auto sphere_ptr make_sharedsphere(point3(0,0,0), 1.0); 在我们的代码中我们将使用 shared_ptr因为它允许多个几何体共享一个公共实例例如一组使用相同颜色材质的球体并且使内存管理自动化并更易于理解。 std::shared_ptr 包含在 memory 头文件中。 第二个您可能不熟悉的 C 特性是 std::vector。它是一个泛型的类似数组的集合可以存储任意类型的元素。在上面的代码中我们使用了一个 hittable 指针的集合。std::vector 会在添加更多值时自动扩展objects.push_back(object) 将一个值添加到 std::vector 成员变量 objects 的末尾。 std::vector 包含在 vector 头文件中。 最后在第21行的 using 语句告诉编译器我们将从 std 库中获取 shared_ptr 和 make_shared因此我们在引用它们时不需要每次都加上 std:: 前缀。   6.7 常见的常量和实用函数 我们需要一些数学常数在它们自己的头文件中方便地进行定义。现在我们只需要无穷大infinity但稍后我们还会在其中添加我们自己对圆周率pi的定义因为我们以后会用到它。关于pi没有标准的可移植定义所以我们只需为其定义我们自己的常量。我们将把常见有用的常数和未来的实用函数放在rtweekend.h中这是我们的主要通用头文件。 #ifndef RTWEEKEND_H #define RTWEEKEND_H#include cmath #include limits #include memory// Usings Using std::shared_ptr; using std::make_shared; using std::sqrt;// Constants const double infinity std::numeric_limitsdouble::infinity(); const double pi 3.1415926535897932385;// Utility Functions inline double degrees_to_radians(double degrees) { return degrees * pi / 180.0; }// Common Headers #include ray.h #include vec3.h#endif 新的main 函数 #include rtweekend.h #include color.h #include hittable.h #include hittable_list.h #include sphere.h#include iostreamdouble hit_sphere(const point3 center, double radius, const ray r) {... }color ray_color(const ray r, const hittable world) { hit_record rec;if (world.hit(r, 0, infinity, rec)) {return 0.5 * (rec.normal color(1,1,1)); }vec3 unit_direction unit_vector(r.direction()); auto a 0.5*(unit_direction.y() 1.0);return (1.0-a)*color(1.0, 1.0, 1.0) a*color(0.5, 0.7, 1.0); }int main() { // Image auto aspect_ratio 16.0 / 9.0; int image_width 400;// Calculate the image height, and ensure that its at least 1. int image_height static_castint(image_width / aspect_ratio); image_height (image_height 1) ? 1 : image_height;// World hittable_list world; world.add(make_sharedsphere(point3(0,0,-1), 0.5)); world.add(make_sharedsphere(point3(0,-100.5,-1), 100));// Camera auto focal_length 1.0; auto viewport_height 2.0; auto viewport_width viewport_height * (static_castdouble(image_width)/image_height); auto camera_center point3(0, 0, 0);// Calculate the vectors across the horizontal and down the vertical viewport edges. auto viewport_u vec3(viewport_width, 0, 0); auto viewport_v vec3(0, -viewport_height, 0);// Calculate the horizontal and vertical delta vectors from pixel to pixel. auto pixel_delta_u viewport_u / image_width; auto pixel_delta_v viewport_v / image_height;// Calculate the location of the upper left pixel. auto viewport_upper_left camera_center - vec3(0, 0, focal_length) - viewport_u/2 - viewport_v/2; auto pixel00_loc viewport_upper_left 0.5 * (pixel_delta_u pixel_delta_v);// Renderstd::cout P3\n image_width image_height \n255\n; for (int j 0; j image_height; j) {std::clog \rScanlines remaining: (image_height - j) std::flush;for (int i 0; i image_width; i) {auto pixel_center pixel00_loc (i * pixel_delta_u) (j * pixel_delta_v);auto ray_direction pixel_center - camera_center;ray r(camera_center, ray_direction); color pixel_color ray_color(r, world);write_color(std::cout, pixel_color);} } std::clog \rDone. \n; } 这会产生一张图片实际上只是一个显示球体位置及其表面法线的可视化图像。这通常是查看几何模型的任何缺陷或特定特征的绝佳方式。Image 5: Resulting render of normals-colored sphere with ground   6.8 An Interval Class 在我们继续之前我们将实现一个区间类来管理具有最小值和最大值的实数区间。随着我们的进展我们将经常使用这个类。  #ifndef INTERVAL_H #define INTERVAL_Hclass interval {public: double min, max;interval() : min(infinity), max(-infinity) {} // Default interval is empty interval(double _min, double _max) : min(_min), max(_max) {}bool contains(double x) const {return min x x max; }bool surrounds(double x) const {return min x x max; }static const interval empty, universe; };const static interval empty (infinity, -infinity); const static interval universe(-infinity, infinity);#endif Listing 26: [interval.h] Introducing the new interval class   class hittable_list : public hittable {public: ... bool hit(const ray r, interval ray_t, hit_record rec) const override {hit_record temp_rec;bool hit_anything false;auto closest_so_far ray_t.max;for (const auto object : objects) {if (object-hit(r, interval(ray_t.min, closest_so_far), temp_rec)) {hit_anything true;closest_so_far temp_rec.t;rec temp_rec;}}return hit_anything; }... }; Listing 29: [hittable_list.h] hittable_list::hit() using interval class sphere : public hittable {public: ... bool hit(const ray r, interval ray_t, hit_record rec) const override {...// Find the nearest root that lies in the acceptable range.auto root (-half_b - sqrtd) / a;if (!ray_t.surrounds(root)) {root (-half_b sqrtd) / a;if (!ray_t.surrounds(root))return false;} ... }... }; Listing 30: [sphere.h] sphere using interval ... color ray_color(const ray r, const hittable world) {hit_record rec;if (world.hit(r, interval(0, infinity), rec)) {return 0.5 * (rec.normal color(1,1,1)); }vec3 unit_direction unit_vector(r.direction());auto a 0.5*(unit_direction.y() 1.0);return (1.0-a)*color(1.0, 1.0, 1.0) a*color(0.5, 0.7, 1.0); } ... Listing 31: [main.cc] The new main using interval
http://www.zqtcl.cn/news/880118/

相关文章:

  • 做外贸什么网站比较好做dede鲜花网站模板下载
  • 网站广告推广怎么做网站怎么优化关键词排名
  • 怎样做易支付网站数字化校园建设网站
  • 东莞做网站哪里好公司网站维护怎么维护
  • 微信网站界面设计江阴网站开发公司电话
  • 手机制作网站的软件离石做网站的网络公司
  • 贺州住房和城乡建设部网站广州商城网站建设地址
  • 响应式网站报价服务器上的wordpress
  • 做培训的都上哪些网站东莞网站新站排名
  • 济南网站制郑州快速建站公司
  • 网站推广企业网站建设属于什么工作
  • 公司做网站还是做app用土豆做美食的视频网站
  • 做网站除了广告还有什么收入的中国计算机技术职业资格网
  • 陕西建设银行网站查排名的软件有哪些
  • 企业网站备案教程北京专业做网站的
  • 音乐网站如何建设的如何做学校网站
  • 济南比较好的网站开发公司个人注册网站怎么注册
  • 济南高端网站设计策划图书馆网站建设情况汇报
  • 知识付费网站建设做网站源码
  • php网站开发实训报告书怎么做兼职类网站吗
  • 建设银行u盾用网站打不开中企动力值不值得入职
  • 织梦做的网站有点慢商贸网站
  • 海外红酒网站建设wordpress 分类 文章
  • 七星彩网站建设wordpress w3
  • 广州网站建设全包百度怎么优化关键词排名
  • 中山网站制作服务公司做环评的网站
  • 江山市住房和城乡建设局网站iis部署网站 错误400
  • 网站域名如何备案建设厅公积金中心网站
  • 网站怎么建设?电子商务网站开发相关技术
  • 苏州网站设计公司济南兴田德润厉害吗python基础教程第3版