LearnOpenGL-纹理|看不到令人敬畏的面孔.png



因此,尽管我尝试以与wall.jpg相同的方式加载awesomeface.png,但它是不可见的(如图所示(。老实说,我认为我在激活texture2制服的部分做错了什么,但我不知道如何修复它,所以如果你能帮助我了解如何修复它或如何调试代码,我将不胜感激。

main.rs

extern crate gl;
extern crate glfw;
extern crate image;
pub mod shaders;
use gl::types::*;
use glfw::Context;
use shaders::Shader;
fn main() {
// Setting up glfw
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap(); // Initialize Glfw library
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3)); // Using OGL version 330
glfw.window_hint(glfw::WindowHint::OpenGlProfile(
glfw::OpenGlProfileHint::Core, // Using core profile
));
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
// Setting up the window and the events receiver
let (mut window, events) = glfw
.create_window(1080, 720, "Hello Triangle", glfw::WindowMode::Windowed)
.expect("Failed to create GLFW window");
window.make_current();
window.set_key_polling(true); // Handle keyboard input
window.set_framebuffer_size_polling(true); // Handle window resize
window.set_resizable(true);
// Setting up gl
gl::load_with(|s| glfw.get_proc_address_raw(s));
// Setting up Shader and Program
let shader = Shader::new("shaders/triangle.vert", "shaders/triangle.frag").unwrap();
//shader.set_float_uniform("green", 0.1);
shader.set_int_uniform("texture1", 0);
shader.set_int_uniform("texture2", 1);
shader.set_used();
// Rectangle
let vertices: [GLfloat; 24] = [
// positions    // colors      // texture
0.5, -0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // bottom right
-0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, // bottom left
0.0, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 1.0, // top
];
let indices: [u32; 3] = [
0, 1, 2, // first triangle
];
let mut vao = 0;
let mut vbo = 0;
let mut ebo = 0;
let mut texture1 = 0;
let mut texture2 = 0;
unsafe {
gl::GenVertexArrays(1, &mut vao); // Generate VAO
gl::GenBuffers(1, &mut vbo); // Generate VBO
gl::GenBuffers(1, &mut ebo); // Generate EBO
gl::BindVertexArray(vao); // Bind VAO
gl::BindBuffer(gl::ARRAY_BUFFER, vbo); // Bind VBO
gl::BufferData(
gl::ARRAY_BUFFER,
(vertices.len() * std::mem::size_of::<GLfloat>()) as GLsizeiptr,
vertices.as_ptr() as *const GLvoid,
gl::DYNAMIC_DRAW,
);
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, ebo); // Bind EBO
gl::BufferData(
gl::ELEMENT_ARRAY_BUFFER,
(indices.len() * std::mem::size_of::<GLuint>()) as GLsizeiptr,
indices.as_ptr() as *const GLvoid,
gl::STATIC_DRAW,
);
gl::EnableVertexAttribArray(0); // Enable "Position" in triangle.vert (the index is 0 because the "location" = 0)
gl::VertexAttribPointer(
0,
3,
gl::FLOAT,
gl::FALSE,
(8 * std::mem::size_of::<f32>()) as GLint,
std::ptr::null(),
);
gl::EnableVertexAttribArray(1); // Enable "Color" in triangle.vert (the index is 0 because the "location" = 1)
gl::VertexAttribPointer(
1,
3,
gl::FLOAT,
gl::FALSE,
(8 * std::mem::size_of::<f32>()) as GLint,
(3 * std::mem::size_of::<f32>()) as *const GLvoid,
);
gl::EnableVertexAttribArray(2);
gl::VertexAttribPointer(
2,
2,
gl::FLOAT,
gl::FALSE,
(8 * std::mem::size_of::<f32>()) as GLint,
(6 * std::mem::size_of::<f32>()) as *const GLvoid,
);
/* let border_color = [1.0, 1.0, 0.0, 1.0];
gl::TextureParameterfv(
gl::TEXTURE_2D,
gl::TEXTURE_BORDER_COLOR,
border_color.as_ptr(),
); */
gl::TextureParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_MIN_FILTER,
gl::LINEAR_MIPMAP_LINEAR as i32,
);
gl::TextureParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
let texture_image_1 = image::io::Reader::open("texture/wall.jpg")
.unwrap()
.decode()
.unwrap();
let texture_image_2 = image::io::Reader::open("texture/awesomeface.png")
.unwrap()
.decode()
.unwrap();
gl::GenTextures(1, &mut texture1);
gl::BindTexture(gl::TEXTURE_2D, texture1);
gl::TextureParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_S,
gl::MIRRORED_REPEAT as i32,
);
gl::TextureParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_T,
gl::MIRRORED_REPEAT as i32,
);
gl::TextureParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
gl::TextureParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGB as GLint,
texture_image_1.width() as GLint,
texture_image_1.height() as GLint,
0,
gl::RGB,
gl::UNSIGNED_BYTE,
texture_image_1.as_bytes().as_ptr() as *const GLvoid,
);
gl::GenerateMipmap(gl::TEXTURE_2D);
gl::GenTextures(1, &mut texture2);
gl::BindTexture(gl::TEXTURE_2D, texture2);
gl::TextureParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_S,
gl::MIRRORED_REPEAT as i32,
);
gl::TextureParameteri(
gl::TEXTURE_2D,
gl::TEXTURE_WRAP_T,
gl::MIRRORED_REPEAT as i32,
);
gl::TextureParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as i32);
gl::TextureParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);
gl::TexImage2D(
gl::TEXTURE_2D,
0,
gl::RGB as GLint,
texture_image_2.width() as GLint,
texture_image_2.height() as GLint,
0,
gl::RGBA,
gl::UNSIGNED_BYTE,
texture_image_2.as_bytes().as_ptr() as *const GLvoid,
);
gl::GenerateMipmap(gl::TEXTURE_2D);
}
// Main Loop
while !window.should_close() {
// Input handling
process_input(&mut glfw, &mut window, &events);
// Rendering
unsafe {
gl::ClearColor(0.0, 0.0, 0.0, 0.0);
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::ActiveTexture(gl::TEXTURE0);
gl::BindTexture(gl::TEXTURE_2D, texture1);
gl::ActiveTexture(gl::TEXTURE1);
gl::BindTexture(gl::TEXTURE_2D, texture2);
gl::BindVertexArray(vao); // Bind vao
gl::DrawElements(gl::TRIANGLES, 3, gl::UNSIGNED_INT, std::ptr::null()); // Rendering the triangle
gl::BindVertexArray(0); // Unbind vao
}
// Swap front and back buffer
window.swap_buffers();
}
}
#[allow(clippy::single_match)]
fn process_input(
glfw: &mut glfw::Glfw,
window: &mut glfw::Window,
events: &std::sync::mpsc::Receiver<(f64, glfw::WindowEvent)>,
) {
// Poll events
glfw.poll_events();
for (_, event) in glfw::flush_messages(events) {
match event {
glfw::WindowEvent::Key(glfw::Key::Escape, _, glfw::Action::Press, _) => {
window.set_should_close(true);
}
glfw::WindowEvent::Key(glfw::Key::W, _, glfw::Action::Press, _) => unsafe {
gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);
},
glfw::WindowEvent::Key(glfw::Key::F, _, glfw::Action::Press, _) => unsafe {
gl::PolygonMode(gl::FRONT_AND_BACK, gl::FILL);
},
_ => {}
}
}
}

