基于光线追踪的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(&params->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鱼眼镜头的编程实现 作者:华文广相关推荐

  1. Maya mental ray 焦散

    什么是焦散? 焦散是三维软件中的一个名词,它主要在后期渲染的时候,才会被提及.它的主要作用就是产生水波纹的光影效果,为了达到真实的效果,它可以计算很精致.准确的光影.但是好的效果,都是要付出渲染时间的 ...

  2. 关于Mental Ray

    Mental Ray是mental images这家德国公司旗下一款专业级3D渲染软件.如今mental images已经成为nvidia全资拥有的子公司(http://www.nvidia.com/ ...

  3. 如何调用DLL (基于Visual C++6.0的DLL编程实现)

    如何调用DLL (基于Visual C++6.0的DLL编程实现) http://www.programfan.com/article/showarticle.asp?id=2923 一.前言 自从微 ...

  4. C++ 基于 Visual C++6.0 的 DLL 编程实现

    基于 Visual C++6.0 的 DLL 编程实现 一.前言  自从微软推出 16 位的 Windows 操作系统起,此后每种版本的 Windows 操作系统都非常依赖于动态链接库 (DLL) 中 ...

  5. 计算机科学与python编程导论_【基于Python】MIT OCW 计算机科学与编程导论

    [基于Python]MIT OCW 计算机科学与编程导论 (MIT Course Number 6.0001)Introduction to Computer Science and Programm ...

  6. day26-2 基于TCP协议的套接字编程

    目录 基于TCP协议的套接字编程 套接字 套接字工作流程 基于TCP协议的套接字编程(简单) 服务端 客户端 基于TCP协议的套接字编程(循环) 服务端 客户端1 客户端2 基于TCP协议的套接字编程 ...

  7. 基于数字孪生的机器人焊接自动编程关键技术

    在焊接制造中,存在着大量非标准化.定制化焊接件,需要机器人在焊接过程中具有较高的适应性和柔性,传统的示教-再现型机器人很难直接应用于这样的实际焊接生产中,因此要实现机器人智能化焊接应用还有很多亟需解决 ...

  8. 基于MATLAB软件GUI界面的可编程电音合成器软件

    基于MATLAB软件GUI界面的可编程电音合成器软件 1 总体设计 1.1 设计思路 1.2 软件运行 2 软件功能说明 2.1 软件界面 2.1.1 菜单栏 2.1.2 工具栏 2.1.3 MySy ...

  9. 3dmax:3dmax三维VR渲染设置之高级灯光渲染(常规参数设置—灯光类型、阴影贴图、区域阴影、强度颜色衰减、衰退、远距衰减、聚光灯参数、大气和效果mental ray间接照明)图文教程之详细攻略

    3dmax:3dmax三维VR渲染设置之高级灯光渲染(常规参数设置-灯光类型.阴影贴图.区域阴影.强度颜色衰减.衰退.远距衰减.聚光灯参数.大气和效果mental ray间接照明)图文教程之详细攻略 ...

最新文章

  1. 第一篇:text preprocessing文本预处理
  2. ---西游记~~中的公司政治
  3. 吐槽小程序开发踩过的坑,以及一些解决方法
  4. 判断long类型是否为空_数据类型
  5. IE新0day漏洞(979352)(又称极光零日漏洞)***将扩散
  6. 使用python重命名某个文件下的所有的文件
  7. go语言第一个程序-hello world
  8. .NET Framework 工具
  9. 用HTML5实现人脸识别
  10. 将光标放在EditText的文本末尾
  11. C Tricks(二)—— 按块访问二维数组
  12. 论文解读——An Analysis of Scale Invariance in Object Detection – SNIP
  13. UML建模:学习笔记(1)
  14. python编写的bt爬虫实践
  15. 网站刷关键词_B2B关键词调研:如何精准地定位B端客户?(下)
  16. Unity Recorder屏幕录制问题
  17. C语言 基于循环结构的程序设计(PTA)
  18. 并发编程-初级之认识并发编程
  19. linux模拟手机号码,虚拟手机号码接收短信
  20. iOS图像最佳实践总结

热门文章

  1. linux 系统创建ora文件,手动创建oracle数据库
  2. java kafka api_kafka java API的使用
  3. 脏读、不可重复读 共享锁、悲观锁 和 事务五种隔离级别
  4. linux命令查看cpu负载,怎么使用Linux命令查看CPU使用率
  5. linux正则表达式_号称“天书”的正则表达式,要这么来讲,我小学三年级已经满分了
  6. LPSTR, LPCSTR ,LPTSTR,LPCSTR,LPWSTR LPCWSTR
  7. 生成随机密码的十种方法
  8. 数据数字mongodb 模糊查询以及$type使用
  9. 移植uboot第九步:支持yaffs映像烧写
  10. 读文件 —— WEB前端读取本地文件内容哪些事(前台解析txt文件)……