我正在try 在OpenGL中渲染以下图像:

Render target image

(忽略白线,这不是图像的一部分)

为了渲染,我将文本的静态纹理设置为PNG,如下所示:

enter image description here

目前,这是我的Cargo.toml分:

[package]
name = "render-clock"
version = "0.1.0"
edition = "2021"

[dependencies]
elara-gfx = { git = "https://github.com/elaraproject/elara-gfx" }

这是我的顶点着色器代码:

#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);
}

和我的片段着色器:

#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个四边形,其中一个文本是透明的,下面是一个填充了纯色的矩形四边形.文本四边形需要有纹理坐标,但矩形四边形不应该有(也不需要)纹理坐标.然而,try 使用单个着色器程序/VAO/VBO渲染两者似乎不是OpenGL所能做到的.我必须求助于使用2个VAOS/VBO/着色器程序来在矩形四边形上分层文本四边形吗?有没有更好的办法?

推荐答案

使用2个或更多VAOS/VBO/着色器程序没有任何错误.任何实际的应用程序都会使用几十个这样的应用程序.但使用单个过程渲染这两个矩形也相当容易:只需添加更多三角形,其中外部三角形的纹理坐标对应于纹理的透明部分(0,0).

enter image description here

Rust相关问答推荐

捕获Rust因C++异常而产生panic

是否可以为`T:Copy`执行`T. clone`的测试

如何在原始字符串中转义";#和#";

关于Rust 中回归的逻辑

rust 迹-内存管理-POP所有权-链表

防止cargo test 中的竞争条件

如何将映射反序列化为具有与键匹配的字段的定制 struct 的向量?

`actix-web` 使用提供的 `tokio` 运行时有何用途?

Rust proc_macro 和 syn:解析空格

RUST 中的读写器锁定模式

`UnsafeCell` 在没有锁定的情况下跨线程共享 - 这可能会导致 UB,对吗?

Rust FFI 和 CUDA C 性能差异

部署Rust发布二进制文件的先决条件

Rust并发读写引起的死锁问题

str 和 String 的 Rust 生命周期

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

Rust 异步和 AsRef 未被发送

如何为返回正确类型的枚举实现 get 方法?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

返回 &str 但不是 String 时,borrow 时间比预期长