我尝试在OpenGL中渲染以下图像:
(忽略白色,它不是图像的一部分)
为了渲染,我将文本的静态纹理作为PNG,如下所示:
下面是我的Cargo.toml
:
[package]
name = "render-clock"
version = "0.1.0"
edition = "2021"
[dependencies]
elara-gfx = { git = "https://github.com/elaraproject/elara-gfx" }
这是我的vertex shader代码:
#version 100
attribute highp vec2 position;
attribute highp vec2 tex_coord;
attribute lowp vec4 vertex_color;
varying highp vec2 TexCoord;
varying lowp vec4 VertexColor;
void main() {
VertexColor = vertex_color;
TexCoord = tex_coord;
gl_Position = vec4(position.x * 0.66, position.y, 0.0, 1.0);
}
我的Fragment Shader:
#version 100
varying highp vec2 TexCoord;
varying lowp vec4 VertexColor;
uniform sampler2D uTexture;
void main() {
lowp vec4 col = texture2D(uTexture, TexCoord);
gl_FragColor = vec4(VertexColor.rgb, col.a);
}
我的程序代码:
use elara_gfx::{Buffer, BufferType, Program, Shader, VertexArray, PixelArray, Texture2D};
use elara_gfx::{GLWindow, HandlerResult, WindowHandler};
use std::error::Error;
const VERT_SHADER: &str = include_str!("shaders/clock.vert"); // code given above
const FRAG_SHADER: &str = include_str!("shaders/clock.frag"); // code given above
const IMG_PATH: &str = "clock_text.png"; // image shown above
struct Handler {
vao: VertexArray,
texture: Texture2D
}
impl Handler {
fn new() -> Result<Handler, String> {
let vertices: [f32; 42] = [
// positions // colors // texture coords
0.5, 0.5, 0.13, 0.15, 0.16, 1.0, 1.0, // top right
0.5, -0.5, 0.13, 0.15, 0.16, 1.0, 0.0, // bottom right
-0.5, 0.5, 0.13, 0.15, 0.16, 0.0, 1.0, // top left
0.5, -0.5, 0.13, 0.15, 0.16, 1.0, 0.0, // bottom right
-0.5, -0.5, 0.13, 0.15, 0.16, 0.0, 0.0, // bottom left
-0.5, 0.5, 0.13, 0.15, 0.16, 0.0, 1.0, // top left
];
let texture = Texture2D::new()?;
texture.bind();
texture.parameter_2d(gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
texture.parameter_2d(gl::TEXTURE_MAG_FILTER, gl::NEAREST as i32);
let mut img = PixelArray::load_png(IMG_PATH).unwrap();
img.flipv();
texture.set_image_2d(img);
texture.generate_mipmap();
let vao = VertexArray::new()?;
vao.bind();
let vbo = Buffer::new()?;
vbo.bind(BufferType::Array);
vbo.data::<f32>(BufferType::Array, &vertices, gl::STATIC_DRAW);
let vertex_shader = Shader::new(&VERT_SHADER, gl::VERTEX_SHADER)?;
let fragment_shader = Shader::new(&FRAG_SHADER, gl::FRAGMENT_SHADER)?;
let program = Program::new(&[vertex_shader, fragment_shader])?;
program.use_program();
let pos_attrib = vao.get_attrib_location(&program, "position");
let col_attrib = vao.get_attrib_location(&program, "vertex_color");
let tex_coord_attrib = vao.get_attrib_location(&program, "tex_coord");
vao.enable_vertex_attrib(pos_attrib as u32);
vao.enable_vertex_attrib(col_attrib as u32);
vao.enable_vertex_attrib(tex_coord_attrib as u32);
vao.vertex_attrib_pointer::<f32>(pos_attrib as u32, 2, gl::FLOAT, false, 7, 0);
vao.vertex_attrib_pointer::<f32>(col_attrib as u32, 3, gl::FLOAT, false, 7, 2);
vao.vertex_attrib_pointer::<f32>(tex_coord_attrib as u32, 2, gl::FLOAT, false, 7, 5);
Ok(Handler {vao, texture})
}
}
impl WindowHandler for Handler {
fn on_draw(&mut self) -> HandlerResult<()> {
unsafe {
gl::ClearColor(1.0, 1.0, 1.0, 1.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
self.texture.bind();
self.vao.bind();
gl::DrawArrays(gl::TRIANGLES, 0, 6);
self.vao.unbind();
self.texture.unbind();
}
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
let (app, window) = GLWindow::new_with_title("OpenGL clock")?;
window.get_context()?;
let render_handler = Handler::new()?;
app.run_loop(window, render_handler);
Ok(())
}
我的困境是,要渲染我想要的图像,需要渲染2个四边形,其中一个文本是透明的,下面是一个用纯色填充的矩形四边形。文本四边形需要有纹理坐标,但矩形四边形不应该有(也不需要)纹理坐标。然而,尝试使用单个着色器程序/ VAO /VBO渲染两者似乎是OpenGL无法做到的。我是否必须使用2个VAO/VBO/着色器程序来将文本四边形层放在矩形四边形上?有更好的办法吗?
1条答案
按热度按时间zbwhf8kr1#
使用2个或更多的VAO/VBO/着色器程序没有什么错。任何实际的应用程序都会使用几十个。但是使用一个通道渲染这两个矩形也相当容易:你只需要添加更多的三角形,其外部三角形的纹理坐标对应于纹理的透明部分(0,0)。