Draw a texture at the correct scale

This commit is contained in:
Simon Gellis 2020-08-01 17:06:20 -04:00
parent 7bd11fe72f
commit 043153acf0
4 changed files with 233 additions and 16 deletions

178
Cargo.lock generated
View File

@ -42,6 +42,27 @@ dependencies = [
"log",
]
[[package]]
name = "approx"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
dependencies = [
"num-traits",
]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]]
name = "backtrace"
version = "0.3.50"
@ -56,6 +77,12 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bytes"
version = "0.5.6"
@ -74,6 +101,26 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cgmath"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "283944cdecc44bf0b8dd010ec9af888d3b4f142844fdbe026c20ef68148d6fe7"
dependencies = [
"approx",
"num-traits",
"rand",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "combine"
version = "4.2.1"
@ -104,6 +151,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "gimli"
version = "0.22.0"
@ -183,12 +236,136 @@ dependencies = [
"adler",
]
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg 1.0.0",
]
[[package]]
name = "object"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.7",
"libc",
"rand_chacha",
"rand_core 0.4.2",
"rand_hc",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.3.1",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "regex"
version = "1.3.9"
@ -242,6 +419,7 @@ name = "vvb"
version = "0.1.0"
dependencies = [
"android_logger",
"cgmath",
"gl_generator",
"jni",
"log",

View File

@ -7,6 +7,7 @@ build = "build.rs"
[dependencies]
android_logger = "0.9.0"
cgmath = "0.17.0"
jni = "0.17.0"
log = "0.4.11"

View File

@ -1,7 +1,7 @@
// This is the output of build.rs, but with Generator::Global instead of Generator::Static.
// It's copied here so windows builds and autocomplete can work.
#![cfg(target_os == "windows")]
#![cfg(target_os = "windows")]
mod __gl_imports {
pub use std::mem;

View File

@ -14,10 +14,11 @@ mod gl {
use gl::types::{GLboolean,GLshort,GLuint,GLint,GLsizei,GLchar,GLvoid,GLfloat,GLenum};
use std::ffi::{CStr,CString};
// use log::{debug};
use cgmath::{self,Matrix4,SquareMatrix,vec4};
use log::{debug};
const GL_TRUE: GLboolean = 1;
// const GL_FALSE: GLboolean = 0;
const GL_FALSE: GLboolean = 0;
macro_rules! c_string {
($string:expr) => {
@ -49,9 +50,10 @@ impl<T> AsVoidptr for [T] {
const VERTEX_SHADER: &str = "\
attribute vec4 a_Pos;
attribute vec2 a_TexCoord;
uniform mat4 u_MV;
varying vec2 v_TexCoord;
void main() {
gl_Position = a_Pos;
gl_Position = u_MV * a_Pos;
v_TexCoord = a_TexCoord;
}
";
@ -59,18 +61,24 @@ void main() {
const FRAGMENT_SHADER: &str = "\
precision mediump float;
varying vec2 v_TexCoord;
uniform sampler2D s_Texture;
uniform sampler2D u_Texture;
void main() {
gl_FragColor = texture2D(s_Texture, v_TexCoord);
gl_FragColor = texture2D(u_Texture, v_TexCoord);
}
";
const VB_WIDTH: i32 = 384;
const VB_HEIGHT: i32 = 224;
const TEXTURE_WIDTH: GLfloat = (VB_WIDTH * 2) as GLfloat;
const TEXTURE_HEIGHT: GLfloat = VB_HEIGHT as GLfloat;
const POS_VERTICES: [GLfloat; 8] = [
-0.5, 0.5,
-0.5, -0.5,
0.5, -0.5,
0.5, 0.5
];
const TEX_VERTICES: [GLfloat; 8] = [
0.0, 0.0,
0.0, 1.0,
@ -83,16 +91,16 @@ const SQUARE_INDICES: [GLshort; 6] = [0, 1, 2, 0, 2, 3];
const VERTEX_SIZE: GLsizei = 2;
const VERTEX_STRIDE: GLsizei = 0;
const VB_WIDTH: i32 = 384;
const VB_HEIGHT: i32 = 224;
const TEXTURE_SIZE: usize = (VB_WIDTH * VB_HEIGHT * 2 * 3) as usize;
const TEXTURE_SIZE: usize = (TEXTURE_WIDTH * TEXTURE_HEIGHT) as usize * 3;
pub struct Renderer {
program_id: GLuint,
position_location: GLuint,
tex_coord_location: GLuint,
modelview_location : GLint,
texture_location: GLint,
texture_id: GLuint
texture_id: GLuint,
modelview: Vec<GLfloat>
}
unsafe fn make_shader(type_: GLenum, source: &str) -> Result<GLuint, String> {
@ -149,7 +157,7 @@ fn load_texture() -> Result<Vec<u8>, String> {
for r in (0..TEXTURE_SIZE).step_by(3) {
let i = r / 3;
let checker_x = (i / 16) % 2;
let checker_y = 1 - ((i / 224) / 16) % 2;
let checker_y = 1 - ((i / TEXTURE_WIDTH as usize) / 16) % 2;
if checker_x != checker_y {
texture_data[r] = 0xff;
}
@ -166,7 +174,7 @@ fn create_texture() -> Result<GLuint, String> {
});
check_error("generate a texture")?;
gl::BindTexture(gl::TEXTURE_2D, texture_id);
gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGB as GLint, VB_WIDTH, VB_HEIGHT, 0, gl::RGB, gl::UNSIGNED_BYTE, texture_data.as_voidptr());
gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGB as GLint, TEXTURE_WIDTH as GLsizei, TEXTURE_HEIGHT as GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, texture_data.as_voidptr());
check_error("load a texture")?;
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
@ -175,6 +183,15 @@ fn create_texture() -> Result<GLuint, String> {
}
}
fn as_vec<S: Clone>(mat: cgmath::Matrix4<S>) -> Vec<S> {
let mut res = Vec::with_capacity(16);
let rows: [[S;4];4] = mat.into();
for row in rows.iter() {
res.extend_from_slice(row);
}
res
}
impl Renderer {
pub fn new() -> Result<Renderer, String> {
@ -197,7 +214,8 @@ impl Renderer {
let position_location = gl::GetAttribLocation(program_id, c_string!("a_Pos")?.as_ptr()) as GLuint;
let tex_coord_location = gl::GetAttribLocation(program_id, c_string!("a_TexCoord")?.as_ptr()) as GLuint;
let texture_location= gl::GetUniformLocation(program_id, c_string!("s_Texture")?.as_ptr());
let modelview_location = gl::GetUniformLocation(program_id, c_string!("u_MV")?.as_ptr());
let texture_location= gl::GetUniformLocation(program_id, c_string!("u_Texture")?.as_ptr());
let texture_id = create_texture()?;
@ -208,18 +226,36 @@ impl Renderer {
program_id,
position_location,
tex_coord_location,
modelview_location,
texture_location,
texture_id
texture_id,
modelview: as_vec(Matrix4::identity())
}
};
Ok(state)
}
pub fn on_surface_changed(&mut self, width: i32, height: i32) {
pub fn on_surface_changed(&mut self, screen_width: i32, screen_height: i32) {
unsafe {
gl::Viewport(0, 0, width, height);
gl::Viewport(0, 0, screen_width, screen_height);
}
let hsw = screen_width as GLfloat / 2.0;
let hsh = screen_height as GLfloat / 2.0;
let htw = TEXTURE_WIDTH / 2.0;
let hth = TEXTURE_HEIGHT / 2.0;
let projection = cgmath::ortho(-hsw, hsw, -hsh, hsh, -100.0, 100.0);
// The texture should take up as much of the screen as possible
let scale_to_fit = (hsw / htw).min(hsh / hth);
let vm = projection * Matrix4::from_nonuniform_scale(TEXTURE_WIDTH * scale_to_fit, TEXTURE_HEIGHT * scale_to_fit, 0.0);
let bottom_left = vm * vec4(-htw, -hth, 0.0, 1.0);
let top_right = vm * vec4(htw, hth, 0.0, 1.0);
debug!("Screen stretches from from {:?} to {:?}", bottom_left, top_right);
self.modelview = as_vec(vm);
}
pub fn on_draw_frame(&self) -> Result<(), String> {
@ -240,6 +276,8 @@ impl Renderer {
gl::EnableVertexAttribArray(self.position_location);
gl::EnableVertexAttribArray(self.tex_coord_location);
gl::UniformMatrix4fv(self.modelview_location, 1, GL_FALSE, self.modelview.as_ptr());
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, self.texture_id);