fmt: run rustfmt and clippy
This commit is contained in:
parent
e911d40429
commit
5ed6cc6e52
|
@ -1,7 +1,8 @@
|
||||||
use std::borrow::Borrow;
|
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
use gl::types::GLint;
|
use gl::types::GLint;
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableSemantics};
|
use librashader_reflect::reflect::semantics::{
|
||||||
|
MemberOffset, SemanticMap, TextureSemantics, VariableSemantics,
|
||||||
|
};
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum VariableLocation {
|
pub enum VariableLocation {
|
||||||
|
@ -12,7 +13,7 @@ pub enum VariableLocation {
|
||||||
impl VariableLocation {
|
impl VariableLocation {
|
||||||
pub fn location(&self) -> UniformLocation<GLint> {
|
pub fn location(&self) -> UniformLocation<GLint> {
|
||||||
match self {
|
match self {
|
||||||
VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l
|
VariableLocation::Ubo(l) | VariableLocation::Push(l) => *l,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +41,7 @@ impl UniformLocation<GLint> {
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum MemberLocation {
|
pub enum MemberLocation {
|
||||||
Offset(MemberOffset),
|
Offset(MemberOffset),
|
||||||
Uniform(UniformLocation<GLint>)
|
Uniform(UniformLocation<GLint>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
|
|
||||||
use librashader_presets::{ShaderPassConfig, ShaderPreset};
|
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableSemantics};
|
|
||||||
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic};
|
|
||||||
use std::path::Path;
|
|
||||||
use std::error::Error;
|
|
||||||
use librashader::{FilterMode, ShaderSource};
|
|
||||||
use librashader_reflect::back::cross::GlVersion;
|
|
||||||
use librashader_reflect::back::targets::{FromCompilation, GLSL};
|
|
||||||
use spirv_cross::spirv::Decoration;
|
|
||||||
use librashader::image::Image;
|
|
||||||
use librashader_reflect::back::CompileShader;
|
|
||||||
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
||||||
use crate::filter_pass::FilterPass;
|
use crate::filter_pass::FilterPass;
|
||||||
use crate::framebuffer::Framebuffer;
|
use crate::framebuffer::Framebuffer;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport};
|
use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport};
|
||||||
|
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
|
||||||
|
use librashader::image::Image;
|
||||||
|
use librashader::{FilterMode, ShaderSource};
|
||||||
|
use librashader_presets::{ShaderPassConfig, ShaderPreset};
|
||||||
|
use librashader_reflect::back::cross::GlVersion;
|
||||||
|
use librashader_reflect::back::targets::{FromCompilation, GLSL};
|
||||||
|
use librashader_reflect::back::CompileShader;
|
||||||
|
use librashader_reflect::reflect::semantics::{
|
||||||
|
MemberOffset, SemanticMap, TextureSemantics, UniformMeta, VariableSemantics,
|
||||||
|
};
|
||||||
|
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
use spirv_cross::spirv::Decoration;
|
||||||
|
use std::error::Error;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
static QUAD_VBO_DATA: &'static [f32; 16] = &[
|
static QUAD_VBO_DATA: &[f32; 16] = &[
|
||||||
0.0f32, 0.0f32, 0.0f32, 0.0f32,
|
0.0f32, 0.0f32, 0.0f32, 0.0f32, 1.0f32, 0.0f32, 1.0f32, 0.0f32, 0.0f32, 1.0f32, 0.0f32, 1.0f32,
|
||||||
1.0f32, 0.0f32, 1.0f32, 0.0f32,
|
|
||||||
0.0f32, 1.0f32, 0.0f32, 1.0f32,
|
|
||||||
1.0f32, 1.0f32, 1.0f32, 1.0f32,
|
1.0f32, 1.0f32, 1.0f32, 1.0f32,
|
||||||
];
|
];
|
||||||
|
|
||||||
impl FilterChain {
|
impl FilterChain {
|
||||||
fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
|
fn load_pass_semantics(
|
||||||
config: &ShaderPassConfig) {
|
uniform_semantics: &mut FxHashMap<String, UniformSemantic>,
|
||||||
|
texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
|
||||||
|
config: &ShaderPassConfig,
|
||||||
|
) {
|
||||||
let Some(alias) = &config.alias else {
|
let Some(alias) = &config.alias else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
@ -40,24 +43,36 @@ impl FilterChain {
|
||||||
let index = config.id as usize;
|
let index = config.id as usize;
|
||||||
|
|
||||||
// PassOutput
|
// PassOutput
|
||||||
texture_semantics.insert(alias.clone(), SemanticMap {
|
texture_semantics.insert(
|
||||||
semantics: TextureSemantics::PassOutput,
|
alias.clone(),
|
||||||
index
|
SemanticMap {
|
||||||
});
|
semantics: TextureSemantics::PassOutput,
|
||||||
uniform_semantics.insert(format!("{alias}Size"), UniformSemantic::Texture(SemanticMap {
|
index,
|
||||||
semantics: TextureSemantics::PassOutput,
|
},
|
||||||
index
|
);
|
||||||
}));
|
uniform_semantics.insert(
|
||||||
|
format!("{alias}Size"),
|
||||||
|
UniformSemantic::Texture(SemanticMap {
|
||||||
|
semantics: TextureSemantics::PassOutput,
|
||||||
|
index,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
// PassFeedback
|
// PassFeedback
|
||||||
texture_semantics.insert(format!("{alias}Feedback"), SemanticMap {
|
texture_semantics.insert(
|
||||||
semantics: TextureSemantics::PassFeedback,
|
format!("{alias}Feedback"),
|
||||||
index
|
SemanticMap {
|
||||||
});
|
semantics: TextureSemantics::PassFeedback,
|
||||||
uniform_semantics.insert(format!("{alias}FeedbackSize"), UniformSemantic::Texture(SemanticMap {
|
index,
|
||||||
semantics: TextureSemantics::PassFeedback,
|
},
|
||||||
index
|
);
|
||||||
}));
|
uniform_semantics.insert(
|
||||||
|
format!("{alias}FeedbackSize"),
|
||||||
|
UniformSemantic::Texture(SemanticMap {
|
||||||
|
semantics: TextureSemantics::PassFeedback,
|
||||||
|
index,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation {
|
fn reflect_uniform_location(pipeline: GLuint, meta: &impl UniformMeta) -> VariableLocation {
|
||||||
|
@ -71,10 +86,7 @@ impl FilterChain {
|
||||||
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
|
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
|
||||||
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
|
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
|
||||||
|
|
||||||
VariableLocation::Ubo(UniformLocation {
|
VariableLocation::Ubo(UniformLocation { vertex, fragment })
|
||||||
vertex,
|
|
||||||
fragment
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MemberOffset::PushConstant(_) => {
|
MemberOffset::PushConstant(_) => {
|
||||||
|
@ -84,15 +96,11 @@ impl FilterChain {
|
||||||
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
|
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
|
||||||
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
|
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
|
||||||
|
|
||||||
VariableLocation::Push(UniformLocation {
|
VariableLocation::Push(UniformLocation { vertex, fragment })
|
||||||
vertex,
|
|
||||||
fragment
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FilterChain {
|
pub struct FilterChain {
|
||||||
|
@ -116,50 +124,66 @@ impl FilterChain {
|
||||||
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
|
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
|
||||||
let preset = ShaderPreset::try_parse(path)?;
|
let preset = ShaderPreset::try_parse(path)?;
|
||||||
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
|
||||||
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = Default::default();
|
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> =
|
||||||
|
Default::default();
|
||||||
|
|
||||||
let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter()
|
let passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset
|
||||||
|
.shaders
|
||||||
|
.iter()
|
||||||
.map(|shader| {
|
.map(|shader| {
|
||||||
eprintln!("[gl] loading {}", &shader.name.display());
|
eprintln!("[gl] loading {}", &shader.name.display());
|
||||||
let source: ShaderSource = librashader_preprocess::load_shader_source(&shader.name)
|
let source: ShaderSource =
|
||||||
.unwrap();
|
librashader_preprocess::load_shader_source(&shader.name).unwrap();
|
||||||
|
|
||||||
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source)
|
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source).unwrap();
|
||||||
.unwrap();
|
let reflect = GLSL::from_compilation(spirv).unwrap();
|
||||||
let mut reflect = GLSL::from_compilation(spirv).unwrap();
|
|
||||||
|
|
||||||
for parameter in source.parameters.iter() {
|
for parameter in source.parameters.iter() {
|
||||||
uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap {
|
uniform_semantics.insert(
|
||||||
semantics: VariableSemantics::FloatParameter,
|
parameter.id.clone(),
|
||||||
index: ()
|
UniformSemantic::Variable(SemanticMap {
|
||||||
}));
|
semantics: VariableSemantics::FloatParameter,
|
||||||
|
index: (),
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
(shader, source, reflect)
|
(shader, source, reflect)
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// todo: this can probably be extracted out.
|
// todo: this can probably be extracted out.
|
||||||
|
|
||||||
for details in &passes {
|
for details in &passes {
|
||||||
FilterChain::load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0)
|
FilterChain::load_pass_semantics(
|
||||||
|
&mut uniform_semantics,
|
||||||
|
&mut texture_semantics,
|
||||||
|
details.0,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add lut params
|
// add lut params
|
||||||
for (index, texture) in preset.textures.iter().enumerate() {
|
for (index, texture) in preset.textures.iter().enumerate() {
|
||||||
texture_semantics.insert(texture.name.clone(), SemanticMap {
|
texture_semantics.insert(
|
||||||
semantics: TextureSemantics::User,
|
texture.name.clone(),
|
||||||
index
|
SemanticMap {
|
||||||
});
|
semantics: TextureSemantics::User,
|
||||||
|
index,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap {
|
uniform_semantics.insert(
|
||||||
semantics: TextureSemantics::User,
|
format!("{}Size", texture.name),
|
||||||
index
|
UniformSemantic::Texture(SemanticMap {
|
||||||
}));
|
semantics: TextureSemantics::User,
|
||||||
|
index,
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let semantics = ReflectSemantics {
|
let semantics = ReflectSemantics {
|
||||||
uniform_semantics,
|
uniform_semantics,
|
||||||
non_uniform_semantics: texture_semantics
|
non_uniform_semantics: texture_semantics,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut filters = Vec::new();
|
let mut filters = Vec::new();
|
||||||
|
@ -167,7 +191,7 @@ impl FilterChain {
|
||||||
|
|
||||||
// initialize passes
|
// initialize passes
|
||||||
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
|
||||||
let mut semantics = semantics.clone();
|
let semantics = semantics.clone();
|
||||||
|
|
||||||
let reflection = reflect.reflect(index, &semantics)?;
|
let reflection = reflect.reflect(index, &semantics)?;
|
||||||
let glsl = reflect.compile(GlVersion::V4_60)?;
|
let glsl = reflect.compile(GlVersion::V4_60)?;
|
||||||
|
@ -184,7 +208,11 @@ impl FilterChain {
|
||||||
gl::AttachShader(program, fragment);
|
gl::AttachShader(program, fragment);
|
||||||
|
|
||||||
for res in &vertex_resources.stage_inputs {
|
for res in &vertex_resources.stage_inputs {
|
||||||
let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?;
|
let loc = glsl
|
||||||
|
.context
|
||||||
|
.compiler
|
||||||
|
.vertex
|
||||||
|
.get_decoration(res.id, Decoration::Location)?;
|
||||||
let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0");
|
let loc_name = format!("LIBRA_ATTRIBUTE_{loc}\0");
|
||||||
eprintln!("{loc_name}");
|
eprintln!("{loc_name}");
|
||||||
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
|
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
|
||||||
|
@ -203,7 +231,8 @@ impl FilterChain {
|
||||||
|
|
||||||
for binding in &glsl.context.sampler_bindings {
|
for binding in &glsl.context.sampler_bindings {
|
||||||
let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding);
|
let loc_name = format!("LIBRA_TEXTURE_{}\0", *binding);
|
||||||
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
|
let location =
|
||||||
|
gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
|
||||||
if location >= 0 {
|
if location >= 0 {
|
||||||
// eprintln!("setting sampler {location} to sample from {binding}");
|
// eprintln!("setting sampler {location} to sample from {binding}");
|
||||||
gl::Uniform1i(location, *binding as GLint);
|
gl::Uniform1i(location, *binding as GLint);
|
||||||
|
@ -211,10 +240,19 @@ impl FilterChain {
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::UseProgram(0);
|
gl::UseProgram(0);
|
||||||
(program, UniformLocation {
|
(
|
||||||
vertex: gl::GetUniformBlockIndex(program, b"LIBRA_UBO_VERTEX\0".as_ptr().cast()),
|
program,
|
||||||
fragment: gl::GetUniformBlockIndex(program, b"LIBRA_UBO_FRAGMENT\0".as_ptr().cast()),
|
UniformLocation {
|
||||||
})
|
vertex: gl::GetUniformBlockIndex(
|
||||||
|
program,
|
||||||
|
b"LIBRA_UBO_VERTEX\0".as_ptr().cast(),
|
||||||
|
),
|
||||||
|
fragment: gl::GetUniformBlockIndex(
|
||||||
|
program,
|
||||||
|
b"LIBRA_UBO_FRAGMENT\0".as_ptr().cast(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let ubo_ring = if let Some(ubo) = &reflection.ubo {
|
let ubo_ring = if let Some(ubo) = &reflection.ubo {
|
||||||
|
@ -224,7 +262,12 @@ impl FilterChain {
|
||||||
gl::GenBuffers(16, ring.items_mut().as_mut_ptr());
|
gl::GenBuffers(16, ring.items_mut().as_mut_ptr());
|
||||||
for buffer in ring.items() {
|
for buffer in ring.items() {
|
||||||
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
|
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
|
||||||
gl::BufferData(gl::UNIFORM_BUFFER, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW);
|
gl::BufferData(
|
||||||
|
gl::UNIFORM_BUFFER,
|
||||||
|
size as GLsizeiptr,
|
||||||
|
std::ptr::null(),
|
||||||
|
gl::STREAM_DRAW,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
|
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
@ -233,24 +276,55 @@ impl FilterChain {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let uniform_buffer = vec![0; reflection.ubo.as_ref().map(|ubo| ubo.size as usize).unwrap_or(0)].into_boxed_slice();
|
let uniform_buffer = vec![
|
||||||
let push_buffer = vec![0; reflection.push_constant.as_ref().map(|push| push.size as usize).unwrap_or(0)].into_boxed_slice();
|
0;
|
||||||
|
reflection
|
||||||
|
.ubo
|
||||||
|
.as_ref()
|
||||||
|
.map(|ubo| ubo.size as usize)
|
||||||
|
.unwrap_or(0)
|
||||||
|
]
|
||||||
|
.into_boxed_slice();
|
||||||
|
let push_buffer = vec![
|
||||||
|
0;
|
||||||
|
reflection
|
||||||
|
.push_constant
|
||||||
|
.as_ref()
|
||||||
|
.map(|push| push.size as usize)
|
||||||
|
.unwrap_or(0)
|
||||||
|
]
|
||||||
|
.into_boxed_slice();
|
||||||
|
|
||||||
// todo: reflect indexed parameters
|
// todo: reflect indexed parameters
|
||||||
let mut locations = FxHashMap::default();
|
let mut locations = FxHashMap::default();
|
||||||
for param in reflection.meta.parameter_meta.values() {
|
for param in reflection.meta.parameter_meta.values() {
|
||||||
locations.insert(UniformBinding::Parameter(param.id.clone()),
|
locations.insert(
|
||||||
(FilterChain::reflect_uniform_location(program, param), param.offset));
|
UniformBinding::Parameter(param.id.clone()),
|
||||||
|
(
|
||||||
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
param.offset,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.variable_meta {
|
for (semantics, param) in &reflection.meta.variable_meta {
|
||||||
locations.insert(UniformBinding::SemanticVariable(semantics.clone()),
|
locations.insert(
|
||||||
(FilterChain::reflect_uniform_location(program, param), param.offset));
|
UniformBinding::SemanticVariable(*semantics),
|
||||||
|
(
|
||||||
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
param.offset,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (semantics, param) in &reflection.meta.texture_size_meta {
|
for (semantics, param) in &reflection.meta.texture_size_meta {
|
||||||
locations.insert(UniformBinding::TextureSize(semantics.clone()),
|
locations.insert(
|
||||||
(FilterChain::reflect_uniform_location(program, param), param.offset));
|
UniformBinding::TextureSize(*semantics),
|
||||||
|
(
|
||||||
|
FilterChain::reflect_uniform_location(program, param),
|
||||||
|
param.offset,
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// need output framebuffers.
|
// need output framebuffers.
|
||||||
|
@ -275,7 +349,7 @@ impl FilterChain {
|
||||||
push_buffer,
|
push_buffer,
|
||||||
variable_bindings: locations,
|
variable_bindings: locations,
|
||||||
source,
|
source,
|
||||||
config: config.clone()
|
config: config.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,15 +368,28 @@ impl FilterChain {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::GenTextures(1, &mut handle);
|
gl::GenTextures(1, &mut handle);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, handle);
|
gl::BindTexture(gl::TEXTURE_2D, handle);
|
||||||
gl::TexStorage2D(gl::TEXTURE_2D, levels as GLsizei, gl::RGBA8,
|
gl::TexStorage2D(
|
||||||
image.width as GLsizei, image.height as GLsizei);
|
gl::TEXTURE_2D,
|
||||||
|
levels as GLsizei,
|
||||||
|
gl::RGBA8,
|
||||||
|
image.width as GLsizei,
|
||||||
|
image.height as GLsizei,
|
||||||
|
);
|
||||||
|
|
||||||
gl::PixelStorei(gl::UNPACK_ROW_LENGTH, 0);
|
gl::PixelStorei(gl::UNPACK_ROW_LENGTH, 0);
|
||||||
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4);
|
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4);
|
||||||
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);
|
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);
|
||||||
gl::TexSubImage2D(gl::TEXTURE_2D, 0, 0, 0,
|
gl::TexSubImage2D(
|
||||||
image.width as GLsizei, image.height as GLsizei,
|
gl::TEXTURE_2D,
|
||||||
gl::RGBA, gl::UNSIGNED_BYTE, image.bytes.as_ptr().cast());
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
image.width as GLsizei,
|
||||||
|
image.height as GLsizei,
|
||||||
|
gl::RGBA,
|
||||||
|
gl::UNSIGNED_BYTE,
|
||||||
|
image.bytes.as_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
let mipmap = levels > 1;
|
let mipmap = levels > 1;
|
||||||
let linear = texture.filter_mode == FilterMode::Linear;
|
let linear = texture.filter_mode == FilterMode::Linear;
|
||||||
|
@ -313,8 +400,16 @@ impl FilterChain {
|
||||||
gl::GenerateMipmap(gl::TEXTURE_2D);
|
gl::GenerateMipmap(gl::TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, GLenum::from(texture.wrap_mode) as GLint);
|
gl::TexParameteri(
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, GLenum::from(texture.wrap_mode) as GLint);
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_S,
|
||||||
|
GLenum::from(texture.wrap_mode) as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_T,
|
||||||
|
GLenum::from(texture.wrap_mode) as GLint,
|
||||||
|
);
|
||||||
|
|
||||||
if !linear {
|
if !linear {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
||||||
|
@ -322,39 +417,52 @@ impl FilterChain {
|
||||||
} else {
|
} else {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as GLint);
|
||||||
if mipmap {
|
if mipmap {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER,
|
gl::TexParameteri(
|
||||||
gl::LINEAR_MIPMAP_LINEAR as GLint);
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_MIN_FILTER,
|
||||||
|
gl::LINEAR_MIPMAP_LINEAR as GLint,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER,
|
gl::TexParameteri(
|
||||||
gl::LINEAR as GLint);
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_MIN_FILTER,
|
||||||
|
gl::LINEAR as GLint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::BindTexture(gl::TEXTURE_2D, 0);
|
gl::BindTexture(gl::TEXTURE_2D, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
luts.insert(index, Texture {
|
luts.insert(
|
||||||
image: GlImage {
|
index,
|
||||||
handle,
|
Texture {
|
||||||
format: gl::RGBA8,
|
image: GlImage {
|
||||||
size: Size {
|
handle,
|
||||||
width: image.width,
|
format: gl::RGBA8,
|
||||||
height: image.height
|
size: Size {
|
||||||
|
width: image.width,
|
||||||
|
height: image.height,
|
||||||
|
},
|
||||||
|
padded_size: Size::default(),
|
||||||
},
|
},
|
||||||
padded_size: Size::default()
|
filter: texture.filter_mode,
|
||||||
|
mip_filter: texture.filter_mode,
|
||||||
|
wrap_mode: texture.wrap_mode,
|
||||||
},
|
},
|
||||||
filter: texture.filter_mode,
|
);
|
||||||
mip_filter: texture.filter_mode,
|
|
||||||
wrap_mode: texture.wrap_mode
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut quad_vbo = 0;
|
let mut quad_vbo = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::GenBuffers(1, &mut quad_vbo);
|
gl::GenBuffers(1, &mut quad_vbo);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbo);
|
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbo);
|
||||||
gl::BufferData(gl::ARRAY_BUFFER, std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr,
|
gl::BufferData(
|
||||||
QUAD_VBO_DATA.as_ptr().cast(), gl::STATIC_DRAW);
|
gl::ARRAY_BUFFER,
|
||||||
|
std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr,
|
||||||
|
QUAD_VBO_DATA.as_ptr().cast(),
|
||||||
|
gl::STATIC_DRAW,
|
||||||
|
);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -375,11 +483,11 @@ impl FilterChain {
|
||||||
luts,
|
luts,
|
||||||
outputs: output_framebuffers,
|
outputs: output_framebuffers,
|
||||||
quad_vbo,
|
quad_vbo,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) {
|
pub fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, _clear: bool) {
|
||||||
if self.passes.is_empty() {
|
if self.passes.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -391,17 +499,29 @@ impl FilterChain {
|
||||||
|
|
||||||
// todo: copy framebuffer
|
// todo: copy framebuffer
|
||||||
// shader_gl3: 2067
|
// shader_gl3: 2067
|
||||||
let filter = self.common.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
|
let filter = self
|
||||||
let wrap_mode = self.common.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
|
.common
|
||||||
|
.preset
|
||||||
|
.shaders
|
||||||
|
.first()
|
||||||
|
.map(|f| f.filter)
|
||||||
|
.unwrap_or_default();
|
||||||
|
let wrap_mode = self
|
||||||
|
.common
|
||||||
|
.preset
|
||||||
|
.shaders
|
||||||
|
.first()
|
||||||
|
.map(|f| f.wrap_mode)
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let original = Texture {
|
let original = Texture {
|
||||||
image: input,
|
image: input,
|
||||||
filter,
|
filter,
|
||||||
mip_filter: filter,
|
mip_filter: filter,
|
||||||
wrap_mode
|
wrap_mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut source = original.clone();
|
let mut source = original;
|
||||||
|
|
||||||
let passes_len = self.passes.len();
|
let passes_len = self.passes.len();
|
||||||
let (pass, last) = self.passes.split_at_mut(passes_len - 1);
|
let (pass, last) = self.passes.split_at_mut(passes_len - 1);
|
||||||
|
@ -409,10 +529,24 @@ impl FilterChain {
|
||||||
for (index, pass) in pass.iter_mut().enumerate() {
|
for (index, pass) in pass.iter_mut().enumerate() {
|
||||||
{
|
{
|
||||||
let target = &mut self.common.outputs[index];
|
let target = &mut self.common.outputs[index];
|
||||||
let framebuffer_size = target.scale(pass.config.scaling.clone(), pass.get_format(), vp, &original, &source);
|
let _framebuffer_size = target.scale(
|
||||||
|
pass.config.scaling.clone(),
|
||||||
|
pass.get_format(),
|
||||||
|
vp,
|
||||||
|
&original,
|
||||||
|
&source,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
let target = &self.common.outputs[index];
|
let target = &self.common.outputs[index];
|
||||||
pass.draw(&self.common, count, 1, vp, &original, &source, RenderTarget::new(target, None));
|
pass.draw(
|
||||||
|
&self.common,
|
||||||
|
count,
|
||||||
|
1,
|
||||||
|
vp,
|
||||||
|
&original,
|
||||||
|
&source,
|
||||||
|
RenderTarget::new(target, None),
|
||||||
|
);
|
||||||
let target = target.as_texture(pass.config.filter, pass.config.wrap_mode);
|
let target = target.as_texture(pass.config.filter, pass.config.wrap_mode);
|
||||||
|
|
||||||
// todo: update-pass-outputs
|
// todo: update-pass-outputs
|
||||||
|
@ -424,7 +558,15 @@ impl FilterChain {
|
||||||
for pass in last {
|
for pass in last {
|
||||||
source.filter = pass.config.filter;
|
source.filter = pass.config.filter;
|
||||||
source.mip_filter = pass.config.filter;
|
source.mip_filter = pass.config.filter;
|
||||||
pass.draw(&self.common, count, 1, vp, &original, &source, RenderTarget::new(&vp.output, vp.mvp));
|
pass.draw(
|
||||||
|
&self.common,
|
||||||
|
count,
|
||||||
|
1,
|
||||||
|
vp,
|
||||||
|
&original,
|
||||||
|
&source,
|
||||||
|
RenderTarget::new(vp.output, vp.mvp),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
use std::borrow::Borrow;
|
|
||||||
use std::iter::Filter;
|
|
||||||
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
|
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
|
||||||
use librashader_reflect::back::cross::GlslangGlslContext;
|
use librashader_reflect::back::cross::GlslangGlslContext;
|
||||||
use librashader_reflect::back::ShaderCompilerOutput;
|
use librashader_reflect::back::ShaderCompilerOutput;
|
||||||
use librashader_reflect::reflect::ShaderReflection;
|
use librashader_reflect::reflect::ShaderReflection;
|
||||||
use librashader_reflect::reflect::TextureSemanticMap;
|
|
||||||
use librashader_reflect::reflect::VariableSemanticMap;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use librashader::{ShaderFormat, ShaderSource};
|
use librashader::{ShaderFormat, ShaderSource};
|
||||||
use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderPreset};
|
use librashader_presets::ShaderPassConfig;
|
||||||
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics};
|
use librashader_reflect::reflect::semantics::{
|
||||||
use crate::framebuffer::Framebuffer;
|
MemberOffset, TextureImage, TextureSemantics, VariableSemantics,
|
||||||
|
};
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
use crate::binding::{UniformBinding, UniformLocation, VariableLocation};
|
||||||
use crate::filter_chain::{FilterChain, FilterCommon};
|
use crate::filter_chain::FilterCommon;
|
||||||
use crate::render_target::RenderTarget;
|
use crate::render_target::RenderTarget;
|
||||||
use crate::util::{GlImage, RingBuffer, Size, Texture, Viewport};
|
use crate::util::{RingBuffer, Size, Texture, Viewport};
|
||||||
|
|
||||||
pub struct FilterPass {
|
pub struct FilterPass {
|
||||||
pub reflection: ShaderReflection,
|
pub reflection: ShaderReflection,
|
||||||
|
@ -26,7 +25,7 @@ pub struct FilterPass {
|
||||||
pub push_buffer: Box<[u8]>,
|
pub push_buffer: Box<[u8]>,
|
||||||
pub variable_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
pub variable_bindings: FxHashMap<UniformBinding, (VariableLocation, MemberOffset)>,
|
||||||
pub source: ShaderSource,
|
pub source: ShaderSource,
|
||||||
pub config: ShaderPassConfig
|
pub config: ShaderPassConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterPass {
|
impl FilterPass {
|
||||||
|
@ -36,7 +35,12 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: Size) {
|
fn build_vec4(location: UniformLocation<GLint>, buffer: &mut [u8], size: Size) {
|
||||||
let vec4 = [size.width as f32, size.height as f32, 1.0 / size.width as f32, 1.0/ size.height as f32];
|
let vec4 = [
|
||||||
|
size.width as f32,
|
||||||
|
size.height as f32,
|
||||||
|
1.0 / size.width as f32,
|
||||||
|
1.0 / size.height as f32,
|
||||||
|
];
|
||||||
if location.fragment >= 0 || location.vertex >= 0 {
|
if location.fragment >= 0 || location.vertex >= 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
if location.vertex >= 0 {
|
if location.vertex >= 0 {
|
||||||
|
@ -53,8 +57,14 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn build_uniform<T>(location: UniformLocation<GLint>, buffer: &mut [u8], value: T, glfn: unsafe fn(GLint, T) -> ())
|
fn build_uniform<T>(
|
||||||
where T: Copy, T: bytemuck::Pod
|
location: UniformLocation<GLint>,
|
||||||
|
buffer: &mut [u8],
|
||||||
|
value: T,
|
||||||
|
glfn: unsafe fn(GLint, T) -> (),
|
||||||
|
) where
|
||||||
|
T: Copy,
|
||||||
|
T: bytemuck::Pod,
|
||||||
{
|
{
|
||||||
if location.fragment >= 0 || location.vertex >= 0 {
|
if location.fragment >= 0 || location.vertex >= 0 {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -66,7 +76,7 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut buffer = bytemuck::cast_slice_mut(buffer);
|
let buffer = bytemuck::cast_slice_mut(buffer);
|
||||||
buffer[0] = value;
|
buffer[0] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,10 +99,26 @@ impl FilterPass {
|
||||||
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
gl::ActiveTexture(gl::TEXTURE0 + binding.binding);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||||
|
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, GLenum::from(texture.filter) as GLint);
|
gl::TexParameteri(
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, texture.filter.gl_mip(texture.mip_filter) as GLint);
|
gl::TEXTURE_2D,
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, GLenum::from(texture.wrap_mode) as GLint);
|
gl::TEXTURE_MAG_FILTER,
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, GLenum::from(texture.wrap_mode) as GLint);
|
GLenum::from(texture.filter) as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_MIN_FILTER,
|
||||||
|
texture.filter.gl_mip(texture.mip_filter) as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_S,
|
||||||
|
GLenum::from(texture.wrap_mode) as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_T,
|
||||||
|
GLenum::from(texture.wrap_mode) as GLint,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +133,16 @@ impl FilterPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
// todo: fix rendertargets (i.e. non-final pass is internal, final pass is user provided fbo)
|
||||||
pub fn draw(&mut self, parent: &FilterCommon, frame_count: u32,
|
pub fn draw(
|
||||||
frame_direction: i32, viewport: &Viewport, original: &Texture, source: &Texture, output: RenderTarget) {
|
&mut self,
|
||||||
|
parent: &FilterCommon,
|
||||||
|
frame_count: u32,
|
||||||
|
frame_direction: i32,
|
||||||
|
viewport: &Viewport,
|
||||||
|
original: &Texture,
|
||||||
|
source: &Texture,
|
||||||
|
output: RenderTarget,
|
||||||
|
) {
|
||||||
let framebuffer = output.framebuffer;
|
let framebuffer = output.framebuffer;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -117,18 +150,33 @@ impl FilterPass {
|
||||||
gl::UseProgram(self.program);
|
gl::UseProgram(self.program);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.build_semantics(parent, output.mvp, frame_count, frame_direction, framebuffer.size, viewport, original, source);
|
self.build_semantics(
|
||||||
|
parent,
|
||||||
|
output.mvp,
|
||||||
|
frame_count,
|
||||||
|
frame_direction,
|
||||||
|
framebuffer.size,
|
||||||
|
viewport,
|
||||||
|
original,
|
||||||
|
source,
|
||||||
|
);
|
||||||
// shader_gl3:1514
|
// shader_gl3:1514
|
||||||
|
|
||||||
if self.ubo_location.vertex != gl::INVALID_INDEX && self.ubo_location.fragment != gl::INVALID_INDEX {
|
if self.ubo_location.vertex != gl::INVALID_INDEX
|
||||||
|
&& self.ubo_location.fragment != gl::INVALID_INDEX
|
||||||
|
{
|
||||||
if let (Some(ubo), Some(ring)) = (&self.reflection.ubo, &mut self.ubo_ring) {
|
if let (Some(ubo), Some(ring)) = (&self.reflection.ubo, &mut self.ubo_ring) {
|
||||||
let size = ubo.size;
|
let size = ubo.size;
|
||||||
let buffer = ring.current();
|
let buffer = ring.current();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
|
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
|
||||||
gl::BufferSubData(gl::UNIFORM_BUFFER, 0, size as GLsizeiptr,
|
gl::BufferSubData(
|
||||||
self.uniform_buffer.as_ptr().cast());
|
gl::UNIFORM_BUFFER,
|
||||||
|
0,
|
||||||
|
size as GLsizeiptr,
|
||||||
|
self.uniform_buffer.as_ptr().cast(),
|
||||||
|
);
|
||||||
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
|
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
|
||||||
|
|
||||||
if self.ubo_location.vertex != gl::INVALID_INDEX {
|
if self.ubo_location.vertex != gl::INVALID_INDEX {
|
||||||
|
@ -150,7 +198,12 @@ impl FilterPass {
|
||||||
gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32);
|
gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32);
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
//
|
//
|
||||||
gl::Viewport(0, 0, framebuffer.size.width as GLsizei, framebuffer.size.height as GLsizei);
|
gl::Viewport(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
framebuffer.size.width as GLsizei,
|
||||||
|
framebuffer.size.height as GLsizei,
|
||||||
|
);
|
||||||
|
|
||||||
if framebuffer.format == gl::SRGB8_ALPHA8 {
|
if framebuffer.format == gl::SRGB8_ALPHA8 {
|
||||||
gl::Enable(gl::FRAMEBUFFER_SRGB);
|
gl::Enable(gl::FRAMEBUFFER_SRGB);
|
||||||
|
@ -170,13 +223,24 @@ impl FilterPass {
|
||||||
/// the provided pointers are of OpenGL provenance with respect to the buffer bound to quad_vbo,
|
/// the provided pointers are of OpenGL provenance with respect to the buffer bound to quad_vbo,
|
||||||
/// and not a known provenance to the Rust abstract machine, therefore we give it invalid pointers.
|
/// and not a known provenance to the Rust abstract machine, therefore we give it invalid pointers.
|
||||||
/// that are inexpressible in Rust
|
/// that are inexpressible in Rust
|
||||||
gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, (4 * std::mem::size_of::<f32>()) as GLsizei,
|
gl::VertexAttribPointer(
|
||||||
std::ptr::invalid(0));
|
0,
|
||||||
gl::VertexAttribPointer(1, 2, gl::FLOAT, gl::FALSE, (4 * std::mem::size_of::<f32>()) as GLsizei,
|
2,
|
||||||
std::ptr::invalid(2 * std::mem::size_of::<f32>()));
|
gl::FLOAT,
|
||||||
|
gl::FALSE,
|
||||||
|
(4 * std::mem::size_of::<f32>()) as GLsizei,
|
||||||
|
std::ptr::invalid(0),
|
||||||
|
);
|
||||||
|
gl::VertexAttribPointer(
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
gl::FLOAT,
|
||||||
|
gl::FALSE,
|
||||||
|
(4 * std::mem::size_of::<f32>()) as GLsizei,
|
||||||
|
std::ptr::invalid(2 * std::mem::size_of::<f32>()),
|
||||||
|
);
|
||||||
gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);
|
gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
gl::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||||
gl::DisableVertexAttribArray(0);
|
gl::DisableVertexAttribArray(0);
|
||||||
gl::DisableVertexAttribArray(1);
|
gl::DisableVertexAttribArray(1);
|
||||||
|
@ -185,78 +249,133 @@ impl FilterPass {
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// todo: draw image onto fbo
|
// todo: draw image onto fbo
|
||||||
// shader_gl3 1579
|
// shader_gl3 1579
|
||||||
}
|
}
|
||||||
|
|
||||||
// framecount should be pre-modded
|
// framecount should be pre-modded
|
||||||
fn build_semantics(&mut self, parent: &FilterCommon, mvp: &[f32], frame_count: u32, frame_direction: i32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) {
|
fn build_semantics(
|
||||||
if let Some((_location, offset)) = self.variable_bindings.get(&VariableSemantics::MVP.into()) {
|
&mut self,
|
||||||
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
parent: &FilterCommon,
|
||||||
let (buffer, offset) = match offset {
|
mvp: &[f32],
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
frame_count: u32,
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
frame_direction: i32,
|
||||||
};
|
fb_size: Size,
|
||||||
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
|
viewport: &Viewport,
|
||||||
}
|
original: &Texture,
|
||||||
|
source: &Texture,
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::Output.into()) {
|
) {
|
||||||
|
if let Some((_location, offset)) =
|
||||||
|
self.variable_bindings.get(&VariableSemantics::MVP.into())
|
||||||
|
{
|
||||||
|
let mvp_size = mvp.len() * std::mem::size_of::<f32>();
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
|
};
|
||||||
|
FilterPass::build_mvp(&mut buffer[offset..][..mvp_size], mvp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&VariableSemantics::Output.into())
|
||||||
|
{
|
||||||
|
let (buffer, offset) = match offset {
|
||||||
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
|
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size)
|
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], fb_size)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FinalViewport.into()) {
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&VariableSemantics::FinalViewport.into())
|
||||||
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], viewport.output.size)
|
FilterPass::build_vec4(
|
||||||
|
location.location(),
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
viewport.output.size,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FrameCount.into()) {
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&VariableSemantics::FrameCount.into())
|
||||||
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
FilterPass::build_uint(location.location(), &mut buffer[offset..][..4], frame_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&VariableSemantics::FrameDirection.into()) {
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&VariableSemantics::FrameDirection.into())
|
||||||
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
FilterPass::build_sint(location.location(), &mut buffer[offset..][..4], frame_direction)
|
FilterPass::build_sint(
|
||||||
|
location.location(),
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
frame_direction,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) {
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Original.semantics(0))
|
||||||
|
{
|
||||||
eprintln!("setting original binding to {}", binding.binding);
|
eprintln!("setting original binding to {}", binding.binding);
|
||||||
FilterPass::bind_texture(binding, original);
|
FilterPass::bind_texture(binding, original);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Original.semantics(0).into()) {
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&TextureSemantics::Original.semantics(0).into())
|
||||||
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], original.image.size);
|
FilterPass::build_vec4(
|
||||||
|
location.location(),
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
original.image.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) {
|
if let Some(binding) = self
|
||||||
|
.reflection
|
||||||
|
.meta
|
||||||
|
.texture_meta
|
||||||
|
.get(&TextureSemantics::Source.semantics(0))
|
||||||
|
{
|
||||||
// eprintln!("setting source binding to {}", binding.binding);
|
// eprintln!("setting source binding to {}", binding.binding);
|
||||||
FilterPass::bind_texture(binding, source);
|
FilterPass::bind_texture(binding, source);
|
||||||
}
|
}
|
||||||
if let Some((location, offset)) = self.variable_bindings.get(&TextureSemantics::Source.semantics(0).into()) {
|
if let Some((location, offset)) = self
|
||||||
|
.variable_bindings
|
||||||
|
.get(&TextureSemantics::Source.semantics(0).into())
|
||||||
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4], source.image.size);
|
FilterPass::build_vec4(
|
||||||
|
location.location(),
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
source.image.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// // todo: history
|
// // todo: history
|
||||||
|
@ -273,60 +392,72 @@ impl FilterPass {
|
||||||
// // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
// // FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
||||||
// // }
|
// // }
|
||||||
//
|
//
|
||||||
for (id, (location, offset)) in self.variable_bindings.iter()
|
for (id, (location, offset)) in
|
||||||
.filter_map(|(binding, value)| match binding {
|
self.variable_bindings
|
||||||
UniformBinding::Parameter(id) => {
|
.iter()
|
||||||
Some((id, value))
|
.filter_map(|(binding, value)| match binding {
|
||||||
}
|
UniformBinding::Parameter(id) => Some((id, value)),
|
||||||
_ => None
|
_ => None,
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let id = id.as_str();
|
let id = id.as_str();
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
|
|
||||||
// presets override params
|
// presets override params
|
||||||
let default = self.source.parameters.iter().find(|&p| p.id == id)
|
let default = self
|
||||||
|
.source
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.find(|&p| p.id == id)
|
||||||
.map(|f| f.initial)
|
.map(|f| f.initial)
|
||||||
.unwrap_or(0f32);
|
.unwrap_or(0f32);
|
||||||
|
|
||||||
let value = parent.preset.parameters.iter().find(|&p| p.name == id)
|
let value = parent
|
||||||
|
.preset
|
||||||
|
.parameters
|
||||||
|
.iter()
|
||||||
|
.find(|&p| p.name == id)
|
||||||
.map(|p| p.value)
|
.map(|p| p.value)
|
||||||
.unwrap_or(default);
|
.unwrap_or(default);
|
||||||
|
|
||||||
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
FilterPass::build_float(location.location(), &mut buffer[offset..][..4], value)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (id, (location, offset)) in self.variable_bindings.iter()
|
for (id, (location, offset)) in
|
||||||
.filter_map(|(binding, value)| match binding {
|
self.variable_bindings
|
||||||
UniformBinding::TextureSize(semantics) => {
|
.iter()
|
||||||
if semantics.semantics == TextureSemantics::User {
|
.filter_map(|(binding, value)| match binding {
|
||||||
Some((semantics, value))
|
UniformBinding::TextureSize(semantics) => {
|
||||||
} else {
|
if semantics.semantics == TextureSemantics::User {
|
||||||
None
|
Some((semantics, value))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
_ => None,
|
||||||
_ => None
|
})
|
||||||
})
|
|
||||||
{
|
{
|
||||||
let (buffer, offset) = match offset {
|
let (buffer, offset) = match offset {
|
||||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, *offset),
|
||||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset)
|
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, *offset),
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(lut) = parent.luts.get(&id.index) {
|
if let Some(lut) = parent.luts.get(&id.index) {
|
||||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&id) {
|
if let Some(binding) = self.reflection.meta.texture_meta.get(id) {
|
||||||
FilterPass::bind_texture(binding, lut);
|
FilterPass::bind_texture(binding, lut);
|
||||||
}
|
}
|
||||||
|
|
||||||
FilterPass::build_vec4(location.location(), &mut buffer[offset..][..4],
|
FilterPass::build_vec4(
|
||||||
lut.image.size);
|
location.location(),
|
||||||
|
&mut buffer[offset..][..4],
|
||||||
|
lut.image.size,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// // todo history
|
// // todo history
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
use crate::util;
|
||||||
|
use crate::util::{GlImage, Size, Texture, Viewport};
|
||||||
use gl::types::{GLenum, GLsizei, GLuint};
|
use gl::types::{GLenum, GLsizei, GLuint};
|
||||||
use librashader::{FilterMode, ShaderFormat, WrapMode};
|
use librashader::{FilterMode, ShaderFormat, WrapMode};
|
||||||
use librashader_presets::{Scale2D, ScaleType, Scaling};
|
use librashader_presets::{Scale2D, ScaleType, Scaling};
|
||||||
use crate::util;
|
|
||||||
use crate::util::{GlImage, Size, Texture, Viewport};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Framebuffer {
|
pub struct Framebuffer {
|
||||||
|
@ -12,7 +12,7 @@ pub struct Framebuffer {
|
||||||
pub max_levels: u32,
|
pub max_levels: u32,
|
||||||
pub levels: u32,
|
pub levels: u32,
|
||||||
pub handle: GLuint,
|
pub handle: GLuint,
|
||||||
pub init: bool
|
pub init: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Framebuffer {
|
impl Framebuffer {
|
||||||
|
@ -26,24 +26,33 @@ impl Framebuffer {
|
||||||
|
|
||||||
Framebuffer {
|
Framebuffer {
|
||||||
image: 0,
|
image: 0,
|
||||||
size: Size { width: 1, height: 1 },
|
size: Size {
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
},
|
||||||
format: 0,
|
format: 0,
|
||||||
max_levels,
|
max_levels,
|
||||||
levels: 0,
|
levels: 0,
|
||||||
handle: framebuffer,
|
handle: framebuffer,
|
||||||
init: false
|
init: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_raw(texture: GLuint, handle: GLuint, format: GLenum, size: Size, miplevels: u32) -> Framebuffer {
|
pub fn new_from_raw(
|
||||||
|
texture: GLuint,
|
||||||
|
handle: GLuint,
|
||||||
|
format: GLenum,
|
||||||
|
size: Size,
|
||||||
|
miplevels: u32,
|
||||||
|
) -> Framebuffer {
|
||||||
Framebuffer {
|
Framebuffer {
|
||||||
image: texture,
|
image: texture,
|
||||||
size,
|
size,
|
||||||
format,
|
format,
|
||||||
max_levels: miplevels,
|
max_levels: miplevels,
|
||||||
levels: miplevels,
|
levels: miplevels,
|
||||||
handle: handle,
|
handle,
|
||||||
init: true
|
init: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,78 +62,76 @@ impl Framebuffer {
|
||||||
handle: self.image,
|
handle: self.image,
|
||||||
format: self.format,
|
format: self.format,
|
||||||
size: self.size,
|
size: self.size,
|
||||||
padded_size: Default::default()
|
padded_size: Default::default(),
|
||||||
},
|
},
|
||||||
filter,
|
filter,
|
||||||
mip_filter: filter,
|
mip_filter: filter,
|
||||||
wrap_mode
|
wrap_mode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale(&mut self, scaling: Scale2D, format: ShaderFormat, viewport: &Viewport, original: &Texture, source: &Texture) -> Size {
|
pub fn scale(
|
||||||
|
&mut self,
|
||||||
|
scaling: Scale2D,
|
||||||
|
format: ShaderFormat,
|
||||||
|
viewport: &Viewport,
|
||||||
|
_original: &Texture,
|
||||||
|
source: &Texture,
|
||||||
|
) -> Size {
|
||||||
let mut width = 0f32;
|
let mut width = 0f32;
|
||||||
let mut height = 0f32;
|
let mut height = 0f32;
|
||||||
|
|
||||||
match scaling.x {
|
match scaling.x {
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Input,
|
scale_type: ScaleType::Input,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => width = source.image.size.width * factor,
|
||||||
width = source.image.size.width * factor
|
|
||||||
},
|
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Absolute,
|
scale_type: ScaleType::Absolute,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => width = factor.into(),
|
||||||
width = factor.into()
|
|
||||||
}
|
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Viewport,
|
scale_type: ScaleType::Viewport,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => width = viewport.output.size.width * factor,
|
||||||
width = viewport.output.size.width * factor
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match scaling.y {
|
match scaling.y {
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Input,
|
scale_type: ScaleType::Input,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => height = source.image.size.height * factor,
|
||||||
height = source.image.size.height * factor
|
|
||||||
},
|
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Absolute,
|
scale_type: ScaleType::Absolute,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => height = factor.into(),
|
||||||
height = factor.into()
|
|
||||||
}
|
|
||||||
Scaling {
|
Scaling {
|
||||||
scale_type: ScaleType::Viewport,
|
scale_type: ScaleType::Viewport,
|
||||||
factor
|
factor,
|
||||||
} => {
|
} => height = viewport.output.size.height * factor,
|
||||||
height = viewport.output.size.height * factor
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let size = Size {
|
let size = Size {
|
||||||
width: width.round() as u32,
|
width: width.round() as u32,
|
||||||
height: height.round() as u32
|
height: height.round() as u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.size != size {
|
if self.size != size {
|
||||||
self.size = size;
|
self.size = size;
|
||||||
|
|
||||||
self.init(size,if format == ShaderFormat::Unknown {
|
self.init(
|
||||||
ShaderFormat::R8G8B8A8Unorm
|
size,
|
||||||
} else {
|
if format == ShaderFormat::Unknown {
|
||||||
format
|
ShaderFormat::R8G8B8A8Unorm
|
||||||
});
|
} else {
|
||||||
|
format
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self, mut size: Size, mut format: impl Into<GLenum>) {
|
fn init(&mut self, mut size: Size, format: impl Into<GLenum>) {
|
||||||
self.format = format.into();
|
self.format = format.into();
|
||||||
self.size = size;
|
self.size = size;
|
||||||
|
|
||||||
|
@ -133,7 +140,13 @@ impl Framebuffer {
|
||||||
|
|
||||||
// reset the framebuffer image
|
// reset the framebuffer image
|
||||||
if self.image != 0 {
|
if self.image != 0 {
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0);
|
gl::FramebufferTexture2D(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
gl::DeleteTextures(1, &self.image);
|
gl::DeleteTextures(1, &self.image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +168,20 @@ impl Framebuffer {
|
||||||
self.levels = 1;
|
self.levels = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, self.format, size.width as GLsizei, size.height as GLsizei);
|
gl::TexStorage2D(
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
|
gl::TEXTURE_2D,
|
||||||
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0);
|
self.levels as GLsizei,
|
||||||
|
self.format,
|
||||||
|
size.width as GLsizei,
|
||||||
|
size.height as GLsizei,
|
||||||
|
);
|
||||||
|
gl::FramebufferTexture2D(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
self.image,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER);
|
let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER);
|
||||||
if status != gl::FRAMEBUFFER_COMPLETE {
|
if status != gl::FRAMEBUFFER_COMPLETE {
|
||||||
|
@ -165,8 +189,13 @@ impl Framebuffer {
|
||||||
gl::FRAMEBUFFER_UNSUPPORTED => {
|
gl::FRAMEBUFFER_UNSUPPORTED => {
|
||||||
eprintln!("unsupported fbo");
|
eprintln!("unsupported fbo");
|
||||||
|
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
|
gl::FramebufferTexture2D(
|
||||||
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0);
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
);
|
||||||
gl::DeleteTextures(1, &self.image);
|
gl::DeleteTextures(1, &self.image);
|
||||||
gl::GenTextures(1, &mut self.image);
|
gl::GenTextures(1, &mut self.image);
|
||||||
gl::BindTexture(1, self.image);
|
gl::BindTexture(1, self.image);
|
||||||
|
@ -179,12 +208,24 @@ impl Framebuffer {
|
||||||
self.levels = 1;
|
self.levels = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, ShaderFormat::R8G8B8A8Unorm.into(), size.width as GLsizei, size.height as GLsizei);
|
gl::TexStorage2D(
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
|
gl::TEXTURE_2D,
|
||||||
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0);
|
self.levels as GLsizei,
|
||||||
self.init = gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
|
ShaderFormat::R8G8B8A8Unorm.into(),
|
||||||
|
size.width as GLsizei,
|
||||||
|
size.height as GLsizei,
|
||||||
|
);
|
||||||
|
gl::FramebufferTexture2D(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
self.image,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
self.init =
|
||||||
|
gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
|
||||||
}
|
}
|
||||||
_ => panic!("failed to complete: {status:x}")
|
_ => panic!("failed to complete: {status:x}"),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.init = true;
|
self.init = true;
|
||||||
|
@ -207,4 +248,4 @@ impl Drop for Framebuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,10 @@ use std::convert::TryInto;
|
||||||
use std::ffi::{c_void, CStr};
|
use std::ffi::{c_void, CStr};
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
|
|
||||||
use glfw;
|
|
||||||
use glfw::{Context, Glfw, Window, WindowEvent};
|
use glfw::{Context, Glfw, Window, WindowEvent};
|
||||||
use gl;
|
|
||||||
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
|
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
|
||||||
use glfw::Key::P;
|
|
||||||
use crate::filter_chain::FilterChain;
|
use crate::filter_chain::FilterChain;
|
||||||
use crate::framebuffer::Framebuffer;
|
use crate::framebuffer::Framebuffer;
|
||||||
use crate::util::{GlImage, Size, Viewport};
|
use crate::util::{GlImage, Size, Viewport};
|
||||||
|
@ -18,7 +17,12 @@ const TITLE: &str = "Hello From OpenGL World!";
|
||||||
pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
||||||
let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) };
|
let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) };
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ShaderSource(vertex_shader, 1, &vertex.as_bytes().as_ptr().cast(), &vertex.len().try_into().unwrap());
|
gl::ShaderSource(
|
||||||
|
vertex_shader,
|
||||||
|
1,
|
||||||
|
&vertex.as_bytes().as_ptr().cast(),
|
||||||
|
&vertex.len().try_into().unwrap(),
|
||||||
|
);
|
||||||
gl::CompileShader(vertex_shader);
|
gl::CompileShader(vertex_shader);
|
||||||
|
|
||||||
let mut success = 0;
|
let mut success = 0;
|
||||||
|
@ -31,13 +35,21 @@ pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
||||||
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
let mut v: Vec<u8> = Vec::with_capacity(1024);
|
||||||
gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
gl::GetShaderInfoLog(vertex_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
||||||
v.set_len(log_len.try_into().unwrap());
|
v.set_len(log_len.try_into().unwrap());
|
||||||
panic!("Vertex Shader Compile Error: {}", String::from_utf8_lossy(&v));
|
panic!(
|
||||||
|
"Vertex Shader Compile Error: {}",
|
||||||
|
String::from_utf8_lossy(&v)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let fragment_shader = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) };
|
let fragment_shader = unsafe { gl::CreateShader(gl::FRAGMENT_SHADER) };
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ShaderSource(fragment_shader, 1, &fragment.as_bytes().as_ptr().cast(), &fragment.len().try_into().unwrap());
|
gl::ShaderSource(
|
||||||
|
fragment_shader,
|
||||||
|
1,
|
||||||
|
&fragment.as_bytes().as_ptr().cast(),
|
||||||
|
&fragment.len().try_into().unwrap(),
|
||||||
|
);
|
||||||
gl::CompileShader(fragment_shader);
|
gl::CompileShader(fragment_shader);
|
||||||
|
|
||||||
let mut success = 0;
|
let mut success = 0;
|
||||||
|
@ -47,7 +59,10 @@ pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
||||||
let mut log_len = 0_i32;
|
let mut log_len = 0_i32;
|
||||||
gl::GetShaderInfoLog(fragment_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
gl::GetShaderInfoLog(fragment_shader, 1024, &mut log_len, v.as_mut_ptr().cast());
|
||||||
v.set_len(log_len.try_into().unwrap());
|
v.set_len(log_len.try_into().unwrap());
|
||||||
panic!("Fragment Shader Compile Error: {}", String::from_utf8_lossy(&v));
|
panic!(
|
||||||
|
"Fragment Shader Compile Error: {}",
|
||||||
|
String::from_utf8_lossy(&v)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,39 +91,53 @@ pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
||||||
shader_program
|
shader_program
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "system" fn debug_callback(
|
||||||
extern "system" fn debug_callback(source: GLenum, err_type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: *const GLchar, _user: *mut c_void) {
|
_source: GLenum,
|
||||||
|
_err_type: GLenum,
|
||||||
|
_id: GLuint,
|
||||||
|
_severity: GLenum,
|
||||||
|
_length: GLsizei,
|
||||||
|
message: *const GLchar,
|
||||||
|
_user: *mut c_void,
|
||||||
|
) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let message = CStr::from_ptr(message);
|
let message = CStr::from_ptr(message);
|
||||||
eprintln!("{:?}", message);
|
eprintln!("{message:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) {
|
pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) {
|
||||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
||||||
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
||||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
|
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
|
||||||
|
glfw::OpenGlProfileHint::Core,
|
||||||
|
));
|
||||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||||
glfw.window_hint(glfw::WindowHint::Resizable(false));
|
glfw.window_hint(glfw::WindowHint::Resizable(false));
|
||||||
glfw.window_hint(glfw::WindowHint::OpenGlDebugContext(true));
|
glfw.window_hint(glfw::WindowHint::OpenGlDebugContext(true));
|
||||||
|
|
||||||
let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
|
let (mut window, events) = glfw
|
||||||
|
.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed)
|
||||||
|
.unwrap();
|
||||||
let (screen_width, screen_height) = window.get_framebuffer_size();
|
let (screen_width, screen_height) = window.get_framebuffer_size();
|
||||||
|
|
||||||
window.make_current();
|
window.make_current();
|
||||||
window.set_key_polling(true);
|
window.set_key_polling(true);
|
||||||
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
||||||
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::Enable(gl::DEBUG_OUTPUT);
|
gl::Enable(gl::DEBUG_OUTPUT);
|
||||||
gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS);
|
gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
|
||||||
gl::DebugMessageCallback(Some(debug_callback), std::ptr::null_mut());
|
gl::DebugMessageCallback(Some(debug_callback), std::ptr::null_mut());
|
||||||
gl::DebugMessageControl(gl::DONT_CARE,
|
gl::DebugMessageControl(
|
||||||
gl::DONT_CARE,
|
gl::DONT_CARE,
|
||||||
gl::DONT_CARE,
|
gl::DONT_CARE,
|
||||||
0, std::ptr::null(), gl::TRUE);
|
gl::DONT_CARE,
|
||||||
|
0,
|
||||||
|
std::ptr::null(),
|
||||||
|
gl::TRUE,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -147,20 +176,24 @@ void main()
|
||||||
let shader_program = compile_program(VERT_SHADER, FRAG_SHADER);
|
let shader_program = compile_program(VERT_SHADER, FRAG_SHADER);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::ObjectLabel(gl::SHADER, shader_program, -1, b"color_shader\0".as_ptr().cast());
|
gl::ObjectLabel(
|
||||||
|
gl::SHADER,
|
||||||
|
shader_program,
|
||||||
|
-1,
|
||||||
|
b"color_shader\0".as_ptr().cast(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let vertices = &[
|
let vertices = &[
|
||||||
// positions // colors
|
// positions // colors
|
||||||
0.5f32, -0.5, 0.0, 1.0, 0.0, 0.0, // bottom right
|
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.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
|
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, // top
|
||||||
];
|
];
|
||||||
let mut vbo: gl::types::GLuint = 0;
|
let mut vbo: gl::types::GLuint = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::GenBuffers(1, &mut vbo);
|
gl::GenBuffers(1, &mut vbo);
|
||||||
gl::ObjectLabel(gl::BUFFER, vbo, -1, b"triangle_vbo\0".as_ptr().cast());
|
gl::ObjectLabel(gl::BUFFER, vbo, -1, b"triangle_vbo\0".as_ptr().cast());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -180,7 +213,6 @@ void main()
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::GenVertexArrays(1, &mut vao);
|
gl::GenVertexArrays(1, &mut vao);
|
||||||
gl::ObjectLabel(gl::VERTEX_ARRAY, vao, -1, b"triangle_vao\0".as_ptr().cast());
|
gl::ObjectLabel(gl::VERTEX_ARRAY, vao, -1, b"triangle_vao\0".as_ptr().cast());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -217,15 +249,24 @@ void main()
|
||||||
gl::ClearColor(0.3, 0.3, 0.5, 1.0);
|
gl::ClearColor(0.3, 0.3, 0.5, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------
|
// -------------------------------------------
|
||||||
println!("OpenGL version: {}", gl_get_string(gl::VERSION));
|
println!("OpenGL version: {}", gl_get_string(gl::VERSION));
|
||||||
println!("GLSL version: {}", gl_get_string(gl::SHADING_LANGUAGE_VERSION));
|
println!(
|
||||||
|
"GLSL version: {}",
|
||||||
|
gl_get_string(gl::SHADING_LANGUAGE_VERSION)
|
||||||
|
);
|
||||||
|
|
||||||
(glfw, window, events, shader_program, vao)
|
(glfw, window, events, shader_program, vao)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, triangle_program: GLuint, triangle_vao: GLuint, filter: &mut FilterChain) {
|
pub fn do_loop(
|
||||||
|
mut glfw: Glfw,
|
||||||
|
mut window: Window,
|
||||||
|
events: Receiver<(f64, WindowEvent)>,
|
||||||
|
triangle_program: GLuint,
|
||||||
|
triangle_vao: GLuint,
|
||||||
|
filter: &mut FilterChain,
|
||||||
|
) {
|
||||||
let mut rendered_framebuffer = 0;
|
let mut rendered_framebuffer = 0;
|
||||||
let mut rendered_texture = 0;
|
let mut rendered_texture = 0;
|
||||||
let mut quad_vbuf = 0;
|
let mut quad_vbuf = 0;
|
||||||
|
@ -239,24 +280,54 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
||||||
gl::GenFramebuffers(1, &mut rendered_framebuffer);
|
gl::GenFramebuffers(1, &mut rendered_framebuffer);
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer);
|
||||||
|
|
||||||
gl::ObjectLabel(gl::FRAMEBUFFER, rendered_framebuffer, -1, b"rendered_framebuffer\0".as_ptr().cast());
|
gl::ObjectLabel(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
rendered_framebuffer,
|
||||||
|
-1,
|
||||||
|
b"rendered_framebuffer\0".as_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
// make tetxure
|
// make tetxure
|
||||||
gl::GenTextures(1, &mut rendered_texture);
|
gl::GenTextures(1, &mut rendered_texture);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, rendered_texture);
|
gl::BindTexture(gl::TEXTURE_2D, rendered_texture);
|
||||||
|
|
||||||
gl::ObjectLabel(gl::TEXTURE, rendered_texture, -1, b"rendered_texture\0".as_ptr().cast());
|
gl::ObjectLabel(
|
||||||
|
gl::TEXTURE,
|
||||||
|
rendered_texture,
|
||||||
|
-1,
|
||||||
|
b"rendered_texture\0".as_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
// empty image
|
// empty image
|
||||||
gl::TexStorage2D(gl::TEXTURE_2D, 1, gl::RGBA8, WIDTH as GLsizei, HEIGHT as GLsizei);
|
gl::TexStorage2D(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
1,
|
||||||
|
gl::RGBA8,
|
||||||
|
WIDTH as GLsizei,
|
||||||
|
HEIGHT as GLsizei,
|
||||||
|
);
|
||||||
|
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
|
gl::TexParameteri(
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_S,
|
||||||
|
gl::CLAMP_TO_EDGE as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_T,
|
||||||
|
gl::CLAMP_TO_EDGE as GLint,
|
||||||
|
);
|
||||||
|
|
||||||
// set color attachment
|
// set color attachment
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, rendered_texture, 0);
|
gl::FramebufferTexture2D(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
rendered_texture,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
let buffers = [gl::COLOR_ATTACHMENT0];
|
let buffers = [gl::COLOR_ATTACHMENT0];
|
||||||
gl::DrawBuffers(1, buffers.as_ptr());
|
gl::DrawBuffers(1, buffers.as_ptr());
|
||||||
|
@ -266,21 +337,17 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
||||||
}
|
}
|
||||||
|
|
||||||
let fullscreen_fbo = [
|
let fullscreen_fbo = [
|
||||||
-1.0f32, -1.0, 0.0,
|
-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,
|
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,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
gl::GenBuffers(1, &mut quad_vbuf);
|
gl::GenBuffers(1, &mut quad_vbuf);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbuf);
|
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbuf);
|
||||||
gl::BufferData(
|
gl::BufferData(
|
||||||
gl::ARRAY_BUFFER, // target
|
gl::ARRAY_BUFFER, // target
|
||||||
(fullscreen_fbo.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
|
(fullscreen_fbo.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
|
||||||
fullscreen_fbo.as_ptr() as *const gl::types::GLvoid, // pointer to data
|
fullscreen_fbo.as_ptr() as *const gl::types::GLvoid, // pointer to data
|
||||||
gl::STATIC_DRAW, // usage
|
gl::STATIC_DRAW, // usage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,24 +356,54 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
||||||
gl::GenFramebuffers(1, &mut output_framebuffer_handle);
|
gl::GenFramebuffers(1, &mut output_framebuffer_handle);
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, output_framebuffer_handle);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, output_framebuffer_handle);
|
||||||
|
|
||||||
gl::ObjectLabel(gl::FRAMEBUFFER, output_framebuffer_handle, -1, b"output_framebuffer\0".as_ptr().cast());
|
gl::ObjectLabel(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
output_framebuffer_handle,
|
||||||
|
-1,
|
||||||
|
b"output_framebuffer\0".as_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
// make tetxure
|
// make tetxure
|
||||||
gl::GenTextures(1, &mut output_texture);
|
gl::GenTextures(1, &mut output_texture);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, output_texture);
|
gl::BindTexture(gl::TEXTURE_2D, output_texture);
|
||||||
|
|
||||||
gl::ObjectLabel(gl::TEXTURE, output_texture, -1, b"output_texture\0".as_ptr().cast());
|
gl::ObjectLabel(
|
||||||
|
gl::TEXTURE,
|
||||||
|
output_texture,
|
||||||
|
-1,
|
||||||
|
b"output_texture\0".as_ptr().cast(),
|
||||||
|
);
|
||||||
|
|
||||||
// empty image
|
// empty image
|
||||||
gl::TexStorage2D(gl::TEXTURE_2D, 1, gl::RGBA8, WIDTH as GLsizei, HEIGHT as GLsizei);
|
gl::TexStorage2D(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
1,
|
||||||
|
gl::RGBA8,
|
||||||
|
WIDTH as GLsizei,
|
||||||
|
HEIGHT as GLsizei,
|
||||||
|
);
|
||||||
|
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as GLint);
|
gl::TexParameteri(
|
||||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_S,
|
||||||
|
gl::CLAMP_TO_EDGE as GLint,
|
||||||
|
);
|
||||||
|
gl::TexParameteri(
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
gl::TEXTURE_WRAP_T,
|
||||||
|
gl::CLAMP_TO_EDGE as GLint,
|
||||||
|
);
|
||||||
|
|
||||||
// set color attachment
|
// set color attachment
|
||||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, output_texture, 0);
|
gl::FramebufferTexture2D(
|
||||||
|
gl::FRAMEBUFFER,
|
||||||
|
gl::COLOR_ATTACHMENT0,
|
||||||
|
gl::TEXTURE_2D,
|
||||||
|
output_texture,
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
|
||||||
let buffers = [gl::COLOR_ATTACHMENT0];
|
let buffers = [gl::COLOR_ATTACHMENT0];
|
||||||
gl::DrawBuffers(1, buffers.as_ptr());
|
gl::DrawBuffers(1, buffers.as_ptr());
|
||||||
|
@ -316,21 +413,17 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
||||||
}
|
}
|
||||||
|
|
||||||
let fullscreen_fbo = [
|
let fullscreen_fbo = [
|
||||||
-1.0f32, -1.0, 0.0,
|
-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,
|
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,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
gl::GenBuffers(1, &mut output_quad_vbuf);
|
gl::GenBuffers(1, &mut output_quad_vbuf);
|
||||||
gl::BindBuffer(gl::ARRAY_BUFFER, output_quad_vbuf);
|
gl::BindBuffer(gl::ARRAY_BUFFER, output_quad_vbuf);
|
||||||
gl::BufferData(
|
gl::BufferData(
|
||||||
gl::ARRAY_BUFFER, // target
|
gl::ARRAY_BUFFER, // target
|
||||||
(fullscreen_fbo.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
|
(fullscreen_fbo.len() * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, // size of data in bytes
|
||||||
fullscreen_fbo.as_ptr() as *const gl::types::GLvoid, // pointer to data
|
fullscreen_fbo.as_ptr() as *const gl::types::GLvoid, // pointer to data
|
||||||
gl::STATIC_DRAW, // usage
|
gl::STATIC_DRAW, // usage
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,17 +452,22 @@ void main()
|
||||||
color=texture(texSampler, v_tex);
|
color=texture(texSampler, v_tex);
|
||||||
}";
|
}";
|
||||||
|
|
||||||
|
|
||||||
let quad_programid = compile_program(VERT_SHADER, FRAG_SHADER);
|
let quad_programid = compile_program(VERT_SHADER, FRAG_SHADER);
|
||||||
let mut quad_vao = 0;
|
let mut quad_vao = 0;
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::GenVertexArrays(1, &mut quad_vao);
|
gl::GenVertexArrays(1, &mut quad_vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
let fb = Framebuffer::new_from_raw(output_texture, output_framebuffer_handle, gl::RGBA8, Size {
|
let fb = Framebuffer::new_from_raw(
|
||||||
width: WIDTH,
|
output_texture,
|
||||||
height: HEIGHT
|
output_framebuffer_handle,
|
||||||
}, 1);
|
gl::RGBA8,
|
||||||
|
Size {
|
||||||
|
width: WIDTH,
|
||||||
|
height: HEIGHT,
|
||||||
|
},
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
|
||||||
while !window.should_close() {
|
while !window.should_close() {
|
||||||
glfw.poll_events();
|
glfw.poll_events();
|
||||||
|
@ -382,14 +480,12 @@ void main()
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer);
|
||||||
// gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
// gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
|
||||||
gl::Viewport(0, 0, WIDTH as GLsizei, HEIGHT as GLsizei);
|
gl::Viewport(0, 0, WIDTH as GLsizei, HEIGHT as GLsizei);
|
||||||
|
|
||||||
// clear color
|
// clear color
|
||||||
clear_color(Color(0.3, 0.4, 0.6, 1.0));
|
clear_color(Color(0.3, 0.4, 0.6, 1.0));
|
||||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
|
||||||
// do the drawing
|
// do the drawing
|
||||||
gl::UseProgram(triangle_program);
|
gl::UseProgram(triangle_program);
|
||||||
// select vertices
|
// select vertices
|
||||||
|
@ -403,7 +499,6 @@ void main()
|
||||||
|
|
||||||
// unselect fbo
|
// unselect fbo
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// eprintln!("[core] rendered texture is {rendered_texture}");
|
// eprintln!("[core] rendered texture is {rendered_texture}");
|
||||||
|
@ -415,20 +510,25 @@ void main()
|
||||||
// gl::BindTexture(gl::TEXTURE_2D, rendered_texture);
|
// gl::BindTexture(gl::TEXTURE_2D, rendered_texture);
|
||||||
// }
|
// }
|
||||||
unsafe {
|
unsafe {
|
||||||
filter.frame(0, &Viewport {
|
filter.frame(
|
||||||
x: 0,
|
0,
|
||||||
y: 0,
|
&Viewport {
|
||||||
output: &fb,
|
x: 0,
|
||||||
mvp: None
|
y: 0,
|
||||||
}, GlImage {
|
output: &fb,
|
||||||
handle: rendered_texture,
|
mvp: None,
|
||||||
format: gl::RGBA8,
|
|
||||||
size: Size {
|
|
||||||
width: WIDTH,
|
|
||||||
height: HEIGHT
|
|
||||||
},
|
},
|
||||||
padded_size: Default::default()
|
GlImage {
|
||||||
}, false)
|
handle: rendered_texture,
|
||||||
|
format: gl::RGBA8,
|
||||||
|
size: Size {
|
||||||
|
width: WIDTH,
|
||||||
|
height: HEIGHT,
|
||||||
|
},
|
||||||
|
padded_size: Default::default(),
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -440,8 +540,6 @@ void main()
|
||||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||||
gl::UseProgram(quad_programid);
|
gl::UseProgram(quad_programid);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gl::ActiveTexture(gl::TEXTURE0);
|
gl::ActiveTexture(gl::TEXTURE0);
|
||||||
gl::BindTexture(gl::TEXTURE_2D, output_texture);
|
gl::BindTexture(gl::TEXTURE_2D, output_texture);
|
||||||
|
|
||||||
|
@ -467,14 +565,14 @@ pub fn gl_get_string<'a>(name: gl::types::GLenum) -> &'a str {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn glfw_handle_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
|
fn glfw_handle_event(window: &mut glfw::Window, event: glfw::WindowEvent) {
|
||||||
use glfw::WindowEvent as Event;
|
|
||||||
use glfw::Key;
|
|
||||||
use glfw::Action;
|
use glfw::Action;
|
||||||
|
use glfw::Key;
|
||||||
|
use glfw::WindowEvent as Event;
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::Key(Key::Escape, _, Action::Press, _) => {
|
Event::Key(Key::Escape, _, Action::Press, _) => {
|
||||||
window.set_should_close(true);
|
window.set_should_close(true);
|
||||||
},
|
}
|
||||||
_ => {},
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +1,26 @@
|
||||||
#![feature(strict_provenance)]
|
#![feature(strict_provenance)]
|
||||||
|
|
||||||
mod hello_triangle;
|
|
||||||
mod filter_pass;
|
|
||||||
mod util;
|
|
||||||
mod framebuffer;
|
|
||||||
mod binding;
|
mod binding;
|
||||||
mod filter_chain;
|
mod filter_chain;
|
||||||
|
mod filter_pass;
|
||||||
|
mod framebuffer;
|
||||||
|
mod hello_triangle;
|
||||||
mod render_target;
|
mod render_target;
|
||||||
|
mod util;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::filter_chain::FilterChain;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::filter_chain::FilterChain;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn triangle() {
|
fn triangle() {
|
||||||
let (glfw, window, events, shader, vao) = hello_triangle::setup();
|
let (glfw, window, events, shader, vao) = hello_triangle::setup();
|
||||||
let mut filter = FilterChain::load("../test/basic.slangp").unwrap();
|
let mut filter = FilterChain::load("../test/basic.slangp").unwrap();
|
||||||
|
|
||||||
|
|
||||||
// FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap();
|
// FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap();
|
||||||
|
|
||||||
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter );
|
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
// #[test]
|
||||||
|
|
|
@ -2,36 +2,33 @@ use crate::framebuffer::Framebuffer;
|
||||||
use crate::util::Viewport;
|
use crate::util::Viewport;
|
||||||
|
|
||||||
static DEFAULT_MVP: &[f32] = &[
|
static DEFAULT_MVP: &[f32] = &[
|
||||||
2f32, 0.0, 0.0, 0.0,
|
2f32, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, -1.0, -1.0, 0.0, 1.0,
|
||||||
0.0, 2.0, 0.0, 0.0,
|
|
||||||
0.0, 0.0, 2.0, 0.0,
|
|
||||||
-1.0, -1.0, 0.0, 1.0
|
|
||||||
];
|
];
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct RenderTarget<'a> {
|
pub struct RenderTarget<'a> {
|
||||||
pub mvp: &'a [f32],
|
pub mvp: &'a [f32],
|
||||||
pub framebuffer: &'a Framebuffer
|
pub framebuffer: &'a Framebuffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> RenderTarget<'a> {
|
impl<'a> RenderTarget<'a> {
|
||||||
pub fn new(backbuffer: &'a Framebuffer, mvp: Option<&'a [f32]>) -> Self {
|
pub fn new(backbuffer: &'a Framebuffer, mvp: Option<&'a [f32]>) -> Self {
|
||||||
if let Some(mvp) = mvp {
|
if let Some(mvp) = mvp {
|
||||||
RenderTarget {
|
RenderTarget {
|
||||||
framebuffer: backbuffer,
|
framebuffer: backbuffer,
|
||||||
mvp
|
mvp,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
RenderTarget {
|
RenderTarget {
|
||||||
framebuffer: backbuffer,
|
framebuffer: backbuffer,
|
||||||
mvp: DEFAULT_MVP
|
mvp: DEFAULT_MVP,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <'a> From<&Viewport<'a>> for RenderTarget<'a> {
|
impl<'a> From<&Viewport<'a>> for RenderTarget<'a> {
|
||||||
fn from(value: &Viewport<'a>) -> Self {
|
fn from(value: &Viewport<'a>) -> Self {
|
||||||
RenderTarget::new(value.output, value.mvp)
|
RenderTarget::new(value.output, value.mvp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use gl::types::{GLenum, GLint, GLuint};
|
|
||||||
use librashader::{FilterMode, WrapMode};
|
|
||||||
use crate::framebuffer::Framebuffer;
|
use crate::framebuffer::Framebuffer;
|
||||||
|
use gl::types::{GLenum, GLuint};
|
||||||
|
use librashader::{FilterMode, WrapMode};
|
||||||
|
|
||||||
pub fn calc_miplevel(width: u32, height: u32) -> u32 {
|
pub fn calc_miplevel(width: u32, height: u32) -> u32 {
|
||||||
let mut size = std::cmp::max(width, height);
|
let mut size = std::cmp::max(width, height);
|
||||||
|
@ -10,7 +10,7 @@ pub fn calc_miplevel(width: u32, height: u32) -> u32 {
|
||||||
size >>= 1;
|
size >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return levels;
|
levels
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -18,7 +18,7 @@ pub struct Texture {
|
||||||
pub image: GlImage,
|
pub image: GlImage,
|
||||||
pub filter: FilterMode,
|
pub filter: FilterMode,
|
||||||
pub mip_filter: FilterMode,
|
pub mip_filter: FilterMode,
|
||||||
pub wrap_mode: WrapMode
|
pub wrap_mode: WrapMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
@ -26,7 +26,7 @@ pub struct Viewport<'a> {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
pub output: &'a Framebuffer,
|
pub output: &'a Framebuffer,
|
||||||
pub mvp: Option<&'a [f32]>
|
pub mvp: Option<&'a [f32]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
@ -40,10 +40,10 @@ pub struct GlImage {
|
||||||
pub handle: GLuint,
|
pub handle: GLuint,
|
||||||
pub format: GLenum,
|
pub format: GLenum,
|
||||||
pub size: Size,
|
pub size: Size,
|
||||||
pub padded_size: Size
|
pub padded_size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T, const SIZE: usize> RingBuffer<T, SIZE> {
|
impl<T, const SIZE: usize> RingBuffer<T, SIZE> {
|
||||||
pub fn current(&self) -> &T {
|
pub fn current(&self) -> &T {
|
||||||
&self.items[self.index]
|
&self.items[self.index]
|
||||||
}
|
}
|
||||||
|
@ -58,16 +58,18 @@ impl <T, const SIZE: usize> RingBuffer<T, SIZE> {
|
||||||
|
|
||||||
pub struct RingBuffer<T, const SIZE: usize> {
|
pub struct RingBuffer<T, const SIZE: usize> {
|
||||||
items: [T; SIZE],
|
items: [T; SIZE],
|
||||||
index: usize
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <T, const SIZE: usize> RingBuffer<T, SIZE>
|
impl<T, const SIZE: usize> RingBuffer<T, SIZE>
|
||||||
where T: Copy, T: Default
|
where
|
||||||
|
T: Copy,
|
||||||
|
T: Default,
|
||||||
{
|
{
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
items: [T::default(); SIZE],
|
items: [T::default(); SIZE],
|
||||||
index: 0
|
index: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +84,12 @@ where T: Copy, T: Default
|
||||||
|
|
||||||
pub unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
|
pub unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
|
||||||
let shader = gl::CreateShader(stage);
|
let shader = gl::CreateShader(stage);
|
||||||
gl::ShaderSource(shader, 1, &source.as_bytes().as_ptr().cast(), std::ptr::null());
|
gl::ShaderSource(
|
||||||
|
shader,
|
||||||
|
1,
|
||||||
|
&source.as_bytes().as_ptr().cast(),
|
||||||
|
std::ptr::null(),
|
||||||
|
);
|
||||||
gl::CompileShader(shader);
|
gl::CompileShader(shader);
|
||||||
let mut compile_status = 0;
|
let mut compile_status = 0;
|
||||||
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status);
|
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status);
|
||||||
|
|
Loading…
Reference in a new issue