1
+ #include "GLTools.h"
2
+
3
+ #include <fstream>
4
+ #include <sstream>
5
+ #include <memory>
6
+ #include <cstring>
7
+
8
+ #include "Image.h"
9
+
10
+ namespace tankwars {
11
+ GLuint createAndCompileShader(const GLchar* source, GLenum type) {
12
+ auto shader = glCreateShader(type);
13
+ glShaderSource(shader, 1, &source, nullptr);
14
+ glCompileShader(shader);
15
+
16
+ GLint compileStatus;
17
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
18
+
19
+ if (!compileStatus) {
20
+ GLint infoLogLength;
21
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
22
+
23
+ if (infoLogLength > 0) {
24
+ std::unique_ptr<GLchar[]> infoLogBuffer(new GLchar[infoLogLength]);
25
+ glGetShaderInfoLog(shader, infoLogLength, nullptr, infoLogBuffer.get());
26
+
27
+ std::string errorMessage("Failed to compile shader with error message:\n");
28
+ errorMessage += infoLogBuffer.get();
29
+ throw std::runtime_error(errorMessage);
30
+ }
31
+
32
+ glDeleteShader(shader);
33
+ }
34
+
35
+ return shader;
36
+ }
37
+
38
+ GLuint createShaderFromFile(const std::string& path, GLenum type) {
39
+ std::ifstream file(path);
40
+ if (!file.is_open()) {
41
+ throw std::runtime_error("Failed to open shader-file: " + path);
42
+ }
43
+
44
+ std::stringstream buffer;
45
+ buffer << file.rdbuf();
46
+ return createAndCompileShader(buffer.str().c_str(), type);
47
+ }
48
+
49
+ GLuint createAndLinkProgram(GLuint vertexShader, GLuint fragmentShader) {
50
+ auto program = glCreateProgram();
51
+ glAttachShader(program, vertexShader);
52
+ glAttachShader(program, fragmentShader);
53
+ glLinkProgram(program);
54
+
55
+ GLint linkStatus;
56
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
57
+
58
+ if (!linkStatus) {
59
+ GLint infoLogLength;
60
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
61
+
62
+ std::unique_ptr<GLchar[]> infoLogBuffer(new GLchar[infoLogLength]);
63
+ glGetProgramInfoLog(program, infoLogLength, nullptr, infoLogBuffer.get());
64
+ glDeleteProgram(program);
65
+
66
+ std::string errorMessage("Failed to link program with error message:\n");
67
+ errorMessage += infoLogBuffer.get();
68
+ throw std::runtime_error(errorMessage);
69
+ }
70
+
71
+ glValidateProgram(program);
72
+
73
+ GLint validateStatus;
74
+ glGetProgramiv(program, GL_VALIDATE_STATUS, &validateStatus);
75
+
76
+ if (!validateStatus) {
77
+ GLint infoLogLength;
78
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
79
+
80
+ std::unique_ptr<GLchar[]> infoLogBuffer(new GLchar[infoLogLength]);
81
+ glGetProgramInfoLog(program, infoLogLength, nullptr, infoLogBuffer.get());
82
+ glDeleteProgram(program);
83
+
84
+ std::string errorMessage("Failed to validate program with error message:\n");
85
+ errorMessage += infoLogBuffer.get();
86
+ throw std::runtime_error(errorMessage);
87
+ }
88
+
89
+ return program;
90
+ }
91
+
92
+ GLuint createTextureFromFile(const std::string& path, bool generateMipMaps, bool srgb) {
93
+ static const GLint channelToFormat[] = {
94
+ GL_R8, GL_RG8, GL_RGB8, GL_RGBA8
95
+ };
96
+
97
+ Image image(path);
98
+ GLint format = channelToFormat[image.getNumChannels() - 1];
99
+ GLenum textureFormat;
100
+ GLenum textureFormatType = GL_UNSIGNED_BYTE;
101
+
102
+ switch (format) {
103
+ case GL_R8: textureFormat = GL_RED; break;
104
+ case GL_RG8: textureFormat = GL_RG; break;
105
+ case GL_RGB8: textureFormat = GL_RGB; break;
106
+ case GL_RGBA8: textureFormat = GL_RGBA; break;
107
+ }
108
+
109
+ if (srgb && textureFormat == GL_RGB8) {
110
+ format = GL_SRGB8;
111
+ }
112
+ else if (srgb && textureFormat == GL_RGBA8) {
113
+ format = GL_SRGB8_ALPHA8;
114
+ }
115
+
116
+ if (!textureFormat || !textureFormatType) {
117
+ throw std::runtime_error("invalid texture format");
118
+ }
119
+
120
+ GLuint texture;
121
+ glGenTextures(1, &texture);
122
+ glBindTexture(GL_TEXTURE_2D, texture);
123
+ glTexImage2D(GL_TEXTURE_2D, 0, format, image.getWidth(), image.getHeight(), 0,
124
+ textureFormat, textureFormatType, image.getImage());
125
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
126
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
127
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, generateMipMaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
128
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
129
+
130
+ if (generateMipMaps) {
131
+ glGenerateMipmap(GL_TEXTURE_2D);
132
+ }
133
+
134
+ return texture;
135
+ }
136
+
137
+ bool isExtensionSupported(const std::string& name) {
138
+ int numExtensions;
139
+ glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
140
+
141
+ for(int i = 0; i < numExtensions; i++) {
142
+ const GLubyte* extStr = glGetStringi(GL_EXTENSIONS, i);
143
+ if (strcmp(reinterpret_cast<const char*>(extStr), name.c_str()) == 0 ){
144
+ return true;
145
+ }
146
+ }
147
+
148
+ return false;
149
+ }
150
+ }
0 commit comments