VTK灯光:
灯光介绍:
在生活中,我们能看见东西是因为有光照,光照分为很多类型,不同的光照会导致我们看见事物(看见的影像)也不同。同样的,光照是3D渲染中必备的因数之一(相机、事物也是)。
VTK中的灯光与现实的灯光类似,在生活中,光源形式千变万化,例如太阳光,可以看成是一个平行光源,手电筒可以看成聚光(锥形光),普通灯泡可以看成点光源。在vtk中,光源为vtkLight,常用的有位置光源和方向光源:
(1)位置光源:位置光源是处于某个位置的光源,可以指定其空间坐标、光照颜色、光照衰减值、锥形角等。
(2)方向光源:方向光源不需要指定光源位置,光源处于无穷远,类似与太阳光(平行光)
vtkLight默认为方向光照(平行光),光源的位置和照射焦点连线即为光照方向
示例:
class vtkMyCallback : public vtkCommand
{
public:
static vtkMyCallback *New()
{
return new vtkMyCallback;
}
virtual void Execute(vtkObject *caller, unsigned long, void*) // 强制实现的方法
{
vtkRenderer *ren = reinterpret_cast<vtkRenderer*>(caller);
cout << ren->GetActiveCamera()->GetPosition()[0] << " "
<< ren->GetActiveCamera()->GetPosition()[1] << " "
<< ren->GetActiveCamera()->GetPosition()[2] << "\n";
}
};
int main()
{
vtkSmartPointer<vtkRenderWindow> m_pRenderWin = vtkRenderWindow::New();
vtkSmartPointer<vtkRenderWindowInteractor> m_pInteractor = vtkRenderWindowInteractor::New();
vtkSmartPointer<vtkInteractorStyleTrackballCamera> m_pInteractorStyle = vtkInteractorStyleTrackballCamera::New();
vtkSmartPointer<vtkActor> m_actor = vtkActor::New();
vtkSmartPointer<vtkRenderer> m_render = vtkRenderer::New();
vtkSmartPointer<vtkCylinderSource> m_cylinderSrc = vtkCylinderSource::New();
vtkSmartPointer<vtkPolyDataMapper> m_cylinderMap = vtkPolyDataMapper::New();
vtkSmartPointer<vtkTransform> m_trans = vtkTransform::New();
vtkSmartPointer<vtkCamera> m_pCamera = vtkCamera::New();
vtkSmartPointer<vtkLight> m_lightRed = vtkLight::New();
vtkSmartPointer<vtkLight> m_lightGreen = vtkLight::New();
vtkSmartPointer<vtkLight> m_lightBlue = vtkLight::New();
m_cylinderSrc->SetHeight(10);
m_cylinderSrc->SetRadius(5);
m_cylinderSrc->SetResolution(36); // 精度
m_cylinderMap->SetInputConnection(m_cylinderSrc->GetOutputPort());
//m_trans->Translate(0, 0, 0);
m_trans->RotateX(45); // 沿x轴正方向顺时针旋转
m_actor->SetMapper(m_cylinderMap);
m_actor->SetUserTransform(m_trans);
m_actor->GetProperty()->SetDiffuse(0.6); // 漫反射
m_actor->GetProperty()->SetSpecular(0.3); // 镜面反射
m_actor->GetProperty()->SetSpecularPower(20);
// m_actor->VisibilityOff(); // 隐藏模型
m_render->AddActor(m_actor);
m_pCamera->SetPosition(0, 0, 50);
m_pCamera->SetFocalPoint(0, 0, 0);
m_render->SetActiveCamera(m_pCamera);
m_render->SetViewport(0.0, 0.0, 1.0, 1.0);
vtkMyCallback* mol = vtkMyCallback::New();
m_render->AddObserver(vtkCommand::StartEvent, mol); // 为渲染器添加观察器(回调函数)
mol->Delete();
m_lightRed->SetColor(1.0, 0.0, 0.0);
m_lightRed->SetPosition(20, 0, 0);
m_lightRed->SetFocalPoint(m_pCamera->GetFocalPoint()); // 光线照向相机聚焦点
m_lightGreen->SetColor(0.0, 1.0, 0.0);
m_lightGreen->SetPosition(0, 20, 0);
m_lightGreen->SetFocalPoint(m_pCamera->GetFocalPoint()); // 光线照向相机聚焦点
m_lightBlue->SetColor(0.0, 0.0, 1.0);
m_lightBlue->SetPosition(0, 0, 20);
m_lightBlue->SetFocalPoint(m_pCamera->GetFocalPoint()); // 光线照向相机聚焦点
m_render->AddLight(m_lightRed);
m_render->AddLight(m_lightGreen);
m_render->AddLight(m_lightBlue);
m_render->SetBackground(0.5, 0.3, 0.2);
m_render->SetGradientBackground(true); // 背景色渐变
m_pRenderWin->AddRenderer(m_render);
m_pRenderWin->SetSize(800, 600);
m_pRenderWin->Render();
m_pInteractor->SetInteractorStyle(m_pInteractorStyle);
m_pInteractor->SetRenderWindow(m_pRenderWin);
m_pRenderWin->Render();
m_pInteractor->Start();
return 0;
}
上面,设置了三个灯光,分别位于世界坐标xyz轴上20的位置,x轴上为红色灯,y轴上为绿色灯,z轴上为蓝色灯,灯光方向均照向原点处(相机焦点)。上面,我们将模型旋转了45度,因此,顶面既可以接收到y轴的绿光,还可以接收到z轴的蓝光,以下为效果图:
从这个效果图,以及render回调函数打印的相机位置,我们都可以很直观的看出vtk的坐标系系统是怎样的,为右手坐标系,默认情况下,屏幕右边为X正方向,屏幕上面为Y轴正方向,出屏幕方向(垂直屏幕向外)为Z正方向。
vtk光照详解:
vtkLight是vtk中用于3D渲染的虚拟灯,它提供了设定光源位置、光源颜色、光源亮度、光源属性以及打开关闭光源的方法:
(1)SetColor:设置灯光颜色,以0~1之间的小数指定RGB强度。
(2)SetPosition:设置灯光位置。
(3)SetFocalPoint:设置灯光焦点。
(4)SetIntensity:设置光照强度(0~1)。
(5)SetSwitch、SwitchOn、SwitchOff:打开/关闭光照。
同样,Set方法一般都会有对应的Get方法,例如:GetPosition可以获取灯光位置,GetSwitch可以获取灯光是否打开,GetFocalPoint可以获取灯光焦点。
实际上,我们在vtkLight中,找不到GetSet这些方法,实际上,vtk里面做了宏定义,如下:
vtkSetMacro(Switch,int);
vtkGetMacro(Switch,int);
在里面,就定义了对应的Get和Set方法。这样做为了代码的整洁与统一,更有益于团队开发。
vtkLight其他方法:一般Set方法都会有对应的Get方法
(1)SetAmbientColor:设置环境光照颜色。
(2)SetDiffuseColor:设置漫反射光颜色。
(3)SetSpecularColor:设置镜面反射光颜色。
(4)SetColor:设置上面三种光照为同一种颜色。
(5)SetPositional:设置是否为位置照明(位置光),此外有对应的On和Off版本。
(6)SetExponent:设置位置照明中使用的余弦参数。
(7)SetConeAngle:设置光源锥度(单位为度°)。
(8)SetAttenuationValues:设置光源二次衰减常数。
(9)SetTransformMatrix:设置光源的变换矩阵。
(10)GetTransformPosition:获取灯光世界空间坐标(由变换矩阵得来)。
(11)GetTransformFocalPoint:获取灯光焦点(有变换矩阵得来)。
(12)SetDirectionAngle:根据高程和方位角设置灯光位置和焦点。
(13)DeepCopy:深层复制相机。
(14)SetLightType:设置灯光类型。
(15)SetLightTypeToHeadlight:设置灯光类型为前照灯(始终位于相机处,指向相机焦点)。
(16)SetLightTypeToSceneLight:设置灯光类型为世界坐标灯光。
(17)SetLightToCameraLight:设置灯光类型为相机灯(并不一定位于相机处)
(18)SetShadowAttenuation:设置阴影强度,光被阻挡的强度(0~1),1为完全阻挡
例如,在上面程序的灯光设置中,加入以下代码:
m_lightRed->SetPositional(1);
m_lightGreen->SetPositional(1);
m_lightBlue->SetPositional(1);
// m_lightRed->SetExponent(0.5);
// m_lightGreen->SetExponent(0.5);
// m_lightBlue->SetExponent(0.5);
m_lightRed->SetConeAngle(15);
m_lightGreen->SetConeAngle(15);
m_lightBlue->SetConeAngle(15);
m_lightRed->SetShadowAttenuation(0.5);
m_lightGreen->SetShadowAttenuation(0.5);
m_lightBlue->SetShadowAttenuation(0.5);
其对应的效果如下图:
对于其他的,例如相机坐标转换,转换矩阵等,可以在使用的时候再做具体测试。
vtk中,相机也不只有vtkLight,还有vtkLightActor、vtkLightCollection等。