CB编OpenGL问题(100分)

  • 主题发起人 主题发起人 TComponent
  • 开始时间 开始时间
T

TComponent

Unregistered / Unconfirmed
GUEST, unregistred user!
我把一个Delphi的OpenGL程序改成CB的
总是不对
不知怎么回事
源程序如下
BOOL bSetupPixelFormat(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd, *ppfd;
int pixelformat;
ppfd = &pfd;
ppfd->nSize = sizeof(PIXELFORMATDESCRIPTOR);
ppfd->nVersion = 1;
ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER;
ppfd->iPixelType = PFD_TYPE_RGBA;
ppfd->cColorBits = 8;
//ppfd->cRedBits = 8;
//ppft->cRedShift = 8;
//ppfd->cGreenBits = 8;
//ppft->cGreenShift = 8;
//ppfd->cBlueBits = 8;
//ppft->cBlueShift = 8;
//ppfd->cAlphaBits = 8;
//ppft->cAlphaShift = 8;
ppfd->cAccumBits = 0;
//ppfd->cAccumRedBits =0;
//ppfd->cAccumGreenBits =0;
//ppfd->cAccumBlueBits =0;
//ppfd->cAccumAlphaBits =0;
ppfd->cDepthBits = 16;
ppfd->cStencilBits = 0;
//ppfd->cAuxBuffers
//ppfd->iLayerType
//ppfd->bReserved
ppfd->dwLayerMask = PFD_MAIN_PLANE;
//ppfd->dwVisibleMask
//ppfd->dwDamageMask
if ( (pixelformat = ChoosePixelFormat(hdc, ppfd)) == 0 )
{
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
if (SetPixelFormat(hdc, pixelformat, ppfd) == FALSE)
{
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
return TRUE;
}
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
ghDC = GetDC(Handle);
if (!bSetupPixelFormat(ghDC))
Close();
ghRC = wglCreateContext(ghDC);
if(ghRC == NULL)
ShowMessage(":-)~ ghRC == NULL");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if (ghRC)
wglDeleteContext(ghRC);
if (ghDC)
ReleaseDC(Handle, ghDC);
}
//---------------------------------------------------------------------------
void TForm1::DrawScene(void)
{
//TODO: Add your source code here
if(wglMakeCurrent(ghDC, ghRC)==false)
ShowMessage("Could not MakeCurrent 1");
glClearColor(1.0,1.0,1.0,0.0);
glClear( GL_COLOR_BUFFER_BIT);
glOrtho(-1.0,1.0,-1.0,1.0,-1.0,1.0);
glBegin(GL_POLYGON);
glColor3f(1.0,0.0,0.0);
glVertex3f(-0.5,-0.5,0.0);
glColor3f(0.0,1.0,0.0);
glVertex3f(-0.5,0.5,0.0);
glColor3f(0.0,0.0,1.0);
glVertex3f(0.5,0.5,0.0);
glColor3f(1.0,1.0,1.0);
glVertex3f(0.5,-0.5,0.0);
glEnd;
if(wglMakeCurrent(ghDC, ghRC)==false)
ShowMessage("Could not MakeCurrent 2");
SwapBuffers(ghDC);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormPaint(TObject *Sender)
{
DrawScene();
}
//---------------------------------------------------------------------------
请问合适调用wglMakeCurrent
运行时DrawScene第一次调用没问题
第二次一般总是同不过(result==false)
那位大侠帮我看看
不胜感激

 
wglMakeCurrent不可以放在DrawSence里吧,应放在wglCreateContext后面
只调用一次。

请看我以前写的函数。

void glInit(HWND ghWnd)
{ PIXELFORMATDESCRIPTOR pfd;
pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion=1;
pfd.dwFlags=PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
pfd.dwLayerMask=PFD_MAIN_PLANE;
pfd.iPixelType=PFD_TYPE_RGBA;
pfd.cColorBits=24;
pfd.cDepthBits=32;
pfd.cAccumBits=0;
pfd.cStencilBits=0;
ghDC=GetDC(ghWnd);
SetPixelFormat(ghDC,ChoosePixelFormat(ghDC,&pfd),&pfd);
ghRC=wglCreateContext(ghDC);
wglMakeCurrent(ghDC,ghRC);
}
 
谢谢
我试了试
还是不行
请问能将您的程序Mail一份给我么?
luojianwen@263.net
 
请说说怎么不行,没有wglMakeCurrent的问题了吧,那么又出现了什么问题?

 
程序运行时只有填充背景色
并不画多边形

wglMakeCurrent调用的位置移到OnShow()也不行

还有,我有一个疑问
wglMakeCurrent指调用一次
和SwapBuffer是否矛盾

谢谢
 
wglMakeCurrent指调用一次和SwapBuffer并不矛盾。

你的程序除wglMakeCurrent外并无问题,问题在于VCL,不能及时地刷新。
(只是指你的DrawScene里的这一段代码,画别的东西还没发现有这种情况。)
把DrawScene放在Timer里,Interval设为100或更小,等6,7秒后图形才能出来。真怪!

我用API重写了一遍(就是说完全不用VCL),BCB4编译,程序一运行多边形就画出来了。

VCL并不是用在哪儿都好啊。
 
可是在Delphi下并没有这种问题
莫名其妙
 
那就是说除了VCL,还与编译器有关。:-(
 
我参考的一个Delphi的例程
是在每次绘图都调用了一下wglMakeCurrent
而且我也试着在Delphi下编过
sigh...

 
应该说只有一点问题,那就是,你不应该在FORMPAINT事件中调用绘制场景的函数。
实际上,程序在开始时正常,那么说,问题就不大。因为程序的运行后,第一次,肯定要绘制窗口的屏幕图象,可是在运行后,如果窗口没事的时候是不会去做PAINT工作的。如果切换多个程序,或者最小化,然后回到你的程序,屏幕刷新,那么也应该可以看到你的绘图结果.如果做动画对时间要求不高的话,可以使用TIMER。否则最好使用
ONIDLE事件。
另外,你的代码中,检查出错误的地方,最好是让后面的代码不要再运行下去了,
因为这样会增加调试的难度。
再者,场景绘制的函数中:调用了两遍条件语句
if(wglMakeCurrent(ghDC, ghRC)==false)
ShowMessage("Could not MakeCurrent 1");
这是不应该的,后面的条件语句应该改为
if(wglMakeCurrent(null,null)==false)
{ ShowMessage("Could not MakeCurrent 1");
break//伪码;
}
意思是,前面一次激活RC,后面一次关闭RC.并且在调用SwapBuffers函数前可以调用
Flush函数保证绘图工作的绝对执行.
还有,这样写的话,通常用于多线程程序.单线程的话,不必如此,只要在绘图工作之前
调用wglMakeCurrent函数激活RC即可.
声明:我不是很喜欢CB,上面的代码我可没有试验过.----啲啲嗒
 
多人接受答案了。
 
后退
顶部