只有第一个生成的纹理具有透明度

问题描述 投票:0回答:1

我试图显示两个具有(不同)透明纹理的对象,但第二个对象总是会失去透明度,无论顺序如何(即,如果我生成纹理 A,则 B,B 会失去透明度;如果我加载 B,则加载 A ,A 失去透明度)。

这似乎来自

glGenTextures
函数,因为如果我评论与纹理相关的所有其他内容,我仍然会遇到这个问题(我什至不需要加载图像)。我什至可以实例化一个空材质,只要我不实例化第一个纹理,其他纹理就可以工作。

这就是它的样子。

如果我用草纹理注释线条,这就是它的样子。

(由于某种原因,它被分配了窗口纹理,但我假设这是一个不相关的问题。)

这些是我认为我的代码中最相关的部分:

fn draw_scene(
    scene: &Vec<&SceneObject>,
    object_shader: &ShaderProgram,
    outline_shader: &ShaderProgram,
    camera: &Camera,
    lighting: &Lighting,
) {
    let projection = &perspective(1.0, camera.get_fov(), 0.1, 100.0);
    let reinitialize_object_shader = || {
        object_shader.use_program();
        object_shader.set_view(&camera);

        object_shader.set_directional_light("dirLight", &lighting.dir);
        object_shader.set_matrix_4fv("projectionMatrix", projection);
        for (i, point) in lighting.point.iter().enumerate() {
            object_shader.set_point_light(format!("pointLights[{}]", i).as_str(), &point);
        }
        object_shader.set_spotlight("spotlight", &lighting.spot);
    };
    let reinitialize_outline_shader = || {
        outline_shader.use_program();
        outline_shader.set_view(&camera);
        outline_shader.set_matrix_4fv("projectionMatrix", projection);
    };

    let mut ordered_scene = scene.clone();

    let distance_compare = |a: &&SceneObject, b: &&SceneObject| {
        let distance_a = length(&(camera.get_pos() - a.get_pos()));
        let distance_b = length(&(camera.get_pos() - b.get_pos()));
        distance_b.partial_cmp(&distance_a).unwrap()
    };

    ordered_scene.sort_by(distance_compare);

    reinitialize_object_shader();
    for object in ordered_scene {
        object.draw(&object_shader);
        if object.has_outline() {
            reinitialize_outline_shader();
            object.draw_outline(&outline_shader);
            reinitialize_object_shader();
        }
    }
}

fn main() {
    [...]
    unsafe {
        let fun =
            |x: *const u8| win.get_proc_address(x as *const i8) as *const std::os::raw::c_void;
        load_global_gl(&fun);

        glEnable(GL_DEPTH_TEST);
        glEnable(GL_STENCIL_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    }

    let mut scene: Vec<&SceneObject> = vec![];

    let mut grass_mesh = Mesh::square(1.0);
    let mut grass_tex = Texture::new(TextureType::Diffuse);
    grass_tex.load(Path::new(GRASS_TEXTURE));
    grass_tex.set_wrapping(GL_CLAMP_TO_EDGE);
    grass_mesh.material = Material::new(vec![grass_tex], vec![], 1.0);
    let mut grass: SceneObject = SceneObject::from(grass_mesh);
    grass.set_outline(vec3(0.04, 0.28, 0.26));
    grass.enable_outline(true);
    scene.push(&grass);

    let mut window_mesh = Mesh::square(1.0);
    let mut window_tex = Texture::new(TextureType::Diffuse);
    window_tex.load(Path::new(WINDOW_TEXTURE));
    window_tex.set_wrapping(GL_CLAMP_TO_EDGE);
    window_mesh.material = Material::new(vec![window_tex], vec![], 1.0);
    let mut window1 = SceneObject::from(window_mesh.clone());
    window1.translate(&vec3(0.0, 0.0, -1.0));
    scene.push(&window1);

    rendering::clear_color(0.2, 0.3, 0.3, 1.0);

    [...]

    'main_loop: loop {
        [...]

        unsafe {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        }

        draw_scene(
            &scene,
            &shader_program_model,
            &shader_program_outline,
            &main_camera,
            &lighting,
        );

        win.swap_window();
    }
}
pub struct Texture {
    id: u32,
    ttype: TextureType,
    path: String,
}

