提要

经过上次的学习,我们已经可以建立一个简单的光线追踪的场景,接下来,我们继续我们的征程。

今天要得到的最终效果如下:

光线与物体求交

在光线追踪算法中,最重要的就是求光线与物体的相交,也就是实现IntersectResult Object::isIntersected(CRay _ray)方法。  因为我求得交点之后就可以对该点的像素进行计算,然后显示,后续的很多效果(透明,反射....)还有算法的优化加速,都是在对相交算法的改进。

之前已经讨论了光线与球体的相交,今天讨论平面,三角形和多个物体,且不考虑折射和反射。

平面

平面在空间几何中可以用一个向量(法向量)和平面中的一点P0来表示。

平面就是满足下式的点集:n.(P-P0)=0

得到:n.P=d;d=n.P0;

给定射线p(t)=p0+tu,平面方程为n.p+d=0,将p(t)带入到平面方程,最后求得t:

t=(-d-(n.p0))/(n.u)

三角形

渲染中的基本图元 包括点,线,还有三角形,建模中多面体大部分都是用三角形的拼接来表示。

首先来看一下空间三角形的表示。

假设用空间上a,b,c三点来表示一个三角形。

则三角平面内的任意一点可以表示为

法线向量表示为
将光线向量P = e + td带入,得到:
当B>0,r>0且B+r<1的时候,P在三角形内。
对方程进行变换并改写成矩阵的形式:
由克莱莫法则求得B,r,t
其中
 
则三角形和光线求交的伪代码可以表示为:
[cpp]view plaincopy
  1. boolean raytri (ray r, vector3 a, vector3 b, vector3 c, interval [t0 , t1 ])
  2. compute t
  3. if (t < t0 ) or (t > t1 ) then
  4. return false
  5. compute γ
  6. if (γ < 0) or (γ > 1) then
  7. return false
  8. compute β
  9. if (β < 0) or (β > 1 − γ) then
  10. return false
  11. return true

平面多边形

已知条件是平面的m个顶点(p1...pm)还有平面的法向量n。

平面内的向量和法向量时垂直的,即点乘结果为0,可以且接方程:
                         (p − p1 ) · n = 0
其中p = e + td,解得:
这样我们就可以 求得p点,如果p在平面内,则光线与平面相交,否则不相交。
但是如何知道p是否在平面内呢?
siggragh course上的解决方法是:从相交点往平面内的任意方向做一条射线,如果射线与多边形的边的交点数量为奇数则p在平面内,否则在平面外。
这个很好理解,用笔画一下 就知道了。
一个场景
 一个场景包含很多个图元,球体,正方体。。。
 回到光线追踪的原理,从摄像机发射一条射线之后,当场景中只有单个物体,只需计算一个,就可以得到一个result,当场景中又多个物体的时候,我们需要做的就是计算多次,取距离最近的那个result。
伪代码
[cpp]view plaincopy
  1. hit = false
  2. for each object o in the group do
  3. if (o is hit at ray parameter t and t ∈ [t0 , t1 ]) then
  4. hit = true
  5. hitobject = o
  6. t1 = t
  7. return hit

平面类的实现

平面类我们就可以用代码这样来描述:

[cpp]view plaincopy
  1. <span style="font-size:14px;">#ifndef Plane_H
  2. #define Plane_H
  3. #include "gvector3.h"
  4. #include "intersectresult.h"
  5. #include "cray.h"
  6. #include "checkermaterial.h"
  7. #include "cobject.h"
  8. class Plane:public CObject
  9. {
  10. public:
  11. Plane();
  12. Plane(const GVector3& _normal,float _d);
  13. virtual ~Plane();
  14. virtual IntersectResult isIntersected(CRay& RAY);
  15. protected:
  16. private:
  17. //法向量
  18. GVector3 normal;
  19. //到原点的距离
  20. float d;
  21. };
  22. #endif // Plane_H
  23. </span>

接下来是求光线到平面的距离。

代码实现如下:

