在绘制到屏幕之前,opengl纹理中发生意外像素变化
我正在编写一个框架,以便能够在屏幕上绘制像素。然而,现在我正在尝试更新屏幕,前4个像素显示随机颜色 当我只是向我的窗口模块发送一个指向图像数据的指针时,我没有这个问题,但是现在我正在传递一个绘图函数作为闭包,这就开始发生了。我不认为这是我的绘图功能中的一个问题,因为我写了这些像素,它们仍然被修改 我的主要绘图功能:在绘制到屏幕之前,opengl纹理中发生意外像素变化,opengl,rust,ffi,unsafe,raw-pointer,Opengl,Rust,Ffi,Unsafe,Raw Pointer,我正在编写一个框架,以便能够在屏幕上绘制像素。然而,现在我正在尝试更新屏幕,前4个像素显示随机颜色 当我只是向我的窗口模块发送一个指向图像数据的指针时,我没有这个问题,但是现在我正在传递一个绘图函数作为闭包,这就开始发生了。我不认为这是我的绘图功能中的一个问题,因为我写了这些像素,它们仍然被修改 我的主要绘图功能: //定义绘图函数 fn随机像素(图像宽度:usize,图像高度:usize)->*常数标准::ffi::c\U无效 { //定义颜色 让黑色像素=图像::颜色{红色:0,绿色:0,蓝
//定义绘图函数
fn随机像素(图像宽度:usize,图像高度:usize)->*常数标准::ffi::c\U无效
{
//定义颜色
让黑色像素=图像::颜色{红色:0,绿色:0,蓝色:0};
让白色=图像::颜色{红色:255,绿色:255,蓝色:255};
//创建空白图像
让多个像素:image::image=image::image::new(图像宽度、图像高度、黑色像素);
//得到两个随机数
使用rand::Rng;
让mut rng=rand::thread_rng();
设rand_x=rng.gen:()%图像宽度;
设rand_y=rng.gen:()%图像高度;
//改变像素
像素。设置像素(随机x、随机y、白色像素);
//返回指针
像素。获取
}
我的窗口绘制例程:
//执行绘图函数
让image_ptr=draw_函数();
不安全的
{
//创建纹理
让mut tex_id:gl::types::GLuint=0;
德国劳埃德船级社:GenTextures(1,&mut tex_id);
gl::BindTexture(gl::TEXTURE\u 2D,tex\u id);
//将像素移动到纹理
gl::Texamage2D(gl::TEXTURE_2D,0,gl::RGBA as i32,
图像宽度,图像高度,0,gl::RGBA,gl::无符号字节,图像ptr);
gl::TexParameteri(gl::TEXTURE_2D,gl::TEXTURE_MIN_FILTER,gl::NEAREST as i32);
gl::TexParameteri(gl::TEXTURE_2D,gl::TEXTURE_MAG_FILTER,gl::NEAREST as i32);
//创建读帧缓冲区
让mut读取\u fbo\u id:gl::types::GLuint=0;
gl::GenFramebuffers(1,&mut read\u fbo\u id);
gl::BindFramebuffer(gl::READ\u FRAMEBUFFER,READ\u fbo\u id);
//将纹理绑定到读取帧缓冲区
gl::FramebufferTexture2D(gl::READ_FRAMEBUFFER,gl::COLOR_ATTACHMENT0,gl::TEXTURE_2D,tex_id,0);
//从读取帧缓冲区传输到绘制帧缓冲区
gl::BlitFramebuffer(0,0,图像宽度,图像高度,
0,0,窗宽为i32,窗高为i32,
gl::颜色\缓冲区\位,gl::最近);
//清除读取帧缓冲区
gl::BindFramebuffer(gl::READ\u帧缓冲区,0);
gl::DeleteFramebuffers(1,&mut read\u fbo\u id);
};
//更新屏幕
让u=windowed_context.swap_buffers();
std::thread::sleep(std::time::Duration::from_millis(15));
可在以下位置找到完整的项目:
我期待一个黑屏,每一帧屏幕上随机画一个白色像素。但是,左下角包含4个随机像素。第一和第三像素改变,而第二和第四像素不变
显示结果的图像:函数
rand\u pixel
在局部变量中创建一个image::image
,然后返回指向它的指针。问题是图像被放在函数的末尾,所以这个指针悬空
取消对该指针的引用是未定义的行为,这显然在应用程序中表现为某些像素绘制错误的颜色。在图像
被删除后,它用来存储像素的内存可以重新用于任何其他用途。看起来大部分数据还没有被重新使用,但一些数据已经写入了前几个字节
在安全代码中,Rust通过检查引用的生存期是否超出引用变量的范围来保护您免受此类错误的影响。但是,当您使用不安全的代码并使用原始指针时,您必须自己确保内存安全
一种可能的修复方法是使绘图函数对图像进行可变引用,而不是拥有图像本身:
fn rand_pixel(pixels: &mut image::Image) -> *const std::ffi::c_void {
// Define colors
let black_pixel = image::Color { red: 0, green: 0, blue: 0 };
let white_pixel = image::Color { red: 255, green: 255, blue: 255 };
// Overwrite with a blank image
*pixels = image::Image::new(pixels.width, pixels.height, black_pixel);
// Get two random numbers
use rand::Rng;
let mut rng = rand::thread_rng();
let rand_x = rng.gen() % pixels.width;
let rand_y = rng.gen() % pixels.height;
// Change pixels
pixels.set_pixel(rand_x, rand_y, white_pixel);
// return pointer (still valid because the image lives longer than this function)
pixels.get_ptr()
}
在主函数中,您拥有图像,并通过可变引用进行传递:
// this variable lives longer than the call to window::create_window
let mut pixels = image::Image::new(image_width, image_height, image::Color { red: 0, green: 0, blue: 0} );
// Define draw function
let draw_fun = || rand_pixel(&mut pixels);
// Create new window
window::create_window(1600.0, 900.0, image_width as i32, image_height as i32, draw_fun);
注意,您还必须更改create_window
的签名以接受FnMut
而不是Fn