魔法师の高塔

About OpenGL with Rust

Rust的Glium库十分有意思,是关于OpenGL的,用起来如丝般顺滑。

卷积核滤镜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#[macro_use]
extern crate glium;
extern crate image;
use std::io::Cursor;
fn main() {
use glium::{DisplayBuild, Surface};
let display = glium::glutin::WindowBuilder::new().build_glium().unwrap();
let image = image::load(Cursor::new(&include_bytes!("../src/test.png")[..]),
image::PNG)
.unwrap()
.to_rgba();
let width = image.width();
let height = image.height();
let image_dimensions = image.dimensions();
let image = glium::texture::RawImage2d::from_raw_rgba_reversed(image.into_raw(),
image_dimensions);
let texture = glium::texture::Texture2d::new(&display, image).unwrap();
#[derive(Copy, Clone)]
struct Vertex {
position: [f32; 2],
tex_coords: [f32; 2],
}
implement_vertex!(Vertex, position, tex_coords);
let vertex1 = Vertex {
position: [-1.0, -1.0],
tex_coords: [0.0, 0.0],
};
let vertex2 = Vertex {
position: [-1.0, 1.0],
tex_coords: [0.0, 1.0],
};
let vertex3 = Vertex {
position: [1.0, -1.0],
tex_coords: [1.0, 0.0],
};
let vertex4 = Vertex {
position: [1.0, 1.0],
tex_coords: [1.0, 1.0],
};
let shape = vec![vertex1, vertex2, vertex3, vertex4];
let vertex_buffer = glium::VertexBuffer::new(&display, &shape).unwrap();
let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip);
let vertex_shader_src = r#"
#version 140
in vec2 position;
in vec2 tex_coords;
uniform float texelWidth;
uniform float texelHeight;
out vec2 v_tex_coords;
out vec2 left_v_tex_coords;
out vec2 right_v_tex_coords;
out vec2 top_v_tex_coords;
out vec2 top_left_v_tex_coords;
out vec2 top_right_v_tex_coords;
out vec2 bottom_v_tex_coords;
out vec2 bottom_left_v_tex_coords;
out vec2 bottom_right_v_tex_coords;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
vec2 widthStep = vec2(texelWidth,0.0);
vec2 heightSetp = vec2(0.0,texelHeight);
vec2 widthHeightStep = vec2(texelWidth,texelHeight);
vec2 widthNegativeHeightStep = vec2(texelWidth,-texelHeight);
v_tex_coords = tex_coords;
left_v_tex_coords = tex_coords - widthStep;
right_v_tex_coords = tex_coords + widthStep;
top_v_tex_coords = tex_coords - heightSetp;
top_left_v_tex_coords = tex_coords - widthHeightStep;
top_right_v_tex_coords = tex_coords + widthNegativeHeightStep;
bottom_v_tex_coords = tex_coords + heightSetp;
bottom_left_v_tex_coords = tex_coords - widthNegativeHeightStep;
bottom_right_v_tex_coords = tex_coords + widthHeightStep;
}
"#;
let fragment_shader_src = r#"
#version 140
in vec2 v_tex_coords;
in vec2 left_v_tex_coords;
in vec2 right_v_tex_coords;
in vec2 top_v_tex_coords;
in vec2 top_left_v_tex_coords;
in vec2 top_right_v_tex_coords;
in vec2 bottom_v_tex_coords;
in vec2 bottom_left_v_tex_coords;
in vec2 bottom_right_v_tex_coords;
out vec4 color;
uniform sampler2D tex;
uniform float init;
uniform mat3 convolutionMatrix;
void main() {
vec3 bottom_color = texture(tex,bottom_v_tex_coords).rgb;
vec3 bottom_left_color = texture(tex,bottom_left_v_tex_coords).rgb;
vec3 bottom_right_color = texture(tex,bottom_right_v_tex_coords).rgb;
vec4 center_color = texture(tex,v_tex_coords);
vec3 left_color = texture(tex,left_v_tex_coords).rgb;
vec3 right_color = texture(tex,right_v_tex_coords).rgb;
vec3 top_color = texture(tex,top_v_tex_coords).rgb;
vec3 top_right_color = texture(tex,top_right_v_tex_coords).rgb;
vec3 top_left_color = texture(tex,top_left_v_tex_coords).rgb;
vec3 result_color = top_left_color*convolutionMatrix[0][0]+top_color*convolutionMatrix[0][1]+top_right_color*convolutionMatrix[0][2];
result_color += left_color*convolutionMatrix[1][0]+center_color.rgb*convolutionMatrix[1][1]+right_color*convolutionMatrix[1][2];
result_color += bottom_left_color*convolutionMatrix[2][0]+bottom_color*convolutionMatrix[2][1]+bottom_right_color*convolutionMatrix[2][2];
color = vec4(result_color*init,center_color.a);
}
"#;
let program =
glium::Program::from_source(&display, vertex_shader_src, fragment_shader_src, None)
.unwrap();
let texel_width = 1.0 / (width as f32);
let texel_height = 1.0 / (height as f32);
loop {
let mut target = display.draw();
target.clear_color(0.0, 0.0, 1.0, 1.0);
let uniforms = uniform! {
tex: &texture,
texelWidth: texel_width,
texelHeight: texel_height,
convolutionMatrix:[
[0.0,0.0,0.0],
[0.0,1.0,0.0],
[0.0,0.0,0.0f32],
],
init: 1.0f32,
};
target.draw(&vertex_buffer,
&indices,
&program,
&uniforms,
&Default::default())
.unwrap();
target.finish().unwrap();
for ev in display.poll_events() {
match ev {
glium::glutin::Event::Closed => return,
_ => (),
}
}
}
}
边界问题我没有考虑,以后补充。