看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《bbbbbbjeff (雲伴風 風隨雲)》之銘言: : 各位網友好,想請教關於用OpenGL貼圖的問題, : 目前用VC++ 2010的Windows Form專案寫了一個程式,需要貼 : 很多張圖,目前遇到的問題是所貼的圖其寬高在某些維度程式會爆 : ,某些維度不會??? 看超級手冊第2版第8章貼圖的部分有提 : 到寬高必須是2的冪次方,但我發現只要顯示卡是nVidia的晶 : 片不用2的冪次方也可以貼,而且每張貼圖大小可以不同,例如 : 下面兩張擷圖: : 1 : http://homepage8.seed.net.tw/web@5/bbbbbb/TemporaryShare/Texture1.jpg
: 2 : http://homepage8.seed.net.tw/web@5/bbbbbb/TemporaryShare/Texture2.jpg
: 在第1張擷圖內共貼3張圖,第1張貼圖的寬高是1000*600, : 第2張貼圖的寬高是3000*2000 : 在第2張擷圖內,是第1張擷圖沿著y軸轉180度,可以看到第3張貼圖, : 第3張貼圖的寬高是1920*1200 : 也就是說,3張貼圖的寬高完全不是2的冪次方也可以貼,只要顯示卡是 : nVidia的晶片就ok。(在Intel的顯示卡上就完全不行,變成空白一片) : 現在我的問題是,3000*2000都可以貼了,若小很多的應該沒問題才是 : ,但我試了以下幾種寬高,有的可以有的不行?? : 999*1000 ==>不行 ??? : 1000*1000 ==>可以 : 537*590 ==>可以 : 199x203 ==>可以 : 1999x2003 ==>不行 ??? : 我有以 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); : 去測試我的卡可以顯示的最大維是:8192,所以不能貼應該不是太大 : 才對... : 請問是否有網友知道問題在哪?? 抱歉,上一篇文可能說得不夠仔細,我提到的貼某些維度的圖 會程式會爆的意思是,程式就直接寫錯誤,然後就關閉了,以 下是目前我在 GeForce 8600GTS 測試會錯誤的維度: 999*1000 (24Bits bmp檔) 1999x2003 (24Bits jpg檔) 2854x2894 (24Bits jpg檔) 我讀檔的方式主要是用 .NET Framework 提供的 Bitmap 物件,搭配 Bitmap 物件內的 LockBits 函式 將好幾張影像鎖在記憶體內,再取 出RGB三個通道的值,存到三維陣列內。不管是bmp jpg tif ...都是這樣 取出RGB三個通道的值。如果是8bits灰階圖,也是用一樣這個方式讀, 只是我還是將它視為24bits的圖,以三個通道的記憶體去存一張8bits 的圖,三個通道的灰階值設都設為一樣就存到一個三維陣列內就是了。 接著再 new 一個 GLubyte **Pixels,將存到三維陣列內的值轉存到 GLubyte型態的二維陣列內,並且三維的值要存成一維,以符合glTexImage2D() 此函式的規定。以下是我在此函式內的參數: glTexImage2D(GL_TEXTURE_2D, 0, 3, Images[z]->Width, Images[z]->Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Pixels[z]); z就代表第z張image。 反覆看了可以貼圖的影像寬高與無法貼圖的影像寬高,還是不懂為什麼 有些可以貼,有些一貼程式就出現錯誤而停?? -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.116.82.254
NDark:這個問題是像素未達到memory alignment導致. 02/23 22:21
NDark:長及寬 都要可以除以 某個值(譬如說4) 02/23 22:22
NDark:確切的值多少要查. 總之npot 是讓你不用 512 , 1024 這樣跳 02/23 22:22
NDark:但也並非是任何 長寬像素都允許 ,算是一個潛規則 02/23 22:23
NDark:總之.不要故意找麻煩.把貼圖放大/加空白 到標準的解析度再傳 02/23 22:25
NDark:就算有NPOT,到顯示卡裡面還是2^n次方.只是顯示卡幫你填空白 02/23 22:27
bbbbbbjeff:謝謝指點,我試看看 02/23 22:40
VictorTom:N大說的是Gfx HW這端的可能實作方式, 但是spec上並沒有 02/23 23:47
VictorTom:對寫AP的programmer定出這樣的限制; 所以如果真的是N大 02/23 23:48
VictorTom:所提的問題, 那是Gfx的driver或HW沒有處理好這個feature 02/23 23:48
VictorTom:, 這應該是Gfx端的bug. 所以請問原po用的顯示卡與驅動程 02/23 23:49
VictorTom:式版本. 02/23 23:50
VictorTom:啊, 看到是86GTS了, 先試著換driver到新一點的版本試試, 02/23 23:51
VictorTom:(但不要到最新, N家A家的最新版驅動對舊世代顯卡通常都 02/23 23:51
VictorTom:不是最佳的); 如果可以的話找不同家顯卡或不同世代的卡 02/23 23:52
VictorTom:也交叉測試看看. (當然檢查NPOT的支援還是要做的XD) 02/23 23:52
VictorTom:剛發現漏了一個盲點, 程式錯誤要關閉前有訊息告知你錯誤 02/23 23:58
bbbbbbjeff:昨天剛更新到最新版... 02/23 23:59
VictorTom:的module是哪個嗎??或者可以看看windows的事件檢視器. 02/23 23:59
VictorTom:主要是希望釐清問題是texture餵給GL畫以後才發生, 還是 02/24 00:00
VictorTom:讀/解圖檔的時候使用的lib或中間自己處理的code有疏乎:) 02/24 00:00
bbbbbbjeff:沒有告訴我是哪個模組錯,只寫Project.exe已經停止運作 02/24 00:03
bbbbbbjeff:還有個除錯的按鈕可按,按下後出現一個訊息: 於0x0573f 02/24 00:05
bbbbbbjeff:c29 的Project.exe 中發生未處理的例外狀況: 0xC000000 02/24 00:06
bbbbbbjeff:5: 讀取位置0x0e00c001 時發生存取違規. 02/24 00:07
VictorTom:0xC0000005嗎?? 這個比較像是您的code或其他SW的lib端出 02/24 00:07
VictorTom:錯ㄟ.... 啊, 不好意思, 不小心斷到....Orz 02/24 00:08
bbbbbbjeff:我按下中斷後,反組譯碼有個黃箭頭停在這一行: 02/24 00:09
VictorTom:疑!?原來沒斷到XD 按下除錯後應該還會有VC的視窗導引你 02/24 00:09
bbbbbbjeff:0573FC29 movzx ebx,byte ptr [esi+2] 02/24 00:09
VictorTom:除錯程序, 找找看error發生的斷點是不是你的source code 02/24 00:09
VictorTom:不是的話, 就看一下執行位址(就是0573FC29), 在VC的 02/24 00:10
VictorTom:module list頁籤裡, 是屬於哪一個.exe或.dll的. 02/24 00:10
bbbbbbjeff:除錯後發現,中斷在glTexImage2D()出現的那行 02/24 00:13
bbbbbbjeff:我讀999*1000的彩色BMP,中斷在glTexImage2D()這行 02/24 00:15
VictorTom:查一下call glTexImage2D這行時傳進去的圖檔指標, 算一 02/24 00:18
VictorTom:一下 0x0e00c001 是不是正好超過你傳進去的圖檔所佔記憶 02/24 00:19
VictorTom:體的範圍. 不過如果該位址和您傳入的指標距離相差甚遠關 02/24 00:21
VictorTom:係兜不起來, 就比較難辦了XD 不過仍然可以看一下module 02/24 00:21
VictorTom:的頁籤, 看一下 0573FC29 這位址是屬於誰的range :) 02/24 00:22
bbbbbbjeff:我擷圖給你看 02/24 00:23
purpose:>讀取位置0x0e00c001 時發生存取違規 對kernel用的 02/24 00:25
purpose:位址做讀取。 02/24 00:25
bbbbbbjeff:除錯畫面:http://goo.gl/8cVYQ 02/24 00:26
VictorTom:0x0e開使應該還不到kernel的位址區域吧?? 02/24 00:29
purpose:欸,少看了0x右邊的0,位址>=0x80000000才是kernel 02/24 00:29
VictorTom:請scroll一下module的頁籤向右, 應該會有memory range, 02/24 00:29
VictorTom:只是看起來似乎是NV的OGL driver出包機率比較高@_@" 02/24 00:30
bbbbbbjeff:有,我再擷一張 02/24 00:31
VictorTom:順便請教您的圖傳入glTexImage2D時的address值:) 02/24 00:32
VictorTom:雄雄發現, nv的dll都是0x69開頭, 出錯的位址不像它了Orz 02/24 00:34
bbbbbbjeff:在此 http://goo.gl/dT0f5 02/24 00:34
VictorTom:不在圖裡XD 看一下它在誰的range回一下名字就行了XD 02/24 00:37
bbbbbbjeff:傳入glTexImage2D時的address值是:0x01213950 02/24 00:38
bbbbbbjeff:將addres range排序號,發現沒有0573FC29所屬的範圍? 02/24 00:41
VictorTom:這....那小弟我只能投子了Orz 介意把程式與當前這張圖檔 02/24 00:47
VictorTom:share出來跑跑看嗎? 02/24 00:47
bbbbbbjeff: 你是VC2010嗎? 02/24 00:52
VictorTom:我只有2005 XD 不過只拿.exe與.bmp的話, 應該VC版本就無 02/24 00:56
bbbbbbjeff:OK,我傳到網路,稍等 02/24 00:57
VictorTom:關了吧@_@" 不過.exe可能RTL要用沒dll的那個選項build. 02/24 00:57
bbbbbbjeff:連.NET Framework 4 (Standalone Installer)與 02/24 01:02
bbbbbbjeff:Microsoft Visual C++ 2010 可轉散發套件一併給你,你 02/24 01:02
bbbbbbjeff:可能要先安裝這兩個套件才能跑VC2010寫的EXE檔 02/24 01:03
bbbbbbjeff:50幾MB,上傳中,快好了 02/24 01:07
VictorTom:.Net4好像我在Windows Update就裝過了, VC2010 redist 02/24 01:10
VictorTom:MS不知道抓不抓得到XD 02/24 01:10
bbbbbbjeff:喔,那你的電腦OpenGL相關的.h .lib .dll 都已經有了吧 02/24 01:14
bbbbbbjeff:點這下載 http://goo.gl/YvnUU 02/24 01:17
purpose:蠻難偵錯的案例。第一次碰到非 kernel space 就禁止讀取的 02/24 01:19
bbbbbbjeff:purpose大 也請幫幫忙吧 02/24 01:21
VictorTom:對啊, 頗有趣的, 其實小弟對那個0573FC29這個resolve不 02/24 01:22
VictorTom:出的module很有興趣XD 不過, 體力還能撐多久就....Orz 02/24 01:22
bbbbbbjeff:RAR檔內有個MQOpenGLControl.DLL檔,是我另外安裝的元 02/24 01:24
bbbbbbjeff:件,要跟EXE放在同一資料夾內才可執行 02/24 01:25
bbbbbbjeff:我在glTexImage2D()前加上下面的CODE,還是錯一樣? 02/24 01:35
bbbbbbjeff:glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 02/24 01:36
bbbbbbjeff:不是說加上glPixelStorei();去對齊就OK了嗎? 02/24 01:36
VictorTom:個人覺得這裡alignment下1不應該有什麼錯, 另外, 小弟這 02/24 02:06
VictorTom:邊NV 88GT, driver 178.24, XP sp3 32bit, 可以做出一樣 02/24 02:07
VictorTom:的錯誤, 而且錯誤的disasm address還一模一樣. 初步看了 02/24 02:08
VictorTom:一下該段disasm的內容, 的確應該是在搬你的圖檔到某個位 02/24 02:10
VictorTom:址去, 還沒跟到是不是就這樣搬到超過範圍; 不過暫時建議 02/24 02:10
VictorTom:您改借個ATI的平台先測測看....@_@" 02/24 02:11
bbbbbbjeff:喔喔 那可能要找看看有沒有ATI的平台了... 02/24 02:13
bbbbbbjeff:還是感謝兩位 謝謝 02/24 02:13
bbbbbbjeff:終於OK了 ^^ 02/24 02:22
VictorTom:查了一下, PACK與UNPACK的alignment, 對應到原po的issue 02/24 02:35
VictorTom:應該是glTexImage2D餵進去的圖是3byte緊連的, row與row 02/24 02:37
VictorTom:中間沒有特殊alignment, 所以此時UNPACK的alignment應該 02/24 02:38
VictorTom:設為1, 設成4的話driver會以為來源影像的row有對齊4byte 02/24 02:39
VictorTom:於是這case大概copy到最後幾個row時就超過source範圍了. 02/24 02:40
VictorTom:相對的如果餵入的source有做ROW的2/4/8 alignment, 就需 02/24 02:40
VictorTom:要把alignment設成2/4/8, 這樣driver才會copy到正確的 02/24 02:41
VictorTom:pixels. 小弟以前多是餵3byte不align的texture, 所以 02/24 02:42
VictorTom:alignment自己老設為1, 所以....XD 02/24 02:42
VictorTom:除了GL官網的man page, 剛goo到的這網頁寫的也不錯: 02/24 02:43
VictorTom:http://book.51cto.com/art/200809/88181.htm (簡中) 02/24 02:43
VictorTom:所以這error應該不是driver有錯, 而且glTexImage2D的 02/24 02:44
VictorTom:source的alignment與glPixelStore的UNPACK alignment設 02/24 02:44
VictorTom:定不一致所造成的, 所以改成1能夠解決原po的issue:) 02/24 02:45
Bencrie:我覺得原po你先把24bits BMP弄到ok再說 ... 讀圖檔應該用 02/24 09:00
Bencrie:不到二維陣列,直接讀進去連 alignment都不用改就能用了XD 02/24 09:01
VictorTom:確實是不用二維陣列, 但是如果直接把BMP的DIB拿進來用, 02/24 09:08
VictorTom:反而可能需要設alignment為4, 因為BMP的DIB在row上是會 02/24 09:08
VictorTom:做padding的@_@" 不過目前看起來原po處理模式是透過lib 02/24 09:09
VictorTom:把raw直接連續串起來餵給TexImage2D, 所以alignment設1 02/24 09:10
VictorTom:以後就能解決了:) 02/24 09:10
VictorTom:PS. 上面這段推的alignment是只GL的UNPACK alignment. 02/24 09:11
bbbbbbjeff:用到二維陣列是因為我會有好幾張圖要存,如果有10張我 02/24 23:32
bbbbbbjeff:會動態宣告一個(10)*(寬*高*3)的二維陣列,也就是我是 02/24 23:34
bbbbbbjeff:將每一張24bits圖存成1維的,擺到該2維陣列的某一列, 02/24 23:35
bbbbbbjeff:然後,glTexImage2D()是放在for裡面,裡面參數是: 02/24 23:37
bbbbbbjeff:glTexImage2D(GL_TEXTURE_2D,0,3,w,h,0,GL_RGB, 02/24 23:39
bbbbbbjeff:GL_UNSIGNED_BYTE,Pixels[z]); 陣列索引z就代表第幾張 02/24 23:40
bbbbbbjeff:所以寫Pixels[z]也是只送一維的資料進去繪 02/24 23:42
Bencrie:了解 XD 另外 BMP 通常是 GL_BGR 排列 02/24 23:52
bbbbbbjeff:了解^^ 02/25 02:25