[cpp]view plaincopy
  1. <span style="font-size:14px;">#include "plane.h"
  2. Plane::Plane()
  3. {
  4. //ctor
  5. }
  6. Plane::~Plane()
  7. {
  8. //dtor
  9. }
  10. Plane::Plane(const GVector3& _normal,float _d)
  11. {
  12. normal=_normal;
  13. d=_d;
  14. }
  15. IntersectResult Plane::isIntersected(CRay& ray)
  16. {
  17. IntersectResult result = IntersectResult::noHit();
  18. float a = ray.getDirection().dotMul(this->normal);
  19. if (a <0)
  20. {
  21. result.isHit=1;
  22. result.object = this;
  23. float b = this->normal.dotMul(ray.getOrigin()-normal*d);
  24. result.distance = -b / a;
  25. result.position = ray.getPoint(result.distance);
  26. result.normal = this->normal;
  27. return result;
  28. }
  29. }
  30. </span>

接下来我们在场景中创建一个平面,然后渲染深度,得到下面的效果:

材质

在真实世界中,白色物体在绿光照射下看起来是绿色而不是白色,红色物体在绿光照射下看起来是黑色,而有的同样颜色的物体在同样的光照下亮度却不同,这都是由物体的材质不同造成的。
首先在项目中添加一个颜色类,然后定义一些方法。

color.h

[cpp]view plaincopy
  1. #ifndef COLOR_H
  2. #define COLOR_H
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <cmath>
  6. #include <iostream>
  7. using namespace std;
  8. class Color
  9. {
  10. public:
  11. float r;
  12. float g;
  13. float b;
  14. Color();
  15. Color(float _r,float _g,float _b);
  16. Color add(const Color& c);
  17. Color multiply(float s) const;
  18. Color modulate(const Color& c) const;
  19. void saturate();
  20. void show();
  21. virtual ~Color();
  22. static inline Color black(){ return Color(0,0,0); }
  23. static inline Color white(){ return Color(1,1,1); }
  24. static inline Color red()  { return Color(1,0,0); }
  25. static inline Color green(){ return Color(0,1,0); }
  26. static inline Color blue() { return Color(0,0,1); }
  27. protected:
  28. private:
  29. };
  30. #endif // COLOR_H

color.cpp

[cpp]view plaincopy
  1. #include "color.h"
  2. Color::Color()
  3. {
  4. //ctor
  5. }
  6. Color::~Color()
  7. {
  8. //dtor
  9. }
  10. Color::Color(float _r,float _g,float _b)
  11. {
  12. r=_r;g=_g;b=_b;
  13. }
  14. Color Color::add(const Color& c)
  15. {
  16. return Color(r + c.r, g + c.g, b + c.b);
  17. }
  18. Color Color::multiply(float s) const
  19. {
  20. return Color(r * s, g * s, b * s);
  21. }
  22. Color Color::modulate(const Color&c) const
  23. {
  24. return Color(r * c.r, g * c.g, b * c.b);
  25. }
  26. void Color::saturate()
  27. {
  28. r = r>1.0?1.0:r;
  29. g = g>1.0?1.0:g;
  30. b = b>1.0?1.0:b;
  31. }
  32. void Color::show()
  33. {
  34. cout<<"r:"<<r<<"g:"<<g<<"b:"<<b<<endl;
  35. }

然后是定义一个材质的基类,后面要实现的各种材质都继承它:

material.h

[cpp]view plaincopy
  1. #ifndef Material_H
  2. #define Material_H
  3. #include "gvector3.h"
  4. #include "intersectresult.h"
  5. #include "cray.h"
  6. #include "color.h"
  7. class Material
  8. {
  9. public:
  10. Material();
  11. Material(float _reflectiveness);
  12. float getRef();
  13. void setRef(float _reflectiveness);
  14. virtual ~Material();
  15. virtual Color sample(const CRay& ray,const GVector3& position,const GVector3& normal);
  16. protected:
  17. float reflectiveness;
  18. private:
  19. };
  20. #endif // Material_H

material.cpp

