update: 2013/08/29
reference:
0. 原文: Rendering 3D Anaglyph in OpenGL
1. I touchs: Rendering 3D Anaglyph in OpenGL - 1
2. I touchs: Rendering 3D Anaglyph in OpenGL - 2
3. I touchs: Rendering 3D Anaglyph in OpenGL - 3
4. I touchs: Rendering 3D Anaglyph in OpenGL - 4
5. I touchs: Rendering 3D Anaglyph in OpenGL - 5
I. Mac OS X 實作
1. 新增專案:
Xcode > File > New > Project... > OS X > Application >
Command Line Tool > Next
Company Identifier: com.blogspot
Type: C++
Use Automatic Reference Counting: checked
> Next > Create
OpenGL
- OpenGL is the premier environment for developing portable,
interactive 2D and 3D graphics applications.
GLUT
- OpenGL Utility Toolkit- OpenGL is the premier environment for developing portable,
interactive 2D and 3D graphics applications.
GLUT
3. 新增檔案:
a. 立體攝影機類別:
Xcode > File > New > File...
> OS X > C and C++ > C++ Class > Next
b. 繪圖函式:
Xcode > File > New > File...
> OS X > C and C++ > C++ Class > Next
Save As: draw.cpp
Targets: 3DAnaglyph (勾選)> Create
a. 開啓 StereoCamera.h 檔案, 修改如下:
#ifndef ___DAnaglyph__StereoCamera__
#define ___DAnaglyph__StereoCamera__
#include <iostream>
//@add
#include <OpenGL/OpenGL.h> // OpenGL Library
#include <GLUT/GLUT.h> // OpenGL Utility Toolkit
#include <math.h>
#endif /* defined(___DAnaglyph__StereoCamera__) */
b. 開啓 StereoCamera.cpp 檔案, 修改如下:
#include "StereoCamera.h"
//@add
class StereoCamera
{
public:
// 建構子
StereoCamera(
float Convergence, // 收斂距離
float EyeSeparation, // 二眼間隔
float AspectRatio, // 寬高比
float FOV, // 視野角度
float NearClippingDistance, // 近截距
float FarClippingDistance // 遠截距
)
{
mConvergence = Convergence;
mEyeSeparation = EyeSeparation;
mAspectRatio = AspectRatio;
//mFOV = FOV * PI / 180.0f;
//@update
mFOV = FOV * M_PI / 180.0f;
mNearClippingDistance = NearClippingDistance;
mFarClippingDistance = FarClippingDistance;
}
// 套用左視錐
void ApplyLeftFrustum()
{
float top, bottom, left, right;
top = mNearClippingDistance * tan(mFOV/2);
bottom = -top;
float a = mAspectRatio * tan(mFOV/2) * mConvergence;
float b = a - mEyeSeparation/2;
float c = a + mEyeSeparation/2;
left = -b * mNearClippingDistance/mConvergence;
right = c * mNearClippingDistance/mConvergence;
// 設置投影矩陣 (會後做)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, bottom, top, mNearClippingDistance, mFarClippingDistance);
// 設置 模型/視野 矩陣 (會先做)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// 將世界座標往右位移: 二眼間隔的一半距離
glTranslatef(mEyeSeparation/2, 0.0f, 0.0f);
}
// 套用右視錐
void ApplyRightFrustum()
{
float top, bottom, left, right;
top = mNearClippingDistance * tan(mFOV/2);
bottom = -top;
float a = mAspectRatio * tan(mFOV/2) * mConvergence;
float b = a - mEyeSeparation/2;
float c = a + mEyeSeparation/2;
left = -c * mNearClippingDistance/mConvergence;
right = b * mNearClippingDistance/mConvergence;
// 設置投影矩陣 (會後做)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(left, right, bottom, top, mNearClippingDistance, mFarClippingDistance);
// 設置 模型/視野 矩陣 (會先做)
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// 將世界座標往左位移: 二眼間隔的一半距離
glTranslatef(-mEyeSeparation/2, 0.0f, 0.0f);
}
// 內部變數
private:
float mConvergence;
float mEyeSeparation;
float mAspectRatio;
float mFOV;
float mNearClippingDistance;
float mFarClippingDistance;
};
6. 新增: 繪圖函式
a. 開啓 draw.h 檔案, 修改如下:
#ifndef ___DAnaglyph__draw__
#define ___DAnaglyph__draw__
//#include <iostream>
//@add
#include "StereoCamera.cpp"
#endif /* defined(___DAnaglyph__draw__) */
//@add
void DrawGLScene();
void PlaceSceneElements();
b. 開啓 draw.cpp 檔案, 修改如下:
//@add
// 主要的繪圖函式
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 設定立體攝影機系統
StereoCamera cam(
2000.0f, // Convergence (收斂距離)
35.0f, // Eye Separation (二眼間隔)
1.3333f, // Aspect Ratio (寬高比)
45.0f, // FOV along Y in degrees (沿著 Y 軸的視野角度)
10.0f, // Near Clipping Distance (近截距)
20000.0f); // Far Clipping Distance (遠截距)
cam.ApplyLeftFrustum();
glColorMask(true, false, false, false); // 只將紅色寫入緩沖區(紅色遮罩)
PlaceSceneElements(); // 在場景中放入物體
glClear(GL_DEPTH_BUFFER_BIT) ;
cam.ApplyRightFrustum();
glColorMask(false, true, true, false); // 只將綠色及藍色寫入緩沖區(綠藍色遮罩)
PlaceSceneElements(); // 在場景中放入物體
glColorMask(true, true, true, true); // 恢復將所有色彩寫入緩沖區
//@add: flush!
glFlush();
//@add: swap the double buffer
glutSwapBuffers();
}
//@add
// 在場景中放入物體
void PlaceSceneElements()
{
// 沿著負 Z 軸, 位移到適當的深度
glTranslatef(0.0f, 0.0f, -1800.0f);
// 旋囀場景以便觀看
glRotatef(-60.0f, 1.0f, 0.0f, 0.0f);
glRotatef(-45.0f, 0.0f, 0.0f, 1.0f);
// 繪製相交的環形圓紋曲面(tori)
glPushMatrix();
glTranslatef(0.0f, 0.0f, 240.0f);
glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
glColor3f(0.2, 0.2, 0.6);
glutSolidTorus(40, 200, 20, 30);
glColor3f(0.7f, 0.7f, 0.7f);
glutWireTorus(40, 200, 20, 30);
glPopMatrix();
glPushMatrix();
glTranslatef(240.0f, 0.0f, 240.0f);
glColor3f(0.2, 0.2, 0.6);
glutSolidTorus(40, 200, 20, 30);
glColor3f(0.7f, 0.7f, 0.7f);
glutWireTorus(40, 200, 20, 30);
glPopMatrix();
}
7. 修改主程式:
開啓 main.cpp 檔案, 修改如下:
//#include <iostream>
//@add
#include "draw.h"
//@add: initialize OpenGL state
void init()
{
// This determines the background color, in this case: gray
// state: current clear color
glClearColor(0.5, 0.5, 0.5, 1.0); // R, G, B, A
// Determines which matrix to apply operations to.
// value: GL_PROJECTION or GL_MODELVIEW
glMatrixMode(GL_PROJECTION); // default
// Loads the Identity matrix
glLoadIdentity();
// 投影(Projection)
//
// default: 正投影(Orthographic Projection)
}
//int main(int argc, const char * argv[])
//@update: just remove "const"
int main(int argc, char * argv[])
{
// insert code here...
//std::cout << "Hello, World!\n";
// Init glut
glutInit(&argc, argv);
// Display mode
int mode = GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH;
glutInitDisplayMode(mode);
// Init Window
glutInitWindowSize(800, 600);
glutInitWindowPosition(100, 100);
glutCreateWindow("3D Anaglyph");
// initialize: set OpenGL state
init();
// Callback Functions Registration
glutDisplayFunc(DrawGLScene); // drawing
// enter event processing loop
glutMainLoop();
// will not be executed
return 0;
}
8. 編譯並執行: