1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
// Copyright 2022-2023 Gabriel Bjørnager Jensen.
#include <bow/client.hxx>
#include <cstdio>
#include <filesystem>
#include <fmt/core.h>
#include <glad/glad.h>
#include <stdexcept>
#include <string>
#include <vector>
using namespace ::std::literals::string_literals;
auto bow::ShaderProgram::compile_shader(::std::string const& name, ::bow::ShaderType const pretty_type) -> ::GLuint {
auto const type = [pretty_type]() -> ::GLuint {
using ::bow::ShaderType;
switch (pretty_type) {
case ShaderType::Fragment:
return GL_FRAGMENT_SHADER;
case ShaderType::Geometry:
return GL_GEOMETRY_SHADER;
case ShaderType::Vertex:
return GL_VERTEX_SHADER;
}
}();
auto const type_suffix = [type]() -> ::std::string {
switch (type) {
default:
// Until C++23:
::__builtin_unreachable();
case GL_FRAGMENT_SHADER:
return "frag"s;
case GL_GEOMETRY_SHADER:
return "geom"s;
case GL_VERTEX_SHADER:
return "vert"s;
}
}();
auto const type_string = [type]() -> ::std::string {
switch (type) {
default:
::__builtin_unreachable();
case GL_FRAGMENT_SHADER:
return "fragment"s;
case GL_GEOMETRY_SHADER:
return "geometry"s;
case GL_VERTEX_SHADER:
return "vertex"s;
}
}();
using ::bow::DATA_DIRECTORY;
auto const path = DATA_DIRECTORY + "/shaders/" + name + "." + type_suffix + "." + ::bow::SHADER_FILE_SUFFIX;
::fmt::print(stderr, "[client] compiling {} shader at \"{}\"\n", type_string, path);
::std::FILE* file = ::std::fopen(path.c_str(), "r");
auto const file_size = ::std::filesystem::file_size(path);
static_assert(sizeof (::GLchar) == sizeof (char));
auto source = ::std::vector<::GLchar>(file_size + 0x1u);
if (::std::fread(source.data(), sizeof (::GLchar), file_size, file) < file_size) [[unlikely]] {
throw ::std::runtime_error("unable to read shader source");
}
source.push_back('\x00');
auto const source_pointer = source.data();
auto shader = glCreateShader(type);
glShaderSource(shader, 0x1, const_cast<::GLchar const* const*>(&source_pointer), nullptr);
glCompileShader(shader);
::GLint compilation_status = 0x0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compilation_status);
if (compilation_status == GL_FALSE) [[unlikely]] {
::GLint log_length = 0x0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
auto log = new ::GLchar[static_cast<::std::size_t>(log_length)];
glGetShaderInfoLog(shader, log_length, nullptr, log);
::fmt::print(stderr, "[client] unable to compiler shader:\n");
::std::fwrite(log, 0x1u, static_cast<::std::size_t>(log_length), stderr);
delete[] log;
throw ::std::runtime_error("unable to compile shader");
}
return shader;
}
|