feat: assignment 3
This commit is contained in:
		| @@ -1,5 +1,12 @@ | ||||
| uniform int useTexture; | ||||
| uniform sampler2D texSampler; | ||||
| varying vec3 fcolor; | ||||
| varying vec2 ftexcoord; | ||||
|  | ||||
| void main() { | ||||
| 	gl_FragColor = vec4(fcolor, 1); | ||||
| 	if (useTexture == 1) { | ||||
| 		gl_FragColor = texture2D(texSampler, ftexcoord); | ||||
| 	} else { | ||||
| 		gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,12 @@ | ||||
| uniform mat4 mvp; | ||||
| attribute vec3 vpos; | ||||
| attribute vec3 vcolor; | ||||
| attribute vec2 vtexcoord; | ||||
| varying vec3 fcolor; | ||||
| varying vec2 ftexcoord; | ||||
|  | ||||
| void main() { | ||||
| 	gl_Position = mvp * vec4(vpos, 1); | ||||
| 	fcolor = vcolor; | ||||
| 	ftexcoord = vtexcoord; | ||||
| } | ||||
| @@ -10,10 +10,12 @@ | ||||
| #include "buffer.h" | ||||
| #include "camera.h" | ||||
| #include "logger.h" | ||||
| #include "material.h" | ||||
| #include "mesh.h" | ||||
| #include "model.h" | ||||
| #include "shader.h" | ||||
| #include "state.h" | ||||
| #include "texture.h" | ||||
| #include "vertex.h" | ||||
| #include "world.h" | ||||
|  | ||||
| @@ -83,8 +85,8 @@ void Engine::initialize() | ||||
|  | ||||
| 	// Initialize default shader | ||||
| 	Logger::info("Loading default shaders..."); | ||||
| 	state::default_shader = | ||||
| 	    std::make_shared<Shader>("data/shaders/vertex.glsl", "data/shaders/fragment.glsl"); | ||||
| 	state::default_shader = std::make_shared<Shader>( | ||||
| 	    "data/shaders/vertex.glsl", "data/shaders/fragment.glsl"); | ||||
| 	if (std::strlen(state::default_shader->error()) > 0) { | ||||
| 		Logger::error(sstr("Failed to initialize shaders: ", | ||||
| 				   state::default_shader->error())); | ||||
| @@ -140,9 +142,10 @@ void Engine::setup() | ||||
| 	world_ = std::make_unique<World>(); | ||||
| 	Logger::info("World created"); | ||||
|  | ||||
| 	// Create camera | ||||
| 	// Create camera at position (0, 1, 3) with -20 degrees X rotation | ||||
| 	camera_ = std::make_shared<Camera>(); | ||||
| 	camera_->set_position(glm::vec3(0.0f, 0.0f, 6.0f)); | ||||
| 	camera_->set_position(glm::vec3(0.0f, 1.0f, 3.0f)); | ||||
| 	camera_->set_rotation(glm::vec3(glm::radians(-20.0f), 0.0f, 0.0f)); | ||||
| 	camera_->set_projection( | ||||
| 	    glm::perspective(glm::radians(45.0f), | ||||
| 			     static_cast<float>(screen_width_) | ||||
| @@ -153,31 +156,79 @@ void Engine::setup() | ||||
| 	world_->add_entity(camera_); | ||||
| 	Logger::info("Camera created and added to world"); | ||||
|  | ||||
| 	// Create triangle mesh | ||||
| 	std::vector<Vertex> vertices = { | ||||
| 	    {{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}}, | ||||
| 	    {{-0.5f, -0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}}, | ||||
| 	    {{0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}}}; | ||||
| 	std::vector<uint16_t> indices = {0, 1, 2}; | ||||
| 	// Load textures | ||||
| 	auto top_texture   = Texture::load("data/textures/top.png"); | ||||
| 	auto front_texture = Texture::load("data/textures/front.png"); | ||||
|  | ||||
| 	auto buffer = std::make_shared<Buffer>(vertices, indices); | ||||
| 	// Create cube mesh with two buffers | ||||
| 	mesh_ = std::make_shared<Mesh>(); | ||||
| 	mesh_->add_buffer(buffer); | ||||
| 	Logger::info(sstr("Mesh created with ", vertices.size(), | ||||
| 			  " vertices and ", indices.size(), " indices")); | ||||
|  | ||||
| 	// Create 9 models in a 3x3 grid | ||||
| 	for (int row = 0; row < 3; ++row) { | ||||
| 		for (int col = 0; col < 3; ++col) { | ||||
| 	// Buffer 1: Top and bottom faces | ||||
| 	std::vector<Vertex> top_bottom_vertices = { | ||||
| 	    // Top face (y = 0.5) | ||||
| 	    {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, | ||||
| 	    {{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, | ||||
| 	    // Bottom face (y = -0.5) | ||||
| 	    {{-0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, | ||||
| 	    {{0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{-0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}}; | ||||
| 	std::vector<uint16_t> top_bottom_indices = {// Top face | ||||
| 						    0, 1, 2, 0, 2, 3, | ||||
| 						    // Bottom face | ||||
| 						    4, 6, 5, 4, 7, 6}; | ||||
|  | ||||
| 	auto top_bottom_buffer = | ||||
| 	    std::make_shared<Buffer>(top_bottom_vertices, top_bottom_indices); | ||||
| 	Material top_material(top_texture); | ||||
| 	mesh_->add_buffer(top_bottom_buffer, top_material); | ||||
|  | ||||
| 	// Buffer 2: Front, back, left, right faces | ||||
| 	std::vector<Vertex> side_vertices = { | ||||
| 	    // Front face (z = 0.5) | ||||
| 	    {{-0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, | ||||
| 	    {{0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, | ||||
| 	    // Back face (z = -0.5) | ||||
| 	    {{-0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, | ||||
| 	    {{0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, | ||||
| 	    // Left face (x = -0.5) | ||||
| 	    {{-0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}, | ||||
| 	    {{-0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{-0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{-0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, | ||||
| 	    // Right face (x = 0.5) | ||||
| 	    {{0.5f, -0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}}, | ||||
| 	    {{0.5f, 0.5f, -0.5f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}}, | ||||
| 	    {{0.5f, 0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, | ||||
| 	    {{0.5f, -0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}}}; | ||||
| 	std::vector<uint16_t> side_indices = {// Front face | ||||
| 					      0, 1, 2, 0, 2, 3, | ||||
| 					      // Back face | ||||
| 					      4, 5, 6, 4, 6, 7, | ||||
| 					      // Left face | ||||
| 					      8, 9, 10, 8, 10, 11, | ||||
| 					      // Right face | ||||
| 					      12, 13, 14, 12, 14, 15}; | ||||
|  | ||||
| 	auto side_buffer = | ||||
| 	    std::make_shared<Buffer>(side_vertices, side_indices); | ||||
| 	Material side_material(front_texture); | ||||
| 	mesh_->add_buffer(side_buffer, side_material); | ||||
|  | ||||
| 	Logger::info("Cube mesh created with two buffers"); | ||||
|  | ||||
| 	// Create model at origin | ||||
| 	auto model = std::make_shared<Model>(mesh_); | ||||
| 			model->set_position( | ||||
| 			    glm::vec3(-3.0f + static_cast<float>(col) * 3.0f, | ||||
| 				      0.0f, static_cast<float>(-row) * 3.0f)); | ||||
| 	model->set_position(glm::vec3(0.0f, 0.0f, 0.0f)); | ||||
| 	models_.push_back(model); | ||||
| 	world_->add_entity(model); | ||||
| 		} | ||||
| 	} | ||||
| 	Logger::info(sstr("Created ", models_.size(), " models in scene")); | ||||
|  | ||||
| 	Logger::info("Scene setup complete"); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										61
									
								
								src/material.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/material.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| #include "material.h" | ||||
|  | ||||
| #include "../lib/glm/glm.hpp" | ||||
|  | ||||
| #include "shader.h" | ||||
| #include "state.h" | ||||
| #include "texture.h" | ||||
|  | ||||
| Material::Material(const std::shared_ptr<Texture>& tex, | ||||
| 		   const std::shared_ptr<Shader>&  shader) | ||||
|     : shader_(shader), texture_(tex) | ||||
| { | ||||
| } | ||||
|  | ||||
| const std::shared_ptr<Shader>& Material::shader() const | ||||
| { | ||||
| 	return shader_ ? shader_ : state::default_shader; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Shader>& Material::shader() | ||||
| { | ||||
| 	return shader_ ? shader_ : state::default_shader; | ||||
| } | ||||
|  | ||||
| void Material::set_shader(const std::shared_ptr<Shader>& shader) | ||||
| { | ||||
| 	shader_ = shader; | ||||
| } | ||||
|  | ||||
| void Material::prepare() | ||||
| { | ||||
| 	// Activate shader | ||||
| 	std::shared_ptr<Shader> active_shader = shader(); | ||||
| 	if (!active_shader) | ||||
| 		return; | ||||
|  | ||||
| 	active_shader->use(); | ||||
|  | ||||
| 	// Set uniform variables | ||||
| 	const glm::mat4 mvp = | ||||
| 	    state::projection_matrix * state::view_matrix * state::model_matrix; | ||||
| 	const int mvp_loc = active_shader->uniform_location("mvp"); | ||||
| 	Shader::set_mat4(mvp_loc, mvp); | ||||
|  | ||||
| 	// Set texture-related uniforms | ||||
| 	const int use_texture_loc = | ||||
| 	    active_shader->uniform_location("useTexture"); | ||||
| 	if (texture_) { | ||||
| 		Shader::set_int(use_texture_loc, 1); | ||||
| 		const int sampler_loc = | ||||
| 		    active_shader->uniform_location("texSampler"); | ||||
| 		Shader::set_int(sampler_loc, 0); // Texture unit 0 | ||||
| 	} else { | ||||
| 		Shader::set_int(use_texture_loc, 0); | ||||
| 	} | ||||
|  | ||||
| 	// Bind texture if available | ||||
| 	if (texture_) { | ||||
| 		texture_->bind(); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										35
									
								
								src/material.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/material.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #ifndef MATERIAL_H_ | ||||
| #define MATERIAL_H_ | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| class Shader; | ||||
| class Texture; | ||||
|  | ||||
| class Material { | ||||
| public: | ||||
| 	Material(const std::shared_ptr<Texture>& tex	= nullptr, | ||||
| 		 const std::shared_ptr<Shader>&	 shader = nullptr); | ||||
| 	~Material() = default; | ||||
|  | ||||
| 	[[nodiscard]] const std::shared_ptr<Shader>& shader() const; | ||||
| 	[[nodiscard]] std::shared_ptr<Shader>&	     shader(); | ||||
| 	void set_shader(const std::shared_ptr<Shader>& shader); | ||||
|  | ||||
| 	[[nodiscard]] const std::shared_ptr<Texture>& texture() const | ||||
| 	{ | ||||
| 		return texture_; | ||||
| 	} | ||||
| 	void set_texture(const std::shared_ptr<Texture>& tex) | ||||
| 	{ | ||||
| 		texture_ = tex; | ||||
| 	} | ||||
|  | ||||
| 	void prepare(); | ||||
|  | ||||
| private: | ||||
| 	std::shared_ptr<Shader>	 shader_; | ||||
| 	std::shared_ptr<Texture> texture_; | ||||
| }; | ||||
|  | ||||
| #endif // MATERIAL_H_ | ||||
							
								
								
									
										27
									
								
								src/mesh.cpp
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/mesh.cpp
									
									
									
									
									
								
							| @@ -1,33 +1,20 @@ | ||||
| #include "mesh.h" | ||||
|  | ||||
| #include "buffer.h" | ||||
| #include "shader.h" | ||||
| #include "state.h" | ||||
| #include "material.h" | ||||
|  | ||||
| void Mesh::add_buffer(const std::shared_ptr<Buffer>& buffer, | ||||
| 		      const std::shared_ptr<Shader>& shader) | ||||
| 		      const Material& material) | ||||
| { | ||||
| 	buffers_.push_back(buffer); | ||||
| 	shaders_.push_back(shader); | ||||
| 	materials_.push_back(material); | ||||
| } | ||||
|  | ||||
| void Mesh::draw() | ||||
| { | ||||
| 	// Calculate MVP matrix | ||||
| 	glm::mat4 mvp = state::projection_matrix * state::view_matrix | ||||
| 	    * state::model_matrix; | ||||
|  | ||||
| 	// Draw each buffer with its shader | ||||
| 	// Draw each buffer with its material | ||||
| 	for (size_t i = 0; i < buffers_.size(); ++i) { | ||||
| 		// Use buffer's shader if available, otherwise use default | ||||
| 		// shader | ||||
| 		std::shared_ptr<Shader> shader = | ||||
| 		    shaders_[i] ? shaders_[i] : state::default_shader; | ||||
|  | ||||
| 		if (shader) { | ||||
| 			shader->use(); | ||||
| 			int mvpLoc = shader->uniform_location("mvp"); | ||||
| 			Shader::set_mat4(mvpLoc, mvp); | ||||
| 			buffers_[i]->draw(*shader); | ||||
| 		} | ||||
| 		materials_[i].prepare(); | ||||
| 		buffers_[i]->draw(*materials_[i].shader()); | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										16
									
								
								src/mesh.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/mesh.h
									
									
									
									
									
								
							| @@ -4,8 +4,9 @@ | ||||
| #include <memory> | ||||
| #include <vector> | ||||
|  | ||||
| #include "material.h" | ||||
|  | ||||
| class Buffer; | ||||
| class Shader; | ||||
|  | ||||
| class Mesh { | ||||
| public: | ||||
| @@ -13,7 +14,7 @@ public: | ||||
| 	~Mesh() = default; | ||||
|  | ||||
| 	void add_buffer(const std::shared_ptr<Buffer>& buffer, | ||||
| 			const std::shared_ptr<Shader>& shader = nullptr); | ||||
| 			const Material&		       material); | ||||
|  | ||||
| 	[[nodiscard]] size_t num_buffers() const | ||||
| 	{ | ||||
| @@ -28,11 +29,20 @@ public: | ||||
| 		return buffers_[index]; | ||||
| 	} | ||||
|  | ||||
| 	[[nodiscard]] const Material& material(size_t index) const | ||||
| 	{ | ||||
| 		return materials_[index]; | ||||
| 	} | ||||
| 	[[nodiscard]] Material& material(size_t index) | ||||
| 	{ | ||||
| 		return materials_[index]; | ||||
| 	} | ||||
|  | ||||
| 	void draw(); | ||||
|  | ||||
| private: | ||||
| 	std::vector<std::shared_ptr<Buffer>> buffers_; | ||||
| 	std::vector<std::shared_ptr<Shader>> shaders_; | ||||
| 	std::vector<Material>		     materials_; | ||||
| }; | ||||
|  | ||||
| #endif // MESH_H_ | ||||
|   | ||||
| @@ -10,11 +10,11 @@ | ||||
| #include "logger.h" | ||||
| #include "vertex.h" | ||||
|  | ||||
| Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath) | ||||
| Shader::Shader(const std::string& vertex_path, const std::string& fragment_path) | ||||
| { | ||||
| 	const uint32_t vshader = compile_shader(GL_VERTEX_SHADER, vertexPath); | ||||
| 	const uint32_t vshader = compile_shader(GL_VERTEX_SHADER, vertex_path); | ||||
| 	const uint32_t fshader = | ||||
| 	    compile_shader(GL_FRAGMENT_SHADER, fragmentPath); | ||||
| 	    compile_shader(GL_FRAGMENT_SHADER, fragment_path); | ||||
|  | ||||
| 	if (vshader == 0 || fshader == 0) { | ||||
| 		program_id_ = 0; | ||||
| @@ -65,6 +65,14 @@ void Shader::setup_attribs() const | ||||
| 		    loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), | ||||
| 		    reinterpret_cast<const void*>(offsetof(Vertex, color))); | ||||
| 	} | ||||
|  | ||||
| 	loc = glGetAttribLocation(program_id_, "vtexcoord"); | ||||
| 	if (loc != -1) { | ||||
| 		glEnableVertexAttribArray(loc); | ||||
| 		glVertexAttribPointer( | ||||
| 		    loc, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), | ||||
| 		    reinterpret_cast<const void*>(offsetof(Vertex, tex_coord))); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int Shader::uniform_location(const char* key) const | ||||
| @@ -141,9 +149,8 @@ uint32_t Shader::compile_shader(uint32_t type, const std::string& source_path) | ||||
| 		char buffer[1024]; | ||||
| 		glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); | ||||
| 		error_ = buffer; | ||||
| 		Logger::error( | ||||
| 		    sstr("Shader compilation failed (", shader_type_name, "): ", | ||||
| 			 buffer)); | ||||
| 		Logger::error(sstr("Shader compilation failed (", | ||||
| 				   shader_type_name, "): ", buffer)); | ||||
| 		glDeleteShader(shader); | ||||
| 		return 0; | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										83
									
								
								src/texture.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								src/texture.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| #include "texture.h" | ||||
|  | ||||
| #include <algorithm> | ||||
|  | ||||
| #include "../lib/glew/GL/glew.h" | ||||
| #include "../lib/glfw/glfw3.h" | ||||
|  | ||||
| #define STB_IMAGE_IMPLEMENTATION | ||||
| #include "../lib/stb/stb_image.h" | ||||
|  | ||||
| #include "logger.h" | ||||
|  | ||||
| Texture::Texture(uint32_t id, const glm::ivec2& size) | ||||
|     : id_(id), size_(size) | ||||
| { | ||||
| } | ||||
|  | ||||
| Texture::~Texture() | ||||
| { | ||||
| 	if (id_ != 0) { | ||||
| 		glDeleteTextures(1, &id_); | ||||
| 		Logger::info(sstr("Texture ", id_, " destroyed")); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Texture> Texture::load(const char* filename) | ||||
| { | ||||
| 	Logger::info(sstr("Loading texture: ", filename)); | ||||
|  | ||||
| 	// Load image | ||||
| 	int	 width, height, channels; | ||||
| 	stbi_uc* pixels = | ||||
| 	    stbi_load(filename, &width, &height, &channels, STBI_rgb_alpha); | ||||
|  | ||||
| 	if (!pixels) { | ||||
| 		Logger::error(sstr("Failed to load texture: ", filename, " - ", | ||||
| 				   stbi_failure_reason())); | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	// Flip image vertically (OpenGL expects bottom row first) | ||||
| 	const int row_size   = width * 4; // 4 channels (RGBA) | ||||
| 	auto*	  row_buffer = new stbi_uc[row_size]; | ||||
| 	for (int y = 0; y < height / 2; ++y) { | ||||
| 		stbi_uc* row1 = pixels + y * row_size; | ||||
| 		stbi_uc* row2 = pixels + (height - 1 - y) * row_size; | ||||
| 		std::copy(row1, row1 + row_size, row_buffer); | ||||
| 		std::copy(row2, row2 + row_size, row1); | ||||
| 		std::copy(row_buffer, row_buffer + row_size, row2); | ||||
| 	} | ||||
| 	delete[] row_buffer; | ||||
|  | ||||
| 	// Generate OpenGL texture | ||||
| 	GLuint texture_id; | ||||
| 	glGenTextures(1, &texture_id); | ||||
| 	glBindTexture(GL_TEXTURE_2D, texture_id); | ||||
|  | ||||
| 	// Upload texture data | ||||
| 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, | ||||
| 		     GL_UNSIGNED_BYTE, pixels); | ||||
|  | ||||
| 	// Set trilinear filtering | ||||
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, | ||||
| 			GL_LINEAR_MIPMAP_LINEAR); | ||||
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
|  | ||||
| 	// Generate mipmaps | ||||
| 	glGenerateMipmap(GL_TEXTURE_2D); | ||||
|  | ||||
| 	// Free image data | ||||
| 	stbi_image_free(pixels); | ||||
|  | ||||
| 	Logger::info(sstr("Texture loaded successfully: ", filename, " (", | ||||
| 			  width, "x", height, ", ", channels, " channels)")); | ||||
|  | ||||
| 	return std::shared_ptr<Texture>( | ||||
| 	    new Texture(texture_id, glm::ivec2(width, height))); | ||||
| } | ||||
|  | ||||
| void Texture::bind() const | ||||
| { | ||||
| 	glBindTexture(GL_TEXTURE_2D, id_); | ||||
| } | ||||
							
								
								
									
										35
									
								
								src/texture.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/texture.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #ifndef TEXTURE_H_ | ||||
| #define TEXTURE_H_ | ||||
|  | ||||
| #include <cstdint> | ||||
| #include <memory> | ||||
| #include <string> | ||||
|  | ||||
| #include "../lib/glm/glm.hpp" | ||||
|  | ||||
| class Texture { | ||||
| public: | ||||
| 	Texture() = delete; | ||||
| 	~Texture(); | ||||
|  | ||||
| 	static std::shared_ptr<Texture> load(const char* filename); | ||||
|  | ||||
| 	[[nodiscard]] uint32_t id() const | ||||
| 	{ | ||||
| 		return id_; | ||||
| 	} | ||||
| 	[[nodiscard]] const glm::ivec2& size() const | ||||
| 	{ | ||||
| 		return size_; | ||||
| 	} | ||||
|  | ||||
| 	void bind() const; | ||||
|  | ||||
| private: | ||||
| 	Texture(uint32_t id, const glm::ivec2& size); | ||||
|  | ||||
| 	uint32_t   id_; | ||||
| 	glm::ivec2 size_; | ||||
| }; | ||||
|  | ||||
| #endif // TEXTURE_H_ | ||||
| @@ -6,6 +6,7 @@ | ||||
| struct Vertex { | ||||
| 	glm::vec3 position{0.0f, 0.0f, 0.0f}; | ||||
| 	glm::vec3 color{0.0f, 0.0f, 0.0f}; | ||||
| 	glm::vec2 tex_coord{0.0f, 0.0f}; | ||||
| }; | ||||
|  | ||||
| #endif // VERTEX_H_ | ||||
|   | ||||
| @@ -159,15 +159,18 @@ | ||||
|     <ClInclude Include="lib\glew\GL\glew.h" /> | ||||
|     <ClInclude Include="lib\glfw\glfw3.h" /> | ||||
|     <ClInclude Include="lib\glfw\glfw3native.h" /> | ||||
|     <ClInclude Include="lib\stb\stb_image.h" /> | ||||
|     <ClInclude Include="src\buffer.h" /> | ||||
|     <ClInclude Include="src\camera.h" /> | ||||
|     <ClInclude Include="src\engine.h" /> | ||||
|     <ClInclude Include="src\entity.h" /> | ||||
|     <ClInclude Include="src\logger.h" /> | ||||
|     <ClInclude Include="src\material.h" /> | ||||
|     <ClInclude Include="src\mesh.h" /> | ||||
|     <ClInclude Include="src\model.h" /> | ||||
|     <ClInclude Include="src\shader.h" /> | ||||
|     <ClInclude Include="src\state.h" /> | ||||
|     <ClInclude Include="src\texture.h" /> | ||||
|     <ClInclude Include="src\vertex.h" /> | ||||
|     <ClInclude Include="src\world.h" /> | ||||
|   </ItemGroup> | ||||
| @@ -179,15 +182,17 @@ | ||||
|     <ClCompile Include="src\entity.cpp" /> | ||||
|     <ClCompile Include="src\logger.cpp" /> | ||||
|     <ClCompile Include="src\main.cpp" /> | ||||
|     <ClCompile Include="src\material.cpp" /> | ||||
|     <ClCompile Include="src\mesh.cpp" /> | ||||
|     <ClCompile Include="src\model.cpp" /> | ||||
|     <ClCompile Include="src\shader.cpp" /> | ||||
|     <ClCompile Include="src\texture.cpp" /> | ||||
|     <ClCompile Include="src\vertex.cpp" /> | ||||
|     <ClCompile Include="src\world.cpp" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="data\fragment.glsl" /> | ||||
|     <None Include="data\vertex.glsl" /> | ||||
|     <None Include="data\shaders\fragment.glsl" /> | ||||
|     <None Include="data\shaders\vertex.glsl" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||
|   <ImportGroup Label="ExtensionTargets"> | ||||
|   | ||||
| @@ -19,6 +19,9 @@ | ||||
|     <Filter Include="glew"> | ||||
|       <UniqueIdentifier>{296e1ba9-28bc-4e0b-8d4e-413551edca96}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="stb"> | ||||
|       <UniqueIdentifier>{e3c5a7f2-1d4b-4a9c-8f2e-9b5c8d7a6e4f}</UniqueIdentifier> | ||||
|     </Filter> | ||||
|     <Filter Include="Shaders"> | ||||
|       <UniqueIdentifier>{0628083b-a31c-4825-822c-11b6f933e7bd}</UniqueIdentifier> | ||||
|     </Filter> | ||||
| @@ -33,6 +36,9 @@ | ||||
|     <ClInclude Include="lib\glew\GL\glew.h"> | ||||
|       <Filter>glew</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="lib\stb\stb_image.h"> | ||||
|       <Filter>stb</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="src\vertex.h"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClInclude> | ||||
| @@ -66,6 +72,12 @@ | ||||
|     <ClInclude Include="src\logger.h"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="src\material.h"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClInclude> | ||||
|     <ClInclude Include="src\texture.h"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClInclude> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClCompile Include="src\main.cpp"> | ||||
| @@ -104,12 +116,18 @@ | ||||
|     <ClCompile Include="src\logger.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\material.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="src\texture.cpp"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <None Include="data\fragment.glsl"> | ||||
|     <None Include="data\shaders\fragment.glsl"> | ||||
|       <Filter>Shaders</Filter> | ||||
|     </None> | ||||
|     <None Include="data\vertex.glsl"> | ||||
|     <None Include="data\shaders\vertex.glsl"> | ||||
|       <Filter>Shaders</Filter> | ||||
|     </None> | ||||
|   </ItemGroup> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user