[cpp]view plaincopy
  1. #include "material.h"
  2. Material::Material()
  3. {
  4. //ctor
  5. }
  6. Material::Material(float _reflectiveness)
  7. {
  8. reflectiveness=_reflectiveness;
  9. }
  10. Material::~Material()
  11. {
  12. //dtor
  13. }
  14. float Material::getRef()
  15. {
  16. return reflectiveness;
  17. }
  18. void Material::setRef(float _reflectiveness)
  19. {
  20. reflectiveness=_reflectiveness;
  21. }
  22. Color Material::sample(const CRay& ray,const GVector3& position,const GVector3& normal)
  23. {
  24. cout<<"Base sample!"<<endl;
  25. }

实现两种材质,一种是棋盘材质,一种phong材质。

checkermaterial.h

[cpp]view plaincopy
  1. #ifndef CHECKERMATERIAL_H
  2. #define CHECKERMATERIAL_H
  3. #include "material.h"
  4. #include "color.h"
  5. #include <stdlib.h>
  6. class CheckerMaterial:public Material
  7. {
  8. public:
  9. CheckerMaterial();
  10. CheckerMaterial(float _scale,float _reflectiveness=0);
  11. virtual ~CheckerMaterial();
  12. virtual Color sample(const CRay& ray,const GVector3& position,const GVector3& normal);
  13. protected:
  14. private:
  15. float scale;
  16. };
  17. #endif // CHECKERMATERIAL_H

checkermaterial.cpp

[cpp]view plaincopy
  1. #include "checkermaterial.h"
  2. CheckerMaterial::CheckerMaterial()
  3. {
  4. //ctor
  5. }
  6. CheckerMaterial::CheckerMaterial(float _scale,float _reflectiveness)
  7. {
  8. scale=_scale;
  9. reflectiveness=_reflectiveness;
  10. }
  11. CheckerMaterial::~CheckerMaterial()
  12. {
  13. //dtor
  14. }
  15. Color CheckerMaterial::sample(const CRay& ray,const GVector3& position,const GVector3& normal)
  16. {
  17. float d=abs((floor(position.x * this->scale) + floor(position.z * this->scale)));
  18. d=fmod(d,2);
  19. return  d < 1 ? Color::black() : Color::white();
  20. }

phongmaterial.h

[cpp]view plaincopy
  1. #ifndef PHONGMATERIAL_H
  2. #define PHONGMATERIAL_H
  3. #include"gvector3.h"
  4. #include "color.h"
  5. #include "cray.h"
  6. #include "material.h"
  7. // global temp
  8. static GVector3 lightDir = GVector3(1, 1, 1).normalize();
  9. static Color lightColor = Color::white();
  10. class PhongMaterial:public Material
  11. {
  12. public:
  13. PhongMaterial();
  14. PhongMaterial(const Color& _diffuse,const Color& _specular,const float& _shininess,float _reflectiveness=0);
  15. virtual Color sample(const CRay& ray,const GVector3& position,const GVector3& normal);
  16. virtual ~PhongMaterial();
  17. protected:
  18. private:
  19. Color   diffuse;
  20. Color   specular;
  21. float   shininess;
  22. };
  23. #endif // PHONGMATERIAL_H

phongmaterial.cpp

[cpp]view plaincopy
  1. #include "phongmaterial.h"
  2. PhongMaterial::PhongMaterial()
  3. {
  4. //ctor
  5. }
  6. PhongMaterial::PhongMaterial(const Color& _diffuse,const Color& _specular,const float& _shininess,float _reflectiveness)
  7. {
  8. diffuse=_diffuse;
  9. specular=_specular;
  10. shininess=_shininess;
  11. reflectiveness=_reflectiveness;
  12. }
  13. PhongMaterial::~PhongMaterial()
  14. {
  15. //dtor
  16. }
  17. Color PhongMaterial::sample(const CRay& ray,const GVector3& position,const GVector3& normal)
  18. {
  19. float NdotL = normal.dotMul(lightDir);
  20. GVector3 H = (lightDir-ray.getDirection()).normalize();
  21. float NdotH = normal.dotMul(H);
  22. Color diffuseTerm = this->diffuse.multiply(std::max(NdotL, (float)0));
  23. Color specularTerm = this->specular.multiply(pow(std::max(NdotH, (float)0), this->shininess));
  24. return lightColor.modulate(diffuseTerm.add(specularTerm));
  25. }

