OpenGL -如何同时渲染无纹理四边形和有纹理四边形

lskq00tm  于 2023-06-29  发布在  其他
关注(0)|答案(1)|浏览(132)

我尝试在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/着色器程序来将文本四边形层放在矩形四边形上?有更好的办法吗?

zbwhf8kr

zbwhf8kr1#

使用2个或更多的VAO/VBO/着色器程序没有什么错。任何实际的应用程序都会使用几十个。但是使用一个通道渲染这两个矩形也相当容易:你只需要添加更多的三角形,其外部三角形的纹理坐标对应于纹理的透明部分(0,0)。

相关问题