110 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			110 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include <asset_parser/assets/text.hpp>
 | 
						|
 | 
						|
namespace lt {
 | 
						|
 | 
						|
glShader::glShader(
 | 
						|
    const Ref<Assets::TextAsset> &vertex_asset,
 | 
						|
    const Ref<Assets::TextAsset> &pixel_asset
 | 
						|
)
 | 
						|
    : m_shader_id(glCreateProgram())
 | 
						|
{
 | 
						|
	auto vertex_blob_metadata = vertex_asset->get_blob_metadata(Assets::BlobMetadata::Tag::text);
 | 
						|
	auto pixel_blob_metadata = pixel_asset->get_blob_metadata(Assets::BlobMetadata::Tag::text);
 | 
						|
 | 
						|
	auto vertex_blob = Assets::Blob(vertex_blob_metadata.uncompressed_size);
 | 
						|
	auto pixel_blob = Assets::Blob(pixel_blob_metadata.uncompressed_size);
 | 
						|
 | 
						|
	vertex_asset->unpack_blob(vertex_blob_metadata.tag, vertex_blob.data(), vertex_blob.size());
 | 
						|
	pixel_asset->unpack_blob(pixel_blob_metadata.tag, pixel_blob.data(), pixel_blob.size());
 | 
						|
 | 
						|
	auto vertex_source = std::string {
 | 
						|
		reinterpret_cast<char *>(vertex_blob.data()),
 | 
						|
		reinterpret_cast<char *>(vertex_blob.data()) + vertex_blob.size(), // NOLINT
 | 
						|
	};
 | 
						|
 | 
						|
	auto pixel_source = std::string {
 | 
						|
		reinterpret_cast<char *>(pixel_blob.data()),
 | 
						|
		reinterpret_cast<char *>(pixel_blob.data()) + pixel_blob.size(), // NOLINT
 | 
						|
	};
 | 
						|
 | 
						|
	const auto vertex_shader = compile_shader(vertex_source, Shader::Stage::vertex);
 | 
						|
	const auto pixel_shader = compile_shader(pixel_source, Shader::Stage::pixel);
 | 
						|
 | 
						|
	glAttachShader(m_shader_id, vertex_shader);
 | 
						|
	glAttachShader(m_shader_id, pixel_shader);
 | 
						|
 | 
						|
	glLinkProgram(m_shader_id);
 | 
						|
 | 
						|
	glDeleteShader(vertex_shader);
 | 
						|
	glDeleteShader(pixel_shader);
 | 
						|
}
 | 
						|
 | 
						|
glShader::~glShader()
 | 
						|
{
 | 
						|
	glDeleteProgram(m_shader_id);
 | 
						|
}
 | 
						|
 | 
						|
void glShader::bind()
 | 
						|
{
 | 
						|
	glUseProgram(m_shader_id);
 | 
						|
}
 | 
						|
 | 
						|
void glShader::un_bind()
 | 
						|
{
 | 
						|
	glUseProgram({});
 | 
						|
}
 | 
						|
 | 
						|
auto glShader::compile_shader(const std::string &source, Shader::Stage stage) -> unsigned int
 | 
						|
{
 | 
						|
	// &(address of) needs an lvalue
 | 
						|
	const auto *lvalue_source = source.c_str();
 | 
						|
	auto shader = glCreateShader(
 | 
						|
	    stage == Shader::Stage::vertex   ? GL_VERTEX_SHADER :
 | 
						|
	    stage == Shader::Stage::pixel    ? GL_FRAGMENT_SHADER :
 | 
						|
	    stage == Shader::Stage::geometry ? GL_GEOMETRY_SHADER :
 | 
						|
	                                       0
 | 
						|
	);
 | 
						|
 | 
						|
	// compile
 | 
						|
	glShaderSource(shader, 1, &lvalue_source, nullptr);
 | 
						|
	glCompileShader(shader);
 | 
						|
 | 
						|
	// check
 | 
						|
	auto isCompiled = 0;
 | 
						|
	glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
 | 
						|
	if (isCompiled == GL_FALSE)
 | 
						|
	{
 | 
						|
		auto logLength = 0;
 | 
						|
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
 | 
						|
 | 
						|
		auto *errorLog = (char *)alloca(logLength);
 | 
						|
		glGetShaderInfoLog(shader, logLength, &logLength, &errorLog[0]);
 | 
						|
 | 
						|
		log_err(
 | 
						|
		    "glShader::glShader: failed to compile {} shader:\n        {}",
 | 
						|
		    stage == Shader::Stage::vertex ? "Vertex" : "Pixel",
 | 
						|
		    errorLog
 | 
						|
		);
 | 
						|
 | 
						|
		return {};
 | 
						|
	}
 | 
						|
#define LIGHT_OPENGL_ENABLE_SHADER_INFO_LOG
 | 
						|
#ifdef LIGHT_OPENGL_ENABLE_SHADER_INFO_LOG
 | 
						|
	// info log
 | 
						|
	{
 | 
						|
		auto logLength = 0;
 | 
						|
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
 | 
						|
		if (logLength)
 | 
						|
		{
 | 
						|
			char *infoLog = (char *)alloca(logLength);
 | 
						|
			glGetShaderInfoLog(shader, logLength, &logLength, &infoLog[0]);
 | 
						|
 | 
						|
			log_wrn("Shader info: {}", infoLog);
 | 
						|
		}
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	return shader;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace lt
 |