试着来渲染一下。

[cpp]view plaincopy
  1. void renderDepth()
  2. {
  3. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  4. glLoadIdentity();                                   // Reset The View
  5. glTranslatef(-0.5f,-0.5f,-1.0f);
  6. glPointSize(2.0);
  7. PerspectiveCamera camera( GVector3(0, 10, 10),GVector3(0, -0.5, -1),GVector3(0, 1, 0), 90);
  8. Plane plane1(GVector3(0, 1, 0),1.0);
  9. CSphere sphere1(GVector3(0, 5, -10), 5.0);
  10. plane1.material=new CheckerMaterial(0.1f);
  11. sphere1.material=new PhongMaterial(Color::red(), Color::white(), 16);
  12. long maxDepth=20;
  13. float dx=1.0f/WINDOW_WIDTH;
  14. float dy=1.0f/WINDOW_HEIGHT;
  15. float dD=255.0f/maxDepth;
  16. glBegin(GL_POINTS);
  17. for (long y = 0; y < WINDOW_HEIGHT; ++y)
  18. {
  19. float sy = 1 - dy*y;
  20. for (long x = 0; x < WINDOW_WIDTH; ++x)
  21. {
  22. float sx =dx*x;
  23. CRay ray(camera.generateRay(sx, sy));
  24. IntersectResult result = sphere1.isIntersected(ray);
  25. //IntersectResult result = plane1.isIntersected(ray);
  26. if (result.isHit)
  27. {
  28. Color color = sphere1.material->sample(ray, result.position, result.normal);
  29. //Color color =plane1.material->sample(ray, result.position, result.normal);
  30. color.saturate();
  31. //color.show();
  32. glColor3ub(color.r*255,color.g*255,color.b*255);
  33. glVertex2f(sx,sy);
  34. }
  35. }
  36. }
  37. glEnd();
  38. // 交换缓冲区
  39. glfwSwapBuffers();
  40. }

结果如下:

材质这一块有很多东西可以来探讨,而且它和光照联系的很紧密,这里先不探讨。

联合

之前的渲染测试我们都只渲染了单个的物体,现在我们需要在场景中显示多个物体,就上开篇的那副图一样。

创建一个union类,在渲染的时候将要渲染的东西都丟进去。

union.h

[cpp]view plaincopy
  1. #ifndef UNION_H
  2. #define UNION_H
  3. #include "cobject.h"
  4. #include <vector>
  5. using namespace std;
  6. class Union:public CObject
  7. {
  8. public:
  9. Union();
  10. virtual ~Union();
  11. void push(CObject* object);
  12. virtual IntersectResult isIntersected(CRay& _ray);
  13. protected:
  14. private:
  15. vector<CObject*> cobjects;
  16. };
  17. #endif // UNION_H

union.cpp

[cpp]view plaincopy
  1. #include "union.h"
  2. Union::Union()
  3. {
  4. //ctor
  5. }
  6. Union::~Union()
  7. {
  8. //dtor
  9. }
  10. void Union::push(CObject* object)
  11. {
  12. cobjects.push_back(object);
  13. }
  14. IntersectResult Union::isIntersected(CRay& _ray)
  15. {
  16. const float Infinity=1e30;
  17. float minDistance = Infinity;
  18. IntersectResult minResult = IntersectResult::noHit();
  19. long size=this->cobjects.size();
  20. for (long i=0;i<size;++i){
  21. IntersectResult result = this->cobjects[i]->isIntersected(_ray);
  22. if (result.object && (result.distance < minDistance)) {
  23. minDistance = result.distance;
  24. minResult = result;
  25. }
  26. }
  27. return minResult;
  28. }

最后的渲染代码

