基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广
基于光線追蹤的Mental Ray魚眼鏡頭的編程實現(xiàn)
作者:華文廣 ????????????????????????????????????????????????????????????????????????????????? 日期2010/12/3
一、什么是魚眼鏡頭
從攝影識知來講,魚眼鏡頭是一種焦距約在6-16毫米之間的短焦距超廣角攝影鏡頭,“魚眼鏡頭”是它的俗稱。為使鏡頭達到最大的攝影視角,這種攝影鏡頭的前鏡片直徑且呈拋物狀向鏡頭前部凸出,與魚的眼睛頗為相似,“魚眼鏡頭”因此而得名。
??? 魚眼鏡頭最大的作用是增大視角范圍,視角一般可達到220·或230·,這為近距離拍攝大范圍景物創(chuàng)造了條件;魚眼鏡頭在接近被攝物拍攝時能造成非常強烈的透視效果,強調(diào)被攝物近大遠小的對比,使所攝畫面具有一種震撼。如下圖所示:
??? 在現(xiàn)實應(yīng)用中,也有很多地方會用到魚眼鏡頭,最常見的就是球幕投影。圖片經(jīng)過魚眼變形之后,再反投回到球幕上,就能得到正常的視覺效果。
二、在Mental Ray中模擬魚眼鏡頭的實現(xiàn)
在MAYA中,相機的鏡頭都是平面的。要想渲染出魚眼效果,就得做一些特別處理。在網(wǎng)上,我們也能找到幾種不同的解決方案。方案一,使用天空盒技術(shù),就是分別渲染前后左右上下六個面組成一個天空盒,然后再在天空盒里面放一個球進行境面反射,這種方案有個優(yōu)點就是渲染速度比較快,如果配置合理,完全可以達到實時的要求。關(guān)于這種實現(xiàn)方案,這個網(wǎng)址http://strlen.com/gfxengine/fisheyequake/上有比較長詳細的介紹。然而,這個技術(shù)也有一些不缺點,比如,如果場景的燈光與攝像機的視線方向有光,那么六張圖的明暗效果就沒辦法平滑過渡。方案二、使用多圖拼接技術(shù),就是從不同角度拍一系列圖片,然后用拼接軟件,把這些圖片自動拼成一張360度全景圖,Autodesk Stitcher Unlimited就是一個非常優(yōu)秀的全景圖制作工具,當然,這個方案對于制作人員來說,工作量也是相當巨大的。
?
?
在這里我們詳細介紹一下第三種解決方案,就是基于光線追蹤的魚眼鏡頭的模擬實現(xiàn)。我們知道,Mental Ray是一款非常出色的基于光線追蹤的渲染工具。正常情況下,攝像機發(fā) ??
a
???
射出來的光線是沿直線方向投射到場景中去的,如果a所示:
如果我們能截獲這個光線,然后改變它的前進方向,便能很容易實現(xiàn)魚眼效果,如圖b所示,在相機前加入一個半球形的鏡頭,然后再根據(jù)光的折射原理,計算新的光線方向。以下就是魚眼鏡頭的實現(xiàn)代碼:
?
#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
?
// 定義一個輸入?yún)?shù)結(jié)構(gòu)體,用于從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;
?
???????? // 根據(jù)像素坐標,來計算該像素離中心的半。
???????? r = MI_SQRT( ( x * x ) + ( y * y ) );
?
???????? if ( r < 1.0 ) {
?????????????????? // 根據(jù)球面坐標公式來計算 phi...
?????????????????? if ( (r > -EPSILON) && (r < EPSILON) ) {
??????????????????????????? phi = 0.0;
?????????????????? } else {
?
??????????????????????????? if ( x < EPSILON ) {
???????????????????????????????????? phi = M_PI - asin( y / r );
??????????????????????????? } else {
???????????????????????????????????? phi = asin( y / r );
??????????????????????????? }
?????????????????? }
?
?????????????????? // 把輸入的角度值轉(zhuǎn)換為弧度
?????????????????? 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));
?
?????????????????? // 把光線轉(zhuǎn)換為相機空間
?????????????????? mi_vector_from_camera(state, &ray, &ray);
?????????????????? // 發(fā)射新的改變方向之后的光線
?????????????????? 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 的魚眼鏡頭就開發(fā)完成了。
我們知道,光線追蹤的光線發(fā)射是從相機窗口的每個像素出發(fā)的,那么,基于像素的二維的圖像坐標,如何轉(zhuǎn)換成球面坐標系的角度坐標呢?這里Paul Bourke給我們提供了一個方案:
?
?
?
?
逆向運算如下:
u = r cos(phi) + 0.5
v = r sin(phi) + 0.5
轉(zhuǎn)換成球面坐標。
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的相機屬性的鏡頭參數(shù)中去,這個你渲出來的圖片,就會有魚眼效果了。
?
?
???????? 以上是一個簡單的例子,用來解析如何編寫一個Mental Ray 的鏡頭。事實上,如果我們能理解透徹光線追蹤的原理,我們可以用其它你所相要的方式來改變光線的方線,從而實現(xiàn)不同的鏡頭效果,如環(huán)幕鏡頭,球幕鏡頭,天空盒鏡頭等等。
環(huán)幕全景鏡頭效果圖
?
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的基于光线追踪的Mental Ray鱼眼镜头的编程实现 作者:华文广的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 车道检测与跟踪
- 下一篇: 低秩矩阵的应用--背景建模