光
光在我们周围无处不在,光学成像技术也和我们的生活密不可分,如各种相机、摄像机、望远镜、投影仪等;
在现实中,人、相机以及各种各样的采集显示世界信息的收影设施都是通过收集物体反射到人眼中的光线在底板上成像;参考小孔成像,一些照相机和摄影机就是利用了小孔成像的原理——镜头是小孔(大多数安装凸透镜以保证光线成像距离),景物通过小孔进入暗室,像被一些特殊的化学物质(如卤化银等)留在胶片上(数码相机、摄影机等则是把像通过一些感光元件存储在存储卡内)。
没有灯光或者物体吸收了所有光线,而造成物体光线没有反射到采集器中就会出现,类似黑洞的现象;在话剧舞台上,如果没有灯光,那么台下的观众啥也看不到了。所以光对于人眼来说是唯一的成像依据,毕竟人不等同于动物,可以采集红外等不可见光成像;
光在三维成像中也是基本元素,光照,灯光,已经光的各个属性都是渲染处理必不可少的因素;
镜面反射
镜面反射是指反射波(电磁波、或声波,水波)有确定方向的反射;其反射波的方向与反射平面的法线夹角(反射角),与入射波方向与该反射平面法线的夹角(入射角)相等,且入射波、反射波,及平面法线同处于一个平面内。摄影时应避免镜面反射光线进入摄影机镜头,由于镜面反射光线极强,在像片上将形成一片白色亮点,影响地物本身在像片上的显现。
镜面反射遵循光的反射定律。
镜面反射所成像的性质是正立的,等大的,位于物体异侧的虚像。
镜面反射是入射光线是平行光线时,反射到光滑的镜面,又以平行光线出去。
漫反射
漫反射,是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时,表面会把光线向着四面八方反射,所以入射线虽然互相平行,由于各点的法线方向不一致,造成反射光线向不同的方向无规则地反射,这种反射称之为“漫反射”或“漫射”。这种反射的光称为漫射光。很多物体,如植物、墙壁、衣服等,其表面粗看起来似乎是平滑,但用放大镜仔细观察,就会看到其表面是凹凸不平的,所以本来是平行的太阳光被这些表面反射后,弥漫地射向不同方向。
人眼之所以能看清物体的全貌,主要是靠漫反射光在眼内的成像。如是全部单向反射的物体表面,不但看不清物体的外貌,还会引起某一方向上的眩光干扰现象。
人们依靠漫反射现象才能从不同方向看到物体。在环境光学中,常把无光泽的饰面材料近似地看作均匀漫反射表面,吸声材料测试用的混响室具有足够的扩散,保持着其墙面满足漫反射条件。
镜面反射和漫反射异同
镜面反射和漫反射,反射角度和入射角相等,唯一的区别,就是镜面反射的反射面比较平,因而光束比较统一而且反射方向比较一致,漫反射的反射平面,高低不平导致反射光的光束也杂乱无章。两者都符合反射定律。
反射规律
1.反射角等于入射角(等角);
2.反射光线,入射光线,与法线在同一平面内(共面);
3.反射光线和入射光线分别位于法线两侧;
环境光
在生活中,错综复杂的光线与凹凸不平的物体表面相互反射,使得整个环境都被照亮,仿佛整个场景被一层环境光所笼罩。通过调节环境光,是调节环境整体光照最为直接的方式,也是一种有效表达环境气氛的方式。利用环境光可以描述一块区域的亮度,通常在场 景中,环境光的颜色是一个常量。在三维渲染中,环境光就被建模为一个没有光源、没有方向并且对场景中的所有物体产生相同的点亮效果的一种光。
散射光
摄影照明光线有直射光和散射光之分。直射光为硬光、散射光为软光。直射光属硬光,在拍摄人像时经常会产生明显的阴影,使得画面较有立体感,但不利于表现人像的肌肤质感。 散射光为发光面积较大的光源发出的光线。其典型的散射光是天空光。以及带柔光玻璃的灯具,环境反射光也大多是散射光。如水面、墙面、地面等。散射光的特征是光线软,受光面和背光面过渡柔合,没有明显的投影,明暗反差较弱,缺乏光影效果。因此对被摄对象的形体、轮廓、起伏表现不够鲜明。这种光线柔和,宜减弱对象粗糙不平的质感,使其柔化。用于拍人物老的显得年青些,年轻的显得漂亮些。
光线的选择,对勾画被摄对象的形状、体积、质地、轮廓等外部特征具有重要意义。在自然光照明条件下,有时只有散射光照明,只有单一的直射光照明是极少见的,大都是直射光和散射光混合光照明。
vtkLight
vtkLight是用于三维渲染的虚拟灯光。
它提供了定位和指向灯光、打开和关闭灯光以及设置灯光亮度和颜色的方法。除了基本的无限远点光源属性外,还可以指定光衰减值和锥角。这些属性仅在灯光是位置灯光时使用。默认为平行光(光源在无限远的地方)。
灯光的类型描述了灯光相对于摄影机的移动方式。前照灯始终位于当前相机位置,并照射在相机的焦点上。CameraLight也会随摄影机移动,但可能与摄影机不重合。CameraLights是在标准化的坐标空间中定义的,相机位于(0,0,1),相机注视(0,0,0),向上是(0,1,0)。最后,场景光是场景本身的一部分,不随摄影机移动(渲染器负责根据灯光的类型移动灯光。
灯光有一个变换矩阵,用于描述它们所在的空间。灯光的世界空间位置和焦点由其局部位置和焦点定义,并通过变换矩阵(如果存在)进行变换。
当前VTK8.2版本中,vtkLight的派生继承关系如下图:
VTK中的灯光与现实的灯光类似,在生活中,光源形式千变万化,例如太阳光,可以看成是一个平行光源,手电筒可以看成聚光(锥形光),普通灯泡可以看成点光源。在vtk中,光源为vtkLight,常用的有位置光源和方向光源:
1.位置光源:位置光源是处于某个位置的光源,可以指定其空间坐标、光照颜色、光照衰减值、锥形角等。
2.方向光源:方向光源不需要指定光源位置,光源处于无穷远,类似与太阳光(平行光)
vtkLight默认为方向光照(平行光),光源的位置和照射焦点连线即为光照方向;
接口
灯光位置和焦点
vtkLight使用Position记录灯光坐标位置,FocalPoint记录焦点位置;
光源的位置和焦点的连线定义光线的方向,默认的vtkLight即为方向光照。
double FocalPoint[3];
double Position[3];
vtkSetVector3Macro(Position, double);
vtkGetVectorMacro(Position, double, 3);
void SetPosition(const float* a) { this->SetPosition(a[0], a[1], a[2]); }
vtkSetVector3Macro(FocalPoint, double);
vtkGetVectorMacro(FocalPoint, double, 3);
void SetFocalPoint(const float* a) { this->SetFocalPoint(a[0], a[1], a[2]); }
灯光的变换矩阵。
如果为灯光设置了矩阵,则灯光的参数(位置和焦点)将在渲染之前由矩阵进行变换。
vtkMatrix4x4* TransformMatrix;
double TransformedFocalPointReturn[3];
double TransformedPositionReturn[3];
virtual void SetTransformMatrix(vtkMatrix4x4*);
vtkGetObjectMacro(TransformMatrix, vtkMatrix4x4);
void GetTransformedPosition(double& x, double& y, double& z);
void GetTransformedPosition(double a[3]);
double* GetTransformedPosition() VTK_SIZEHINT(3);
void GetTransformedFocalPoint(double& x, double& y, double& z);
void GetTransformedFocalPoint(double a[3]);
double* GetTransformedFocalPoint() VTK_SIZEHINT(3);
void TransformPoint(double a[3], double b[3]);
void TransformVector(double a[3], double b[3]);
基于仰角和方位角设置灯光的位置和焦点。
光被移动,所以它从给定的角度发光。角度以度为单位。如果光源是位置光源,则改为使其具有方向性。
void SetDirectionAngle(double elevation, double azimuth);
void SetDirectionAngle(const double ang[2]) { this->SetDirectionAngle(ang[0], ang[1]); }
灯聚光角度
聚光灯的角度;
double ConeAngle;
vtkSetMacro(ConeAngle, double);
vtkGetMacro(ConeAngle, double);
灯的开关
vtkTypeBool Switch;
vtkSetMacro(Switch, vtkTypeBool);
vtkGetMacro(Switch, vtkTypeBool);
vtkBooleanMacro(Switch, vtkTypeBool);
环境光、镜面反射光、漫反射光颜色
double AmbientColor[3];
double DiffuseColor[3];
double SpecularColor[3];
vtkSetVector3Macro(AmbientColor, double);
vtkGetVectorMacro(AmbientColor, double, 3);
vtkSetVector3Macro(DiffuseColor, double);
vtkGetVectorMacro(DiffuseColor, double, 3);
vtkSetVector3Macro(SpecularColor, double);
vtkGetVectorMacro(SpecularColor, double, 3);
void SetColor(double, double, double);
void SetColor(const double a[3]) { this->SetColor(a[0], a[1], a[2]); }
在vtkActor的属性中可以配置被渲染物体的光照属性,
SetAmbient用来设置环境光;SetDiffuse用来设置散射光;SetSpecular用来设置镜面光;
// 创建一个演员,表示球体在渲染场景中的实体;
vtkActor *sphereActor = vtkActor::New();
sphereActor->SetMapper(sphereMapper);
// 设置相关属性:颜色,环境光,漫反射,镜面反射;
sphereActor->GetProperty()->SetColor(1, 0, 0);
sphereActor->GetProperty()->SetAmbient(0.0);
sphereActor->GetProperty()->SetDiffuse(0.0);
sphereActor->GetProperty()->SetSpecular(0.0);
在这三个系数中,当环境光系数占主导时,阴影效果不明显;当散射光系数占主导时,显示效果会比较粗糙;当反射光系数占主动时,显示效果比较光滑。当没有光照属性时,等同于环境光系数为1.0,其他系数为0;高光强度系数用于控制渲染的外观平滑程度;
灯光强度
使用Intensity表示灯光强度;
double Intensity;
vtkSetMacro(Intensity, double);
vtkGetMacro(Intensity, double);
SetColor()将漫反射和镜面反射颜色设置为相同的颜色;
灯光类型
设置/获取灯光类型。
场景灯是位于世界坐标空间中的灯光。灯光最初创建为场景灯光。
前照灯始终位于相机上,并指向相机的焦点。渲染器可以随时修改相机的位置和焦点。
相机灯也连接到相机,但不一定位于相机的位置。CameraLights是在一个坐标空间中定义的,相机位于(0,0,1),以1的距离朝(0,0,0)看,up是(0,1,0)。CameraLight使用变换矩阵来建立这个空间。
注意:所有SetLightType()和SetLightTypeTo()调用都会清除灯光的变换矩阵。*
int LightType;
virtual void SetLightType(int);
vtkGetMacro(LightType, int);
void SetLightTypeToHeadlight() { this->SetLightType(VTK_LIGHT_TYPE_HEADLIGHT); }
void SetLightTypeToSceneLight() { this->SetLightType(VTK_LIGHT_TYPE_SCENE_LIGHT); }
void SetLightTypeToCameraLight() { this->SetLightType(VTK_LIGHT_TYPE_CAMERA_LIGHT); }
int LightTypeIsHeadlight();
int LightTypeIsSceneLight();
int LightTypeIsCameraLight();
平行光聚光灯
选择设置平行光或者聚光;
vtkTypeBool Positional;
vtkSetMacro(Positional, vtkTypeBool);
vtkGetMacro(Positional, vtkTypeBool);
vtkBooleanMacro(Positional, vtkTypeBool);
阴影衰减
设置/获取阴影强度默认情况下,灯光在阴影中会被完全阻挡通过将此值设置为小于1.0,可以控制灯光在阴影中衰减的程度。
float ShadowAttenuation;
vtkSetMacro(ShadowAttenuation, float);
vtkGetMacro(ShadowAttenuation, float);
光照与阴影
通过vtkVolumeProperty可以设置体绘制的阴影效果,阴影效果主要受环境光系数、散射光系数、反射光系数和高光强度4个参数影响。
SetDiffuse() //设置散射光系数(使具有立体感)
SetAmbient() //设置环境光系数(光的强度)
SetSpecular() //设置反射光系数(光滑度,明暗)
一般情况下,着三个系数之和为1.
高光强度系数用于控制体绘制外观平滑程度,使用SetSpecularPower()函数设置。
vtkVolumeProperty中默认是关闭阴影效果,因此需要显示调用ShadeOn()函数来打开阴影效果。
光线投射中,投射光线上的采样步长是一个很重的参数,设置函数:SetSampleDistance(float),步长越小,采样点越多,效果越好。但计算量变大。当数据变化剧烈时,应该减少采样步长以获得更好的效果。
示例
代码1-循环递增环境光系数
#include "pch.h"
#include <iostream>
#include <thread>
#include <chrono>
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkActor.h"
#include "vtkProperty.h"
#include "vtkLight.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
int main()
{
// 创建一个球体
vtkSphereSource *sphere = vtkSphereSource::New();
// 设置经度和纬度的点数;
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(50);
// 创建一个映射器,用来映射圆球的几何形状;
vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
sphereMapper->SetInputConnection(sphere->GetOutputPort());
// 创建一个演员,表示球体在渲染场景中的实体;
vtkActor *sphereActor = vtkActor::New();
sphereActor->SetMapper(sphereMapper);
// 设置相关属性:颜色,环境光,漫反射,镜面反射;
sphereActor->GetProperty()->SetColor(1, 0, 0);
sphereActor->GetProperty()->SetAmbient(0.0);
sphereActor->GetProperty()->SetDiffuse(0.0);
sphereActor->GetProperty()->SetSpecular(0.0);
// 创建一个光源
vtkLight *light = vtkLight::New();
light->SetFocalPoint(0, 0, 0);
light->SetPosition(-0.8, 0.8, 1);
// 创建渲染场景;添加演员,添加灯光,设置背景色;
vtkRenderer *ren1 = vtkRenderer::New();
ren1->AddActor(sphereActor);
ren1->SetBackground(0.1, 0.2, 0.4);
ren1->AddLight(light);
// 创建渲染显示窗口;
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
renWin->SetSize(300, 300);
// 循环递增环境光系数,每递增一次渲染一次;
for (size_t i = 0; i < 334; i++)
{
sphereActor->GetProperty()->SetAmbient(i*0.003);
renWin->Render();
this_thread::sleep_for(chrono::milliseconds(20));
}
renWin->Delete();
ren1->Delete();
light->Delete();
sphereActor->Delete();
sphereMapper->Delete();
sphere->Delete();
system("pause");
return 0;
}
运行效果如下图:
随着环境光系数属性值的增加,球体越来越亮,但是看上去不像球体,而像个 2D的圆盘。这是因为其他光反射系数都为零了,因而没有很好地反映出现实中物体的实际光照属性。
代码2-循环递增漫反射光系数
#include "pch.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkLight.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <array>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
int main()
{
vtkNew<vtkNamedColors> colors;
std::array<unsigned char, 4> bkg{ {26, 51, 102, 255} };
colors->SetColor("bkg", bkg.data());
vtkNew<vtkSphereSource> sphere;
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(50);
vtkNew<vtkPolyDataMapper> sphereMapper;
sphereMapper->SetInputConnection(sphere->GetOutputPort());
auto const numberOfSpheres = 8;
std::array<vtkNew<vtkActor>, numberOfSpheres> spheres;
auto ambient = 0.3;
auto diffuse = 0.0;
auto specular = 0.0;
std::array<double, 3> position{ {0, 0, 0} };
for (auto i = 0; i < spheres.size(); ++i)
{
spheres[i]->SetMapper(sphereMapper);
spheres[i]->GetProperty()->SetColor(colors->GetColor3d("Red").GetData());
spheres[i]->GetProperty()->SetAmbient(ambient);
spheres[i]->GetProperty()->SetDiffuse(diffuse);
spheres[i]->GetProperty()->SetSpecular(specular);
spheres[i]->AddPosition(position.data());
std::cout << diffuse << std::endl;
diffuse += 0.125;
position[0] += 1.25;
if (i == 3)
{
position[0] = 0;
position[1] = 1.25;
}
}
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
for (auto i = 0; i < numberOfSpheres; ++i)
{
ren->AddActor(spheres[i]);
}
ren->SetBackground(colors->GetColor3d("bkg").GetData());
renWin->SetSize(640, 480);
renWin->SetWindowName("DiffuseSpheres");
vtkNew<vtkLight> light;
light->SetFocalPoint(1.875, 0.6125, 0);
light->SetPosition(0.875, 1.6125, 1);
ren->AddLight(light);
ren->GetActiveCamera()->SetFocalPoint(0, 0, 0);
ren->GetActiveCamera()->SetPosition(0, 0, 1);
ren->GetActiveCamera()->SetViewUp(0, 1, 0);
ren->GetActiveCamera()->ParallelProjectionOn();
ren->ResetCamera();
ren->GetActiveCamera()->SetParallelScale(2.0);
iren->Initialize();
renWin->Render();
iren->Start();
system("pause");
return 0;
}
在截图上,每个球体上方固定环境光系数,如下图所示。我们可以看出:随着漫反射光系数属性值的增加,球体越来越亮,因而没有很好地反映出现实中物体的实际光照属性。
代码3-循环改变高光强度
#include "pch.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkLight.h>
#include <vtkLightActor.h>
#include <vtkLightCollection.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <cstdlib>
#include <array>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
int main()
{
vtkNew<vtkNamedColors> colors;
// Set the background color.
std::array<unsigned char, 4> bkg{ {26, 51, 102, 255} };
colors->SetColor("bkg", bkg.data());
vtkNew<vtkSphereSource> sphere;
sphere->SetThetaResolution(100);
sphere->SetPhiResolution(50);
vtkNew<vtkPolyDataMapper> sphereMapper;
sphereMapper->SetInputConnection(sphere->GetOutputPort());
auto const numberOfSpheres = 8;
std::array<vtkNew<vtkActor>, numberOfSpheres> spheres;
auto ambient = 0.3;
auto diffuse = 0.5;
auto specular = 1.0;
auto spBase = 5.0;
auto spScale = 1.0;
std::array<double, 3> position{ {0, 0, 0} };
for (auto i = 0; i < spheres.size(); ++i)
{
auto specularPower = spBase * spScale;
spheres[i]->SetMapper(sphereMapper);
spheres[i]->GetProperty()->SetColor(colors->GetColor3d("Red").GetData());
spheres[i]->GetProperty()->SetAmbient(ambient);
spheres[i]->GetProperty()->SetDiffuse(diffuse);
spheres[i]->GetProperty()->SetSpecular(specular);
spheres[i]->GetProperty()->SetSpecularPower(specularPower);
spheres[i]->GetProperty()->SetSpecularColor(colors->GetColor3d("White").GetData());
spheres[i]->AddPosition(position.data());
spScale = spScale * 2.0;
position[0] += 1.25;
if (i == 3)
{
specular = 0.5;
spScale = 1.0;
position[0] = 0;
position[1] = 1.25;
}
}
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
for (auto i = 0; i < 8; ++i)
{
ren->AddActor(spheres[i]);
}
ren->SetBackground(colors->GetColor3d("bkg").GetData());
renWin->SetSize(640, 480);
renWin->SetWindowName("SpecularSpheres");
vtkNew<vtkLight> light;
light->SetFocalPoint(1.875, 0.6125, 0);
light->SetPosition(0.875, 1.6125, 1);
ren->AddLight(light);
ren->GetActiveCamera()->SetFocalPoint(0, 0, 0);
ren->GetActiveCamera()->SetPosition(0, 0, 1);
ren->GetActiveCamera()->SetViewUp(0, 1, 0);
ren->GetActiveCamera()->ParallelProjectionOn();
ren->ResetCamera();
ren->GetActiveCamera()->SetParallelScale(2.0);
iren->Initialize();
renWin->Render();
iren->Start();
system("pause");
return 0;
}
代码4-聚光灯
1.开启聚光灯:SetPositional;
2.设置聚光灯范围角度:SetConeAngle;
#include "pch.h"
#include <iostream>
#include <thread>
#include <chrono>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkLight.h>
#include <vtkLightActor.h>
#include <vtkLightCollection.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <cstdlib>
#include <array>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
using namespace std;
int main()
{
vtkNew<vtkNamedColors> colors;
vtkNew<vtkRenderer> renderer;
renderer->SetBackground(colors->GetColor3d("Black").GetData());
double lightPosition[3] = { 0, 0, 1 };
double lightFocalPoint[3] = { 0, 0, 0 };
vtkNew<vtkLight> light;
light->SetLightTypeToSceneLight();
light->SetPosition(lightPosition[0], lightPosition[1], lightPosition[2]);
light->SetPositional(true);
light->SetConeAngle(10);
light->SetFocalPoint(lightFocalPoint[0], lightFocalPoint[1],lightFocalPoint[2]);
light->SetDiffuseColor(colors->GetColor3d("Red").GetData());
light->SetAmbientColor(colors->GetColor3d("Green").GetData());
light->SetSpecularColor(colors->GetColor3d("Blue").GetData());
vtkLightCollection* originalLights = renderer->GetLights();
std::cout << "Originally there are " << originalLights->GetNumberOfItems() << " lights." << std::endl;
// Display where the light is
vtkNew<vtkLightActor> lightActor;
lightActor->SetLight(light);
renderer->AddViewProp(lightActor);
// Display where the light is focused
vtkNew<vtkSphereSource> lightFocalPointSphere;
lightFocalPointSphere->SetCenter(lightFocalPoint);
lightFocalPointSphere->SetRadius(0.1);
lightFocalPointSphere->Update();
vtkNew<vtkPolyDataMapper> lightFocalPointMapper;
lightFocalPointMapper->SetInputConnection(lightFocalPointSphere->GetOutputPort());
vtkNew<vtkActor> lightFocalPointActor;
lightFocalPointActor->SetMapper(lightFocalPointMapper);
lightFocalPointActor->GetProperty()->SetColor(colors->GetColor3d("Yellow").GetData());
renderer->AddViewProp(lightFocalPointActor);
// Create a plane for the light to shine on
vtkNew<vtkPlaneSource> planeSource;
planeSource->SetResolution(100, 100);
planeSource->Update();
vtkNew<vtkPolyDataMapper> planeMapper;
planeMapper->SetInputData(planeSource->GetOutput());
vtkNew<vtkActor> planeActor;
planeActor->SetMapper(planeMapper);
renderer->AddActor(planeActor);
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("Light");
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
std::cout << "Now there are " << originalLights->GetNumberOfItems() << " lights." << std::endl;
renderer->AddLight(light); // must do this after renderWindow->Render();
std::cout << "Now there are " << originalLights->GetNumberOfItems() << " lights." << std::endl;
auto camera = renderer->GetActiveCamera();
camera->SetPosition(-2.17199, -2.50774, 2.18);
camera->SetFocalPoint(-0.144661, -0.146372, 0.180482);
camera->SetViewUp(0.0157883, 0.638203, 0.769706);
camera->SetDistance(3.69921);
camera->SetClippingRange(1.76133, 6.14753);
renderWindowInteractor->Start();
system("pause");
return 0;
}
灯光跟随相机
设置vtkRenderer的LightFollowCameraOn或者LightFollowCameraOff来控制”打开/关闭相机移动时灯光的自动重新定位“功能;
1.如果LightFollowCamera打开,则指定为Headlights或者CameraLights将调整为与此渲染器的摄影机一起移动。
2.如果LightFollowCamera关闭,则不会调整灯光。
注意:在以前版本的vtk中,此灯光跟踪功能是交互器的一部分,而不是渲染器。为了向后兼容,更旧的交互其,默认情况下启用该功能。要禁用此模式,请设置关闭interactor的LightFollowCamera标志,并保留渲染器的LightFollowCamera标志打开。
vtkConeSource* cone = vtkConeSource::New();
cone->SetHeight(3.0);
cone->SetRadius(1.0);
cone->SetResolution(10);
vtkPolyDataMapper* coneMapper = vtkPolyDataMapper::New();
coneMapper->SetInputConnection(cone->GetOutputPort());
vtkActor* coneActor = vtkActor::New();
coneActor->SetMapper(coneMapper);
vtkNew<vtkLight> light;
light->SetLightTypeToCameraLight();
light->SetColor(0, 1, 0);
vtkRenderer* ren1 = vtkRenderer::New();
ren1->AddActor(coneActor);
ren1->AddLight(light);
ren1->SetBackground(0.1, 0.2, 0.4);
ren1->LightFollowCameraOn();
vtkRenderWindow* renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren1);
renWin->SetSize(300, 300);
renWin->Render();
vtkNew<vtkRenderWindowInteractor> render_window_interactor;
renWin->SetInteractor(render_window_interactor);
render_window_interactor->LightFollowCameraOff();
render_window_interactor->Initialize();
render_window_interactor->Start();
参考文献
1.光学成像
2.小孔成像
3.VTK004_vtk-灯光
4.漫反射
5.关于环境光、漫反射、镜面反射
6.散射光
7.vtk灯光效果 vtklight
8.DiffuseSpheres
9.SpecularSpheres