-
Notifications
You must be signed in to change notification settings - Fork 0
/
Shader.C
132 lines (102 loc) · 3 KB
/
Shader.C
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <GL/glew.h>
#include "Shader.h"
#include <cstdio>
#include <vector>
#include "glsw.h"
using std::vector;
Shader::Shader()
: _program(0)
{}
Shader::~Shader()
{
del();
}
void Shader::compile(const char *vs, const char *gs, const char *fs)
{
vector<GLuint> objects;
// Clean up any existing shader program.
del();
// Compile shader objects.
objects.push_back(shaderObj(GL_VERTEX_SHADER, vs));
if (gs) objects.push_back(shaderObj(GL_GEOMETRY_SHADER, gs));
objects.push_back(shaderObj(GL_FRAGMENT_SHADER, fs));
// Create shader program, attach objects, and flag objects for deletion.
_program = glCreateProgram();
vector<GLuint>::iterator itr = objects.begin();
for ( ; itr != objects.end(); ++itr) {
glAttachShader(_program, *itr);
glDeleteShader(*itr);
}
}
void Shader::link()
{
// Link the provided shader objects into a shader program.
glLinkProgram(_program);
// Test for failure. Log an error if so.
GLint status;
glGetProgramiv (_program, GL_LINK_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetProgramiv(_program, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(_program, infoLogLength, NULL, strInfoLog);
fprintf(stderr, "Linker failure: %s\n\n", strInfoLog);
delete [] strInfoLog;
}
}
void Shader::del()
{
// Clean up the shader program.
if (glIsProgram(_program))
glDeleteProgram(_program);
_program = 0;
}
bool Shader::ok() const
{
return glIsProgram(_program);
}
GLuint Shader::prog() const
{
return _program;
}
Shader::operator const GLuint &() const
{
return _program;
}
GLuint Shader::shaderObj(GLenum shaderType, const char *shaderName) const
{
glswInit();
// Load shader program text.
glswSetPath("./shaders/", ".glsl");
const char *shaderText = glswGetShader(shaderName);
if (!shaderText) {
fprintf(stderr, "%s\n", glswGetError());
glswShutdown();
return 0;
}
// Compile the provided shader text into a shader object.
GLuint shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &shaderText, NULL);
glCompileShader(shader);
// Test for failure. Log an error if so.
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
GLint infoLogLength;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog);
const char *strShaderType = NULL;
switch(shaderType) {
case GL_VERTEX_SHADER: strShaderType = "vertex"; break;
case GL_GEOMETRY_SHADER: strShaderType = "geometry"; break;
case GL_FRAGMENT_SHADER: strShaderType = "fragment"; break;
}
fprintf(stderr, "Compilation error in %s shader named \"%s\":\n%s\n",
strShaderType, shaderName, strInfoLog);
delete [] strInfoLog;
}
// Return the compiled shader object.
glswShutdown();
return shader;
}