satanupup 喜歡上這裡的冒險者
註冊時間: 2007-05-29 文章: 80
68.10 果凍幣
|
發表於: 2007-6-28, PM 1:58 星期四 文章主題: [轉貼自程式設計俱樂部]glut 教學 - 把我的圖放到視窗上!! |
|
|
作者 : ma_hty(白老鼠(Gary))
這一次要介紹的, 是使用 glDrawPixels() 來畫圖.
這個, 會用到
"glut 教學 - 第一個視窗" 和
"glut 教學 - 讀取 bmp圖檔"
請先看畢這兩個教學, 才開始這個.
由教學一, 我們得到了基本的 glut 視窗,
由教學二, 我們讀取到 bmp圖檔,
現在, 接著要做的, 就是要把 圖檔畫到視窗上.
------------------------------------------------------------
/////////////////////////
// glutTest03.cpp
//
// Created by Gary Ho, ma_hty@hotmail.com, 2005
//
#include <stdio.h>
#include "glut.h"
#include "g_bmp.h"
GBmp bm0;
void display()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glRasterPos2f( -bm0.w/640.0, -bm0.h/640.0 );
glDrawPixels( bm0.w, bm0.h, GL_RGB, GL_UNSIGNED_BYTE, bm0.rgb );
glutSwapBuffers();
}
void main()
{
glutInitDisplayMode( GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB );
glutInitWindowSize( 640, 640 );
glutCreateWindow( "hihi" );
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glutDisplayFunc(display);
bm0.load( "blank.bmp" );
glutMainLoop();
}
------------------------------------------------------
這個程式 ( glutTest03.cpp ), 會先讀進 blank.bmp, 然後把它畫到視窗的中央.
接著, 我會更詳細的交代部份 glut 的 function 的意思.
----------------------
glRasterPos2f( -bm0.w/640.0, -bm0.h/640.0 ); //決定畫圖的位置.
glDrawPixels( bm0.w, bm0.h, GL_RGB, GL_UNSIGNED_BYTE, bm0.rgb ); //實在畫圖的程序
-----------------
如果你是初學 OpenGL, 可能你會疑惑, "為什麼 畫圖 和 畫圖的位置 會分在兩個不同的 function 去設定呢?"... ...
OpenGL 是 procedural 的模組, 根我們常用的 C++ Object 很不同的, 在 OpenGL 模組內, 它記錄著一大堆全域變數, OpenGL 載入時, 會同時把這些全城變數設成預設值, 如果你用不著的變數, 就讓它繼續是預設值, 不用管它就可以了.
因為 procedural 的關係, 你並沒有物件, 只有全域變數一大堆, 即是說, 如果你把變數改了, 其他會用這個變數的程序也會受影響. 請緊記.
glDrawPixels() 畫圖時畫到什麼位置, 由 OpenGL 之內的某個變數決定的, 要改這個, 你要使用 glRasterPos2f() 去改它.
-----------------
OpenGL 預設的座標系統,
(1,1) 在視窗的右上方,
(0,0) 在視窗中心,
(-1,-1) 在視窗的左下方.
這個, 跟 microsoft 的視窗座標 是完全不同的, 請注意.
------------
glutInitWindowSize( 640, 640 ); // 設定視窗大小
glutCreateWindow( "hihi" ); // 建立視窗, 並把 title 設為 "hihi"
glutDisplayFunc(display); // 註冊負責顯示的 function
glutMainLoop(); // 開始視窗的 message loop
-------------
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // 清空畫面
每次重畫畫面時, 你也需要先清空畫面, 每一次畫圖, 圖其實也是畫到顯示卡的, 在顯示卡之內, 有一個剛畫的圖的 buffer, 如果你不先清空這個, 你就會重複的複到畫面上, 情況就好像, 你在紙上用鉛筆畫東西, 畫完了之後, 沒刷掉就再畫一樣.
------------glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
這個, 是對應著 glDrawPixels 而來的, 因為效率考慮, 所以,
OpenGL 預設, 你給 glDrawPixels 的圖檔資料, 它的每一個 row 的大小 ( 以 byte 來算 ), 也是可以給 4 整除的.
假設你的圖檔是 150x150, 每一個 row 的大小就會是 150 * 3 = 450 , 450 不能被 4 整除的. 如果要強行把它換成可以被 4 整除, 一般的做法, 就是在每一個 row 多加 2 bytes 沒用途的資料 (這個步驟我們叫 padding ), 如此 450 就會變成 452, 452 就可以被 4 整除了.
但是, 每 row 大小, 需要是多少的倍數, 雖然預設了是 4, 但是, 你是可以把它改成 1, 2, 4, 8, 其中任意一個的, 如果你設成 1, 這麼你就可以不用管 padding 的問題了 ( 因為什麼整數也可以被 1 整除呀 ), 但是, 懶散的結果, 就是程式 run-time 時慢一點點.
最好的做法, 應該直接使用 寬 可被 4 整除的圖.
-----------------
致 初學OpenGL的網友,
^^, 恭喜你, 竟然有心機看完這麼長的介紹, 到底... 得到什麼呢?... 就是... 一份功課 @@!!
功課一 :
"載入最少三個圖檔, 畫在畫面上不同的位置"
------------------------- |
|