mirror of https://github.com/mosra/magnum.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
3.8 KiB
137 lines
3.8 KiB
/* |
|
Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
This file is part of Magnum. |
|
|
|
Magnum is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU Lesser General Public License version 3 |
|
only, as published by the Free Software Foundation. |
|
|
|
Magnum is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU Lesser General Public License version 3 for more details. |
|
*/ |
|
|
|
#include "Shader.h" |
|
|
|
#include <fstream> |
|
|
|
#define COMPILER_MESSAGE_MAX_LENGTH 1024 |
|
|
|
/* libgles-omap3-dev_4.03.00.02-r15.6 on BeagleBoard/Ångström linux 2011.3 doesn't have GLchar */ |
|
#ifdef MAGNUM_TARGET_GLES |
|
typedef char GLchar; |
|
#endif |
|
|
|
using namespace std; |
|
|
|
namespace Magnum { |
|
|
|
Shader::Shader(Shader&& other): _type(other._type), _state(other._state), sources(other.sources), shader(other.shader) { |
|
other.shader = 0; |
|
} |
|
|
|
Shader& Shader::operator=(Shader&& other) { |
|
glDeleteShader(shader); |
|
|
|
_type = other._type; |
|
_state = other._state; |
|
sources = other.sources; |
|
shader = other.shader; |
|
|
|
other.shader = 0; |
|
|
|
return *this; |
|
} |
|
|
|
bool Shader::addFile(const std::string& filename) { |
|
/* Open file */ |
|
ifstream file(filename.c_str()); |
|
if(!file.good()) { |
|
file.close(); |
|
|
|
Error() << "Shader file " << '\'' + filename + '\'' << " cannot be opened."; |
|
return false; |
|
} |
|
|
|
/* Get size of shader and initialize buffer */ |
|
file.seekg(0, ios::end); |
|
size_t size = file.tellg(); |
|
char* source = new char[size+1]; |
|
source[size] = '\0'; |
|
|
|
/* Read data, close */ |
|
file.seekg(0, ios::beg); |
|
file.read(source, size); |
|
file.close(); |
|
|
|
/* Add to sources and free the buffer */ |
|
addSource(source); |
|
delete[] source; |
|
|
|
return true; |
|
} |
|
|
|
GLuint Shader::compile() { |
|
/* Already compiled, return */ |
|
if(_state != State::Initialized) return shader; |
|
|
|
/* Array of sources */ |
|
const GLchar** _sources = new const GLchar*[sources.size()]; |
|
for(size_t i = 0; i != sources.size(); ++i) |
|
_sources[i] = static_cast<const GLchar*>(sources[i].c_str()); |
|
|
|
/* Create shader and set its source */ |
|
glShaderSource(shader, sources.size(), _sources, nullptr); |
|
|
|
/* Compile shader */ |
|
glCompileShader(shader); |
|
delete _sources; |
|
|
|
/* Check compilation status */ |
|
GLint status; |
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status); |
|
|
|
/* Display errors or warnings */ |
|
char message[COMPILER_MESSAGE_MAX_LENGTH]; |
|
glGetShaderInfoLog(shader, COMPILER_MESSAGE_MAX_LENGTH, nullptr, message); |
|
|
|
if(status == GL_FALSE || message[0] != 0) { |
|
Error err; |
|
err << "Shader:"; |
|
|
|
switch(_type) { |
|
case Type::Vertex: err << "vertex"; break; |
|
#ifndef MAGNUM_TARGET_GLES |
|
case Type::Geometry: err << "geometry"; break; |
|
#endif |
|
case Type::Fragment: err << "fragment"; break; |
|
#ifndef MAGNUM_TARGET_GLES |
|
case Type::TessellationControl: err << "tessellation control"; break; |
|
case Type::TessellationEvaluation: err << "tessellation evaluation"; break; |
|
#endif |
|
} |
|
|
|
/* Show error log and delete shader */ |
|
if(status == GL_FALSE) { |
|
err << "shader failed to compile with the following message:\n" |
|
<< message; |
|
|
|
/* Or just warnings, if there are any */ |
|
} else if(message[0] != 0) { |
|
err << "shader was successfully compiled with the following message:\n" |
|
<< message; |
|
} |
|
} |
|
|
|
if(status == GL_FALSE) { |
|
_state = State::Failed; |
|
return 0; |
|
} else { |
|
_state = State::Compiled; |
|
return shader; |
|
} |
|
} |
|
|
|
}
|
|
|