nc_renderer/
utils.rs

1//
2// Copyright 2021-Present (c) Raja Lehtihet & Wael El Oraiby
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9//
10// 2. Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13//
14// 3. Neither the name of the copyright holder nor the names of its contributors
15// may be used to endorse or promote products derived from this software without
16// specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28// POSSIBILITY OF SUCH DAMAGE.
29//
30use crate::*;
31use rs_ctypes::*;
32use crate::rs_math3d::*;
33
34///
35/// create a frame buffer with only color & depth render targets
36///
37pub fn create_color_depth_frame_buffer(driver: &mut DriverPtr, width: usize, height: usize) -> Option<FrameBufferPtr> {
38    let color_tex_desc      = SamplerDesc::default(width, height).with_pixel_format(PixelFormat::RGBA8(MinMagFilter::default()));
39    let color_buffer_desc   = TextureDesc { sampler_desc: color_tex_desc, payload: None };
40    let color_buffer        = driver.create_texture(color_buffer_desc).unwrap();
41
42    let depth_tex_desc      = SamplerDesc::default(width, height).with_pixel_format(PixelFormat::D32);
43    let depth_buffer_desc   = RenderTargetDesc { sampler_desc: depth_tex_desc, sample_count: 0 };
44    let depth_buffer        = driver.create_render_target(depth_buffer_desc).unwrap();
45
46    let fb_desc             = FrameBufferDesc {
47        color_attachements: [Some(SurfaceAttachment::Texture(color_buffer)), None, None, None],
48        depth_stencil_attachement: SurfaceAttachment::RenderTarget(depth_buffer)
49    };
50
51    driver.create_frame_buffer(fb_desc)
52}
53
54///
55/// create a frame buffer with color, normal & depth render targets
56///
57pub fn create_color_normal_depth_frame_buffer(driver: &mut DriverPtr, width: usize, height: usize) -> Option<FrameBufferPtr> {
58    let normal_tex_desc     = SamplerDesc::default(width, height).with_pixel_format(PixelFormat::RGBA32F);
59    let normal_buffer_desc  = TextureDesc { sampler_desc: normal_tex_desc, payload: None };
60    let normal_buffer       = driver.create_texture(normal_buffer_desc).unwrap();
61
62    let color_tex_desc      = SamplerDesc::default(width, height).with_pixel_format(PixelFormat::RGBA8(MinMagFilter::default()));
63    let color_buffer_desc   = TextureDesc { sampler_desc: color_tex_desc, payload: None };
64    let color_buffer        = driver.create_texture(color_buffer_desc).unwrap();
65
66    let depth_tex_desc      = SamplerDesc::default(width, height).with_pixel_format(PixelFormat::D32);
67    let depth_buffer_desc   = RenderTargetDesc { sampler_desc: depth_tex_desc, sample_count: 0 };
68    let depth_buffer        = driver.create_render_target(depth_buffer_desc).unwrap();
69
70    let fb_desc             = FrameBufferDesc {
71        color_attachements: [
72            Some(SurfaceAttachment::Texture(color_buffer)),
73            Some(SurfaceAttachment::Texture(normal_buffer)),
74            None,
75            None],
76        depth_stencil_attachement: SurfaceAttachment::RenderTarget(depth_buffer)
77    };
78    driver.create_frame_buffer(fb_desc)
79}
80
81crate::render_data! {
82    vertex QuadVertex {
83        position    : Vec2f,
84        uv          : Vec2f,
85    }
86}
87
88pub struct ScreenQuad {
89    vb          : DeviceBufferPtr,
90    ib          : DeviceBufferPtr,
91    u_pipeline  : PipelinePtr,
92    f_pipeline  : PipelinePtr,
93}
94
95impl ScreenQuad {
96    pub fn get_vb(&self) -> &DeviceBufferPtr { &self.vb }
97    pub fn get_ib(&self) -> &DeviceBufferPtr { &self.ib }
98}
99
100static COPY_VERTEX_SHADER : &'static str = "
101#version 300 es
102precision highp float;
103in          vec2        position;
104in          vec2        uv;
105
106out highp   vec2        vUV;
107
108void main() {
109    gl_Position = vec4(position, 0.0, 1.0);
110    vUV = uv;
111}";
112
113static COPY_UINT_PIXEL_SHADER : &'static str = "
114#version 300 es
115precision highp float;
116precision highp usampler2D;
117
118in highp    vec2        vUV;
119
120uniform     usampler2D   uTexture;
121
122out         vec4        fragColor;
123
124void main() {
125    uvec4 texel = texture(uTexture, vUV);
126    vec4 col = vec4(texel) / 255.0;
127    fragColor = col;
128}";
129
130static COPY_FLOAT_PIXEL_SHADER : &'static str = "
131#version 300 es
132precision highp float;
133precision highp usampler2D;
134
135in highp    vec2        vUV;
136
137uniform     sampler2D   uTexture;
138
139out         vec4        fragColor;
140
141void main() {
142    fragColor = texture(uTexture, vUV);
143}";
144
145
146impl ScreenQuad {
147    fn create_copy_shader(driver: &mut DriverPtr, orig_surface_type: OrigSurfaceType) -> ShaderPtr {
148        let shader_desc =
149        ShaderDesc {
150            vertex_shader       : String::from(COPY_VERTEX_SHADER),
151            pixel_shader        : String::from(
152                match orig_surface_type {
153                    OrigSurfaceType::UInt => COPY_UINT_PIXEL_SHADER,
154                    OrigSurfaceType::Float => COPY_FLOAT_PIXEL_SHADER,
155                }),
156
157            vertex_attributes   : vec!{ QuadVertex::get_attribute_names() },
158            vertex_uniforms     : Vec::new(),
159            vertex_surfaces     : Vec::new(),
160
161            pixel_uniforms      : Vec::new(),
162            pixel_surfaces      : Vec::from([String::from("uTexture")]),
163        };
164
165        driver.create_shader(shader_desc).unwrap()
166    }
167
168    fn create_copy_pipeline(driver: &mut DriverPtr, orig_surface_type: OrigSurfaceType) -> PipelinePtr {
169        let vertex_layout = VertexBufferLayout {
170            buffer_id           : 0,
171            vertex_attributes   : QuadVertex::get_attribute_descriptors(),
172            stride              : QuadVertex::stride(),
173            divisor             : 0,
174        };
175
176        let model_pipeline_desc = PipelineDesc {
177            primitive_type      : PrimitiveType::Triangles,
178            shader              : Self::create_copy_shader(driver, orig_surface_type),
179            buffer_layouts      : vec! { vertex_layout },
180            uniform_descs       : vec! {},
181            index_type          : IndexType::UInt32,
182            face_winding        : FaceWinding::CCW,
183            cull_mode           : CullMode::Winding,
184            depth_write         : true,
185            depth_test          : true,
186            blend               : BlendOp::None,
187        };
188
189        driver.create_pipeline(model_pipeline_desc).unwrap()
190    }
191
192    pub fn new(driver: &mut DriverPtr) -> Self {
193
194        let quad_verts  = vec! {
195            QuadVertex { position: Vec2f::new(-1.0, -1.0), uv: Vec2f::new(0.0, 0.0) },
196            QuadVertex { position: Vec2f::new( 1.0, -1.0), uv: Vec2f::new(1.0, 0.0) },
197            QuadVertex { position: Vec2f::new( 1.0,  1.0), uv: Vec2f::new(1.0, 1.0) },
198            QuadVertex { position: Vec2f::new(-1.0,  1.0), uv: Vec2f::new(0.0, 1.0) },
199        };
200
201        let quad_index  : Vec<u32> = vec! {
202            0, 1, 2,
203            2, 3, 0,
204        };
205
206        let vb_desc = DeviceBufferDesc::Vertex(Usage::Static(Box::new(quad_verts)));
207        let vb = driver.create_device_buffer(vb_desc).unwrap();
208
209        let ib_desc = DeviceBufferDesc::Index(Usage::Static(Box::new(quad_index)));
210        let ib = driver.create_device_buffer(ib_desc).unwrap();
211
212        Self {
213            vb,
214            ib,
215            u_pipeline: Self::create_copy_pipeline(driver, OrigSurfaceType::UInt),
216            f_pipeline: Self::create_copy_pipeline(driver, OrigSurfaceType::Float),
217        }
218    }
219
220    pub fn render(&self, driver: &mut DriverPtr, tex: &TexturePtr) {
221        let bindings = Bindings {
222            vertex_buffers  : vec!{ self.vb.clone() },
223            index_buffer    : Some(self.ib.clone()),
224
225            vertex_images   : Vec::from([]),
226            pixel_images    : Vec::from([tex.clone()]),
227        };
228
229        let pipeline    =
230            match tex.desc().sampler_desc.pixel_format.to_orig_surface_type() {
231                OrigSurfaceType::UInt   => &self.u_pipeline,
232                OrigSurfaceType::Float  => &self.f_pipeline,
233            };
234
235        driver.draw(pipeline, &bindings, core::ptr::null() as *const c_void, 2, 1);
236    }
237}