impl Texture {
    pub fn new(ttype: TextureType) -> Self {
        let mut texture: u32 = 0;
        unsafe {
            glGenTextures(1, &mut texture);
        }
        Self {
            id: texture,
            ttype,
            path: String::new(),
        }
    }
    pub fn load(&mut self, path: &Path) {
        let (mut width, mut height, mut nr_channels): (i32, i32, i32) = (0, 0, 0);
        let path_string = CString::new(path.as_os_str().as_bytes()).unwrap();
        unsafe {
            glBindTexture(GL_TEXTURE_2D, self.id);
            stbi_set_flip_vertically_on_load(1);
            let data = stbi_load(
                path_string.as_ptr(),
                &mut width,
                &mut height,
                &mut nr_channels,
                0,
            );
            let format = match nr_channels {
                4 => GL_RGBA,
                _ => GL_RGB,
            };
            glTexImage2D(
                GL_TEXTURE_2D,
                0,
                GL_RGBA.0 as i32,
                width,
                height,
                0,
                format,
                GL_UNSIGNED_BYTE,
                data as *const c_void,
            );
            glGenerateMipmap(GL_TEXTURE_2D);
            stbi_image_free(data as *mut c_void);
            glBindTexture(GL_TEXTURE_2D, 0);
        }
        self.path = path.display().to_string();
    }

    pub fn bind(&self) {
        unsafe {
            glBindTexture(GL_TEXTURE_2D, self.id);
        }
    }
    [...]
}
impl ShaderProgram {
    [...]
    pub fn set_material(&self, material_name: &str, value: &Material) {
        let diffuse_vector = value.get_diffuse_maps();
        let specular_vector = value.get_specular_maps();
        let mut tex_count = 0;
        for (i, diffuse) in diffuse_vector.iter().enumerate() {
            unsafe {
                glActiveTexture(GLenum(GL_TEXTURE0.0 + tex_count as u32));
            }
            tex_count += 1;
            diffuse.bind();
            let name = format!("{}.Diffuse[{}]", material_name, i);
            self.set_1i(&name, (diffuse.get_id() - 1) as i32);
        }
        for (i, specular) in specular_vector.iter().enumerate() {
            unsafe {
                glActiveTexture(GLenum(GL_TEXTURE0.0 + tex_count as u32));
            }
            tex_count += 1;
            specular.bind();
            let name = format!("{}.Specular[{}]", material_name, i);
            self.set_1i(&name, (specular.get_id() - 1) as i32);
        }
        self.set_1f(
            &format!("{}.shininess", material_name),
            value.get_shininess(),
        );
        self.set_1i(
            &format!("{}.loadedDiffuse", material_name),
            diffuse_vector.len().max(1) as i32,
        );
        self.set_1i(
            &format!("{}.loadedSpecular", material_name),
            specular_vector.len().max(1) as i32,
        );
    }
}
#version 330 core
in vec3 fragPos;
in vec3 normal;
in vec2 texCoords;

#define NR_DIFFUSE_TEXTURES 3
#define NR_SPECULAR_TEXTURES 3

struct Material {
    sampler2D Diffuse[NR_DIFFUSE_TEXTURES];
    sampler2D Specular[NR_SPECULAR_TEXTURES];
    float shininess;
    int loadedDiffuse;
    int loadedSpecular;
};

uniform Material material;

out vec4 fragColor;

vec4 diff_tex_values[NR_DIFFUSE_TEXTURES];
vec4 spec_tex_values[NR_SPECULAR_TEXTURES];

void main() {
    for (int i = 0; i < material.loadedDiffuse; i++)
        diff_tex_values[i] = texture(material . Diffuse[i], texCoords);
    for (int i = 0; i < material.loadedSpecular; i++)
        spec_tex_values[i] = texture(material . Specular[i], texCoords);

    vec3 norm = normalize(normal);
    vec3 viewDir = normalize(viewPos - fragPos);

    vec4 result = calculateDirectionalLight(dirLight, norm, viewDir);

    for (int i = 0; i < NR_POINT_LIGHTS; i++)
        result += calculatePointLight(pointLights[i], norm, fragPos, viewDir);

    result += calculateSpotlight(spotlight, norm, fragPos, viewDir);

    if (result . a < 0.1) {
        discard;
    } else {
        fragColor = result;
    }
}
rust opengl glsl
1个回答
0
投票

发现问题了。将材质传递给着色器时,我使用了纹理的 id,而我应该使用材质结构中纹理及其各自数组(漫反射或镜面反射)的索引。将

set_material
方法内的循环更改为:

for (i, diffuse) in diffuse_vector.iter().enumerate() {
    unsafe {
        glActiveTexture(GLenum(GL_TEXTURE0.0 + tex_count as u32));
    }
    tex_count += 1;
    diffuse.bind();
    let name = format!("{}.Diffuse[{}]", material_name, i);
    self.set_1i(&name, i as i32);
}
for (i, specular) in specular_vector.iter().enumerate() {
    unsafe {
        glActiveTexture(GLenum(GL_TEXTURE0.0 + tex_count as u32));
    }
    tex_count += 1;
    specular.bind();
    let name = format!("{}.Specular[{}]", material_name, i);
    self.set_1i(&name, i as i32);
}

解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.