[cpp]view plaincopy
  1. void renderUnion()
  2. {
  3. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  4. glLoadIdentity();                                   // Reset The View
  5. glTranslatef(-0.5f,-0.5f,-1.0f);
  6. glPointSize(2.0);
  7. PerspectiveCamera camera( GVector3(0, 10, 10),GVector3(0, -0.5, -1),GVector3(0, 1, 0), 90);
  8. Plane* plane1=new Plane(GVector3(0, 1, 0),1.0);
  9. CSphere* sphere1=new CSphere(GVector3(-2, 5, -10), 5.0);
  10. CSphere* sphere2=new CSphere(GVector3(5, 5, -10), 3.0);
  11. plane1->material=new CheckerMaterial(0.1f);
  12. sphere1->material=new PhongMaterial(Color::red(), Color::white(), 16);
  13. sphere2->material=new PhongMaterial(Color::blue(), Color::white(), 16);
  14. Union scence;
  15. scence.push(plane1);
  16. scence.push(sphere1);
  17. scence.push(sphere2);
  18. long maxDepth=20;
  19. float dx=1.0f/WINDOW_WIDTH;
  20. float dy=1.0f/WINDOW_HEIGHT;
  21. float dD=255.0f/maxDepth;
  22. glBegin(GL_POINTS);
  23. for (long y = 0; y < WINDOW_HEIGHT; ++y)
  24. {
  25. float sy = 1 - dy*y;
  26. for (long x = 0; x < WINDOW_WIDTH; ++x)
  27. {
  28. float sx =dx*x;
  29. CRay ray(camera.generateRay(sx, sy));
  30. IntersectResult result = scence.isIntersected(ray);
  31. //IntersectResult result = plane1.isIntersected(ray);
  32. if (result.isHit)
  33. {
  34. Color color = result.object->material->sample(ray, result.position, result.normal);
  35. //Color color =plane1.material->sample(ray, result.position, result.normal);
  36. color.saturate();
  37. //color.show();
  38. glColor3ub(color.r*255,color.g*255,color.b*255);
  39. glVertex2f(sx,sy);
  40. }
  41. }
  42. }
  43. glEnd();
  44. // 交换缓冲区
  45. glfwSwapBuffers();
  46. }

运行结果

最后我们来加一点反射的效果,在main.cpp中添加一个函数。

[cpp]view plaincopy
  1. Color rayTraceRecursive(CObject* scene,CRay& ray,long maxReflect)
  2. {
  3. IntersectResult result = scene->isIntersected(ray);
  4. if (result.object)
  5. {
  6. float reflectiveness = result.object->material->getRef();
  7. Color color = result.object->material->sample(ray, result.position, result.normal);
  8. color = color.multiply(1 - reflectiveness);
  9. if ((reflectiveness > 0) && (maxReflect > 0))
  10. {
  11. GVector3 r = result.normal*(-2 * result.normal.dotMul(ray.getDirection()))+ray.getDirection();
  12. CRay ray = CRay(result.position, r);
  13. Color reflectedColor = rayTraceRecursive(scene, ray, maxReflect - 1);
  14. color = color.add(reflectedColor.multiply(reflectiveness));
  15. }
  16. return color;
  17. }else return Color::black();
  18. }

渲染一下

