Delphi7/WinXP です。
表題の通りOPENGLによるオフスクリーンレンダリングを試みています。
pfd_draw_to_bitmapを設定した上で、Tbitmap(BID)を使っているのですが、
wglMakeCurrentがどうしてもtrueになりません。
解決法をご存知の方いらっしゃいませんか?
procedure TForm1.SetPixelFormatDescriptor;
var
pfd: TPixelFormatDescriptor;
begin
with pfd do begin
nSize := sizeof(TPixelFormatDescriptor);
nVersion := 1;
dwFlags := PFD_DRAW_TO_BITMAP or
PFD_SUPPORT_OPENGL or
PFD_DOUBLEBUFFER
;
iPixelType := PFD_TYPE_RGBA;
cColorBits := 24;
cRedBits := 0;
cRedShift := 0;
cGreenBits := 0;
cGreenShift := 0;
cBlueBits := 0;
cBlueShift := 0;
cAlphaBits := 0;
cAlphaShift := 0;
cAccumBits := 0;
cAccumRedBits := 0;
cAccumGreenBits := 0;
cAccumBlueBits := 0;
cAccumAlphaBits := 0;
cDepthBits := 32;
cStencilBits := 0;
cAuxBuffers := 0;
iLayerType := PFD_MAIN_PLANE;
bReserved := 0;
dwLayerMask := 0;
dwVisibleMask := 0;
dwDamageMask := 0;
end;
nPixelFormat := ChoosePixelFormat(hdc, @pfd);
SetPixelFormat(hdc, nPixelFormat, @pfd);
end;
/////////////
GLCanvas := TBitmap.Create;
GLCanvas.HandleType := bmDIB;
GLCanvas.Width := Panel5.Width;
GLCanvas.Height := Panel5.Height;
GLCanvas.PixelFormat := pf24bit;
hdc := GetDC(GLCanvas.Handle); //hdc は HDC型
SetPixelFormatDescriptor;
hrc := wglCreateContext(hdc); //hrc は HGLRC型
if (wglMakeCurrent(hdc, hrc) = false) then begin //ここがTrueになりません
GLCanvas.Free;
end;
OpenGLは知らないけど、怪しいところを一つ指摘。
hdc := GetDC(GLCanvas.Handle);
↓
hdc := GLCanvas.Canvas.Handle;
だと思う。
GetDCの引数はウィンドウハンドルであって、
ビットマップハンドルではないのでは?
TBitmapのデバイスコンテキストはCanvas.Handleで参照します。
>みんみんさん
レスありがとうございます。
hdc := GetDC(GLCanvas.Handle);
↓
hdc := GLCanvas.Canvas.Handle;
試してみましたが、やはり同じでした。
wglMakeCurrentがfalseのままです。
調べてみたところどうやらTbitmap.canvas.handleが随時更新される
Delphi版TCanvasの仕様が原因らしいです。
しかし具体的な対応策は見つかっていません。
引き続き回答をお待ちしています。
やはり OpenGLは知らないけど、
hdc := GetDC(GLCanvas.Handle);
↓
hdc := GetDC(Panel5.Handle);
ではどうでしょうか?
> hdc := GetDC(GLCanvas.Handle);
> ↓
> hdc := GetDC(Panel5.Handle);
単純なダブルバッファリングであれば、Panel5のDCとればOKですが、
オフスクリーンレンダリングの場合はHBITMAPを作ってやるのが正しいかと。
C++ですが、
http://son-son.sakura.ne.jp/programming/opengl_avi.html
にありました。
DelphiのTBitmapが使えないのであれば、APIで作るしかないかと思います。
>調べてみたところどうやらTbitmap.canvas.handleが随時更新される
>Delphi版TCanvasの仕様が原因らしいです。
>しかし具体的な対応策は見つかっていません。
TCanvasの仕様が原因でしたら、
中村拓男さんのところで紹介されているCanvas.Lockの方法を
試してみてはいかがでしょう?
http://www.asahi-net.or.jp/~ha3t-nkmr/DGS/more_secrets.htm#Secret3
>うんとさん
レスありがとうございます。
現在Panel5.Handleで処理をしているのですが、
これのオフスクリーン化を目論んでいて、
さし当たってまず下処理の方法を考えています。
>にしのさん
レスありがとうございます。
APIで作る・・・なんだか難しそうですが、
少し調べてみたいと思います。
>みんみんさん
再度のレスありがとうございます。
Canvas.Lockを試してみたのですが、やはり結果は変わりません。
Lockの使い方が間違ってる気もするのですが・・・
GLCanvas := TBitmap.Create;
GLCanvas.Lock; //追加しました。
GLCanvas.HandleType := bmDIB;
GLCanvas.Width := Panel5.Width;
GLCanvas.Height := Panel5.Height;
GLCanvas.PixelFormat := pf24bit;
hdc := GetDC(GLCanvas.Handle); //hdc は HDC型
SetPixelFormatDescriptor;
hrc := wglCreateContext(hdc); //hrc は HGLRC型
if (wglMakeCurrent(hdc, hrc) = false) then begin //ここがTrueになりません
GLCanvas.Free;
end;
同じくOpenGLには詳しくありませんが……
みんみんさんが最初に指摘した点(GetDCは間違い)は元に戻しちゃダメでしょう。明らかにおかしいですから。
念のため、hdcが有効なハンドルかどうかちゃんとチェックするようにした方がいいですね。
あと、にしのさんが引用したページにある注意事項(PFD_GDI_SUPPORTが必要)は入れてみましたか?
> Lockの使い方が間違ってる気もするのですが・・・
TBitmapにLockメソッドはないはずだから確かにおかしいですね……
GLCanvas.Canvas.Lockでは? あとUnlockも忘れずに。
>watchさん
レスありがとうございます。
確かに間違ってました。
すいません。
PFD_GDI_SUPPORTも追加しています。
ただ、結果は変わらないです。
なにかもっと根本的な問題かもしれないですね…
GLCanvas := TBitmap.Create;
GLCanvas.canvas.Lock; //追加しました。
GLCanvas.HandleType := bmDIB;
GLCanvas.Width := Panel5.Width;
GLCanvas.Height := Panel5.Height;
GLCanvas.PixelFormat := pf24bit;
hdc := GetDC(GLCanvas.canvas.Handle); //hdc は HDC型
SetPixelFormatDescriptor;
hrc := wglCreateContext(hdc); //hrc は HGLRC型
if (wglMakeCurrent(hdc, hrc) = false) then begin //ここがTrueになりません
GLCanvas.Free;
end;
いや、だからGetDCはいりません。結果を確認すればおかしいことはわかるでしょう?
GetDCがとるのはあくまで「ウィンドウハンドル」であって「ビットマップハンドル」でも「デバイスコンテキストハンドル」でもないです。
あなたがやっていることは、同じ「カード」だからとクレジットカードで自動改札を通ろうとしているようなものです。
この場合、あなたが欲しいものはデバイスコンテキストハンドル(HDC)で、
TBitmap.Canvas.Handle=HDCなんだからその時点で必要なものは得られているでしょう?
とりあえずwglMakeCurrentだけでなく、そこに至るまでの関数もちゃんと成功しているのか
一つ一つ結果をチェックして、悪いところを切り分けてください。
>PFD_GDI_SUPPORTも追加しています。
正しくはPFD_SUPPOR_GDIです。(OPENGL.pas参照)
私の環境(del7+WinXPsp2)では
hdc := GLCanvas.Canvas.Handle;
の部分の修正と
上記のPFD_SUPPOR_GDIフラグの追加で
判定部分の wglMakeCurrent(hdc, hrc)が、
Trueを返すようになるようです。
ここの判定のみでしたらCanvas.Lockは無くても
いいようでした。
よっちさんどうでしょうか?
>みんみんさん
わざわざ検証していただきありがとうございます。
ただ現在出先で、再度確認できるのが1週間後になってしまいます。
申し訳ありません。
ただ、必ず報告させていただきますね。
訂正(^ ^)m
>正しくはPFD_SUPPOR_GDIです。(OPENGL.pas参照)
↓
正しくは PFD_SUPPORT_GDIです。(Windows.pas参照)
です。
無事解決したので報告です。
最終的に、みんみんさんの
>hdc := GLCanvas.Canvas.Handle;
>の部分の修正と
>上記のPFD_SUPPOR_GDIフラグの追加で
>判定部分の wglMakeCurrent(hdc, hrc)が、
>Trueを返すようになるようです。
これで問題がなくなりました。
皆様回答していただきありがとうございました。
解決しましたので
ツイート | ![]() |