着色器.rs

use std::{fs::File, io::Read, path::Path};
use gl::types::*;
pub struct Shader {
id: GLuint,
}
impl Shader {
// Constructor
pub fn new(vertex_shader_path: &str, fragment_shader_path: &str) -> Result<Shader, String> {
// 1. Retrieve the vertex/fragment source code
let vertex_shader_code = code_from_path(Path::new(vertex_shader_path));
let fragment_shader_code = code_from_path(Path::new(fragment_shader_path));
// 2. Compile shader
let vertex_shader = shader_from_source(&vertex_shader_code, gl::VERTEX_SHADER).unwrap();
let fragment_shader =
shader_from_source(&fragment_shader_code, gl::FRAGMENT_SHADER).unwrap();
// 3. Shader Program
let id = create_program([vertex_shader, fragment_shader])?;
Ok(Shader { id })
}
// Get the id
pub fn id(&self) -> GLuint {
self.id
}
// Useactivate the shader
pub fn set_used(&self) {
unsafe { gl::UseProgram(self.id) }
}
// Utility uniform functions
pub fn set_bool_uniform(&self, name: &str, value: bool) {
unsafe {
gl::Uniform1i(
gl::GetUniformLocation(self.id, name.as_ptr() as *const i8),
value as i32,
)
}
}
pub fn set_int_uniform(&self, name: &str, value: i32) {
unsafe {
gl::Uniform1i(
gl::GetUniformLocation(self.id, name.as_ptr() as *const i8),
value,
)
}
}
pub fn set_float_uniform(&self, name: &str, value: f32) {
unsafe {
gl::Uniform1f(
gl::GetUniformLocation(self.id, name.as_ptr() as *const i8),
value,
)
}
}
}
impl Drop for Shader {
fn drop(&mut self) {
unsafe { gl::DeleteProgram(self.id) }
}
}
/// Return CString of specified shader
fn code_from_path(path: &Path) -> std::ffi::CString {
let mut shader_file = File::open(path).unwrap();
let mut shader_code = String::new();
shader_file.read_to_string(&mut shader_code).unwrap();
std::ffi::CString::new(shader_code).unwrap()
}
/// Return CString of specified length
fn create_whitespace_cstring_with_len(len: usize) -> std::ffi::CString {
// allocate buffer of correct size
let mut buffer: Vec<u8> = Vec::with_capacity(len + 1);
// fill it with len spaces
buffer.extend([b' '].iter().cycle().take(len));
// convert buffer to CString
unsafe { std::ffi::CString::from_vec_unchecked(buffer) }
}
/// Base function to generate shader from source
fn shader_from_source(source: &std::ffi::CStr, kind: GLenum) -> Result<GLuint, String> {
let id = unsafe { gl::CreateShader(kind) }; // Create shader
let mut success: GLint = 1;
unsafe {
gl::ShaderSource(id, 1, &source.as_ptr(), std::ptr::null()); // Generate shader with shader source code
gl::CompileShader(id); // Compile shader
gl::GetShaderiv(id, gl::COMPILE_STATUS, &mut success); // Check for successful compilation
}
// Error handling
if success == 0 {
let mut len = 0;
unsafe {
gl::GetShaderiv(id, gl::INFO_LOG_LENGTH, &mut len); // Get length of error
let error = create_whitespace_cstring_with_len(len as usize);
gl::GetShaderInfoLog(id, len, std::ptr::null_mut(), error.as_ptr() as *mut GLchar); // Get the info of the error
return Err(error.to_string_lossy().into_owned()); // Return the error
}
}
Ok(id) // Return the shader
}
/// Create the program given the vertex and fragment shaders
fn create_program(shaders: [u32; 2]) -> Result<GLuint, String> {
let id: GLuint = unsafe { gl::CreateProgram() };
let mut success: GLint = 1;
unsafe {
gl::AttachShader(id, shaders[0]); // Vertex
gl::AttachShader(id, shaders[1]); // Fragment
gl::LinkProgram(id);
gl::GetProgramiv(id, gl::LINK_STATUS, &mut success);
gl::DeleteShader(shaders[0]);
gl::DeleteShader(shaders[1]);
}
if success == 0 {
let mut len = 0;
unsafe {
gl::GetShaderiv(id, gl::INFO_LOG_LENGTH, &mut len); // Get length of error
let error = create_whitespace_cstring_with_len(len as usize);
gl::GetShaderInfoLog(id, len, std::ptr::null_mut(), error.as_ptr() as *mut GLchar); // Get the info of the error
return Err(error.to_string_lossy().into_owned()); // Return the error
}
}
Ok(id)
}