[cpp]view plaincopy
  1. void renderRecursive()
  2. {
  3. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  4. glLoadIdentity();                                   // Reset The View
  5. glTranslatef(-0.5f,-0.5f,-1.0f);
  6. glPointSize(2.0);
  7. PerspectiveCamera camera( GVector3(0, 10, 10),GVector3(0, -0.5, -1),GVector3(0, 1, 0), 90);
  8. Plane* plane1=new Plane(GVector3(0, 1, 0),1.0);
  9. CSphere* sphere1=new CSphere(GVector3(-2, 5, -2), 4.0);
  10. CSphere* sphere2=new CSphere(GVector3(5, 5, -7), 3.0);
  11. plane1->material=new CheckerMaterial(0.1f,0.5f);
  12. sphere1->material=new PhongMaterial(Color::red(), Color::white(), 16,0.25);
  13. sphere2->material=new PhongMaterial(Color::green(), Color::white(), 16,0.25);
  14. Union scene;
  15. scene.push(plane1);
  16. scene.push(sphere1);
  17. scene.push(sphere2);
  18. long maxDepth=20;
  19. long maxReflect=5;
  20. float dx=1.0f/WINDOW_WIDTH;
  21. float dy=1.0f/WINDOW_HEIGHT;
  22. float dD=255.0f/maxDepth;
  23. glBegin(GL_POINTS);
  24. for (long y = 0; y < WINDOW_HEIGHT; ++y)
  25. {
  26. float sy = 1 - dy*y;
  27. for (long x = 0; x < WINDOW_WIDTH; ++x)
  28. {
  29. float sx =dx*x;
  30. CRay ray(camera.generateRay(sx, sy));
  31. IntersectResult result = scene.isIntersected(ray);
  32. //IntersectResult result = plane1.isIntersected(ray);
  33. if (result.isHit)
  34. {
  35. Color color = rayTraceRecursive(&scene, ray, maxReflect);
  36. //Color color = result.object->material->sample(ray, result.position, result.normal);
  37. //Color color =plane1.material->sample(ray, result.position, result.normal);
  38. color.saturate();
  39. //color.show();
  40. glColor3ub(color.r*255,color.g*255,color.b*255);
  41. glVertex2f(sx,sy);
  42. }
  43. }
  44. }
  45. glEnd();
  46. // 交换缓冲区
  47. glfwSwapBuffers();
  48. }

结果就是最上面的那幅图了。

结语

以前自己只玩过一些opengl的东西,不过那些都有现成的接口让你掉,原理上也不用理解得很深,往往一两句语句就可以实现一个简单的效果。

而现在,从原理到实现,每一句代码都需要先在真实世界中想清楚,然后抽象成代码,不管对编程技巧还是数学功底都会有很高的要求,所以在编写这些代码的时候我又回头去看C++ primer,学线性代数。。当然收获也很大。

源码可以点这里下载。

参考

用JavaScript玩转计算机图形学(一)光线追踪入门-http://www.cnblogs.com/miloyip/archive/2010/03/29/1698953.html
光线追踪技术的理论和实践(面向对象)-http://blog.csdn.net/zhangci226/article/details/5664313
Wikipedia, Ray Tracing
计算机图形学(第三版)(美)赫恩 著,(美)巴克 著。

Ray Object Intersections - http://siggraph.org/education/materials/HyperGraph/raytrace/rtinter0.htm

