生锈的Win32 OpenGL窗口:无法加载某些函数指针
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了生锈的Win32 OpenGL窗口:无法加载某些函数指针相关的知识,希望对你有一定的参考价值。
#[cfg(windows)] extern crate winapi;
#[cfg(windows)] use winapi::shared::windef::HWND;
#[cfg(windows)] use winapi::shared::windef::HMENU;
#[cfg(windows)] use winapi::shared::windef::HBRUSH;
#[cfg(windows)] use winapi::shared::minwindef::HINSTANCE;
#[cfg(windows)] use winapi::shared::minwindef::UINT;
#[cfg(windows)] use winapi::shared::minwindef::DWORD;
#[cfg(windows)] use winapi::shared::minwindef::WPARAM;
#[cfg(windows)] use winapi::shared::minwindef::LPARAM;
#[cfg(windows)] use winapi::shared::minwindef::LRESULT;
#[cfg(windows)] use winapi::um::winnt::LPCWSTR;
#[cfg(windows)] use winapi::um::winuser::WS_OVERLAPPEDWINDOW;
#[cfg(windows)] use winapi::um::winuser::WS_VISIBLE;
#[cfg(windows)] use winapi::um::winuser::WNDCLASSW;
#[cfg(windows)] use std::os::windows::ffi::OsStrExt;
#[cfg(windows)] use std::ffi::OsStr;
#[cfg(windows)] use std::os::raw::c_void;
#[cfg(windows)] use winapi::um::libloaderapi::GetProcAddress;
#[cfg(windows)] use gl::types::*;
// Vertex data
static VERTEX_DATA: [GLfloat; 6] = [0.0, 0.5, 0.5, -0.5, -0.5, -0.5];
// Shader sources
static VS_SRC: &'static str = "
#version 150
in vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}";
static FS_SRC: &'static str = "
#version 150
out vec4 out_color;
void main() {
out_color = vec4(1.0, 1.0, 1.0, 1.0);
}";
mod gl
{
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
#[cfg(windows)]
fn to_wstring(str : &str) -> Vec<u16>
{
let v : Vec<u16> =
OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
v
}
#[cfg(windows)]
pub unsafe extern "system" fn window_proc(h_wnd :HWND,
msg :UINT, w_param :WPARAM, l_param :LPARAM) -> LRESULT
{
if msg == winapi::um::winuser::WM_DESTROY {
winapi::um::winuser::PostQuitMessage(0i32);
}
return winapi::um::winuser::DefWindowProcW(h_wnd, msg, w_param, l_param);
}
fn draw_gl_scene(window_width: i32, window_height: i32,
h_dc: winapi::shared::windef::HDC)
{
unsafe
{
let module = winapi::um::libloaderapi::LoadLibraryW(to_wstring("opengl32.dll") .as_ptr());
// gl::load_with(|s| GetProcAddress(module,
// s.as_ptr() as *const i8) as *const c_void);
gl::Viewport::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::Viewport::is_loaded() {
gl::Viewport(0, 0, window_width, window_height);
} else {
panic!("gl::Viewport was not loaded")
}
gl::ClearColor::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::ClearColor::is_loaded() {
gl::ClearColor(0.12109375f32, 0.12109375f32, 0.12109375f32, 1.0f32);
} else {
panic!("gl::ClearColor was not loaded")
}
gl::GetError::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
let error_check_value: GLenum = gl::GetError();
/*
gl::CreateShader::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
let mut vertex_shader_id = 0u32;
if gl::CreateShader::is_loaded() {
vertex_shader_id = gl::CreateShader(gl::VERTEX_SHADER);
} else {
panic!("gl::CreateShader was not loaded")
}
*/
/*
let c_str = std::ffi::CString::new(VS_SRC.as_bytes()).unwrap();
gl::ShaderSource::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::ShaderSource::is_loaded() {
gl::ShaderSource(vertex_shader_id, 1, &c_str.as_ptr(), std::ptr::null_mut());
} else {
// panic!("gl::ShaderSource was not loaded")
}
gl::CompileShader::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::CompileShader::is_loaded() {
gl::CompileShader(vertex_shader_id);
} else {
// panic!("gl::CompileShader was not loaded")
}
let mut vertex_array_id: GLuint = 0u32;
gl::GenVertexArrays::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::GenVertexArrays::is_loaded() {
gl::GenVertexArrays(1, &mut vertex_array_id as *mut u32);
} else {
panic!("gl::GenVertexArrays was not loaded")
}
*/
gl::Clear::load_with(|s| GetProcAddress(module,
s.as_ptr() as *const i8) as *const c_void);
if gl::Clear::is_loaded() {
gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT | gl::STENCIL_BUFFER_BIT);
} else {
panic!("gl::Clear was not loaded")
}
winapi::um::wingdi::SwapBuffers(h_dc);
}
}
fn main()
{
unsafe
{
let class_name = to_wstring("OpenGL");
let h_instance = winapi::um::libloaderapi::GetModuleHandleW(std::ptr::null_mut());
let wnd = WNDCLASSW {
style: 0,
lpfnWndProc: Some(window_proc),
cbClsExtra: 0,
cbWndExtra: 0,
hInstance: h_instance,
hIcon: winapi::um::winuser::LoadIconW(0 as HINSTANCE,
winapi::um::winuser::IDI_APPLICATION),
hCursor: winapi::um::winuser::LoadCursorW(0 as HINSTANCE,
winapi::um::winuser::IDI_APPLICATION),
hbrBackground: 16 as HBRUSH,
lpszMenuName: 0 as LPCWSTR,
lpszClassName: class_name.as_ptr(),
};
winapi::um::winuser::RegisterClassW(&wnd);
let window_width = 640;
let window_height = 480;
let h_wnd_window = winapi::um::winuser::CreateWindowExW(0, class_name.as_ptr(),
to_wstring("OpenGL Example").as_ptr(), WS_OVERLAPPEDWINDOW | WS_VISIBLE,
0, 0, window_width, window_height, 0 as HWND, 0 as HMENU, h_instance,
std::ptr::null_mut());
let mut msg = winapi::um::winuser::MSG {
hwnd : 0 as HWND,
message : 0 as UINT,
wParam : 0 as WPARAM,
lParam : 0 as LPARAM,
time : 0 as DWORD,
pt : winapi::shared::windef::POINT { x: 0, y: 0, },
};
let h_dc = winapi::um::winuser::GetDC(h_wnd_window);
let pfd = winapi::um::wingdi::PIXELFORMATDESCRIPTOR {
nSize: std::mem::size_of::<winapi::um::wingdi::PIXELFORMATDESCRIPTOR>() as u16,
nVersion: 1,
dwFlags: winapi::um::wingdi::PFD_DRAW_TO_WINDOW
| winapi::um::wingdi::PFD_SUPPORT_OPENGL | winapi::um::wingdi::PFD_DOUBLEBUFFER,
iPixelType: winapi::um::wingdi::PFD_TYPE_RGBA,
cColorBits: 64,
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: 8,
cAuxBuffers: 0,
iLayerType: winapi::um::wingdi::PFD_MAIN_PLANE,
bReserved: 0,
dwLayerMask: 0,
dwVisibleMask: 0,
dwDamageMask: 0,
};
let pixel_format = winapi::um::wingdi::ChoosePixelFormat(h_dc,
&pfd as *const winapi::um::wingdi::PIXELFORMATDESCRIPTOR);
winapi::um::wingdi::SetPixelFormat(h_dc, pixel_format,
&pfd as *const winapi::um::wingdi::PIXELFORMATDESCRIPTOR);
let h_rc = winapi::um::wingdi::wglCreateContext(h_dc);
winapi::um::wingdi::wglMakeCurrent(h_dc, h_rc);
winapi::um::winuser::ShowWindow(h_wnd_window, winapi::um::winuser::SW_SHOW);
loop
{
if winapi::um::winuser::PeekMessageW(&mut msg, 0u32 as HWND, 0u32, 0u32,
winapi::um::winuser::PM_REMOVE) > 0i32 {
if msg.message == winapi::um::winuser::WM_QUIT {
break;
} else {
winapi::um::winuser::TranslateMessage(&mut msg);
winapi::um::winuser::DispatchMessageW(&mut msg);
}
} else {
draw_gl_scene(window_width, window_height, h_dc);
}
}
}
}
上面的代码是我在这里过时项目的实现版本:https://www.codeproject.com/tips/1053658/win-gui-programming-in-rust-language/
使用最新版本的winapi和gl_generator作为唯一的两个依赖项,我扩展了入门代码,以便与Win32 API一起成功呈现OpenGL上下文,而不是像货物箱gl-rs的贡献者所建议的glfw。当在Windows机器上运行时,这个项目会显示一个黑屏,如this link.中所示
由于无法加载与着色器或顶点缓冲区对象相关的任何函数指针,因此到目前为止,任何进一步尝试渲染更实质的东西都没有结果。
如果你梳理函数draw_gl_scene,你会看到我有一个通用的“load_with”函数注释掉了一系列特定于函数的“load_with”函数以及执行代码或恐慌,具体取决于所讨论的函数是否“is_loaded”。通用的“load_with”我一直在遏制,直到编写功能特定的“加载”功能不再成立。
对于CreateShader,ShaderSource,CompileShader和GenVertexArrays,如果我取消注释其中任何一个,它们都不会成功加载。我确定这是一个用户错误,winapi和gl-rs之一的可能性或者winapi和gl_generator之间的异常交互是不可能的。我是如何解决这个问题的。如果你读到这么远,我感谢你的时间。
简而言之,对于Windows:
GetProcAddress
仅对OpenGL <= 1.1有效wglGetProcAddress
仅对OpenGL> 1.1有效
此外,着色器的使用需要OpenGL> = 2.0。最好使用OGL> = 3.2 Core Profile。对于这种情况:
- 你需要一个适当的OpenGL> = 3.0的上下文,它是使用
wglCreateContextAttribsARB
创建的。 - 您需要一个有效的当前上下文来使用
wglCreateContextAttribsARB
获取指向wglGetProcAddress
的指针。 - 这种情况可能是暂时的。它可以用
wglCreateContext
创建。你得到那个指针后可以删除它;并创造“真实”的背景。
.
以上是关于生锈的Win32 OpenGL窗口:无法加载某些函数指针的主要内容,如果未能解决你的问题,请参考以下文章
使用 cygwin 编译器的定制 win32 窗口上的 OpenGL 不起作用
在启用 CLR 但没有 CRT 的 VC++ 中创建 Win32 dll