librashader/librashader-runtime-gl/tests/hello_triangle/gl46.rs

443 lines
12 KiB
Rust
Raw Normal View History

2022-11-29 09:42:29 +11:00
use std::sync::mpsc::Receiver;
2024-02-06 10:39:01 +11:00
use std::sync::Arc;
2022-11-29 09:42:29 +11:00
use glfw::{Context, Glfw, Window, WindowEvent};
2024-02-06 10:39:01 +11:00
use glow::HasContext;
2023-01-14 17:58:22 +11:00
use librashader_common::{Size, Viewport};
2022-11-29 09:42:29 +11:00
use librashader_runtime_gl::{FilterChainGL, GLFramebuffer, GLImage};
2022-11-29 09:42:29 +11:00
const WIDTH: u32 = 800;
const HEIGHT: u32 = 600;
const TITLE: &str = "librashader OpenGL 4.6";
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
pub fn setup() -> (
Glfw,
Window,
Receiver<(f64, WindowEvent)>,
glow::Program,
glow::VertexArray,
Arc<glow::Context>,
2022-11-29 09:42:29 +11:00
) {
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
2024-02-06 10:39:01 +11:00
glfw.window_hint(glfw::WindowHint::ContextVersion(4, 6));
2022-11-29 09:42:29 +11:00
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core,
));
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
glfw.window_hint(glfw::WindowHint::Resizable(true));
glfw.window_hint(glfw::WindowHint::OpenGlDebugContext(true));
let (mut window, events) = glfw
.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed)
.unwrap();
let (screen_width, screen_height) = window.get_framebuffer_size();
window.make_current();
window.set_key_polling(true);
2024-02-06 10:39:01 +11:00
let mut gl = unsafe { glow::Context::from_loader_function(|ptr| window.get_proc_address(ptr)) };
2022-11-29 09:42:29 +11:00
unsafe {
2024-02-06 10:39:01 +11:00
gl.enable(glow::DEBUG_OUTPUT);
gl.enable(glow::DEBUG_OUTPUT_SYNCHRONOUS);
gl.debug_message_callback(super::debug_callback);
gl.debug_message_control(glow::DONT_CARE, glow::DONT_CARE, glow::DONT_CARE, &[], true);
2022-11-29 09:42:29 +11:00
}
unsafe {
2024-02-06 10:39:01 +11:00
gl.viewport(0, 0, screen_width, screen_height);
gl.clear_color(0.4, 0.4, 0.4, 1.0);
2022-11-29 09:42:29 +11:00
}
// -------------------------------------------
const VERT_SHADER: &str = "#version 330 core
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Color;
out VS_OUTPUT {
vec3 Color;
} OUT;
void main()
{
gl_Position = vec4(Position, 1.0);
OUT.Color = Color;
}";
const FRAG_SHADER: &str = "#version 330 core
in VS_OUTPUT {
vec3 Color;
} IN;
layout(location = 0) out vec4 Color;
void main()
{
Color = vec4(IN.Color, 1.0f);
}";
2024-02-06 10:39:01 +11:00
let shader_program = super::compile_program(&gl, VERT_SHADER, FRAG_SHADER);
2022-11-29 09:42:29 +11:00
unsafe {
2024-02-06 10:39:01 +11:00
gl.object_label(glow::SHADER, shader_program.0.get(), Some("color_shader"));
2022-11-29 09:42:29 +11:00
}
let vertices = &[
// positions // colors
0.5f32, -0.5, 0.0, 1.0, 0.0, 0.0, // bottom right
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0, // bottom left
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, // top
];
2024-02-06 10:39:01 +11:00
let vbo = unsafe { gl.create_named_buffer().unwrap() };
2022-11-29 09:42:29 +11:00
unsafe {
2024-02-06 10:39:01 +11:00
gl.object_label(glow::BUFFER, vbo.0.get(), Some("triangle_vbo"));
2022-11-29 09:42:29 +11:00
}
unsafe {
2024-02-06 10:39:01 +11:00
gl.named_buffer_data_u8_slice(
2022-11-29 09:42:29 +11:00
vbo,
2024-02-06 10:39:01 +11:00
bytemuck::cast_slice(vertices),
glow::STATIC_DRAW, // usage
2022-11-29 09:42:29 +11:00
);
}
// set up vertex array object
2024-02-06 10:39:01 +11:00
let vao = unsafe { gl.create_named_vertex_array().unwrap() };
2022-11-29 09:42:29 +11:00
// todo: figure this shit out
unsafe {
2024-02-06 10:39:01 +11:00
// gl.object_label(glow::VERTEX_ARRAY, vao.0.get(), Some("triangle_vao"));
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.vertex_array_vertex_buffer(vao, 0, Some(vbo), 0, 6 * std::mem::size_of::<f32>() as i32);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.enable_vertex_array_attrib(vao, 0); // this is "layout (location = 0)" in vertex shader
gl.vertex_array_attrib_format_f32(vao, 0, 3, glow::FLOAT, false, 0);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.enable_vertex_array_attrib(vao, 1);
gl.vertex_array_attrib_format_f32(
2022-11-30 17:38:05 +11:00
vao,
1,
3,
2024-02-06 10:39:01 +11:00
glow::FLOAT,
false,
3 * std::mem::size_of::<f32>() as u32,
2022-11-30 17:38:05 +11:00
);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.vertex_array_attrib_binding_f32(vao, 0, 0);
gl.vertex_array_attrib_binding_f32(vao, 1, 0);
2022-11-29 09:42:29 +11:00
}
// set up shared state for window
unsafe {
2024-02-06 10:39:01 +11:00
gl.viewport(0, 0, 900, 700);
gl.clear_color(0.3, 0.3, 0.5, 1.0);
2022-11-29 09:42:29 +11:00
}
2024-02-06 10:39:01 +11:00
unsafe {
// -------------------------------------------
println!("OpenGL version: {}", gl.get_parameter_string(glow::VERSION));
println!(
"GLSL version: {}",
gl.get_parameter_string(glow::SHADING_LANGUAGE_VERSION)
);
}
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
(glfw, window, events, shader_program, vao, Arc::new(gl))
2022-11-29 09:42:29 +11:00
}
pub fn do_loop(
2024-02-06 10:39:01 +11:00
gl: &Arc<glow::Context>,
2022-11-29 09:42:29 +11:00
mut glfw: Glfw,
mut window: Window,
events: Receiver<(f64, WindowEvent)>,
2024-02-06 10:39:01 +11:00
triangle_program: glow::Program,
triangle_vao: glow::VertexArray,
filter: &mut FilterChainGL,
2022-11-29 09:42:29 +11:00
) {
let mut framecount = 0;
2024-02-06 10:39:01 +11:00
let rendered_framebuffer;
let rendered_texture;
let quad_vbuf;
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
let output_texture;
let output_framebuffer_handle;
let output_quad_vbuf;
2022-11-29 09:42:29 +11:00
unsafe {
// do frmaebuffer
2024-02-06 10:39:01 +11:00
rendered_framebuffer = gl.create_named_framebuffer().unwrap();
gl.object_label(
glow::FRAMEBUFFER,
rendered_framebuffer.0.get(),
Some("rendered_framebuffer"),
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
rendered_texture = gl.create_named_texture(glow::TEXTURE_2D).unwrap();
gl.object_label(
glow::TEXTURE,
rendered_texture.0.get(),
Some("rendered_texture"),
2022-11-29 09:42:29 +11:00
);
// empty image
2024-02-06 10:39:01 +11:00
gl.texture_storage_2d(
2022-11-29 09:42:29 +11:00
rendered_texture,
1,
2024-02-06 10:39:01 +11:00
glow::RGBA8,
WIDTH as i32,
HEIGHT as i32,
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-30 17:38:05 +11:00
rendered_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_MAG_FILTER,
glow::NEAREST as i32,
2022-11-30 17:38:05 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-30 17:38:05 +11:00
rendered_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_MIN_FILTER,
glow::NEAREST as i32,
2022-11-30 17:38:05 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
rendered_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_WRAP_S,
glow::CLAMP_TO_EDGE as i32,
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
rendered_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_WRAP_T,
glow::CLAMP_TO_EDGE as i32,
2022-11-29 09:42:29 +11:00
);
// set color attachment
2024-02-06 10:39:01 +11:00
gl.named_framebuffer_texture(
Some(rendered_framebuffer),
glow::COLOR_ATTACHMENT0,
Some(rendered_texture),
2022-11-29 09:42:29 +11:00
0,
);
2024-02-06 10:39:01 +11:00
gl.named_framebuffer_draw_buffer(Some(rendered_framebuffer), glow::COLOR_ATTACHMENT0);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
if gl.check_named_framebuffer_status(Some(rendered_framebuffer), glow::FRAMEBUFFER)
!= glow::FRAMEBUFFER_COMPLETE
{
2022-11-29 09:42:29 +11:00
panic!("failed to create fbo")
}
let fullscreen_fbo = [
-1.0f32, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
];
2024-02-06 10:39:01 +11:00
quad_vbuf = gl.create_named_buffer().unwrap();
gl.named_buffer_data_u8_slice(
quad_vbuf,
bytemuck::cast_slice(&fullscreen_fbo),
glow::STATIC_DRAW,
2022-11-29 09:42:29 +11:00
);
}
unsafe {
// do frmaebuffer
2024-02-06 10:39:01 +11:00
output_framebuffer_handle = gl.create_named_framebuffer().unwrap();
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.object_label(
glow::FRAMEBUFFER,
output_framebuffer_handle.0.get(),
Some("output_framebuffer"),
2022-11-29 09:42:29 +11:00
);
// make tetxure
2024-02-06 10:39:01 +11:00
output_texture = gl.create_named_texture(glow::TEXTURE_2D).unwrap();
//
gl.object_label(
glow::TEXTURE,
output_texture.0.get(),
Some("output_texture"),
);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.texture_storage_2d(output_texture, 1, glow::RGBA8, WIDTH as i32, HEIGHT as i32);
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
output_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_MAG_FILTER,
glow::NEAREST as i32,
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
output_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_MIN_FILTER,
glow::NEAREST as i32,
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
output_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_WRAP_S,
glow::CLAMP_TO_EDGE as i32,
2022-11-29 09:42:29 +11:00
);
2024-02-06 10:39:01 +11:00
gl.texture_parameter_i32(
2022-11-29 09:42:29 +11:00
output_texture,
2024-02-06 10:39:01 +11:00
glow::TEXTURE_WRAP_T,
glow::CLAMP_TO_EDGE as i32,
2022-11-29 09:42:29 +11:00
);
// set color attachment
2024-02-06 10:39:01 +11:00
gl.named_framebuffer_texture(
Some(output_framebuffer_handle),
glow::COLOR_ATTACHMENT0,
Some(output_texture),
2022-11-29 09:42:29 +11:00
0,
);
2024-02-06 10:39:01 +11:00
gl.named_framebuffer_draw_buffer(Some(output_framebuffer_handle), glow::COLOR_ATTACHMENT0);
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
if gl.check_named_framebuffer_status(Some(output_framebuffer_handle), glow::FRAMEBUFFER)
!= glow::FRAMEBUFFER_COMPLETE
{
2022-11-29 09:42:29 +11:00
panic!("failed to create fbo")
}
let fullscreen_fbo = [
-1.0f32, -1.0, 0.0, 1.0, -1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
];
2024-02-06 10:39:01 +11:00
output_quad_vbuf = gl.create_named_buffer().unwrap();
gl.named_buffer_data_u8_slice(
2022-11-29 09:42:29 +11:00
output_quad_vbuf,
2024-02-06 10:39:01 +11:00
bytemuck::cast_slice(&fullscreen_fbo),
glow::STATIC_DRAW,
2022-11-29 09:42:29 +11:00
);
}
const VERT_SHADER: &str = r"#version 150 core
out vec2 v_tex;
const vec2 pos[4]=vec2[4](vec2(-1.0, 1.0),
vec2(-1.0,-1.0),
vec2( 1.0, 1.0),
vec2( 1.0,-1.0));
void main()
{
v_tex=0.5*pos[gl_VertexID] + vec2(0.5);
gl_Position=vec4(pos[gl_VertexID], 0.0, 1.0);
}
";
const FRAG_SHADER: &str = r"
#version 150 core
in vec2 v_tex;
uniform sampler2D texSampler;
out vec4 color;
void main()
{
color=texture(texSampler, v_tex);
}";
2024-02-06 10:39:01 +11:00
let quad_programid = super::compile_program(gl, VERT_SHADER, FRAG_SHADER);
let quad_vao = unsafe { gl.create_named_vertex_array().unwrap() };
2022-11-29 09:42:29 +11:00
let (fb_width, fb_height) = window.get_framebuffer_size();
let (vp_width, vp_height) = window.get_size();
let output = GLFramebuffer::new_from_raw(
2024-02-06 10:39:01 +11:00
Arc::clone(gl),
Some(output_texture),
2022-11-29 09:42:29 +11:00
output_framebuffer_handle,
2024-02-06 10:39:01 +11:00
glow::RGBA8,
2022-11-29 09:42:29 +11:00
Size::new(vp_width as u32, vp_height as u32),
1,
);
while !window.should_close() {
glfw.poll_events();
for (_, event) in glfw::flush_messages(&events) {
glfw_handle_event(&mut window, event);
}
unsafe {
// render to fb
2024-02-06 10:39:01 +11:00
gl.clear_named_framebuffer_f32_slice(
Some(rendered_framebuffer),
glow::COLOR,
2022-11-30 17:38:05 +11:00
0,
2024-02-06 10:39:01 +11:00
&[0.3f32, 0.4, 0.6, 1.0],
2022-11-30 17:38:05 +11:00
);
2024-02-06 10:39:01 +11:00
gl.bind_framebuffer(glow::FRAMEBUFFER, Some(rendered_framebuffer));
gl.viewport(0, 0, vp_width, vp_height);
2022-11-29 09:42:29 +11:00
// do the drawing
2024-02-06 10:39:01 +11:00
gl.use_program(Some(triangle_program));
2022-11-29 09:42:29 +11:00
// select vertices
2024-02-06 10:39:01 +11:00
gl.bind_vertex_array(Some(triangle_vao));
2022-11-29 09:42:29 +11:00
// draw to bound target
2024-02-06 10:39:01 +11:00
gl.draw_arrays(glow::TRIANGLES, 0, 3);
2022-11-29 09:42:29 +11:00
// unselect vertices
2024-02-06 10:39:01 +11:00
gl.bind_vertex_array(None);
2022-11-29 09:42:29 +11:00
// unselect fbo
2024-02-06 10:39:01 +11:00
gl.bind_framebuffer(glow::FRAMEBUFFER, None);
2022-11-29 09:42:29 +11:00
}
let viewport = Viewport {
2022-12-01 11:05:24 +11:00
x: 0f32,
y: 0f32,
2022-11-29 09:42:29 +11:00
output: &output,
mvp: None,
};
2022-11-30 16:39:42 +11:00
let rendered = GLImage {
2024-02-06 10:39:01 +11:00
handle: Some(rendered_texture),
format: glow::RGBA8,
2022-11-29 09:42:29 +11:00
size: Size {
width: fb_width as u32,
height: fb_height as u32,
},
};
2023-02-17 10:19:38 +11:00
unsafe {
filter
.frame(&rendered, &viewport, framecount, None)
.unwrap();
}
2022-11-29 09:42:29 +11:00
unsafe {
// texture is done now.
// draw quad to screen
2024-02-06 10:39:01 +11:00
gl.use_program(Some(quad_programid));
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.bind_texture_unit(0, Some(output_texture));
2022-11-29 09:42:29 +11:00
2024-02-06 10:39:01 +11:00
gl.bind_vertex_array(Some(quad_vao));
gl.draw_arrays(glow::TRIANGLE_STRIP, 0, 4);
2022-11-29 09:42:29 +11:00
}
framecount += 1;
window.swap_buffers();
}
}
fn glfw_handle_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
use glfw::Action;
use glfw::Key;
use glfw::WindowEvent as Event;
match event {
Event::Key(Key::Escape, _, Action::Press, _) => {
window.set_should_close(true);
}
Event::Size(width, height) => window.set_size(width, height),
_ => {}
}
2022-11-30 17:38:05 +11:00
}