光线追踪(RayTracing)算法理论与实践(二)平面、材质、联合光线与物体求交相关推荐

  1. 光线追踪(RayTracing)算法理论与实践(三)光照

    提要 经过之前的学习,我们已经可以在利用光线追踪实现一些简单的场景.今天我们要探讨的是图形学里面的三种基本光源:方向光源,点光源,聚光灯. 不同于利用现成的Api,这次会从理论到实际一步步用C++实现 ...

  2. 光线追踪技术的理论和实践(面向对象)

    光线追踪技术的理论和实践(面向对象) 收藏 此文于2010-06-18被推荐到CSDN首页 如何被推荐? *原创文章,转载请注明出处* 光线追踪技术的理论和实践(面向对象) Theory & ...

  3. 光线追踪技术的理论和实践(面向对象)【转载】

    光线追踪技术的理论和实践(面向对象) Theory & Practice of Raytracing(Object Oriented) 介绍   这篇文章将介绍光线追踪技术.在计算机图形领域中 ...

  4. ROS理论与实践——二、ROS基础

    ROS理论与实践--二.ROS基础 前言 一.创建工作空间 1 什么是工作空间 2 创建流程 二.创建功能包 1 创建命令 2 创建流程 三.ROS通信编程 1 话题编程 1.1 话题编程流程 1.2 ...

  5. 万字长文详解文本抽取:从算法理论到实践

    导读:"达观杯"文本智能信息抽取挑战赛已吸引来自中.美.英.法.德等26个国家和地区的2400余名选手参赛,目前仍在火热进行中(点击阅读原文进入比赛页面,QQ群见上图或文末二维码) ...

  6. ​万字长文详解文本抽取:从算法理论到实践(附“达观杯”官方baseline实现解析及答疑)...

    [ 导读 ]"达观杯"文本智能信息抽取挑战赛已吸引来自中.美.英.法.德等26个国家和地区的2400余名选手参赛,目前仍在火热进行中(点击"阅读原文"进入比赛页 ...

  7. 吴恩达机器学习系列理论加实践(二 、单变量线性回归及matlab实践)

    二.单变量线性回归 2.1模型表示 同样以之前的房屋价格预测实例开始: 通过学习算法利用训练集训练模型h,对于新输入的数据size of house就可以输出其预测值price: 如何表达这个模型h: ...

  8. Online Learning算法理论与实践

    Online Learning是工业界比较常用的机器学习算法,在很多场景下都能有很好的效果.本文主要介绍Online Learning的基本原理和两种常用的Online Learning算法:FTRL ...

  9. Chapter 12 PCA与SVD算法理论与实践

    前言 ​ 最近,在学习机器学习算法时,看到了PCA(主成分分析)和SVD(奇异值分解),这是两个基本数据降维的算法,而在降维算法中的"降维"主要是指降低特征矩阵中特征数量的维度,直 ...

  10. 光线追踪RayTracing,基本原理,判断物体与光线相交

    光线的三点假设: 光线按直线传播 光线之间不会发生碰撞 光线会经过一系列折射反射进入摄像机 可以从摄像机发出光线,推出可逆的光路 上图中,透明球在与相机直连的线条处,需要将折射和反射的着色点结果相加, ...

最新文章

  1. mysql 集合减法_7 SQL 集合运算
  2. mac平台反编译apk,获取源码,androidmanifest和资源文件
  3. ---随心买统计查询
  4. matlab画倾斜的椭球,在MATLAB中绘制椭圆和椭球
  5. 从迁移到Java 7的小技巧
  6. C语言——找出矩阵最大值
  7. 【腾讯出品】2019互联网行业趋势报告
  8. 拼多多12.12“全民真香节”启动 “真香”农货成为核心与亮点
  9. SpaceX载人龙飞船将于11月份进行首次环绕国际空间站飞行
  10. 【报告分享】2020年中国企业直播服务市场研究报告.pdf(附下载链接)
  11. 美国网站服务器有哪些,可以搭建什么网站?
  12. 计算机网络七版pdf
  13. 【期刊会议系列】IEEE系列模板下载指南
  14. bootstrap 页面垂直居中_bootstrap div垂直居中+水平居中保持响应式
  15. [Kaldi] MFCC特征提取源码详解
  16. 神经网络拓扑图怎么画,神经网络和图神经网络
  17. 专家有料 | 张祖优:腾讯云DevSecOps实践与开源治理探索
  18. vSphere高级功能(一)——VMotion及SVMotion的实现
  19. vs点击方法跳不到对于的地方_【阿司足球】今天带来一场欧国联的比赛,比利时VS冰岛...
  20. Ubuntu+Pytorch开发入门整理——环境搭建

热门文章

  1. 虚拟机连接本地sql服务器,如何从Mac连接到虚拟机上的本地数据库?(平行线)...
  2. Redis内存碎片处理
  3. 【入门篇】SIP 协议详解
  4. 多种方法破解Windows 系统密码
  5. 国产数据库清单(2020年第1季度)
  6. 您好,我想请问为什么地理空间数据云下载解压后只有一个文件格式,不是说有七八个段波样子的文件嘛,你们是怎么解决的呢,感谢回复
  7. 番外5. Python OpenCV 中滑动条详细说明与常见问题解决方案
  8. 越狱环境下代码控制手机重启(IOS,XCODE)
  9. Mujoco模型学习记录
  10. Houdini工程文件合集