webgl_rs/
shader_program.rs

1//! WebGLProgram and WebGLShader and methods
2use glenum::{ProgramParameter, ShaderKind, ShaderParameter, TransformFeedbackBufferMode};
3use rendering_context::WebGL2RenderingContext;
4use uniform_location::{WebGLRSUniformLocation, WebGLUniformLocation};
5use wasm_bindgen::prelude::*;
6
7// TODO WebGLRenderingContext.getAttachedShaders()
8// TODO WebGLRenderingContext.getUniform()
9// The `WebGLRenderingContext.getUniform()` method of the WebGL API returns the value of a uniform variable
10    // at a given location.
11    /* FIXME: this method can have a lot of different return types -> figure out what to do
12    #[wasm_bindgen(method, js_name = getUniform)]
13    pub fn get_uniform(this: &WebGL2RenderingContext, program: WebGLProgram, location: WebGLUniformLocation)
14    */
15
16/// WebGLRSProgram
17
18impl WebGL2RenderingContext {
19    /// Creates and initializes a `WebGLRSProgram`
20    pub fn create_program(&self) -> WebGLRSProgram {
21        WebGLRSProgram {
22            context: self,
23            inner: self._create_program(),
24        }
25    }
26}
27
28/// The `WebGLRSProgram` is part of the WebGL API and is a combination of two compiled WebGLShaders
29/// consisting of a vertex shader and a fragment shader (both written in GLSL). These are then linked
30/// into a usable program.
31#[derive(Clone)]
32pub struct WebGLRSProgram<'ctx> {
33    context: &'ctx WebGL2RenderingContext,
34    inner: WebGLProgram,
35}
36
37impl<'ctx> WebGLRSProgram<'ctx> {
38    /// Deletes this `WebGLRSProgram` object. This method has no effect if the program has already been deleted.
39    pub fn delete(self) {
40        self.context._delete_program(self.inner);
41    }
42
43    /// Detaches a previously attached `WebGLRSShader` from this `WebGLRSProgram`.
44    ///
45    /// # Arguments
46    /// * `shader` - shader to detach
47    pub fn detach_shader(&self, shader: &WebGLRSShader) {
48        self.context._detach_shader(&self.inner, &shader.inner);
49    }
50
51    /// Attaches a `WebGLRSShader` to this `WebGLRSProgram`.
52    ///
53    /// # Arguments
54    /// * `shader` - shader to attach
55    pub fn attach_shader(&self, shader: &WebGLRSShader) {
56        self.context._attach_shader(&self.inner, &shader.inner)
57    }
58
59    /// Binds a generic vertex index to an attribute variable for this `WebGLRSProgram`
60    ///
61    /// # Arguments
62    /// * `index` - specifying the index of the generic vertex to bind.
63    /// * `name` - specifying the name of the variable to bind to the generic vertex index.
64    ///         This name cannot start with "webgl_" or "_webgl_", as these are reserved for use by WebGL.
65    pub fn bind_attrib_location(&self, index: u32, name: &str) {
66        self.context._bind_attrib_location(&self.inner, index, name);
67    }
68
69    /// Returns the information log for this `WebGLRSProgram` object. It contains errors that occurred during
70    /// failed linking or validation of this object.
71    pub fn info_log(&self) -> String {
72        self.context._get_program_info_log(&self.inner)
73    }
74
75    /// Returns true if this `WebGLRSProgram` is valid, false otherwise.
76    pub fn is_valid(&self) -> bool {
77        self.context._is_program(&self.inner)
78    }
79
80    /// Links this `WebGLRSProgram` to the attached vertex and fragment shaders.
81    pub fn link(&self) {
82        self.context._link_program(&self.inner);
83    }
84
85    /// Sets this `WebGLRSProgram` as part of the current rendering state.
86    pub fn enable(&self) {
87        self.context._use_program(&self.inner);
88    }
89
90    /// Validates this `WebGLRSProgram`. Checks if it is successfully linked and if it can be used in the
91    /// current WebGL state.
92    pub fn validate(&self) {
93        self.context._validate_program(&self.inner);
94    }
95
96    /// Returns a `WebGLActiveInfo` object containing size, type, and name of a vertex attribute.
97    ///
98    /// It is generally used when querying unknown uniforms either for debugging or generic library creation.
99    ///
100    /// # Arguments
101    /// * `index` - specifying the index of the vertex attribute to get.
102    pub fn active_attrib(&self, index: u32) -> WebGLActiveInfo {
103        self.context._get_active_attrib(&self.inner, index)
104    }
105
106    /// Returns a WebGLActiveInfo object containing size, type, and name of a uniform attribute.
107    ///
108    /// It is generally used when querying unknown uniforms either for debugging or generic library creation.
109    ///
110    /// # Arguments
111    /// * `index` - specifying the index of the vertex attribute to get.
112    pub fn active_uniform(&self, index: u32) -> WebGLActiveInfo {
113        self.context._get_active_uniform(&self.inner, index)
114    }
115
116    /// Returns the location of an attribute variable in this `WebGLRSProgram`.
117    ///
118    /// # Arguments
119    /// * `name` - specifying the name of the attribute variable whose location to get.  
120    pub fn attrib_location(&self, name: &str) -> u32 {
121        self.context._get_attrib_location(&self.inner, name)
122    }
123
124    /// Returns the location of a specific uniform variable which is part this `WebGLRSProgram`.
125    ///
126    /// The uniform variable is returned as a `WebGLUniformLocation` object, which is an opaque identifier
127    /// used to specify where in the GPU's memory that uniform variable is located.
128    ///
129    /// # Arguments
130    /// * `name`- specifying the name of the uniform variable whose location is to be returned. The name can't
131    ///         have any whitespace in it, and you can't use this function to get the location of any uniforms
132    ///         starting with the reserved string "gl_", since those are internal to the WebGL layer.
133    // FIXME: can be null
134    pub fn uniform_location(&self, name: &str) -> WebGLRSUniformLocation {
135        WebGLRSUniformLocation {
136            context: &self.context,
137            inner: self.context._get_uniform_location(&self.inner, name),
138        }
139    }
140
141    /// Returns the binding of color numbers to user-defined varying out variables.
142    ///
143    /// # Arguments
144    /// * `name` - specifying the name of the user-defined varying out variable.
145    pub fn frag_data_location(&self, name: &str) -> i32 {
146        self.context._get_frag_data_location(&self.inner, name)
147    }
148
149    /// Returns information about varying variables from WebGLTransformFeedback buffers.
150    ///
151    /// # Arguments
152    /// * `index` -  specifying the index of the varying variable whose information to retrieve.
153    pub fn transform_feedback_varying(&self, index: u32) -> WebGLActiveInfo {
154        self.context
155            ._get_transform_feedback_varying(&self.inner, index)
156    }
157
158    /// Retrieves the index of a uniform block in this `WebGLRSProgram`.
159    ///
160    /// # Arguments
161    /// * `uniform_block_name` - specifying the name of the uniform block to whose index to retrieve.
162    pub fn uniform_block_index(&self, uniform_block_name: &str) -> u32 {
163        self.context
164            ._get_uniform_block_index(&self.inner, uniform_block_name)
165    }
166
167    /// Retrieves the name of the active uniform block at a given index in this `WebGLRSProgram`.
168    ///
169    /// # Arguments
170    /// * `uniform_block_index` - specifying the index of the uniform block to whose name to retrieve.
171    pub fn active_uniform_block_name(&self, uniform_block_index: u32) -> String {
172        self.context
173            ._get_active_uniform_block_name(&self.inner, uniform_block_index)
174    }
175
176    /// Asigns binding points for active uniform blocks.
177    ///
178    /// # Arguments
179    /// * `uniform_block_index` - specifying the index of the active uniform block within the program.
180    /// * `uniform_block_binding` - specifying the binding point to which to bind the uniform block.
181    pub fn assign_uniform_block_binding(
182        &self,
183        uniform_block_index: u32,
184        uniform_block_binding: u32,
185    ) {
186        self.context._uniform_block_binding(
187            &self.inner,
188            uniform_block_index,
189            uniform_block_binding,
190        );
191    }
192
193    /// Indicates whether or not the program is flagged for deletion.
194    pub fn delete_status(&self) -> bool {
195        self.context
196            ._get_program_parameter_bool(&self.inner, ProgramParameter::DeleteStatus)
197    }
198
199    /// Indicates whether or not the last link operation was successful.
200    pub fn link_status(&self) -> bool {
201        self.context
202            ._get_program_parameter_bool(&self.inner, ProgramParameter::LinkStatus)
203    }
204
205    /// Indicates whether or not the last validation operation was successful.
206    pub fn validate_status(&self) -> bool {
207        self.context
208            ._get_program_parameter_bool(&self.inner, ProgramParameter::ValidateStatus)
209    }
210
211    /// Returns the number of attached shaders to a program.
212    pub fn attached_shaders(&self) -> i32 {
213        self.context
214            ._get_program_parameter_i32(&self.inner, ProgramParameter::AttachedShaders)
215    }
216
217    /// Returns the number of active attribute variables to a program.
218    pub fn active_attributes(&self) -> i32 {
219        self.context
220            ._get_program_parameter_i32(&self.inner, ProgramParameter::ActiveAttributes)
221    }
222
223    /// Returns the number of active uniform variables to a program.
224    pub fn active_uniforms(&self) -> i32 {
225        self.context
226            ._get_program_parameter_i32(&self.inner, ProgramParameter::ActiveUniforms)
227    }
228
229    /// Returns the buffer mode when transform feedback is active. May be `SeparateAttribs` or `InterleavedAttribs`.
230    pub fn transform_feedback_buffer_mode(&self) -> TransformFeedbackBufferMode {
231        self.context
232            ._get_program_parameter_enum(&self.inner, ProgramParameter::TransformFeedbackBufferMode)
233    }
234
235    /// Returns the number of varying variables to capture in transform feedback mode.
236    pub fn transform_feedback_varyings(&self) -> i32 {
237        self.context
238            ._get_program_parameter_i32(&self.inner, ProgramParameter::TransformFeedbackVaryings)
239    }
240
241    // Returns the number of uniform blocks containing active uniforms.
242    pub fn active_uniform_blocks(&self) -> i32 {
243        self.context
244            ._get_program_parameter_i32(&self.inner, ProgramParameter::ActiveUniformBlocks)
245    }
246}
247
248/// Bindings for WebGLProgram
249#[wasm_bindgen]
250#[derive(Clone, Copy)]
251extern "C" {
252
253    #[derive(Clone)]
254    type WebGLProgram;
255
256    /// Binding for `WebGLRenderingContext.createProgram()`
257    #[wasm_bindgen(method, js_name = createProgram)]
258    fn _create_program(this: &WebGL2RenderingContext) -> WebGLProgram;
259
260    /// Binding for `WebGLRenderingContext.deleteProgram()`.
261    #[wasm_bindgen(method, js_name = deleteProgram)]
262    fn _delete_program(this: &WebGL2RenderingContext, program: WebGLProgram);
263
264    /// Binding for `WebGLRenderingContext.detachShader()`.
265    #[wasm_bindgen(method, js_name = detachShader)]
266    fn _detach_shader(this: &WebGL2RenderingContext, program: &WebGLProgram, shader: &WebGLShader);
267
268    /// Binding for `WebGLRenderingContext.attachShader()`.
269    #[wasm_bindgen(method, js_name = attachShader)]
270    fn _attach_shader(this: &WebGL2RenderingContext, program: &WebGLProgram, shader: &WebGLShader);
271
272    /// Binding for `WebGLRenderingContext.bindAttribLocation()`.
273    #[wasm_bindgen(method, js_name = bindAttribLocation)]
274    fn _bind_attrib_location(
275        this: &WebGL2RenderingContext,
276        program: &WebGLProgram,
277        index: u32,
278        name: &str,
279    );
280
281    /// Binding for `WebGLRenderingContext.getProgramInfoLog`.
282    #[wasm_bindgen(method, js_name = getProgramInfoLog)]
283    fn _get_program_info_log(this: &WebGL2RenderingContext, program: &WebGLProgram) -> String;
284
285    /// Binding for `WebGLRenderingContext.isProgram()`.
286    #[wasm_bindgen(method, js_name = isProgram)]
287    fn _is_program(this: &WebGL2RenderingContext, program: &WebGLProgram) -> bool;
288
289    /// Binding for `WebGLRenderingContext.linkProgram()`.
290    #[wasm_bindgen(method, js_name = linkProgram)]
291    fn _link_program(this: &WebGL2RenderingContext, program: &WebGLProgram);
292
293    /// Binding for `WebGLRenderingContext.useProgram()`.
294    #[wasm_bindgen(method, js_name = useProgram)]
295    fn _use_program(this: &WebGL2RenderingContext, program: &WebGLProgram);
296
297    /// Binding for `WebGLRenderingContext.validateProgram()`.
298    #[wasm_bindgen(method, js_name = validateProgram)]
299    fn _validate_program(this: &WebGL2RenderingContext, program: &WebGLProgram);
300
301    /// Binding for `WebGLRenderingContext.getActiveAttrib()`.
302    #[wasm_bindgen(method, js_name = getActiveAttrib)]
303    fn _get_active_attrib(
304        this: &WebGL2RenderingContext,
305        program: &WebGLProgram,
306        index: u32,
307    ) -> WebGLActiveInfo;
308
309    /// Binding for `WebGLRenderingContext.getActiveUniform()`.
310    #[wasm_bindgen(method, js_name = getActiveUniform)]
311    fn _get_active_uniform(
312        this: &WebGL2RenderingContext,
313        program: &WebGLProgram,
314        index: u32,
315    ) -> WebGLActiveInfo;
316
317    /// Binding for `WebGLRenderingContext.getAttribLocation()`.
318    #[wasm_bindgen(method, js_name = getAttribLocation)]
319    fn _get_attrib_location(
320        this: &WebGL2RenderingContext,
321        program: &WebGLProgram,
322        name: &str,
323    ) -> u32;
324
325    /// Binding for `WebGLRenderingContext method getUniformLocation()`.
326    #[wasm_bindgen(method, js_name = getUniformLocation)]
327    fn _get_uniform_location(
328        this: &WebGL2RenderingContext,
329        program: &WebGLProgram,
330        name: &str,
331    ) -> WebGLUniformLocation;
332
333    /// Binding for `WebGL2RenderingContext.getFragDataLocation()`.
334    #[wasm_bindgen(method, js_name = getFragDataLocation)]
335    fn _get_frag_data_location(
336        this: &WebGL2RenderingContext,
337        program: &WebGLProgram,
338        name: &str,
339    ) -> i32;
340
341    /// Binding for `WebGL2RenderingContext.getTransformFeedbackVarying()`
342    #[wasm_bindgen(method, js_name = getTransfromFeedbackVarying)]
343    fn _get_transform_feedback_varying(
344        this: &WebGL2RenderingContext,
345        program: &WebGLProgram,
346        index: u32,
347    ) -> WebGLActiveInfo;
348
349    /// Binding for `WebGL2RenderingContext.getUniformBlockIndex()`
350    #[wasm_bindgen(method, js_name = getUniformBlockIndex)]
351    fn _get_uniform_block_index(
352        this: &WebGL2RenderingContext,
353        program: &WebGLProgram,
354        uniform_block_name: &str,
355    ) -> u32;
356
357    /// Binding for `WebGL2RenderingContext.getActiveUniformBlockName()`.
358    #[wasm_bindgen(method, js_name = getActiveUniformBlockName)]
359    fn _get_active_uniform_block_name(
360        this: &WebGL2RenderingContext,
361        program: &WebGLProgram,
362        uniform_block_index: u32,
363    ) -> String;
364
365    /// Binding for `WebGL2RenderingContext.uniformBlockBinding()`.
366    #[wasm_bindgen(method, js_name = uniformBlockBinding)]
367    fn _uniform_block_binding(
368        this: &WebGL2RenderingContext,
369        program: &WebGLProgram,
370        uniform_block_index: u32,
371        uniform_block_binding: u32,
372    );
373
374    /// Binding for `WebGL2RenderingContext.getProgramParameter()` when return type is i32
375    #[wasm_bindgen(method, js_name = getProgramParameter)]
376    fn _get_program_parameter_i32(
377        this: &WebGL2RenderingContext,
378        program: &WebGLProgram,
379        pname: ProgramParameter,
380    ) -> i32;
381    /// Binding for `WebGL2RenderingContext.getProgramParameter()` when return type is bool
382    #[wasm_bindgen(method, js_name = getProgramParameter)]
383    fn _get_program_parameter_bool(
384        this: &WebGL2RenderingContext,
385        program: &WebGLProgram,
386        pname: ProgramParameter,
387    ) -> bool;
388    /// Binding for `WebGL2RenderingContext.getProgramParameter()` when return type is enum
389    #[wasm_bindgen(method, js_name = getProgramParameter)]
390    fn _get_program_parameter_enum(
391        this: &WebGL2RenderingContext,
392        program: &WebGLProgram,
393        pname: ProgramParameter,
394    ) -> TransformFeedbackBufferMode;
395}
396
397// WebGLRSShader
398
399impl WebGL2RenderingContext {
400    /// Creates a WebGLRSShader that can then be configured further using `shader_source()` and `compile_shader()`.
401    ///
402    /// # Arguments
403    /// * `kind` - Kind of the shader (Vertex or Fragment)
404    pub fn create_shader(&self, kind: ShaderKind) -> WebGLRSShader {
405        WebGLRSShader {
406            context: self,
407            inner: self._create_shader(kind),
408        }
409    }
410}
411
412/// The `WebGLRSShader` is part of the WebGL API and can either be a vertex or a fragment shader.
413/// A `WebGLRSProgram` requires both types of shaders.
414#[derive(Clone)]
415pub struct WebGLRSShader<'ctx> {
416    context: &'ctx WebGL2RenderingContext,
417    inner: WebGLShader,
418}
419
420impl<'ctx> WebGLRSShader<'ctx> {
421    /// Compiles a GLSL shader into binary data so that it can be used by a `WebGLRSProgram`.
422    pub fn compile(&self) {
423        self.context._compile_shader(&self.inner);
424    }
425
426    /// Deletes this `WebGLRSShader` object.
427    pub fn delete(self) {
428        self.context._delete_shader(self.inner);
429    }
430
431    /// Returns the information log for the specified `WebGLRSShader` object. It contains warnings, debugging
432    /// and compile information.
433    pub fn info_log(&self) -> String {
434        self.context._get_shader_info_log(&self.inner)
435    }
436
437    /// Returns the source code of this `WebGLRSShader` as a `String`.
438    pub fn shader_source(&self) -> String {
439        self.context._get_shader_info_log(&self.inner)
440    }
441
442    /// Returns true if this `WebGLRSShader` is valid, false otherwise.
443    pub fn is_valid(&self) -> bool {
444        self.context._is_shader(&self.inner)
445    }
446
447    /// Sets the source code of the `WebGLRSShader` object.
448    pub fn set_shader_source(&self, source: &str) {
449        self.context._shader_source(&self.inner, source);
450    }
451
452    /// Returns a bool indicating whether or not the `WebGLRSShader` is flagged for deletion.
453    pub fn delete_status(&self) -> bool {
454        self.context
455            ._get_shader_parameter_bool(&self.inner, ShaderParameter::DeleteStatus)
456    }
457
458    /// Returns a bool indicating whether or not the last compilation was successful.
459    pub fn compile_status(&self) -> bool {
460        self.context
461            ._get_shader_parameter_bool(&self.inner, ShaderParameter::CompileStatus)
462    }
463
464    /// Returns a `ShaderKind` value indicating whether the shader is a vertex shader or fragment shader.
465    pub fn kind(&self) -> ShaderKind {
466        self.context
467            ._get_shader_parameter_enum(&self.inner, ShaderParameter::ShaderType)
468    }
469}
470
471/// Bindings for WebGLShader
472#[wasm_bindgen]
473#[derive(Clone, Copy)]
474extern "C" {
475    #[derive(Clone)]
476    type WebGLShader;
477
478    /// Binding for `WebGLRenderingContext.createShader()`
479    #[wasm_bindgen(method, js_name = createShader)]
480    fn _create_shader(this: &WebGL2RenderingContext, kind: ShaderKind) -> WebGLShader;
481
482    /// Binding for `WebGLRenderingContext.compileShader()`
483    #[wasm_bindgen(method, js_name = compileShader)]
484    fn _compile_shader(this: &WebGL2RenderingContext, shader: &WebGLShader);
485
486    /// Binding for `WebGLRenderingContext.deleteShader()`
487    #[wasm_bindgen(method, js_name = deleteShader)]
488    fn _delete_shader(this: &WebGL2RenderingContext, shader: WebGLShader);
489
490    /// Binding for `WebGLRenderingContext.getShaderInfoLog`
491    #[wasm_bindgen(method, js_name = getShaderInfoLog)]
492    fn _get_shader_info_log(this: &WebGL2RenderingContext, shader: &WebGLShader) -> String;
493
494    /// Binding for `WebGLRenderingContext.getShaderSource()`.
495    #[wasm_bindgen(method, js_name = getShaderSource)]
496    fn _get_shader_source(this: &WebGL2RenderingContext, shader: &WebGLShader) -> String;
497
498    /// Binding for `WebGLRenderingContext.isShader()`.
499    #[wasm_bindgen(method, js_name = isShader)]
500    fn _is_shader(this: &WebGL2RenderingContext, shader: &WebGLShader) -> bool;
501
502    /// Binding for `WebGLRenderingContext.shaderSource()`.
503    #[wasm_bindgen(method, js_name = shaderSource)]
504    fn _shader_source(this: &WebGL2RenderingContext, shader: &WebGLShader, source: &str);
505
506    /// Binding for `WebGLRenderingContext.getShaderParameter()` if return type is bool
507    #[wasm_bindgen(method, js_name = getShaderParameter)]
508    fn _get_shader_parameter_bool(
509        this: &WebGL2RenderingContext,
510        shader: &WebGLShader,
511        pname: ShaderParameter,
512    ) -> bool;
513    /// Binding for `WebGLRenderingContext.getShaderParameter()` if return type is enum
514    #[wasm_bindgen(method, js_name = getShaderParameter)]
515    fn _get_shader_parameter_enum(
516        this: &WebGL2RenderingContext,
517        shader: &WebGLShader,
518        pname: ShaderParameter,
519    ) -> ShaderKind;
520}
521
522/// WebGLActiveInfo
523#[wasm_bindgen]
524#[derive(Clone, Copy)]
525extern "C" {
526    pub type WebGLActiveInfo;
527
528    /// The read-only name of the requested variable.
529    #[wasm_bindgen(method, getter)]
530    pub fn name(this: &WebGLActiveInfo) -> String;
531
532    /// The read-only size of the requested variable.
533    #[wasm_bindgen(method, getter)]
534    pub fn size(this: &WebGLActiveInfo) -> u32;
535
536    /// The read-only type of the requested variable.
537    #[wasm_bindgen(method, getter = type)]
538    pub fn data_type(this: &WebGLActiveInfo) -> u32;
539}