1use {
2 glu_sys as gl,
3 sfml::{
4 graphics::{
5 Color, Font, IntRect, RenderTarget, RenderWindow, Sprite, Text, Texture, Transformable,
6 },
7 system::Clock,
8 window::{ContextSettings, Event, Key, Style},
9 SfResult,
10 },
11 std::{ffi::c_void, mem::size_of},
12};
13
14include!("../example_common.rs");
15
16fn main() -> SfResult<()> {
17 example_ensure_right_working_dir();
18
19 let mut exit = false;
20 let mut srgb = false;
21
22 while !exit {
23 let ctx_sett = ContextSettings {
24 depth_bits: 24,
25 srgb_capable: srgb,
26 ..Default::default()
27 };
28
29 let mut window = RenderWindow::new(
30 (800, 600),
31 "SFML graphics with OpenGL",
32 Style::default(),
33 &ctx_sett,
34 )?;
35 window.set_vertical_sync_enabled(true);
36
37 let mut bg_tex = Texture::new()?;
38 bg_tex.set_srgb(srgb);
39 bg_tex.load_from_file("opengl-background.jpg", IntRect::default())?;
40 let bg_sprite = Sprite::with_texture(&bg_tex);
41
42 let font = Font::from_file("sansation.ttf")?;
43 let mut text = Text::new("SFML / OpenGL demo", &font, 32);
44 let mut srgb_instr = Text::new("Press space to toggle sRGB conversion", &font, 32);
45 let mut mipmap_instr = Text::new("Press return to toggle mipmapping", &font, 32);
46 text.set_fill_color(Color::rgba(255, 255, 255, 170));
47 srgb_instr.set_fill_color(Color::rgba(255, 255, 255, 170));
48 mipmap_instr.set_fill_color(Color::rgba(255, 255, 255, 170));
49 text.set_position((250., 450.));
50 srgb_instr.set_position((150., 500.));
51 mipmap_instr.set_position((180., 550.));
52
53 let mut texture = Texture::from_file("texture.jpg")?;
54 texture.generate_mipmap()?;
55 window.set_active(true)?;
56 unsafe {
57 gl::glEnable(gl::GL_DEPTH_TEST);
58 gl::glDepthMask(gl::GL_TRUE as _);
59 gl::glClearDepth(1.);
60 gl::glDisable(gl::GL_LIGHTING);
61 gl::glViewport(0, 0, window.size().x as _, window.size().y as _);
62 gl::glMatrixMode(gl::GL_PROJECTION);
63 gl::glLoadIdentity();
64 let ratio = (window.size().x / window.size().y) as gl::GLdouble;
65 gl::glFrustum(-ratio, ratio, -1., 1., 1., 500.);
66 gl::glEnable(gl::GL_TEXTURE_2D);
67 Texture::bind(&texture);
68 }
69
70 let cube: [f32; 180] = [
71 -20., -20., -20., 0., 0., -20., 20., -20., 1., 0., -20., -20., 20., 0., 1., -20., -20.,
72 20., 0., 1., -20., 20., -20., 1., 0., -20., 20., 20., 1., 1., 20., -20., -20., 0., 0.,
73 20., 20., -20., 1., 0., 20., -20., 20., 0., 1., 20., -20., 20., 0., 1., 20., 20., -20.,
74 1., 0., 20., 20., 20., 1., 1., -20., -20., -20., 0., 0., 20., -20., -20., 1., 0., -20.,
75 -20., 20., 0., 1., -20., -20., 20., 0., 1., 20., -20., -20., 1., 0., 20., -20., 20.,
76 1., 1., -20., 20., -20., 0., 0., 20., 20., -20., 1., 0., -20., 20., 20., 0., 1., -20.,
77 20., 20., 0., 1., 20., 20., -20., 1., 0., 20., 20., 20., 1., 1., -20., -20., -20., 0.,
78 0., 20., -20., -20., 1., 0., -20., 20., -20., 0., 1., -20., 20., -20., 0., 1., 20.,
79 -20., -20., 1., 0., 20., 20., -20., 1., 1., -20., -20., 20., 0., 0., 20., -20., 20.,
80 1., 0., -20., 20., 20., 0., 1., -20., 20., 20., 0., 1., 20., -20., 20., 1., 0., 20.,
81 20., 20., 1., 1.,
82 ];
83
84 unsafe {
85 gl::glEnableClientState(gl::GL_VERTEX_ARRAY);
86 gl::glEnableClientState(gl::GL_TEXTURE_COORD_ARRAY);
87 gl::glVertexPointer(
88 3,
89 gl::GL_FLOAT,
90 5 * size_of::<gl::GLfloat>() as i32,
91 cube.as_ptr() as *const c_void,
92 );
93 gl::glTexCoordPointer(
94 2,
95 gl::GL_FLOAT,
96 5 * size_of::<gl::GLfloat>() as i32,
97 cube.as_ptr().offset(3) as *const c_void,
98 );
99
100 gl::glDisableClientState(gl::GL_NORMAL_ARRAY);
102 gl::glDisableClientState(gl::GL_COLOR_ARRAY);
103 }
104
105 window.set_active(false)?;
106 let clock = Clock::start()?;
107 let mut mipmap_enabled = true;
108
109 while window.is_open() {
110 while let Some(event) = window.poll_event() {
111 match event {
112 Event::Closed
113 | Event::KeyPressed {
114 code: Key::Escape, ..
115 } => {
116 exit = true;
117 window.close();
118 }
119 Event::KeyPressed {
120 code: Key::Enter, ..
121 } => {
122 if mipmap_enabled {
123 texture = Texture::from_file("texture.jpg")?;
124 mipmap_enabled = false;
125 window.set_active(true)?;
126 Texture::bind(&texture);
127 window.set_active(false)?;
128 } else {
129 texture.generate_mipmap()?;
130 mipmap_enabled = true;
131 }
132 }
133 Event::KeyPressed {
134 code: Key::Space, ..
135 } => {
136 srgb = !srgb;
137 window.close();
138 }
139 Event::Resized { width, height } => {
140 window.set_active(true)?;
141 unsafe {
142 gl::glViewport(0, 0, width as _, height as _);
143 }
144 window.set_active(false)?;
145 }
146 _ => {}
147 }
148 }
149 window.push_gl_states();
150 window.draw(&bg_sprite);
151 window.pop_gl_states();
152
153 if let Err(e) = window.set_active(true) {
154 eprintln!("Failed to set window as active: {e}");
155 }
156
157 unsafe {
158 gl::glClear(gl::GL_DEPTH_BUFFER_BIT);
159 let x: f32 =
160 window.mouse_position().x as f32 * 200. / window.size().x as f32 - 100.;
161 let y: f32 =
162 -window.mouse_position().y as f32 * 200. / window.size().y as f32 + 100.;
163
164 gl::glMatrixMode(gl::GL_MODELVIEW);
165 gl::glLoadIdentity();
166 gl::glTranslatef(x, y, -100.);
167 gl::glRotatef(clock.elapsed_time().as_seconds() * 50., 1., 0., 0.);
168 gl::glRotatef(clock.elapsed_time().as_seconds() * 30., 0., 1., 0.);
169 gl::glRotatef(clock.elapsed_time().as_seconds() * 90., 0., 0., 1.);
170 gl::glDrawArrays(gl::GL_TRIANGLES, 0, 36);
171 }
172 if let Err(e) = window.set_active(false) {
173 eprintln!("Failed to set window as active: {e}");
174 }
175 window.push_gl_states();
176 window.draw(&text);
177 window.draw(&srgb_instr);
178 window.draw(&mipmap_instr);
179 window.pop_gl_states();
180 window.display();
181 }
182 }
183 Ok(())
184}