feat: assignment 3
This commit is contained in:
		| @@ -1,5 +1,12 @@ | |||||||
|  | uniform int useTexture; | ||||||
|  | uniform sampler2D texSampler; | ||||||
| varying vec3 fcolor; | varying vec3 fcolor; | ||||||
|  | varying vec2 ftexcoord; | ||||||
|  |  | ||||||
| void main() { | 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; | uniform mat4 mvp; | ||||||
| attribute vec3 vpos; | attribute vec3 vpos; | ||||||
| attribute vec3 vcolor; | attribute vec3 vcolor; | ||||||
|  | attribute vec2 vtexcoord; | ||||||
| varying vec3 fcolor; | varying vec3 fcolor; | ||||||
|  | varying vec2 ftexcoord; | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
| 	gl_Position = mvp * vec4(vpos, 1); | 	gl_Position = mvp * vec4(vpos, 1); | ||||||
| 	fcolor = vcolor; | 	fcolor = vcolor; | ||||||
|  | 	ftexcoord = vtexcoord; | ||||||
| } | } | ||||||
| @@ -10,10 +10,12 @@ | |||||||
| #include "buffer.h" | #include "buffer.h" | ||||||
| #include "camera.h" | #include "camera.h" | ||||||
| #include "logger.h" | #include "logger.h" | ||||||
|  | #include "material.h" | ||||||
| #include "mesh.h" | #include "mesh.h" | ||||||
| #include "model.h" | #include "model.h" | ||||||
| #include "shader.h" | #include "shader.h" | ||||||
| #include "state.h" | #include "state.h" | ||||||
|  | #include "texture.h" | ||||||
| #include "vertex.h" | #include "vertex.h" | ||||||
| #include "world.h" | #include "world.h" | ||||||
|  |  | ||||||
| @@ -83,8 +85,8 @@ void Engine::initialize() | |||||||
|  |  | ||||||
| 	// Initialize default shader | 	// Initialize default shader | ||||||
| 	Logger::info("Loading default shaders..."); | 	Logger::info("Loading default shaders..."); | ||||||
| 	state::default_shader = | 	state::default_shader = std::make_shared<Shader>( | ||||||
| 	    std::make_shared<Shader>("data/shaders/vertex.glsl", "data/shaders/fragment.glsl"); | 	    "data/shaders/vertex.glsl", "data/shaders/fragment.glsl"); | ||||||
| 	if (std::strlen(state::default_shader->error()) > 0) { | 	if (std::strlen(state::default_shader->error()) > 0) { | ||||||
| 		Logger::error(sstr("Failed to initialize shaders: ", | 		Logger::error(sstr("Failed to initialize shaders: ", | ||||||
| 				   state::default_shader->error())); | 				   state::default_shader->error())); | ||||||
| @@ -140,9 +142,10 @@ void Engine::setup() | |||||||
| 	world_ = std::make_unique<World>(); | 	world_ = std::make_unique<World>(); | ||||||
| 	Logger::info("World created"); | 	Logger::info("World created"); | ||||||
|  |  | ||||||
| 	// Create camera | 	// Create camera at position (0, 1, 3) with -20 degrees X rotation | ||||||
| 	camera_ = std::make_shared<Camera>(); | 	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( | 	camera_->set_projection( | ||||||
| 	    glm::perspective(glm::radians(45.0f), | 	    glm::perspective(glm::radians(45.0f), | ||||||
| 			     static_cast<float>(screen_width_) | 			     static_cast<float>(screen_width_) | ||||||
| @@ -153,31 +156,79 @@ void Engine::setup() | |||||||
| 	world_->add_entity(camera_); | 	world_->add_entity(camera_); | ||||||
| 	Logger::info("Camera created and added to world"); | 	Logger::info("Camera created and added to world"); | ||||||
|  |  | ||||||
| 	// Create triangle mesh | 	// Load textures | ||||||
| 	std::vector<Vertex> vertices = { | 	auto top_texture   = Texture::load("data/textures/top.png"); | ||||||
| 	    {{0.0f, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}}, | 	auto front_texture = Texture::load("data/textures/front.png"); | ||||||
| 	    {{-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}; |  | ||||||
|  |  | ||||||
| 	auto buffer = std::make_shared<Buffer>(vertices, indices); | 	// Create cube mesh with two buffers | ||||||
| 	mesh_ = std::make_shared<Mesh>(); | 	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 | 	// Buffer 1: Top and bottom faces | ||||||
| 	for (int row = 0; row < 3; ++row) { | 	std::vector<Vertex> top_bottom_vertices = { | ||||||
| 		for (int col = 0; col < 3; ++col) { | 	    // 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_); | 	auto model = std::make_shared<Model>(mesh_); | ||||||
| 			model->set_position( | 	model->set_position(glm::vec3(0.0f, 0.0f, 0.0f)); | ||||||
| 			    glm::vec3(-3.0f + static_cast<float>(col) * 3.0f, |  | ||||||
| 				      0.0f, static_cast<float>(-row) * 3.0f)); |  | ||||||
| 	models_.push_back(model); | 	models_.push_back(model); | ||||||
| 	world_->add_entity(model); | 	world_->add_entity(model); | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	Logger::info(sstr("Created ", models_.size(), " models in scene")); |  | ||||||
| 	Logger::info("Scene setup complete"); | 	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 "mesh.h" | ||||||
|  |  | ||||||
| #include "buffer.h" | #include "buffer.h" | ||||||
| #include "shader.h" | #include "material.h" | ||||||
| #include "state.h" |  | ||||||
|  |  | ||||||
| void Mesh::add_buffer(const std::shared_ptr<Buffer>& buffer, | void Mesh::add_buffer(const std::shared_ptr<Buffer>& buffer, | ||||||
| 		      const std::shared_ptr<Shader>& shader) | 		      const Material& material) | ||||||
| { | { | ||||||
| 	buffers_.push_back(buffer); | 	buffers_.push_back(buffer); | ||||||
| 	shaders_.push_back(shader); | 	materials_.push_back(material); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Mesh::draw() | void Mesh::draw() | ||||||
| { | { | ||||||
| 	// Calculate MVP matrix | 	// Draw each buffer with its material | ||||||
| 	glm::mat4 mvp = state::projection_matrix * state::view_matrix |  | ||||||
| 	    * state::model_matrix; |  | ||||||
|  |  | ||||||
| 	// Draw each buffer with its shader |  | ||||||
| 	for (size_t i = 0; i < buffers_.size(); ++i) { | 	for (size_t i = 0; i < buffers_.size(); ++i) { | ||||||
| 		// Use buffer's shader if available, otherwise use default | 		materials_[i].prepare(); | ||||||
| 		// shader | 		buffers_[i]->draw(*materials_[i].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); |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								src/mesh.h
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/mesh.h
									
									
									
									
									
								
							| @@ -4,8 +4,9 @@ | |||||||
| #include <memory> | #include <memory> | ||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
|  | #include "material.h" | ||||||
|  |  | ||||||
| class Buffer; | class Buffer; | ||||||
| class Shader; |  | ||||||
|  |  | ||||||
| class Mesh { | class Mesh { | ||||||
| public: | public: | ||||||
| @@ -13,7 +14,7 @@ public: | |||||||
| 	~Mesh() = default; | 	~Mesh() = default; | ||||||
|  |  | ||||||
| 	void add_buffer(const std::shared_ptr<Buffer>& buffer, | 	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 | 	[[nodiscard]] size_t num_buffers() const | ||||||
| 	{ | 	{ | ||||||
| @@ -28,11 +29,20 @@ public: | |||||||
| 		return buffers_[index]; | 		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(); | 	void draw(); | ||||||
|  |  | ||||||
| private: | private: | ||||||
| 	std::vector<std::shared_ptr<Buffer>> buffers_; | 	std::vector<std::shared_ptr<Buffer>> buffers_; | ||||||
| 	std::vector<std::shared_ptr<Shader>> shaders_; | 	std::vector<Material>		     materials_; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| #endif // MESH_H_ | #endif // MESH_H_ | ||||||
|   | |||||||
| @@ -10,11 +10,11 @@ | |||||||
| #include "logger.h" | #include "logger.h" | ||||||
| #include "vertex.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 = | 	const uint32_t fshader = | ||||||
| 	    compile_shader(GL_FRAGMENT_SHADER, fragmentPath); | 	    compile_shader(GL_FRAGMENT_SHADER, fragment_path); | ||||||
|  |  | ||||||
| 	if (vshader == 0 || fshader == 0) { | 	if (vshader == 0 || fshader == 0) { | ||||||
| 		program_id_ = 0; | 		program_id_ = 0; | ||||||
| @@ -65,6 +65,14 @@ void Shader::setup_attribs() const | |||||||
| 		    loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), | 		    loc, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), | ||||||
| 		    reinterpret_cast<const void*>(offsetof(Vertex, color))); | 		    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 | 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]; | 		char buffer[1024]; | ||||||
| 		glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); | 		glGetShaderInfoLog(shader, sizeof(buffer), nullptr, buffer); | ||||||
| 		error_ = buffer; | 		error_ = buffer; | ||||||
| 		Logger::error( | 		Logger::error(sstr("Shader compilation failed (", | ||||||
| 		    sstr("Shader compilation failed (", shader_type_name, "): ", | 				   shader_type_name, "): ", buffer)); | ||||||
| 			 buffer)); |  | ||||||
| 		glDeleteShader(shader); | 		glDeleteShader(shader); | ||||||
| 		return 0; | 		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 { | struct Vertex { | ||||||
| 	glm::vec3 position{0.0f, 0.0f, 0.0f}; | 	glm::vec3 position{0.0f, 0.0f, 0.0f}; | ||||||
| 	glm::vec3 color{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_ | #endif // VERTEX_H_ | ||||||
|   | |||||||
| @@ -159,15 +159,18 @@ | |||||||
|     <ClInclude Include="lib\glew\GL\glew.h" /> |     <ClInclude Include="lib\glew\GL\glew.h" /> | ||||||
|     <ClInclude Include="lib\glfw\glfw3.h" /> |     <ClInclude Include="lib\glfw\glfw3.h" /> | ||||||
|     <ClInclude Include="lib\glfw\glfw3native.h" /> |     <ClInclude Include="lib\glfw\glfw3native.h" /> | ||||||
|  |     <ClInclude Include="lib\stb\stb_image.h" /> | ||||||
|     <ClInclude Include="src\buffer.h" /> |     <ClInclude Include="src\buffer.h" /> | ||||||
|     <ClInclude Include="src\camera.h" /> |     <ClInclude Include="src\camera.h" /> | ||||||
|     <ClInclude Include="src\engine.h" /> |     <ClInclude Include="src\engine.h" /> | ||||||
|     <ClInclude Include="src\entity.h" /> |     <ClInclude Include="src\entity.h" /> | ||||||
|     <ClInclude Include="src\logger.h" /> |     <ClInclude Include="src\logger.h" /> | ||||||
|  |     <ClInclude Include="src\material.h" /> | ||||||
|     <ClInclude Include="src\mesh.h" /> |     <ClInclude Include="src\mesh.h" /> | ||||||
|     <ClInclude Include="src\model.h" /> |     <ClInclude Include="src\model.h" /> | ||||||
|     <ClInclude Include="src\shader.h" /> |     <ClInclude Include="src\shader.h" /> | ||||||
|     <ClInclude Include="src\state.h" /> |     <ClInclude Include="src\state.h" /> | ||||||
|  |     <ClInclude Include="src\texture.h" /> | ||||||
|     <ClInclude Include="src\vertex.h" /> |     <ClInclude Include="src\vertex.h" /> | ||||||
|     <ClInclude Include="src\world.h" /> |     <ClInclude Include="src\world.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| @@ -179,15 +182,17 @@ | |||||||
|     <ClCompile Include="src\entity.cpp" /> |     <ClCompile Include="src\entity.cpp" /> | ||||||
|     <ClCompile Include="src\logger.cpp" /> |     <ClCompile Include="src\logger.cpp" /> | ||||||
|     <ClCompile Include="src\main.cpp" /> |     <ClCompile Include="src\main.cpp" /> | ||||||
|  |     <ClCompile Include="src\material.cpp" /> | ||||||
|     <ClCompile Include="src\mesh.cpp" /> |     <ClCompile Include="src\mesh.cpp" /> | ||||||
|     <ClCompile Include="src\model.cpp" /> |     <ClCompile Include="src\model.cpp" /> | ||||||
|     <ClCompile Include="src\shader.cpp" /> |     <ClCompile Include="src\shader.cpp" /> | ||||||
|  |     <ClCompile Include="src\texture.cpp" /> | ||||||
|     <ClCompile Include="src\vertex.cpp" /> |     <ClCompile Include="src\vertex.cpp" /> | ||||||
|     <ClCompile Include="src\world.cpp" /> |     <ClCompile Include="src\world.cpp" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="data\fragment.glsl" /> |     <None Include="data\shaders\fragment.glsl" /> | ||||||
|     <None Include="data\vertex.glsl" /> |     <None Include="data\shaders\vertex.glsl" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||||||
|   <ImportGroup Label="ExtensionTargets"> |   <ImportGroup Label="ExtensionTargets"> | ||||||
|   | |||||||
| @@ -19,6 +19,9 @@ | |||||||
|     <Filter Include="glew"> |     <Filter Include="glew"> | ||||||
|       <UniqueIdentifier>{296e1ba9-28bc-4e0b-8d4e-413551edca96}</UniqueIdentifier> |       <UniqueIdentifier>{296e1ba9-28bc-4e0b-8d4e-413551edca96}</UniqueIdentifier> | ||||||
|     </Filter> |     </Filter> | ||||||
|  |     <Filter Include="stb"> | ||||||
|  |       <UniqueIdentifier>{e3c5a7f2-1d4b-4a9c-8f2e-9b5c8d7a6e4f}</UniqueIdentifier> | ||||||
|  |     </Filter> | ||||||
|     <Filter Include="Shaders"> |     <Filter Include="Shaders"> | ||||||
|       <UniqueIdentifier>{0628083b-a31c-4825-822c-11b6f933e7bd}</UniqueIdentifier> |       <UniqueIdentifier>{0628083b-a31c-4825-822c-11b6f933e7bd}</UniqueIdentifier> | ||||||
|     </Filter> |     </Filter> | ||||||
| @@ -33,6 +36,9 @@ | |||||||
|     <ClInclude Include="lib\glew\GL\glew.h"> |     <ClInclude Include="lib\glew\GL\glew.h"> | ||||||
|       <Filter>glew</Filter> |       <Filter>glew</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="lib\stb\stb_image.h"> | ||||||
|  |       <Filter>stb</Filter> | ||||||
|  |     </ClInclude> | ||||||
|     <ClInclude Include="src\vertex.h"> |     <ClInclude Include="src\vertex.h"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
| @@ -66,6 +72,12 @@ | |||||||
|     <ClInclude Include="src\logger.h"> |     <ClInclude Include="src\logger.h"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="src\material.h"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="src\texture.h"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="src\main.cpp"> |     <ClCompile Include="src\main.cpp"> | ||||||
| @@ -104,12 +116,18 @@ | |||||||
|     <ClCompile Include="src\logger.cpp"> |     <ClCompile Include="src\logger.cpp"> | ||||||
|       <Filter>Source Files</Filter> |       <Filter>Source Files</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="src\material.cpp"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="src\texture.cpp"> | ||||||
|  |       <Filter>Source Files</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="data\fragment.glsl"> |     <None Include="data\shaders\fragment.glsl"> | ||||||
|       <Filter>Shaders</Filter> |       <Filter>Shaders</Filter> | ||||||
|     </None> |     </None> | ||||||
|     <None Include="data\vertex.glsl"> |     <None Include="data\shaders\vertex.glsl"> | ||||||
|       <Filter>Shaders</Filter> |       <Filter>Shaders</Filter> | ||||||
|     </None> |     </None> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user