基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广
来源:互联网 发布:新版手机淘宝怎么开店 编辑:程序博客网 时间:2024/06/08 08:35
基于光线追踪的Mental Ray鱼眼镜头的编程实现
作者:华文广 日期2010/12/3
一、什么是鱼眼镜头
从摄影识知来讲,鱼眼镜头是一种焦距约在6-16毫米之间的短焦距超广角摄影镜头,“鱼眼镜头”是它的俗称。为使镜头达到最大的摄影视角,这种摄影镜头的前镜片直径且呈抛物状向镜头前部凸出,与鱼的眼睛颇为相似,“鱼眼镜头”因此而得名。
鱼眼镜头最大的作用是增大视角范围,视角一般可达到220·或230·,这为近距离拍摄大范围景物创造了条件;鱼眼镜头在接近被摄物拍摄时能造成非常强烈的透视效果,强调被摄物近大远小的对比,使所摄画面具有一种震撼。如下图所示:
在现实应用中,也有很多地方会用到鱼眼镜头,最常见的就是球幕投影。图片经过鱼眼变形之后,再反投回到球幕上,就能得到正常的视觉效果。
二、在Mental Ray中模拟鱼眼镜头的实现
在MAYA中,相机的镜头都是平面的。要想渲染出鱼眼效果,就得做一些特别处理。在网上,我们也能找到几种不同的解决方案。方案一,使用天空盒技术,就是分别渲染前后左右上下六个面组成一个天空盒,然后再在天空盒里面放一个球进行境面反射,这种方案有个优点就是渲染速度比较快,如果配置合理,完全可以达到实时的要求。关于这种实现方案,这个网址http://strlen.com/gfxengine/fisheyequake/上有比较长详细的介绍。然而,这个技术也有一些不缺点,比如,如果场景的灯光与摄像机的视线方向有光,那么六张图的明暗效果就没办法平滑过渡。方案二、使用多图拼接技术,就是从不同角度拍一系列图片,然后用拼接软件,把这些图片自动拼成一张360度全景图,Autodesk Stitcher Unlimited就是一个非常优秀的全景图制作工具,当然,这个方案对于制作人员来说,工作量也是相当巨大的。
在这里我们详细介绍一下第三种解决方案,就是基于光线追踪的鱼眼镜头的模拟实现。我们知道,Mental Ray是一款非常出色的基于光线追踪的渲染工具。正常情况下,摄像机发
a
射出来的光线是沿直线方向投射到场景中去的,如果a所示:
如果我们能截获这个光线,然后改变它的前进方向,便能很容易实现鱼眼效果,如图b所示,在相机前加入一个半球形的镜头,然后再根据光的折射原理,计算新的光线方向。以下就是鱼眼镜头的实现代码:
#include "math.h"
#include <mi_version.h>
#include <shader.h>
#include <geoshader.h>
#include <stdio.h>
#include <math.h>
#include "shader.h"
#define EPSILON 0.00001
// 定义一个输入参数结构体,用于从MAYA属性窗口来改变该变量
struct ben_fisheye_lens_FOV {
miScalar FOV_Angle; // Fisheye FOV 视野角度
};
extern "C" DLLEXPORT int ben_fisheye_lens_version(void) {return(1);}
extern "C" DLLEXPORT miBoolean ben_fisheye_lens(
miColor *result,
miState *state,
register struct ben_fisheye_lens_FOV *params)
{
miScalar fov_angle_deg = *mi_eval_scalar(¶ms->FOV_Angle);
miGeoScalar fov_angle_rad;
miVector ray;
miGeoScalar x, y, r, phi, theta;
// 单位化 [-1,1]...
x = (2.0 * state->raster_x) / state->camera->x_resolution - 1.0;
y = (2.0 * state->raster_y) / state->camera->y_resolution - 1.0;
// 根据像素坐标,来计算该像素离中心的半。
r = MI_SQRT( ( x * x ) + ( y * y ) );
if ( r < 1.0 ) {
// 根据球面坐标公式来计算 phi...
if ( (r > -EPSILON) && (r < EPSILON) ) {
phi = 0.0;
} else {
if ( x < EPSILON ) {
phi = M_PI - asin( y / r );
} else {
phi = asin( y / r );
}
}
// 把输入的角度值转换为弧度
fov_angle_rad = fov_angle_deg * M_PI / 180.0;
// 计算 theta...
theta = r * ( fov_angle_rad / 2.0 );
// 计算新的光线的方向,沿球面法线方向
ray.x = (float)(sin(theta) * cos(phi));
ray.y = (float)(-sin(theta) * sin(phi));
// 这里我们假定相机的视线方向是 -Z 轴
ray.z = (float)(-cos(theta));
// 把光线转换为相机空间
mi_vector_from_camera(state, &ray, &ray);
// 发射新的改变方向之后的光线
return(mi_trace_eye(result, state, &state->org, &ray));
} else {
result->r = result->g =
result->b = result->a = 0;
return(miFALSE);
}
} /* end of ben_fisheye_lens() */
把以上代码放在VC++中编译成一个ben_fisheye_lens .dll,这样一个基于Mental Ray 的鱼眼镜头就开发完成了。
我们知道,光线追踪的光线发射是从相机窗口的每个像素出发的,那么,基于像素的二维的图像坐标,如何转换成球面坐标系的角度坐标呢?这里Paul Bourke给我们提供了一个方案:
逆向运算如下:
u = r cos(phi) + 0.5
v = r sin(phi) + 0.5
转换成球面坐标。
r = atan2(sqrt(x*x+y*y),p.z) / pi
phi = atan2(y,x)
三、安装和使用
安装我们编译好的鱼眼镜头插件。首先,用记事本新建一个ben_fisheye_lens.mi文件,然后把下面脚本写入到这个mi文件中去:
declare shader
color "ben_fisheye_lens" (
scalar " FOV_Angle ", #: softmin 0.0 softmax 360.0 default 180.0
)
apply lens
version 1
end declare
完成之后,把ben_fisheye_lens.dll文件拷贝到:/Mayax.x/mentalray/lib文件夹,把ben_fisheye_lens.mi文件拷贝到/Mayax.x/mentalray/include文件甲。
打开MAYA,你就可以在mental ray的Shader中看到你所编译的鱼眼镜头了,新建一个镜头shader然后指定到MAYA的相机属性的镜头参数中去,这个你渲出来的图片,就会有鱼眼效果了。
以上是一个简单的例子,用来解析如何编写一个Mental Ray 的镜头。事实上,如果我们能理解透彻光线追踪的原理,我们可以用其它你所相要的方式来改变光线的方线,从而实现不同的镜头效果,如环幕镜头,球幕镜头,天空盒镜头等等。
环幕全景镜头效果图
- 基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广
- 基于光线追踪的Mental Ray鱼眼镜头的编程实现
- 【Ray Trace from Groud Up】光线追踪代码实现解析
- 《基于几何成像模型的鱼眼镜头图像校正算法和技术研究》实现
- 鱼眼镜头的分类
- 鱼眼镜头的选型
- 【GPU编程】基于GPU的光线投射体绘制(GPU-Based Ray-Casting Volume Rendering)入门学习
- 转 光线追踪的基本原理
- 基于几何成像模型的鱼眼镜头图像校正算法和技术研究的实现与改进
- Mental ray Custom Shader 主函数和参数的命名
- Mental ray 的建筑渲染Arch&Design材质
- 光线追踪(Ray Trace) 变形金刚大图
- 光线追踪例子Ray tracing (webgl)
- 基于GPU的光线投射体绘制(GPU-Based Ray-Casting Volume Rendering)入门学习
- 基于GPU的光线投射体绘制(GPU-Based Ray-Casting Volume Rendering)入门学习
- 体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)
- 体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)
- 体绘制(Volume Rendering)概述之4:光线投射算法(Ray Casting)实现流程和代码(基于CPU的实现)
- 云服务器
- web列表导出excel
- 那一年,我们二十七八岁
- 750A New Year and Hurry
- spark安装及环境搭建
- 基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广
- mysql出现错误“ Every derived table must have its own alias”
- 生产者/消费者问题的多种Java实现方式
- 菱形继承与虚拟菱形继承对象模型
- Omi教程-组件通讯
- 并查集模板
- 阿里Java框架分层约束
- QT安装QML环境配置与QML学习指南
- 【maven】如何构建一个可执行的 war