【发布时间】:2020-09-09 01:42:37
【问题描述】:
我正在使用带有 OpenGL/Wiggle 的 C# 在本机 Win32 窗口上创建 OpenGL 上下文。我的代码中没有任何错误,但是当我尝试将上下文的背景颜色更改为黑色时,它保持白色。
Main()
static void Main()
{
MSG Msg = new MSG();
int rv;
if (Program.RegisterClass() == 0)
return;
if (Program.Create() == 0)
return;
// Main message loop:
while ((rv = User32.GetMessage(out Msg, IntPtr.Zero, 0, 0)) > 0)
{
User32.TranslateMessage(ref Msg);
User32.DispatchMessage(ref Msg);
}
}
RegisterClass()
WNDCLASSEX wcex = new WNDCLASSEX();
wcex.style = User32.CS.DBLCLKS | User32.CS.HREDRAW | User32.CS.VREDRAW | User32.CS.OWNDC;
wcex.cbSize = (uint)Marshal.SizeOf(wcex);
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hIcon = User32.LoadIcon(IntPtr.Zero, (IntPtr)User32.IDI_APPLICATION);
wcex.hCursor = User32.LoadCursor(IntPtr.Zero, (int)User32.IDC_ARROW);
wcex.hIconSm = IntPtr.Zero;
wcex.hbrBackground = (IntPtr)(User32.COLOR_WINDOW + 1);
wcex.lpszMenuName = null;
wcex.lpszClassName = "HelloClass";
if (User32.RegisterClassEx(ref wcex) == 0)
{
User32.MessageBox(IntPtr.Zero, "RegisterClassEx failed", "appName",
(int)(User32.MB_OK | User32.MB_ICONEXCLAMATION | User32.MB_SETFOREGROUND));
return (0);
}
return (1);
创建()
public static int Create()
{
IntPtr fakewnd = User32.CreateWindowEx(
0,
"HelloClass",
"OpenGL Window",
User32.WS.CLIPSIBLINGS | User32.WS.CLIPCHILDREN,
0, 0,
250, 250,
IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero
);
IntPtr fakedc = User32.GetDC(fakewnd);
WGL.MakeCurrent(fakedc, IntPtr.Zero);
PixelFormatDescriptor desk = new PixelFormatDescriptor(PFD.Default);
int deskID = DeviceContext.ChoosePixelFormat(fakedc, ref desk);
DeviceContext.SetPixelFormat(fakedc, deskID, ref desk);
IntPtr fakerc = WGL.CreateContext(fakedc);
if (fakerc == IntPtr.Zero) { throw new Exception("Could not create rendering context."); }
if (WGL.MakeCurrent(fakedc, fakerc) == false) throw new Exception("Could not make rendering context current.");
WGL.LoadWGLExtensions();
WGL.MakeCurrent(IntPtr.Zero, IntPtr.Zero);
WGL.DeleteContext(fakerc);
User32.ReleaseDC(fakewnd, fakedc);
User32.DestroyWindow(fakewnd);
IntPtr wnd = User32.CreateWindowEx(
0,
"HelloClass",
"OpenGL Window 2",
User32.WS.CLIPSIBLINGS | User32.WS.CLIPCHILDREN | User32.WS.OVERLAPPEDWINDOW | User32.WS.VISIBLE,
0, 0,
250, 250,
IntPtr.Zero, IntPtr.Zero,
IntPtr.Zero, IntPtr.Zero
);
IntPtr dc = User32.GetDC(wnd);
Dictionary<WGL.wglPixelFormatAttributeARB, object> attribs = new Dictionary<WGL.wglPixelFormatAttributeARB, object>();
attribs.Add(WGL.wglPixelFormatAttributeARB.DRAW_TO_WINDOW_ARB, 1);
attribs.Add(WGL.wglPixelFormatAttributeARB.SUPPORT_OPENGL_ARB, 1);
attribs.Add(WGL.wglPixelFormatAttributeARB.DOUBLE_BUFFER_ARB, 1);
attribs.Add(WGL.wglPixelFormatAttributeARB.PIXEL_TYPE_ARB, WGL.wglPixelTypeARB.RGBA_ARB);
attribs.Add(WGL.wglPixelFormatAttributeARB.ACCELERATION_ARB, WGL.wglAccelerationModeARB.FULL_ACCELERATION_ARB);
attribs.Add(WGL.wglPixelFormatAttributeARB.COLOR_BITS_ARB, 32);
attribs.Add(WGL.wglPixelFormatAttributeARB.ALPHA_BITS_ARB, 8);
attribs.Add(WGL.wglPixelFormatAttributeARB.DEPTH_BITS_ARB, 24);
attribs.Add(WGL.wglPixelFormatAttributeARB.STENCIL_BITS_ARB, 8);
attribs.Add(WGL.wglPixelFormatAttributeARB.SAMPLE_BUFFERS_ARB, 1);
attribs.Add(WGL.wglPixelFormatAttributeARB.SAMPLES_ARB, 4);
int pixelFormatID;
bool status = WGL.ChoosePixelFormatARB(dc, attribs, out pixelFormatID);
if (!status) throw new Exception("Pixel format could not be set.");
PixelFormatDescriptor ndesk = new PixelFormatDescriptor();
DeviceContext.DescribePixelFormat(dc, pixelFormatID, 0, out ndesk);
DeviceContext.SetPixelFormat(dc, pixelFormatID, ref ndesk);
int major = Gl.GetInteger(GetPName.MajorVersion);
int minor = Gl.GetInteger(GetPName.MinorVersion);
int[] contextAttribs = new int[]
{
(int)WGL.wglContextAttributeARB.CONTEXT_MAJOR_VERSION_ARB, major,
(int)WGL.wglContextAttributeARB.CONTEXT_MINOR_VERSION_ARB, minor,
(int)WGL.wglContextProfileMaskARB.CONTEXT_CORE_PROFILE_BIT_ARB, 0
};
IntPtr rc = WGL.CreateContextAttribsARB(dc, IntPtr.Zero, contextAttribs);
if (rc == null) throw new Exception("Could not create rendering context.");
if (!WGL.MakeCurrent(dc, rc)) throw new Exception("Could not make rendering context current.");
return 1;
}
WndProc(IntPtr, uint, IntPtr, IntPtr)
private static IntPtr WndProc(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam)
{
switch (message)
{
case User32.WM.PAINT:
{
IntPtr hDC;
PAINT ps = new PAINT();
hDC = User32.BeginPaint(hWnd, out ps);
Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
Gl.Viewport(0, 0, 250, 250);
Gl.ClearColor(0, 0, 0, 1);
User32.EndPaint(hWnd, ref ps);
return IntPtr.Zero;
}
case User32.WM.DESTROY:
//User32.PostQuitMessage(0);
return IntPtr.Zero;
//case Win32.WM_CREATE:
// return IntPtr.Zero;
default:
return (User32.DefWindowProc(hWnd, message, wParam, lParam));
}
}
我正在使用自定义 Wiggle/Win32/Gdi 包装器和 OpenGL4CSharp。有谁知道我的代码有什么问题?我已经摆弄了几个小时,但我无法找出问题所在。
【问题讨论】:
-
glClearColor() 应该在 glClear() 之前。 glViewport() 也一样
-
@ScottMudge
glViewport不影响glClear。 (当然glClearColor效果glClear) -
@ScottMudge 我尝试了这三行的所有命令,但它仍然没有任何作用。
-
那么很可能 OpenGL 根本无法正常工作。检查 OpenGL 错误状态。