OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
shader.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
21 #include "shader.h"
22 #include "glutil.h"
23 
24 Shader::Shader() : m_id(0), m_attributes(), m_uniforms(), m_shaders()
25 {
26  m_shaders.clear();
27 }
28 
29 bool compile_shader(GLuint shader, GLenum type, const char *source)
30 {
31  const char *src = source;
32  glShaderSource(shader, 1, &src, NULL);
33  glCompileShader(shader);
34  GLint status;
35  glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
36  if (status == GL_FALSE) {
37  GLint length;
38  glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
39  GLchar *info = new GLchar[length];
40  glGetShaderInfoLog(shader, length, NULL, info);
41  LOGE("Error compiling shader: %s\n", info);
42  delete[] info;
43  return false;
44  }
45  return true;
46 }
47 
48 bool link_program(GLuint program, std::vector<GLuint> shaders)
49 {
50  for (unsigned int i = 0; i < shaders.size(); ++i)
51  glAttachShader(program, shaders[i]);
52 
53  glLinkProgram(program);
54 
55  for (unsigned int i = 0; i < shaders.size(); ++i)
56  glDetachShader(program, shaders[i]);
57 
58  GLint status;
59  glGetProgramiv(program, GL_LINK_STATUS, &status);
60  if (status == GL_FALSE) {
61  GLint length;
62  glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
63  GLchar *info = new GLchar[length];
64  glGetProgramInfoLog(program, length, NULL, info);
65  LOGE("Error linking program: %s\n", info);
66  delete[] info;
67  return false;
68  }
69  return true;
70 }
71 
72 bool Shader::load_from_src(const string *sources, GLenum *types, int count)
73 {
74  m_id = glCreateProgram();
75  m_shaders.clear();
76  for (int i = 0; i < count; ++i)
77  {
78  GLuint shader = glCreateShader(types[i]);
79  if (!compile_shader(shader, types[i], sources[i].c_str()))
80  return false;
81  m_shaders.push_back(shader);
82  }
83  return true;
84 }
85 
86 bool Shader::load_from_src(string vs_src, string fs_src)
87 {
88  string sources[] = { vs_src, fs_src };
89  GLenum types[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
90  return load_from_src(sources, types, 2);
91 }
92 
93 bool Shader::load_from_file(const string *paths, GLenum *types, int count)
94 {
95  m_id = glCreateProgram();
96  m_shaders.clear();
97  for (int i = 0; i < count; ++i)
98  {
99  GLuint shader = glCreateShader(types[i]);
100  string src;
101  if (!read_file(paths[i], src))
102  return false;
103  if (!compile_shader(shader, types[i], src.c_str()))
104  return false;
105  m_shaders.push_back(shader);
106  }
107  return true;
108 }
109 
110 bool Shader::load_from_file(string vs_path, string fs_path)
111 {
112  string paths[] = { vs_path, fs_path };
113  GLenum types[] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
114  return load_from_file(paths, types, 2);
115 }
116 
117 bool Shader::link()
118 {
119  return link_program(m_id, m_shaders);
120 }
121 
122 void Shader::dispose()
123 {
124  m_attributes.clear();
125  m_uniforms.clear();
126  for (int i = 0; i < m_shaders.size(); ++i)
127  glDeleteShader(m_shaders[i]);
128  glDeleteProgram(m_id);
129 }
130 
131 void Shader::use()
132 {
133  glUseProgram(m_id);
134 }
135 
136 void Shader::unuse()
137 {
138  glUseProgram(0);
139 }
140 
142 {
143  std::unordered_map<std::string, GLint>::iterator it = m_uniforms.find(name);
144  if(it != m_uniforms.end())
145  {
146  return it->second;
147  }
148  else
149  {
150  GLint location = glGetUniformLocation(m_id, name.c_str());
151  string msg = "Invalid shader uniform [" + name + "]";
152  ASSERT(location >= 0, msg.c_str());
154  return location;
155  }
156 }
157 
158 GLint Shader::get_attribute_location(string name)
159 {
160  std::unordered_map<std::string, GLint>::iterator it = m_attributes.find(name);
161  if(it != m_attributes.end())
162  {
163  return it->second;
164  }
165  else
166  {
167  GLint location = glGetAttribLocation(m_id, name.c_str());
168  string msg = "Invalid shader attribute [" + name + "]";
169  ASSERT(location >= 0, msg.c_str());
171  return location;
172  }
173 }
174 
175 void Shader::set_attribfv(string name, GLsizei num_components,
176  GLsizei stride, GLsizei offset)
177 {
178  GLint loc = get_attribute_location(name);
179  glEnableVertexAttribArray(loc);
180  glVertexAttribPointer(
181  loc,
182  num_components, // in the attribute,
183  GL_FLOAT, // each component is a float,
184  GL_FALSE, // not normalized,
185  stride * sizeof(GLfloat), // the attribs are seperated by this much,
186  (void*)(offset * sizeof(GLfloat)) // beginning at this offset in the array.
187  );
188 }
189 
190 void Shader::unset_attrib(string name)
191 {
192  glDisableVertexAttribArray(get_attribute_location(name));
193 }
194 
195 void Shader::set_uniform(string name, const mat4 &v) { glUniformMatrix4fv(get_uniform_location(name), 1, GL_FALSE, v.value_ptr()); }
196 void Shader::set_uniform(string name, const vec4 &v) { glUniform4f(get_uniform_location(name), v.x, v.y, v.z, v.w); }
197 void Shader::set_uniform(string name, const vec3 &v) { glUniform3f(get_uniform_location(name), v.x, v.y, v.z); }
198 void Shader::set_uniform(string name, const vec2 &v) { glUniform2f(get_uniform_location(name), v.x, v.y); }
199 void Shader::set_uniform(string name, double v) { glUniform1f(get_uniform_location(name), v); }
200 void Shader::set_uniform(string name, float v) { glUniform1f(get_uniform_location(name), v); }
201 void Shader::set_uniform(string name, int v) { glUniform1i(get_uniform_location(name), v); }
202 void Shader::set_uniform(string name, unsigned int v) { glUniform1ui(get_uniform_location(name), v); }
const GLfloat * v
Definition: gl2ext.h:2231
Shader()
Definition: shader.cpp:24
void set_attribfv(string name, GLsizei num_components, GLsizei stride, GLsizei offset)
Definition: shader.cpp:182
Definition: matrix.h:51
Definition: matrix.h:28
bool load_from_file(const string *paths, GLenum *types, int count)
Definition: shader.cpp:93
GLsizei GLenum * sources
Definition: gl2ext.h:136
GLenum GLuint GLintptr offset
Definition: gl2ext.h:629
std::vector< GLuint > m_shaders
Definition: shader.h:61
float z
Definition: matrix.h:55
Definition: matrix.h:75
GLsizei const GLuint * paths
Definition: gl2ext.h:2476
GLenum GLenum GLsizei count
Definition: gl2ext.h:133
const float * value_ptr() const
Definition: matrix.h:150
bool read_file(const std::string &path, std::string &dest)
Definition: glutil.cpp:106
bool link_program(GLuint program, std::vector< GLuint > shaders)
Definition: shader.cpp:48
bool load_from_src(const string *sources, GLenum *types, int count)
Definition: shader.cpp:72
bool compile_shader(GLuint shader, GLenum type, const char *source)
Definition: shader.cpp:29
GLsizei GLsizei GLchar * source
Definition: gl2ext.h:877
void dispose()
Definition: shader.cpp:129
std::unordered_map< string, GLint > m_attributes
Definition: shader.h:58
bool link()
Definition: shader.cpp:124
GLint location
Definition: gl2ext.h:180
void set_uniform(string name, const mat4 &v)
Definition: shader.cpp:202
GLsizei GLenum GLenum * types
Definition: gl2ext.h:136
float y
Definition: matrix.h:31
GLuint m_id
Definition: shader.h:60
float w
Definition: matrix.h:80
void unuse()
Definition: shader.cpp:143
float x
Definition: matrix.h:53
float y
Definition: matrix.h:54
GLenum type
Definition: gl2ext.h:133
GLint get_attribute_location(string name)
Definition: shader.cpp:165
GLuint name
Definition: gl2ext.h:139
GLint get_uniform_location(string name)
Definition: shader.cpp:148
void use()
Definition: shader.cpp:138
GLenum GLuint GLenum GLsizei length
Definition: gl2ext.h:134
Definition: matrix.h:104
const void GLsizei GLsizei stride
Definition: gl2ext.h:1335
float z
Definition: matrix.h:79
#define LOGE(...)
Definition: AstcTextures.h:30
#define ASSERT(x, s)
Definition: common.h:45
float x
Definition: matrix.h:30
typedef GLfloat(GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC)(GLuint path
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLuint program
Definition: gl2ext.h:1475
std::unordered_map< string, GLint > m_uniforms
Definition: shader.h:59
float x
Definition: matrix.h:77
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
void unset_attrib(string name)
Definition: shader.cpp:197
float y
Definition: matrix.h:78
GLenum src
Definition: gl2ext.h:304