Files
2025-12-15 23:22:33 +08:00

226 lines
6.8 KiB
C++

/***********************************************************************************************************************
*
* Copyright (c) 2010 - 2025 by Tech Soft 3D, Inc.
* The information contained herein is confidential and proprietary to Tech Soft 3D, Inc., and considered a trade secret
* as defined under civil and criminal statutes. Tech Soft 3D shall pursue its civil and criminal remedies in the event
* of unauthorized use or misappropriation of its trade secrets. Use of this information by anyone other than authorized
* employees of Tech Soft 3D, Inc. is granted only under a written non-disclosure agreement, expressly prescribing the
* scope and manner of such use.
*
***********************************************************************************************************************/
#include "shader.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
std::string parse_file(const char* filename)
{
try
{
std::ifstream file;
file.open(filename);
std::stringstream filestream;
filestream << file.rdbuf();
file.close();
return filestream.str();
}
catch (std::ifstream::failure& e)
{
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
}
return "";
}
Shader::Shader(const char* vertex_filename, const char* fragment_filename)
{
std::string vertex_filepath = SHADERS_FOLDER;
vertex_filepath.append("/");
vertex_filepath.append(vertex_filename);
std::string vertexCode = parse_file(vertex_filepath.c_str());
const char* vShaderCode = vertexCode.c_str();
std::string fragment_filepath = SHADERS_FOLDER;
fragment_filepath.append("/");
fragment_filepath.append(fragment_filename);
std::string fragmentCode = parse_file(fragment_filepath.c_str());
const char* fShaderCode = fragmentCode.c_str();
unsigned int vertex, fragment;
// vertex shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, nullptr);
glCompileShader(vertex);
compile_errors(vertex, "VERTEX");
// fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, nullptr);
glCompileShader(fragment);
compile_errors(fragment, "FRAGMENT");
// shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
compile_errors(ID, "PROGRAM");
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use()
{
glUseProgram(ID);
}
void Shader::detach()
{
glDeleteProgram(ID);
}
void Shader::add_light_properties(const glm::vec3& light_position)
{
use();
set_vec4("lightColor", 1.f, 1.f, 1.f, 0.f);
set_vec3("lightPos", light_position);
}
void Shader::compile_errors(unsigned int shader, const std::string & type)
{
GLint success;
GLchar infoLog[1024];
if (type != "PROGRAM")
{
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
else
{
glGetProgramiv(shader, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shader, 1024, NULL, infoLog);
std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n"
<< infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
}
}
}
void Shader::set_value(const std::string& name, float value) const
{
glUniform1fv(glGetUniformLocation(ID, name.c_str()), 1, &value);
}
void Shader::set_vec2(const std::string& name, const glm::vec2& value) const
{
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec2(const std::string& name, float x, float y) const
{
glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
}
// ------------------------------------------------------------------------
void Shader::set_vec3(const std::string& name, const glm::vec3& value) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec3(const std::string& name, float x, float y, float z) const
{
glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
}
// ------------------------------------------------------------------------
void Shader::set_vec4(const std::string& name, const glm::vec4& value) const
{
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::set_vec4(const std::string& name, float x, float y, float z, float w) const
{
glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
}
// ------------------------------------------------------------------------
void Shader::set_mat4(const std::string& name, const glm::mat4& mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void Shader::update_view_matrix(const glm::mat4& mat) const
{
set_mat4("view", mat);
}
void Shader::update_world_matrix(const glm::mat4& mat) const
{
set_mat4("world", mat);
}
void Shader::update_model_matrix(const glm::mat4& mat) const
{
set_mat4("model", mat);
set_mat4("model_normal", glm::transpose(glm::inverse(mat)));
}
void Shader::update_projection_matrix(const glm::mat4& mat) const
{
set_mat4("projection", mat);
}
void Shader::update_mesh_color(const glm::vec4& rgba) const
{
set_vec4("material.ambiant", rgba);
set_vec4("material.diffuse", rgba);
set_vec4("material.specular", 0.5f, 0.5f, 0.5f, rgba[3]);
set_vec4("material.emissive", 0.f, 0.f, 0.f, rgba[3]);
set_value("material.shininess", 0.5f);
}
void Shader::update_mesh_material(const utils::properties::style::Material& material) const
{
set_vec4("material.ambiant", material.ambient);
set_vec4("material.diffuse", material.diffuse);
set_vec4("material.specular", material.specular);
set_vec4("material.emissive", material.emissive);
set_value("material.shininess", material.shininess);
}
void Shader::update_mesh_style(const utils::properties::style::Graphics& graphics, bool& is_first)
{
if (!is_first && current_graphics_id == graphics.id)
return;
is_first = false;
current_graphics_id = graphics.id;
if (graphics.id == -1)
{
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::UNDEF)
{
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::TEXTURE)
{
std::cout << "WARNING::TEXTURE::NOT_IMPLEMENTED_IN_THE_SAMPLE" << std::endl;
update_mesh_material(utils::properties::style::default_material);
}
else if (graphics.type == utils::properties::style::Graphics::RGBA)
{
update_mesh_color(graphics.rgba);
}
else if (graphics.type == utils::properties::style::Graphics::MATERIAL)
{
update_mesh_material(graphics.material);
}
else
{
std::cout << "ERROR::STYLE::UNEXPECTED" << std::endl;
update_mesh_material(utils::properties::style::default_material);
}
}