- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试设置一个管道来进行一些光线渲染。
首先,我设置了一个顶点着色器和一个几何着色器,仅采用 1 个任意 float ,并制作了一个四边形,这样我就可以仅使用片段着色器,并通过将数据传递给所有着色器或制服来输入数据。
但后来我遇到了计算着色器,并找到了一些教程,但几乎都是一样的,制作一个四边形并渲染计算着色器输出到它,我认为这很愚蠢,如果你有可能渲染如何您想要使用计算着色器并仍然使用技巧来获得结果。
经过进一步研究,我发现了函数“glFramebufferImage2D”,据我所知,它将一个 ImageTexture(在我的例子中是我用我的计算着色器写入的那个)附加到帧缓冲区(显示的缓冲区据我了解)。所以我不必做四边形生成技巧。但是我写的代码只是显示黑屏。我弄错了什么吗?还是我遗漏了代码中的某些内容?
这是我的代码:(我还不担心警告和分离着色器程序。我现在只想测试这个概念。)
主要.rs
extern crate sdl2;
extern crate gl;
use sdl2::pixels::Color;
use std::ffi::{CStr, CString};
fn main() {
let width = 512;
let height = 512;
let sdl = sdl2::init().unwrap();
let video_sys = sdl.video().unwrap();
let gl_attr = video_sys.gl_attr();
gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
gl_attr.set_context_version(4, 1);
let window = video_sys.window("test", width, height).opengl().build().unwrap();
let gl_ctx = window.gl_create_context().unwrap();
let gl = gl::load_with(|s| video_sys.gl_get_proc_address(s) as *const std::os::raw::c_void);
unsafe {
gl::Viewport(0, 0, width as gl::types::GLsizei, height as gl::types::GLsizei);
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
}
let shader = unsafe { gl::CreateShader(gl::COMPUTE_SHADER) };
unsafe {
gl::ShaderSource(shader, 1, &CString::new(include_str!("screen.comp")).unwrap().as_ptr(), std::ptr::null());
gl::CompileShader(shader);
}
let program = unsafe { gl::CreateProgram() };
unsafe {
gl::AttachShader(program, shader);
gl::LinkProgram(program);
gl::UseProgram(program);
}
let mut tex_out : gl::types::GLuint = 0;
unsafe {
gl::GenTextures(1, &mut tex_out);
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, tex_out);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA32F as gl::types::GLint,
width as gl::types::GLsizei,
height as gl::types::GLsizei,
0,
gl::RGBA,
gl::FLOAT,
std::ptr::null()
);
gl::BindImageTexture(0, tex_out, 0, gl::FALSE, 0, gl::WRITE_ONLY, gl::RGBA32F);
}
let mut event_pump = sdl.event_pump().unwrap();
'main: loop {
for event in event_pump.poll_iter() {
match event {
sdl2::event::Event::Quit {..} => break 'main,
_ => {},
}
}
unsafe {
gl::DispatchCompute(width as gl::types::GLuint, height as gl::types::GLuint, 1);
gl::MemoryBarrier(gl::SHADER_IMAGE_ACCESS_BARRIER_BIT);
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, tex_out, 0);
}
window.gl_swap_window();
}
}
屏幕补偿
#version 430
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img_output;
void main() {
vec4 pixel = vec4(1.0, 1.0, 1.0, 1.0);
ivec2 pixel_coords = ivec2(gl_GlobalInvocationID.xy);
imageStore(img_output, pixel_coords, pixel);
}
编辑:工作代码:(有一些试色)
主要.rs:
extern crate sdl2;
extern crate gl;
use std::ffi::{CStr, CString};
struct Renderer {
width : u32 ,
height : u32 ,
shader : gl::types::GLuint ,
program : gl::types::GLuint ,
}
impl Renderer {
fn new(width : u32, height : u32, shader_name : &CStr) -> Self {
unsafe {
gl::Viewport(0, 0, width as gl::types::GLsizei, height as gl::types::GLsizei);
gl::ClearColor(0.0, 0.0, 0.0, 1.0);
}
let shader = unsafe { gl::CreateShader(gl::COMPUTE_SHADER) };
unsafe {
gl::ShaderSource(shader, 1, &shader_name.as_ptr(), std::ptr::null());
gl::CompileShader(shader);
}
let program = unsafe { gl::CreateProgram() };
unsafe {
gl::AttachShader(program, shader);
gl::LinkProgram(program);
gl::UseProgram(program);
}
let mut tex_out : gl::types::GLuint = 0;
unsafe {
gl::GenTextures(1, &mut tex_out);
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, tex_out);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR as gl::types::GLint);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGBA32F as gl::types::GLint,
width as gl::types::GLsizei,
height as gl::types::GLsizei,
0,
gl::RGBA,
gl::FLOAT,
std::ptr::null()
);
gl::BindImageTexture(0, tex_out, 0, gl::FALSE, 0, gl::WRITE_ONLY, gl::RGBA32F);
}
let mut fbo : gl::types::GLuint = 0;
unsafe {
gl::GenFramebuffers(1, &mut fbo );
gl::BindFramebuffer(gl::FRAMEBUFFER, fbo );
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, tex_out, 0);
gl::BindFramebuffer(gl::READ_FRAMEBUFFER, fbo);
gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, 0);
}
let resolution = unsafe { gl::GetUniformLocation(program, CString::new("iResolution").unwrap().as_ptr()) };
unsafe { gl::Uniform2i(resolution, width as gl::types::GLint, height as gl::types::GLint); }
Self {
width : width ,
height : height ,
shader : shader ,
program : program ,
}
}
fn get_input(&self, name : &str) -> gl::types::GLint {
unsafe { gl::GetUniformLocation(self.program, CString::new(name).unwrap().as_ptr()) }
}
fn input1f(&self, ptr : gl::types::GLint, f : gl::types::GLfloat) {
unsafe { gl::Uniform1f(ptr, f) };
}
fn draw(&self) {
unsafe {
gl::DispatchCompute(self.width as gl::types::GLuint, self.height as gl::types::GLuint, 1);
gl::MemoryBarrier(gl::SHADER_IMAGE_ACCESS_BARRIER_BIT);
gl::BlitFramebuffer(0, 0, self.width as gl::types::GLint, self.height as gl::types::GLint, 0, 0, self.width as gl::types::GLint, self.height as gl::types::GLint, gl::COLOR_BUFFER_BIT, gl::LINEAR);
}
}
}
impl Drop for Renderer {
fn drop(&mut self) {
unsafe {
gl::DeleteShader(self.shader);
gl::DeleteProgram(self.program);
}
}
}
fn main() {
let width = 512;
let height = 512;
let sdl = sdl2::init().unwrap();
let video_sys = sdl.video().unwrap();
let gl_attr = video_sys.gl_attr();
gl_attr.set_context_profile(sdl2::video::GLProfile::Core);
gl_attr.set_context_version(4, 1);
let window = video_sys.window("test", width, height).opengl().build().unwrap();
let _gl_ctx = window.gl_create_context().unwrap();
let _gl = gl::load_with(|s| video_sys.gl_get_proc_address(s) as *const std::os::raw::c_void);
let render = Renderer::new(width, height, &CString::new(include_str!("screen.comp")).unwrap());
let time_attr = render.get_input("time");
let mut event_pump = sdl.event_pump().unwrap();
let mut time = 0.0;
'main: loop {
for event in event_pump.poll_iter() {
match event {
sdl2::event::Event::Quit {..} => break 'main,
_ => {},
}
}
time += 0.01;
if time > 1.0 {
time = 0.0;
}
render.input1f(time_attr, time);
render.draw();
window.gl_swap_window();
}
}
屏幕补偿:
#version 430
layout(local_size_x = 1, local_size_y = 1) in;
layout(rgba32f, binding = 0) uniform image2D img;
uniform ivec2 iResolution;
uniform float time;
void main() {
ivec2 iCoords = ivec2(gl_GlobalInvocationID.xy);
vec2 uv = vec2(iCoords) / vec2(iResolution);
vec4 pixel = vec4(uv, time, 1.0);
imageStore(img, iCoords, pixel);
}
最佳答案
生成纹理时出现问题。 TEXTURE_MIN_FILTER
的初始值为 NEAREST_MIPMAP_LINEAR
。如果您不更改它并且不创建 mipmap,则纹理不“完整”。
将 TEXTURE_MIN_FILTER
设置为 NEAREST
或 LINEAR
以解决问题:
gl::BindTexture(gl::TEXTURE_2D, tex_out);
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR)
您已经将图像从计算着色器渲染到纹理对象,但为了将该纹理 blit 到屏幕,您必须将该纹理图像复制到默认帧缓冲区的颜色平面。不能简单地通过附加纹理来更改默认帧缓冲区的颜色平面。
相反,您需要创建一个名为 Framebuffer Object 的(glGenFramebuffers
,glBindFramebuffer
)并将纹理对象附加到帧缓冲区的颜色平面(glFramebufferTexture2D
)。
let mut fbo : gl::types::GLuint = 0;
gl::GenFramebuffers(1, &mut fbo);
gl::BindFramebuffer(gl::FRAMEBUFFER, fbo);
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, tex_out, 0)
将此帧缓冲区绑定(bind)到目标 GL_READ_FRAMEBUFFER
( glBindFramebuffer
) 并将默认帧缓冲区(零)绑定(bind)到目标 GL_DRAW_FRAMEBUFFER
。
gl::BindFramebuffer(gl::READ_FRAMEBUFFER, fbo);
gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, 0);
最后,在渲染循环中,使用 glBlitFramebuffer
将命名帧缓冲区对象(纹理)的内容复制到默认帧缓冲区的颜色平面。
gl::DispatchCompute(width as gl::types::GLuint, height as gl::types::GLuint, 1);
gl::MemoryBarrier(gl::SHADER_IMAGE_ACCESS_BARRIER_BIT);
gl::BlitFramebuffer(
0, 0, width as gl::types::GLsizei, height as gl::types::GLsizei,
0, 0, width as gl::types::GLsizei, height as gl::types::GLsizei,
gl::COLOR_BUFFER_BIT, gl::LINEAR);
请注意,通过使用 glBlitFramebuffer
,视口(viewport)的大小可以与纹理图像的大小不同。
如果纹理的格式是完整的,则此方法将不起作用。之所以可行,是因为纹理图像的格式是 float ,而默认帧缓冲区的格式是定点数。
关于opengl - 将计算着色器输出渲染到屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58042393/
在 OpenGL/ES 中,在实现渲染到纹理功能时,您必须小心,不要引起反馈循环(从正在写入的同一纹理中读取像素)。由于显而易见的原因,当您读取和写入纹理的相同像素时,行为是未定义的。但是,如果您正在
正如我们最终都知道的那样,规范是一回事,实现是另一回事。大多数错误是我们自己造成的,但有时情况并非如此。 我相信列出以下内容会很有用: GPU 驱动程序中当前已知的与最新版本的 OpenGL 和 GL
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。为了帮助澄清这个问题以便可以重新打开它,visit the help center
我正在学习 OpenGL,非常想知道与显卡的交互如何。 我觉得了解它是如何在图形驱动程序中实现的,会让我了解 opengl 的完整内部结构(通过这个我可以知道哪些阶段/因素影响我对 opengl 性能
我正在尝试绘制到大于屏幕尺寸(即 320x480)的渲染缓冲区 (512x512)。 执行 glReadPixels 后,图像看起来是正确的,除非图像的尺寸超过屏幕尺寸——在本例中,超过 320 水平
我正在 Windows 中制作一个 3D 小行星游戏(使用 OpenGL 和 GLUT),您可以在其中穿过一堆障碍物在太空中移动并生存下来。我正在寻找一种方法来针对无聊的 bg 颜色选项设置图像背景。
如果我想要一个包含 100 个 10*10 像素 Sprite 的 Sprite 表,是否可以将它们全部排成一排来制作 1,000*10 像素纹理?还是 GPU 对不那么窄的纹理表现更好?这对性能有什
这个问题在这里已经有了答案: Rendering 2D sprites in a 3D world? (7 个答案) 关闭 6 年前。 我如何概念化让图像始终面对相机。我尝试将三角函数与 arcta
是否可以在 OpenGL 中增加缓冲区? 假设我想使用实例化渲染。每次在世界上生成一个新对象时,我都必须用实例化数据更新缓冲区。 在这种情况下,我有一个 3 个 float 的缓冲区 std::v
有人可以向我解释为什么下面的代码没有绘制任何东西,但如果我使用 GL_LINE_LOOP 它确实形成了一个闭环吗? glBegin(GL_POLYGON); for(int i = 0; i <= N
正如标题所说,OpenGL 中的渲染目标是什么?我对 OpenGL 很陌生,我看到的所有网站都让我很困惑。 它只是一个缓冲区,我在其中放置稍后将用于渲染的东西吗? 如果您能提供一个很好的引用来阅读它,
当使用 OpenGL 1.4 固定功能多纹理时,每个纹理阶段的输出在传递到下一个阶段之前是否都固定在 [0, 1]? spec说(第 153 页): If the value of TEXTURE_E
我比较了 2 个函数 openGL ES 和 openGL gvec4 texelFetchOffset(gsampler2DArray sampler, ivec3 P, int lod, ivec
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 10 年前。 Improve thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 6年前关闭。 Improve this qu
那么当你调用opengl函数时,比如glDraw或者gLBufferData,是否会导致程序线程停止等待GL完成调用呢? 如果不是,那么 GL 如何处理调用像 glDraw 这样的重要函数,然后立即更
我正在尝试实现级联阴影贴图,当我想访问我的视锥体的每个分区的相应深度纹理时,我遇到了一个错误。 更具体地说,当我想选择正确的阴影纹理时会出现我的问题,如果我尝试下面的代码,我会得到一个像 this 中
我想为OpenGL ES和OpenGL(Windows)使用相同的着色器源。为此,我想定义自定义数据类型并仅使用OpenGL ES函数。 一种方法是定义: #define highp #define
我尝试用 6 个位图映射立方体以实现天空盒效果。我的问题是一个纹理映射到立方体的每个面。我已经检查了 gDEBugger,在立方体纹理内存中我只有一个 图像(因为我尝试加载六个图像)。 代码准备纹理:
在 OpenGL 中偏移深度的最佳方法是什么?我目前每个多边形都有索引顶点属性,我将其传递给 OpenGL 中的顶点着色器。我的目标是在深度上偏移多边形,其中最高索引始终位于较低索引的前面。我目前有这
我是一名优秀的程序员,十分优秀!