Skip to content

Commit 7ab476e

Browse files
committed
Merge #1514
1514: Add render target example r=kvark a=pengowen123 This example also demonstrates the use of geometry shaders, and manual creation of resources when there is no suitable method on `Factory`. Unfortunately, I am not familiar with HLSL, so I did not add shaders for it. Fixes #1512
2 parents 6a6cd40 + 14ea1c0 commit 7ab476e

13 files changed

+482
-0
lines changed

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ path = "examples/particle/main.rs"
143143
name = "trianglell"
144144
path = "examples/trianglell/main.rs"
145145

146+
[[example]]
147+
name = "render_target"
148+
path = "examples/render_target/main.rs"
149+
146150
[dev-dependencies]
147151
cgmath = "0.14"
148152
gfx_gl = "0.3"

examples/render_target/README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--
2+
Copyright 2016 The Gfx-rs Developers.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
17+
# Render target
18+
19+
A small example demonstrating rendering to a render target.
20+
21+
## Screenshot
22+
23+
![Render Target Example](screenshot.png)

examples/render_target/compile.cmd

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@echo off
2+
set FXC="%DXSDK_DIR%\Utilities\bin\x64\fxc.exe" -nologo
3+
if not exist data mkdir data
4+
%FXC% /T vs_4_0 /E Vertex /Fo data/vertex.fx shader/cubemap.hlsl
5+
%FXC% /T ps_4_0 /E Pixel /Fo data/pixel.fx shader/cubemap.hlsl

examples/render_target/data/pixel.fx

596 Bytes
Binary file not shown.

examples/render_target/data/vertex.fx

892 Bytes
Binary file not shown.

examples/render_target/main.rs

