Eclipse RCP 預設不包含 OpenGL 類別,需額外安裝 org.eclipse.opengl 插件。本文記錄從插件安裝、GLCanvas/GLData 使用、渲染迴圈解決畫面閃爍,到完整繪製旋轉三棱錐矩陣的全過程。
eclipse/plugins/ 目錄。MANIFEST.MF 加入 org.eclipse.opengl 依賴。
canvas.setCurrent() 將其設為當前 Context。在 createPartControl 中直接呼叫 swapBuffers(),畫面會瞬間顯示又消失,因 SWT 事件迴圈後續繪製(如邊框、背景)會覆蓋 OpenGL 畫面。
class Refresher implements Runnable {
private static final int DELAY = 100; // 10 FPS
private final GLCanvas canvas;
private float rotate = 0f;
public Refresher(GLCanvas canvas) { this.canvas = canvas; }
public void run() {
if (canvas == null || canvas.isDisposed()) return;
if (!canvas.isCurrent()) canvas.setCurrent();
// 1. 清除緩衝
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
GL.glLoadIdentity();
// 2. 視角變換
GL.glTranslatef(0, 4.5f, -11);
rotate += 0.5f;
GL.glRotatef(rotate, 0, 1f, 0); // 繞 Y 軸旋轉
// 3. 繪製場景(遞迴三棱錐矩陣)
drawPyramid(0, 0, 0, 4);
// 4. 交換緩衝顯示
canvas.swapBuffers();
// 5. 排程下一幀
canvas.getDisplay().timerExec(DELAY, this);
}
private void drawPyramid(float x, float y, float z, int n) {
if (n == 0) return;
GL.glBegin(GL.GL_TRIANGLES);
// 後面 - 紅綠藍三頂點
GL.glColor3f(1,0,0); GL.glVertex3f(x, y, z);
GL.glColor3f(0,1,0); GL.glVertex3f(x+1, y-1.63f, z-0.57f);
GL.glColor3f(0,0,1); GL.glVertex3f(x-1, y-1.63f, z-0.57f);
// 底面、左側、右側...(略,共 12 頂點組成 4 個三角形)
GL.glEnd();
// 遞迴繪製三個子三棱錐
drawPyramid(x, y-1.63f, z+1.15f, n-1);
drawPyramid(x-1, y-1.63f, z-0.57f, n-1);
drawPyramid(x+1, y-1.63f, z-0.57f, n-1);
}
}
public class OpenGLView extends ViewPart {
private GLCanvas canvas;
@Override
public void createPartControl(Composite parent) {
GLData data = new GLData();
data.depthSize = 16; // 16-bit 深度緩衝
data.doubleBuffer = true; // 雙緩衝
canvas = new GLCanvas(parent, SWT.NO_BACKGROUND, data);
// 視窗大小改變時重設投影矩陣
canvas.addControlListener(new ControlAdapter() {
@Override public void controlResized(ControlEvent e) {
Rectangle r = canvas.getClientArea();
if (!canvas.isCurrent()) canvas.setCurrent();
GL.glViewport(0, 0, r.width, r.height);
GL.glMatrixMode(GL.GL_PROJECTION);
GL.glLoadIdentity();
GLU.gluPerspective(45f, (float)r.width/r.height, 0.1f, 100f);
GL.glMatrixMode(GL.GL_MODELVIEW);
GL.glLoadIdentity();
// 通用 OpenGL 狀態初始化
GL.glClearColor(0,0,0,0);
GL.glClearDepth(1f);
GL.glEnable(GL.GL_DEPTH_TEST);
GL.glDepthFunc(GL.GL_LESS);
GL.glShadeModel(GL.GL_SMOOTH);
GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
}
});
canvas.addDisposeListener(e -> dispose());
new Refresher(canvas).run(); // 啟動渲染迴圈
}
@Override public void setFocus() { canvas.setFocus(); }
}
| 函式 | 用途 |
|---|---|
| glViewport(x,y,w,h) | 設定視口區域 |
| glMatrixMode(GL_PROJECTION/GL_MODELVIEW) | 選擇投影/模型觀察矩陣堆疊 |
| glLoadIdentity() | 重置當前矩陣為單位矩陣 |
| gluPerspective(fovy, aspect, zNear, zFar) | 建立透視投影矩陣 |
| glTranslatef(x,y,z) | 平移當前座標系 |
| glRotatef(angle, x, y, z) | 繞 (x,y,z) 軸旋轉 angle 度 |
| glBegin(GL_TRIANGLES)/glEnd() | 開始/結束三角形頂點提交 |
| glVertex3f(x,y,z) | 指定頂點座標 |
| glColor3f(r,g,b) | 設定當前繪圖顏色 (0~1) |
在 SWT 中整合 OpenGL 關鍵在於:使用 GLCanvas 簡化 Context 管理、以 timerExec 驅動持續渲染迴圈、在 ControlListener 中處理視口與投影矩陣重設。掌握此模式,即可將任意 OpenGL 教材範例(C/C++/Python)移植至 Eclipse RCP 專案。