三角形.frag

#version 330 core
out vec4 FragColor;  
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D texture1;
uniform sampler2D texture2;
//uniform float green;
void main()
{
FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2);
}

三角形垂直

#version 330 core
layout (location = 0) in vec3 aPos;   // the position variable has attribute position 0
layout (location = 1) in vec3 aColor; // the color variable has attribute position 1
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor; // output a color to the fragment shader
out vec2 TexCoord;
void main()
{
gl_Position = vec4(aPos, 1.0);
ourColor = aColor; // set ourColor to the input color we got from the vertex data
TexCoord = aTexCoord;
} 

这就是我看到的

编辑:我编辑了main.rs,按照Rabbid76的建议更改了函数调用的顺序,但它仍然不起作用

gl::Uniform在当前安装的程序的默认统一块中设置统一变量的值。因此,您必须安装带有gl::UseProgram的程序,然后才能设置uniform:的值

shader.set_used();
shader.set_int_uniform("texture1", 0);
shader.set_int_uniform("texture2", 1);

由于OpenGL 4.1,您也可以使用gl::ProgramUniform

我能够通过在主循环之前调用shader.get_shader_uniforms_data();使其工作。但我真的不明白为什么它能起作用:-|

不管怎样,这就是功能:

pub fn get_shader_uniforms_data(&self) {
unsafe {
let mut n_uniforms: GLint = 0;
gl::GetProgramiv(self.id(), gl::ACTIVE_UNIFORMS, &mut n_uniforms);
println!("N of uniforms: {}", &n_uniforms);
}
}

这项工作:

gl::GenerateMipmap(gl::TEXTURE_2D);
}
shader.get_shader_uniforms_data();
// Main Loop
while !window.should_close() {

这不是:

gl::GenerateMipmap(gl::TEXTURE_2D);
}
unsafe {
let mut n_uniforms: GLint = 0;
gl::GetProgramiv(self.id(), gl::ACTIVE_UNIFORMS, &mut n_uniforms);
println!("N of uniforms: {}", &n_uniforms);
}
// Main Loop
while !window.should_close() {

如果有人能帮助我理解为什么我会非常感激:-(

最新更新