+349
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,349 @@
1+
// Copyright 2016 The Gfx-rs Developers.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#[macro_use]
16+
extern crate gfx;
17+
extern crate gfx_app;
18+
extern crate cgmath;
19+
20+
pub use gfx_app::ColorFormat;
21+
pub use gfx::format::{Depth, Rgba8};
22+
23+
use cgmath::{Deg, Matrix4};
24+
use gfx::{Bundle, texture, memory, format, handle, state};
25+
use std::time::Instant;
26+
27+
gfx_defines!{
28+
vertex Vertex {
29+
pos: [f32; 2] = "a_Pos",
30+
}
31+
32+
constant Locals {
33+
inv_proj: [[f32; 4]; 4] = "u_InvProj",
34+
view: [[f32; 4]; 4] = "u_WorldToCamera",
35+
}
36+
37+
pipeline pipe {
38+
vbuf: gfx::VertexBuffer<Vertex> = (),
39+
cubemap: gfx::TextureSampler<[f32; 4]> = "t_Cubemap",
40+
locals: gfx::ConstantBuffer<Locals> = "Locals",
41+
out: gfx::RenderTarget<ColorFormat> = "Target0",
42+
}
43+
}
44+
45+
gfx_defines! {
46+
vertex VertexRender {
47+
pos: [f32; 3] = "a_Pos",
48+
}
49+
50+
constant LocalsRender {
51+
pos: [f32; 3] = "pos",
52+
far_plane: f32 = "farPlane",
53+
}
54+
55+
constant Matrix {
56+
matrix: [[f32; 4]; 4] = "matrix",
57+
}
58+
59+
pipeline pipe_render {
60+
vbuf: gfx::VertexBuffer<VertexRender> = (),
61+
locals: gfx::ConstantBuffer<LocalsRender> = "Locals",
62+
matrices: gfx::ConstantBuffer<Matrix> = "u_Matrices",
63+
out_depth: gfx::DepthTarget<DepthFormat> = gfx::preset::depth::LESS_EQUAL_WRITE,
64+
}
65+
}
66+
67+
impl From<cgmath::Matrix4<f32>> for Matrix {
68+
fn from(m: cgmath::Matrix4<f32>) -> Self {
69+
Matrix { matrix: m.into() }
70+
}
71+
}
72+
73+
impl Vertex {
74+
fn new(p: [f32; 2]) -> Vertex {
75+
Vertex { pos: p }
76+
}
77+
}
78+
79+
impl VertexRender {
80+
fn new(p: [f32; 3]) -> VertexRender {
81+
VertexRender { pos: p }
82+
}
83+
}
84+
85+
pub struct DepthFormat;
86+
87+
impl format::Formatted for DepthFormat {
88+
type Surface = format::D24_S8;
89+
type Channel = format::Unorm;
90+
type View = [f32; 4];
91+
92+
fn get_format() -> format::Format {
93+
format::Format(format::SurfaceType::D24_S8, format::ChannelType::Unorm)
94+
}
95+
}
96+
97+
fn create_cubemap<R, F, DF>(
98+
factory: &mut F,
99+
size: texture::Size,
100+
) -> Result<
101+
(handle::ShaderResourceView<R, DF::View>, handle::DepthStencilView<R, DF>),
102+
gfx::CombinedError,
103+
>
104+
where
105+
R: gfx::Resources,
106+
F: gfx::Factory<R>,
107+
DF: format::DepthFormat + format::TextureFormat,
108+
{
109+
// Get texture info
110+
let kind = texture::Kind::Cube(size);
111+
let levels = 1;
112+
let bind = gfx::DEPTH_STENCIL | gfx::SHADER_RESOURCE;
113+
let channel_type = <DF::Channel as format::ChannelTyped>::get_channel_type();
114+
115+
// Create texture
116+
let texture = factory.create_texture(
117+
kind,
118+
levels,
119+
bind,
120+
memory::Usage::Data,
121+
Some(channel_type),
122+
)?;
123+
124+
// View the texture as a shader resource
125+
let srv = factory.view_texture_as_shader_resource::<DF>(
126+
&texture,
127+
(0, 0),
128+
format::Swizzle::new(),
129+
)?;
130+
131+
// View the texture as a depth stencil
132+
let dsv = factory.view_texture_as_depth_stencil_trivial(&texture)?;
133+
134+
Ok((srv, dsv))
135+
}
136+
137+
struct App<R: gfx::Resources> {
138+
bundle: Bundle<R, pipe::Data<R>>,
139+
bundle_render_cubemap: Bundle<R, pipe_render::Data<R>>,
140+
projection: Matrix4<f32>,
141+
proj_render: Matrix4<f32>,
142+
far_plane: f32,
143+
start_time: Instant,
144+
}
145+
146+
impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
147+
fn new<F: gfx::Factory<R>>(
148+
factory: &mut F,
149+
backend: gfx_app::shade::Backend,
150+
window_targets: gfx_app::WindowTargets<R>,
151+
) -> Self {
152+
use gfx::traits::FactoryExt;
153+
154+
let proj = cgmath::perspective(Deg(90.0f32), window_targets.aspect_ratio, 0.01, 100.0);
155+
156+
let (bundle_skybox, dsv) = {
157+
let vs = gfx_app::shade::Source {
158+
glsl_150: include_bytes!("shader/cubemap_150.glslv"),
159+
hlsl_40: include_bytes!("data/vertex.fx"),
160+
..gfx_app::shade::Source::empty()
161+
};
162+
let ps = gfx_app::shade::Source {
163+
glsl_150: include_bytes!("shader/cubemap_150.glslf"),
164+
hlsl_40: include_bytes!("data/pixel.fx"),
165+
..gfx_app::shade::Source::empty()
166+
};
167+
168+
let vertex_data = [
169+
Vertex::new([-1.0, -1.0]),
170+
Vertex::new([3.0, -1.0]),
171+
Vertex::new([-1.0, 3.0]),
172+
];
173+
let (vbuf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());
174+
175+
let (cubemap, dsv) = create_cubemap::<_, _, DepthFormat>(factory, 1024).unwrap();
176+
177+
let sampler = factory.create_sampler_linear();
178+
179+
let pso = factory
180+
.create_pipeline_simple(
181+
vs.select(backend).unwrap(),
182+
ps.select(backend).unwrap(),
183+
pipe::new(),
184+
)
185+
.unwrap();
186+
187+
let data = pipe::Data {
188+
vbuf: vbuf,
189+
cubemap: (cubemap, sampler),
190+
locals: factory.create_constant_buffer(1),
191+
out: window_targets.color,
192+
};
193+
194+
(Bundle::new(slice, pso, data), dsv)
195+
};
196+
197+
let bundle_render_cubemap = {
198+
let vs = gfx_app::shade::Source {
199+
glsl_150: include_bytes!("shader/render_150.glslv"),
200+
..gfx_app::shade::Source::empty()
201+
};
202+
let gs = gfx_app::shade::Source {
203+
glsl_150: include_bytes!("shader/render_150.glslg"),
204+
..gfx_app::shade::Source::empty()
205+
};
206+
let ps = gfx_app::shade::Source {
207+
glsl_150: include_bytes!("shader/render_150.glslf"),
208+
..gfx_app::shade::Source::empty()
209+
};
210+
211+
let vertex_data = [
212+
VertexRender::new([0.0, 0.0, 1.0]),
213+
VertexRender::new([1.0, 1.0, 0.0]),
214+
VertexRender::new([1.0, -1.0, 0.0]),
215+
];
216+
217+
let (vbuf, slice) = factory.create_vertex_buffer_with_slice(&vertex_data, ());
218+
219+
let vs = factory
220+
.create_shader_vertex(&vs.select(backend).unwrap())
221+
.unwrap();
222+
let gs = factory
223+
.create_shader_geometry(&gs.select(backend).unwrap())
224+
.unwrap();
225+
let ps = factory
226+
.create_shader_pixel(&ps.select(backend).unwrap())
227+
.unwrap();
228+
let set = gfx::ShaderSet::Geometry(vs, gs, ps);
229+
230+
let pso = factory
231+
.create_pipeline_state(
232+
&set,
233+
gfx::Primitive::TriangleList,
234+
state::Rasterizer::new_fill(),
235+
pipe_render::new(),
236+
)
237+
.unwrap();
238+
239+
let data = pipe_render::Data {
240+
vbuf: vbuf,
241+
locals: factory.create_constant_buffer(1),
242+
matrices: factory.create_constant_buffer(6),
243+
out_depth: dsv,
244+
};
245+
246+
Bundle::new(slice, pso, data)
247+
248+
};
249+
250+
let far_plane = 10.0;
251+
let proj_render = cgmath::perspective(
252+
cgmath::Deg(90.0),
253+
window_targets.aspect_ratio,
254+
0.1,
255+
far_plane,
256+
);
257+
258+
App {
259+
bundle: bundle_skybox,
260+
bundle_render_cubemap,
261+
projection: proj,
262+
start_time: Instant::now(),
263+
proj_render: proj_render,
264+
far_plane,
265+
}
266+
}
267+
268+
fn render<C: gfx::CommandBuffer<R>>(&mut self, encoder: &mut gfx::Encoder<R, C>) {
269+
use cgmath::{Matrix4, Point3, SquareMatrix, Vector3, vec3};
270+
271+
encoder.clear(&self.bundle.data.out, [0.3, 0.3, 0.3, 1.0]);
272+
self.bundle.encode(encoder);
273+
274+
// Render to the render target
275+
{
276+
encoder.clear_depth(&self.bundle_render_cubemap.data.out_depth, 1.0);
277+
278+
let far_plane = 10.0;
279+
let pos = Point3::new(0.0, 0.0, 0.0);
280+
281+
let mut matrices: [Matrix; 6] =
282+
[
283+
Matrix4::look_at(pos, pos + vec3(1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)).into(),
284+
Matrix4::look_at(pos, pos + vec3(-1.0, 0.0, 0.0), vec3(0.0, -1.0, 0.0)).into(),
285+
Matrix4::look_at(pos, pos + vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)).into(),
286+
Matrix4::look_at(pos, pos + vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, -1.0)).into(),
287+
Matrix4::look_at(pos, pos + vec3(0.0, 0.0, 1.0), vec3(0.0, -1.0, 0.0)).into(),
288+
Matrix4::look_at(pos, pos + vec3(0.0, 0.0, -1.0), vec3(0.0, -1.0, 0.0)).into(),
289+
];
290+
291+
for m in &mut matrices {
292+
m.matrix = (self.proj_render * Matrix4::from(m.matrix)).into();
293+
}
294+
295+
let locals = LocalsRender {
296+
pos: pos.into(),
297+
far_plane,
298+
};
299+
300+
encoder.update_constant_buffer(&self.bundle_render_cubemap.data.locals, &locals);
301+
encoder
302+
.update_buffer(&self.bundle_render_cubemap.data.matrices, &matrices, 0)
303+
.unwrap();
304+
}
305+
306+
encoder.clear_depth(&self.bundle_render_cubemap.data.out_depth, 1.0);
307+
self.bundle_render_cubemap.encode(encoder);
308+
309+
// Display the render target as a skybox
310+
{
311+
// Update camera position
312+
let elapsed = self.start_time.elapsed();
313+
let time = (elapsed.as_secs() as f32 + elapsed.subsec_nanos() as f32 / 1000_000_000.0) *
314+
0.75;
315+
let x = time.sin();
316+
let z = time.cos();
317+
318+
let view = Matrix4::look_at(
319+
Point3::new(x, x / 2.0, z),
320+
Point3::new(0.0, 0.0, 0.0),
321+
Vector3::unit_y(),
322+
);
323+
324+
let locals = Locals {
325+
inv_proj: self.projection.invert().unwrap().into(),
326+
view: view.into(),
327+
};
328+
encoder.update_constant_buffer(&self.bundle.data.locals, &locals);
329+
}
330+
}
331+
332+
fn on_resize(&mut self, window_targets: gfx_app::WindowTargets<R>) {
333+
self.bundle.data.out = window_targets.color;
334+
self.projection =
335+
cgmath::perspective(Deg(90.0f32), window_targets.aspect_ratio, 0.01, 100.0);
336+
337+
self.proj_render = cgmath::perspective(
338+
cgmath::Deg(90.0),
339+
window_targets.aspect_ratio,
340+
0.1,
341+
self.far_plane,
342+
);
343+
}
344+
}
345+
346+
pub fn main() {
347+
use gfx_app::Application;
348+
App::launch_simple("Render target example");
349+
}

examples/render_target/screenshot.png

19.6 KB
Loading

0 commit comments

Comments
 (0)