feat: support textures
This commit is contained in:
parent
43786ef0f6
commit
d9e03f1b7b
|
@ -21,7 +21,7 @@ js-sys = "0.3.61"
|
|||
|
||||
[dependencies.web-sys]
|
||||
version = "0.3.61"
|
||||
features = ["Document", "Element", "HtmlCanvasElement", "WebGlBuffer", "WebGlProgram", "WebGl2RenderingContext", "WebGlShader", "WebGlVertexArrayObject", "Window"]
|
||||
features = ["Document", "Element", "HtmlCanvasElement", "HtmlImageElement", "ImageData", "WebGlBuffer", "WebGlProgram", "WebGl2RenderingContext", "WebGlUniformLocation", "WebGlShader", "WebGlTexture", "WebGlVertexArrayObject", "Window"]
|
||||
|
||||
[profile.release]
|
||||
opt-level = "s" # optimize for small code size
|
||||
|
|
14
src/game.rs
14
src/game.rs
|
@ -9,10 +9,10 @@ pub fn run() -> Result<(), JsValue> {
|
|||
let mut renderer = Renderer::new("canvas")?;
|
||||
|
||||
let vertices: Vec<f32> = vec![
|
||||
-0.5, 0.5, 0.0, 1.0, 0.0, 0.0, //
|
||||
-0.5, -0.5, 0.0, 1.0, 1.0, 0.0, //
|
||||
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, //
|
||||
0.5, 0.5, 0.0, 0.0, 0.0, 1.0, //
|
||||
-0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, //
|
||||
-0.5, -0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, //
|
||||
0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, //
|
||||
0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, //
|
||||
];
|
||||
|
||||
let indices: Vec<u16> = vec![
|
||||
|
@ -22,8 +22,10 @@ pub fn run() -> Result<(), JsValue> {
|
|||
|
||||
renderer.set_buffer(&vertices, &indices, true)?;
|
||||
renderer.set_shader_program(VERT_SRC, FRAG_SRC)?;
|
||||
renderer.map_shader_attribute("aCoord", 3, 6, 0)?;
|
||||
renderer.map_shader_attribute("aColor", 3, 6, 3)?;
|
||||
renderer.map_shader_attribute("aCoord", 3, 8, 0)?;
|
||||
renderer.map_shader_attribute("aColor", 3, 8, 3)?;
|
||||
renderer.map_shader_attribute("aTexCoord", 2, 8, 6)?;
|
||||
renderer.set_texture("/texture.png")?;
|
||||
|
||||
renderer.draw()?;
|
||||
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
use std::mem::size_of;
|
||||
use std::{mem::size_of, rc::Rc};
|
||||
|
||||
use js_sys::{Float32Array, Uint16Array, WebAssembly::Memory};
|
||||
use wasm_bindgen::{JsCast, JsValue};
|
||||
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
|
||||
use web_sys::{
|
||||
window, HtmlCanvasElement, WebGl2RenderingContext, WebGl2RenderingContext as Gl, WebGlBuffer,
|
||||
WebGlProgram, WebGlShader,
|
||||
window, HtmlCanvasElement, HtmlImageElement, WebGl2RenderingContext,
|
||||
WebGl2RenderingContext as Gl, WebGlBuffer, WebGlProgram, WebGlShader, WebGlTexture,
|
||||
};
|
||||
|
||||
use crate::utils;
|
||||
|
||||
pub struct Renderer {
|
||||
gl: WebGl2RenderingContext,
|
||||
buffer: Option<Buffer>,
|
||||
shader_program: Option<WebGlProgram>,
|
||||
texture: Option<Rc<WebGlTexture>>,
|
||||
}
|
||||
|
||||
pub struct Buffer {
|
||||
|
@ -38,6 +41,7 @@ impl Renderer {
|
|||
gl,
|
||||
buffer: None,
|
||||
shader_program: None,
|
||||
texture: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -48,14 +52,25 @@ impl Renderer {
|
|||
.shader_program
|
||||
.as_ref()
|
||||
.ok_or("no shader program is specified")?;
|
||||
let texture = match &self.texture {
|
||||
Some(x) => Some(unsafe { Rc::downgrade(x).as_ptr().as_ref() }.unwrap()),
|
||||
None => None,
|
||||
};
|
||||
|
||||
gl.clear_color(0.0, 0.0, 0.0, 1.0);
|
||||
gl.clear(Gl::COLOR_BUFFER_BIT);
|
||||
|
||||
gl.use_program(Some(shader_program));
|
||||
|
||||
gl.bind_buffer(Gl::ARRAY_BUFFER, Some(&buffer.vertex_buffer));
|
||||
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, Some(&buffer.index_buffer));
|
||||
|
||||
gl.use_program(Some(shader_program));
|
||||
gl.active_texture(Gl::TEXTURE0);
|
||||
gl.bind_texture(Gl::TEXTURE_2D, texture);
|
||||
let sampler_location = gl
|
||||
.get_uniform_location(shader_program, "uTexture")
|
||||
.ok_or("failed to get uniform location")?;
|
||||
gl.uniform1i(Some(&sampler_location), 0);
|
||||
|
||||
gl.draw_elements_with_i32(
|
||||
Gl::TRIANGLES,
|
||||
|
@ -66,6 +81,7 @@ impl Renderer {
|
|||
|
||||
gl.bind_buffer(Gl::ARRAY_BUFFER, None);
|
||||
gl.bind_buffer(Gl::ELEMENT_ARRAY_BUFFER, None);
|
||||
gl.bind_texture(Gl::TEXTURE_2D, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -244,4 +260,65 @@ impl Renderer {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_texture(&mut self, path: &str) -> Result<(), JsValue> {
|
||||
let texture = self.load_texture(path)?;
|
||||
self.texture = Some(texture);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_texture(&self, path: &str) -> Result<Rc<WebGlTexture>, JsValue> {
|
||||
let gl = &self.gl;
|
||||
|
||||
let texture = gl.create_texture().ok_or("failed to create texture")?;
|
||||
gl.bind_texture(Gl::TEXTURE_2D, Some(&texture));
|
||||
|
||||
let pixel: [u8; 4] = [255, 255, 255, 255];
|
||||
gl.tex_image_2d_with_i32_and_i32_and_i32_and_format_and_type_and_opt_u8_array(
|
||||
Gl::TEXTURE_2D,
|
||||
0,
|
||||
Gl::RGBA as i32,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
Gl::RGBA,
|
||||
Gl::UNSIGNED_BYTE,
|
||||
Some(&pixel),
|
||||
)?;
|
||||
|
||||
let img = HtmlImageElement::new().unwrap();
|
||||
img.set_cross_origin(Some(""));
|
||||
let imgrc = Rc::new(img);
|
||||
|
||||
let texture = Rc::new(texture);
|
||||
|
||||
{
|
||||
let img = imgrc.clone();
|
||||
let texture = texture.clone();
|
||||
let gl = Rc::new(gl.clone());
|
||||
let a = Closure::wrap(Box::new(move || {
|
||||
gl.bind_texture(Gl::TEXTURE_2D, Some(&texture));
|
||||
if let Err(e) = gl.tex_image_2d_with_u32_and_u32_and_html_image_element(
|
||||
Gl::TEXTURE_2D,
|
||||
0,
|
||||
Gl::RGBA as i32,
|
||||
Gl::RGBA,
|
||||
Gl::UNSIGNED_BYTE,
|
||||
&img,
|
||||
) {
|
||||
utils::alert_err(e);
|
||||
};
|
||||
gl.generate_mipmap(Gl::TEXTURE_2D);
|
||||
}) as Box<dyn FnMut()>);
|
||||
imgrc.set_onload(Some(a.as_ref().unchecked_ref()));
|
||||
a.forget();
|
||||
}
|
||||
|
||||
imgrc.set_src(path);
|
||||
|
||||
gl.bind_texture(Gl::TEXTURE_2D, None);
|
||||
|
||||
Ok(texture)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
precision mediump float;
|
||||
|
||||
varying vec3 vColor;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(vColor, 1.0);
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * vec4(vColor, 1.0);
|
||||
}
|
||||
|
|
|
@ -2,10 +2,13 @@ precision mediump float;
|
|||
|
||||
attribute vec3 aCoord;
|
||||
attribute vec3 aColor;
|
||||
attribute vec2 aTexCoord;
|
||||
|
||||
varying vec3 vColor;
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = vec4(aCoord, 1.0);
|
||||
vColor = aColor;
|
||||
vTexCoord = aTexCoord;
|
||||
}
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
node_modules
|
||||
dist
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 136 B |
Loading…
Reference in New Issue