基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广
基于光线追踪的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鱼眼镜头的编程实现 作者:华文广相关推荐
- Maya mental ray 焦散
什么是焦散? 焦散是三维软件中的一个名词,它主要在后期渲染的时候,才会被提及.它的主要作用就是产生水波纹的光影效果,为了达到真实的效果,它可以计算很精致.准确的光影.但是好的效果,都是要付出渲染时间的 ...
- 关于Mental Ray
Mental Ray是mental images这家德国公司旗下一款专业级3D渲染软件.如今mental images已经成为nvidia全资拥有的子公司(http://www.nvidia.com/ ...
- 如何调用DLL (基于Visual C++6.0的DLL编程实现)
如何调用DLL (基于Visual C++6.0的DLL编程实现) http://www.programfan.com/article/showarticle.asp?id=2923 一.前言 自从微 ...
- C++ 基于 Visual C++6.0 的 DLL 编程实现
基于 Visual C++6.0 的 DLL 编程实现 一.前言 自从微软推出 16 位的 Windows 操作系统起,此后每种版本的 Windows 操作系统都非常依赖于动态链接库 (DLL) 中 ...
- 计算机科学与python编程导论_【基于Python】MIT OCW 计算机科学与编程导论
[基于Python]MIT OCW 计算机科学与编程导论 (MIT Course Number 6.0001)Introduction to Computer Science and Programm ...
- day26-2 基于TCP协议的套接字编程
目录 基于TCP协议的套接字编程 套接字 套接字工作流程 基于TCP协议的套接字编程(简单) 服务端 客户端 基于TCP协议的套接字编程(循环) 服务端 客户端1 客户端2 基于TCP协议的套接字编程 ...
- 基于数字孪生的机器人焊接自动编程关键技术
在焊接制造中,存在着大量非标准化.定制化焊接件,需要机器人在焊接过程中具有较高的适应性和柔性,传统的示教-再现型机器人很难直接应用于这样的实际焊接生产中,因此要实现机器人智能化焊接应用还有很多亟需解决 ...
- 基于MATLAB软件GUI界面的可编程电音合成器软件
基于MATLAB软件GUI界面的可编程电音合成器软件 1 总体设计 1.1 设计思路 1.2 软件运行 2 软件功能说明 2.1 软件界面 2.1.1 菜单栏 2.1.2 工具栏 2.1.3 MySy ...
- 3dmax:3dmax三维VR渲染设置之高级灯光渲染(常规参数设置—灯光类型、阴影贴图、区域阴影、强度颜色衰减、衰退、远距衰减、聚光灯参数、大气和效果mental ray间接照明)图文教程之详细攻略
3dmax:3dmax三维VR渲染设置之高级灯光渲染(常规参数设置-灯光类型.阴影贴图.区域阴影.强度颜色衰减.衰退.远距衰减.聚光灯参数.大气和效果mental ray间接照明)图文教程之详细攻略 ...
最新文章
- 第一篇:text preprocessing文本预处理
- ---西游记~~中的公司政治
- 吐槽小程序开发踩过的坑,以及一些解决方法
- 判断long类型是否为空_数据类型
- IE新0day漏洞(979352)(又称极光零日漏洞)***将扩散
- 使用python重命名某个文件下的所有的文件
- go语言第一个程序-hello world
- .NET Framework 工具
- 用HTML5实现人脸识别
- 将光标放在EditText的文本末尾
- C Tricks(二)—— 按块访问二维数组
- 论文解读——An Analysis of Scale Invariance in Object Detection – SNIP
- UML建模:学习笔记(1)
- python编写的bt爬虫实践
- 网站刷关键词_B2B关键词调研:如何精准地定位B端客户?(下)
- Unity Recorder屏幕录制问题
- C语言 基于循环结构的程序设计(PTA)
- 并发编程-初级之认识并发编程
- linux模拟手机号码,虚拟手机号码接收短信
- iOS图像最佳实践总结
热门文章
- linux 系统创建ora文件,手动创建oracle数据库
- java kafka api_kafka java API的使用
- 脏读、不可重复读 共享锁、悲观锁 和 事务五种隔离级别
- linux命令查看cpu负载,怎么使用Linux命令查看CPU使用率
- linux正则表达式_号称“天书”的正则表达式,要这么来讲,我小学三年级已经满分了
- LPSTR, LPCSTR ,LPTSTR,LPCSTR,LPWSTR LPCWSTR
- 生成随机密码的十种方法
- 数据数字mongodb 模糊查询以及$type使用
- 移植uboot第九步:支持yaffs映像烧写
- 读文件 —— WEB前端读取本地文件内容哪些事(前台解析txt文件)……