Browse Source

Reworked and cleaned up shader classes.

Removed unneeded member variables, removed wrong assertions and wrong
documentation (most of the state they were fobidding is actually valid).
Retrieving shader log with full length, properly printing non-error
messages to debug output.

Each shader must now be compiled explicitly using compile(), which is
slightly better for the user as it is possible to check compile status
instead of having it weirdly hidden inside attachShader(). link() now
also returns linking status.
pull/278/head
Vladimír Vondruš 13 years ago
parent
commit
6904b38b13
  1. 56
      src/AbstractShaderProgram.cpp
  2. 73
      src/AbstractShaderProgram.h
  3. 124
      src/Shader.cpp
  4. 54
      src/Shader.h
  5. 20
      src/Shaders/DistanceFieldVector.cpp
  6. 20
      src/Shaders/Flat.cpp
  7. 26
      src/Shaders/MeshVisualizer.cpp
  8. 20
      src/Shaders/Phong.cpp
  9. 20
      src/Shaders/Vector.cpp
  10. 20
      src/Shaders/VertexColor.cpp
  11. 20
      src/TextureTools/DistanceField.cpp

56
src/AbstractShaderProgram.cpp

@ -30,8 +30,6 @@
#include "Implementation/ShaderProgramState.h"
#include "Implementation/State.h"
#define LINKER_MESSAGE_MAX_LENGTH 1024
namespace Magnum {
AbstractShaderProgram::Uniform1fvImplementation AbstractShaderProgram::uniform1fvImplementation = &AbstractShaderProgram::uniformImplementationDefault;
@ -88,67 +86,58 @@ Int AbstractShaderProgram::maxSupportedVertexAttributeCount() {
return value;
}
AbstractShaderProgram::AbstractShaderProgram(): _id(glCreateProgram()) {}
AbstractShaderProgram::~AbstractShaderProgram() {
/* Remove current usage from the state */
GLuint& current = Context::current()->state()->shaderProgram->current;
if(current == _id) current = 0;
glDeleteProgram(_id);
if(_id) glDeleteProgram(_id);
}
bool AbstractShaderProgram::use() {
if(state != Linked) return false;
void AbstractShaderProgram::use() {
/* Use only if the program isn't already in use */
GLuint& current = Context::current()->state()->shaderProgram->current;
if(current != _id) glUseProgram(current = _id);
return true;
}
bool AbstractShaderProgram::attachShader(Shader& shader) {
GLuint _shader = shader.compile();
if(!_shader) return false;
glAttachShader(_id, _shader);
return true;
void AbstractShaderProgram::attachShader(Shader& shader) {
glAttachShader(_id, shader.id());
}
void AbstractShaderProgram::bindAttributeLocation(UnsignedInt location, const std::string& name) {
CORRADE_ASSERT(state == Initialized, "AbstractShaderProgram: attribute cannot be bound after linking.", );
glBindAttribLocation(_id, location, name.c_str());
}
#ifndef MAGNUM_TARGET_GLES
void AbstractShaderProgram::bindFragmentDataLocation(UnsignedInt location, const std::string& name) {
CORRADE_ASSERT(state == Initialized, "AbstractShaderProgram: fragment data location cannot be bound after linking.", );
glBindFragDataLocation(_id, location, name.c_str());
}
void AbstractShaderProgram::bindFragmentDataLocationIndexed(UnsignedInt location, UnsignedInt index, const std::string& name) {
CORRADE_ASSERT(state == Initialized, "AbstractShaderProgram: fragment data location cannot be bound after linking.", );
glBindFragDataLocationIndexed(_id, location, index, name.c_str());
}
#endif
void AbstractShaderProgram::link() {
/* Already compiled or failed, exit */
if(state != Initialized) return;
bool AbstractShaderProgram::link() {
/* Link shader program */
glLinkProgram(_id);
/* Check link status */
GLint status;
glGetProgramiv(_id, GL_LINK_STATUS, &status);
/* Display errors or warnings */
char message[LINKER_MESSAGE_MAX_LENGTH];
glGetProgramInfoLog(_id, LINKER_MESSAGE_MAX_LENGTH, nullptr, message);
GLint success, logLength;
glGetProgramiv(_id, GL_LINK_STATUS, &success);
glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength);
/* Error or warning message. The string is returned null-terminated, scrap
the \0 at the end afterwards */
std::string message(logLength, '\n');
if(!message.empty()) {
glGetProgramInfoLog(_id, message.size(), nullptr, &message[0]);
message.resize(logLength-1);
}
/* Show error log and delete shader */
if(status == GL_FALSE) {
if(!success) {
Error out;
out.setFlag(Debug::NewLineAtTheEnd, false);
out.setFlag(Debug::SpaceAfterEachValue, false);
@ -156,7 +145,7 @@ void AbstractShaderProgram::link() {
<< message;
/* Or just warnings, if there are any */
} else if(message[0] != 0) {
} else if(!message.empty()) {
Debug out;
out.setFlag(Debug::NewLineAtTheEnd, false);
out.setFlag(Debug::SpaceAfterEachValue, false);
@ -164,13 +153,10 @@ void AbstractShaderProgram::link() {
<< message;
}
state = status == GL_FALSE ? Failed : Linked;
return success;
}
Int AbstractShaderProgram::uniformLocation(const std::string& name) {
/** @todo What if linking just failed (not programmer error?) */
CORRADE_ASSERT(state == Linked, "AbstractShaderProgram: uniform location cannot be retrieved before linking.", -1);
GLint location = glGetUniformLocation(_id, name.c_str());
if(location == -1)
Warning() << "AbstractShaderProgram: location of uniform \'" + name + "\' cannot be retrieved!";

73
src/AbstractShaderProgram.h

@ -35,8 +35,6 @@
#include "OpenGL.h"
#include "magnumVisibility.h"
/** @todo early asserts (no bool returns?) */
namespace Magnum {
namespace Implementation {
@ -84,12 +82,19 @@ Int TransformationUniform = 0,
gets uniform locations, for example:
@code
MyShader() {
// Load shaders from file and attach them to the program
attachShader(Shader(Version::GL430, Shader::Type::Vertex).attachFile("PhongShader.vert"));
attachShader(Shader(Version::GL430, Shader::Type::Fragment).attachFile("PhongShader.frag"));
// Link
link();
// Load shaders, compile them and attach them to the program
Shader vert(Version::GL430, Shader::Type::Vertex);
vert.attachFile("PhongShader.vert");
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
Shader frag(Version::GL430, Shader::Type::Fragment);
frag.attachFile("PhongShader.vert");
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
// Link the program together
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
}
@endcode
- **Uniform setting functions**, which will provide public interface for
@ -521,9 +526,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* Creates one OpenGL shader program.
* @see @fn_gl{CreateProgram}
*/
inline explicit AbstractShaderProgram(): state(Initialized) {
_id = glCreateProgram();
}
explicit AbstractShaderProgram();
/**
* @brief Destructor
@ -535,12 +538,10 @@ class MAGNUM_EXPORT AbstractShaderProgram {
/**
* @brief Use shader for rendering
* @return False if the program wasn't successfully linked, true
* otherwise.
*
* @see @fn_gl{UseProgram}
*/
bool use();
void use();
protected:
#ifndef MAGNUM_TARGET_GLES2
@ -548,8 +549,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* @brief Allow retrieving program binary
*
* Initially disabled.
* @note This function should be called after attachShader() calls and
* before link().
* @see @fn_gl{ProgramParameter} with @def_gl{PROGRAM_BINARY_RETRIEVABLE_HINT}
* @requires_gl41 %Extension @extension{ARB,get_program_binary}
* @requires_gles30 Always allowed in OpenGL ES 2.0.
@ -563,8 +562,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* @brief Allow the program to be bound to individual pipeline stages
*
* Initially disabled.
* @note This function should be called after attachShader() calls and
* before link().
* @see @fn_gl{ProgramParameter} with @def_gl{PROGRAM_SEPARABLE}
* @requires_gl41 %Extension @extension{ARB,separate_shader_objects}
* @requires_es_extension %Extension @es_extension{EXT,separate_shader_objects}
@ -579,20 +576,11 @@ class MAGNUM_EXPORT AbstractShaderProgram {
}
/**
* @brief Load shader
* @return False if the shader wasn't successfully compiled, true
* otherwise.
* @brief Attach shader
*
* Compiles the shader, if it is not already, and prepares it for
* linking.
* @see Shader::compile(), @fn_gl{AttachShader}
* @fn_gl{AttachShader}
*/
bool attachShader(Shader& shader);
/** @overload */
inline bool attachShader(Shader&& shader) {
return attachShader(shader);
}
void attachShader(Shader& shader);
/**
* @brief Bind attribute to given location
@ -601,8 +589,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
*
* Binds attribute to location which is used later for binding vertex
* buffers.
* @note This function should be called after attachShader() calls and
* before link().
* @deprecated Preferred usage is to specify attribute location
* explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-attribute-location "class documentation"
@ -621,8 +607,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* Binds fragment data to location which is used later for framebuffer
* operations. See also Framebuffer::BlendFunction for more
* information about using color input index.
* @note This function should be called after attachShader() calls and
* before link().
* @deprecated Preferred usage is to specify attribute location
* explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-attribute-location "class documentation"
@ -652,18 +636,19 @@ class MAGNUM_EXPORT AbstractShaderProgram {
/**
* @brief Link the shader
*
* Binds previously specified attributes to given indexes and links the
* shader program together.
* Returns `false` if linking failed, `true` otherwise. Compiler
* message (if any) is printed to error output. All attached shaders
* must be explicitly compiled with Shader::compile() before linking.
* @see @fn_gl{LinkProgram}, @fn_gl{GetProgram} with
* @def_gl{LINK_STATUS}, @fn_gl{GetProgramInfoLog}
* @def_gl{LINK_STATUS} and @def_gl{INFO_LOG_LENGTH},
* @fn_gl{GetProgramInfoLog}
*/
void link();
bool link();
/**
* @brief Get uniform location
* @param name Uniform name
*
* @note This function should be called after link().
* @deprecated Preferred usage is to specify uniform location
* explicitly in the shader instead of using this function. See
* @ref AbstractShaderProgram-uniform-location "class documentation"
@ -717,8 +702,7 @@ class MAGNUM_EXPORT AbstractShaderProgram {
* @extension{EXT,direct_state_access} is available, the shader is
* marked for use before the operation.
* @see setUniform(Int, const T&), @fn_gl{UseProgram}, @fn_gl{Uniform}
* or `glProgramUniform()` from
* @extension{ARB,separate_shader_objects}/@extension{EXT,direct_state_access}.
* or @fn_gl{ProgramUniform}/@fn_gl_extension{ProgramUniform,EXT,direct_state_access}.
*/
inline void setUniform(Int location, UnsignedInt count, const Float* values) {
(this->*uniform1fvImplementation)(location, count, values);
@ -984,12 +968,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
#endif
private:
enum State {
Initialized,
Linked,
Failed
};
static void MAGNUM_LOCAL initializeContextBasedFunctionality(Context* context);
typedef void(AbstractShaderProgram::*Uniform1fvImplementation)(GLint, GLsizei, const GLfloat*);
@ -1155,7 +1133,6 @@ class MAGNUM_EXPORT AbstractShaderProgram {
#endif
GLuint _id;
State state;
};
#ifdef DOXYGEN_GENERATING_OUTPUT

124
src/Shader.cpp

@ -27,8 +27,6 @@
#include <fstream>
#include <Utility/Assert.h>
#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;
@ -36,8 +34,27 @@ typedef char GLchar;
namespace Magnum {
Shader::Shader(Version version, Type type): _type(type), _state(State::Initialized), shader(0) {
shader = glCreateShader(static_cast<GLenum>(_type));
namespace {
std::string shaderName(const Shader::Type type) {
switch(type) {
case Shader::Type::Vertex: return "vertex";
#ifndef MAGNUM_TARGET_GLES
case Shader::Type::Geometry: return "geometry";
case Shader::Type::TessellationControl: return "tessellation control";
case Shader::Type::TessellationEvaluation: return "tessellation evaluation";
case Shader::Type::Compute: return "compute";
#endif
case Shader::Type::Fragment: return "fragment";
}
CORRADE_ASSERT_UNREACHABLE();
}
}
Shader::Shader(const Version version, const Type type): _type(type), _id(0) {
_id = glCreateShader(static_cast<GLenum>(_type));
switch(version) {
#ifndef MAGNUM_TARGET_GLES
@ -62,32 +79,34 @@ Shader::Shader(Version version, Type type): _type(type), _state(State::Initializ
CORRADE_ASSERT_UNREACHABLE();
}
Shader::Shader(Shader&& other): _type(other._type), _state(other._state), sources(std::move(other.sources)), shader(other.shader) {
other.shader = 0;
Shader::Shader(Shader&& other): _type(other._type), _id(other._id), sources(std::move(other.sources)) {
other._id = 0;
}
Shader::~Shader() {
if(_id) glDeleteShader(_id);
}
Shader& Shader::operator=(Shader&& other) {
glDeleteShader(shader);
glDeleteShader(_id);
_type = other._type;
_state = other._state;
sources = std::move(other.sources);
shader = other.shader;
_id = other._id;
other.shader = 0;
other._id = 0;
return *this;
}
Shader& Shader::addSource(std::string source) {
if(source.empty()) return *this;
if(_state == State::Initialized) {
if(!source.empty()) {
/* Fix line numbers, so line 41 of third added file is marked as 3(41).
Source 0 is the #version string added in constructor. */
sources.push_back("#line 1 " + std::to_string(sources.size()) + '\n');
sources.push_back(std::move(source));
}
return *this;
}
@ -111,9 +130,8 @@ Shader& Shader::addFile(const std::string& filename) {
return *this;
}
GLuint Shader::compile() {
/* Already compiled, return */
if(_state != State::Initialized) return shader;
bool Shader::compile() {
CORRADE_ASSERT(sources.size() > 1, "Shader::compile(): no files added", false);
/* Array of sources */
const GLchar** _sources = new const GLchar*[sources.size()];
@ -121,57 +139,45 @@ GLuint Shader::compile() {
_sources[i] = static_cast<const GLchar*>(sources[i].c_str());
/* Create shader and set its source */
glShaderSource(shader, sources.size(), _sources, nullptr);
glShaderSource(_id, sources.size(), _sources, nullptr);
/* Compile shader */
glCompileShader(shader);
glCompileShader(_id);
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;
case Type::TessellationControl: err << "tessellation control"; break;
case Type::TessellationEvaluation: err << "tessellation evaluation"; break;
case Type::Compute: err << "compute"; break;
#endif
case Type::Fragment: err << "fragment"; break;
}
err.setFlag(Debug::NewLineAtTheEnd, false);
err.setFlag(Debug::SpaceAfterEachValue, false);
/* 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;
}
GLint success, logLength;
glGetShaderiv(_id, GL_COMPILE_STATUS, &success);
glGetShaderiv(_id, GL_INFO_LOG_LENGTH, &logLength);
/* Error or warning message. The string is returned null-terminated, scrap
the \0 at the end afterwards */
std::string message(logLength, '\0');
if(!message.empty()) {
glGetShaderInfoLog(_id, message.size(), nullptr, &message[0]);
message.resize(logLength-1);
}
if(status == GL_FALSE) {
_state = State::Failed;
return 0;
} else {
_state = State::Compiled;
return shader;
/* Show error log */
if(!success) {
Error out;
out.setFlag(Debug::NewLineAtTheEnd, false);
out.setFlag(Debug::SpaceAfterEachValue, false);
out << "Shader:" << shaderName(_type)
<< " shader failed to compile with the following message:\n"
<< message;
/* Or just message, if any */
} else if(!message.empty()) {
Error out;
out.setFlag(Debug::NewLineAtTheEnd, false);
out.setFlag(Debug::SpaceAfterEachValue, false);
out << "Shader:" << shaderName(_type)
<< " shader was successfully compiled with the following message:\n"
<< message;
}
return success;
}
}

54
src/Shader.h

@ -41,8 +41,7 @@ namespace Magnum {
/**
@brief %Shader
Allows loading and compiling the shader from file or directly from source
string. See AbstractShaderProgram for more information.
See AbstractShaderProgram for more information.
*/
class MAGNUM_EXPORT Shader {
Shader(const Shader&) = delete;
@ -86,13 +85,6 @@ class MAGNUM_EXPORT Shader {
Fragment = GL_FRAGMENT_SHADER /**< Fragment shader */
};
/** @brief %Shader state */
enum class State {
Initialized, /**< %Shader is loaded */
Compiled, /**< %Shader is compiled */
Failed /**< Compilation failed */
};
/**
* @brief Constructor
* @param version Target version
@ -110,7 +102,7 @@ class MAGNUM_EXPORT Shader {
* Deletes associated OpenGL shader.
* @see @fn_gl{DeleteShader}
*/
inline ~Shader() { if(shader) glDeleteShader(shader); }
~Shader();
/** @brief Move constructor */
Shader(Shader&& other);
@ -118,28 +110,17 @@ class MAGNUM_EXPORT Shader {
/** @brief Move assignment operator */
Shader& operator=(Shader&& other);
/**
* @brief %Shader type
*
* Set in constructor.
*/
inline Type type() const { return _type; }
/**
* @brief Compilation state
*
* Changes after calling compile().
*/
inline State state() const { return _state; }
/** @brief OpenGL shader ID */
inline GLuint id() const { return _id; }
/**
* @brief Add shader source
* @param source String with shader source
* @return Reference to self (for method chaining)
*
* If the shader is not compiled already, adds given source to source
* list. Note that it is possible to compile shader from more than
* one source. If passed string is empty, the function does nothing.
* Adds given source to source list, preceeded with @c \#line directive
* marking first line of the source as `n(1)` where n is number of
* added source. If passed string is empty, the function does nothing.
* @see addFile()
*/
Shader& addSource(std::string source);
@ -149,32 +130,27 @@ class MAGNUM_EXPORT Shader {
* @param filename Name of source file to read from
* @return Reference to self (for method chaining)
*
* The file must exist and must be readable.
* @see addSource()
* The file must exist and must be readable. Calls addSource() with
* the contents.
*/
Shader& addFile(const std::string& filename);
/**
* @brief Compile shader
* @return Compiled shader or 0 if compilation failed.
*
* If the shader has any sources present and hasn't been compiled
* before, it tries to compile it. If compilation fails or no sources
* are present, returns 0. If the shader was compiled already, returns
* already existing shader.
* @see state(), @fn_gl{ShaderSource}, @fn_gl{CompileShader},
* @fn_gl{GetShader} with @def_gl{COMPILE_STATUS},
* Returns `false` if compilation failed, `true` otherwise. Compiler
* message (if any) is printed to error output.
* @see @fn_gl{ShaderSource}, @fn_gl{CompileShader}, @fn_gl{GetShader}
* with @def_gl{COMPILE_STATUS} and @def_gl{INFO_LOG_LENGTH},
* @fn_gl{GetShaderInfoLog}
*/
GLuint compile();
bool compile();
private:
Type _type;
State _state;
GLuint _id;
std::vector<std::string> sources;
GLuint shader;
};
}

20
src/Shaders/DistanceFieldVector.cpp

@ -47,13 +47,17 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
AbstractShaderProgram::attachShader(Shader(v, Shader::Type::Vertex)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())));
AbstractShaderProgram::attachShader(Shader(v, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldVector.frag")));
Shader frag(v, Shader::Type::Vertex);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag);
Shader vert(v, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldVector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
@ -66,7 +70,7 @@ template<UnsignedInt dimensions> DistanceFieldVector<dimensions>::DistanceFieldV
AbstractShaderProgram::bindAttributeLocation(AbstractVector<dimensions>::TextureCoordinates::Location, "textureCoordinates");
}
AbstractShaderProgram::link();
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())

20
src/Shaders/Flat.cpp

@ -46,13 +46,17 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(): transformationProject
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
attachShader(Shader(v, Shader::Type::Vertex)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())));
attachShader(Shader(v, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Flat.frag")));
Shader frag(v, Shader::Type::Vertex);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
Shader vert(v, Shader::Type::Fragment);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Flat.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
@ -64,7 +68,7 @@ template<UnsignedInt dimensions> Flat<dimensions>::Flat(): transformationProject
bindAttributeLocation(Position::Location, "position");
}
link();
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())

26
src/Shaders/MeshVisualizer.cpp

@ -39,19 +39,27 @@ MeshVisualizer::MeshVisualizer(const Flags flags): flags(flags), transformationP
Corrade::Utility::Resource rs("MagnumShaders");
attachShader(Shader(Version::GL330, Shader::Type::Vertex)
.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
Shader vert(Version::GL330, Shader::Type::Vertex);
vert.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("MeshVisualizer.vert")));
.addSource(rs.get("MeshVisualizer.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
if(flags & Flag::Wireframe) attachShader(Shader(Version::GL330, Shader::Type::Geometry)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("MeshVisualizer.geom")));
if(flags & Flag::Wireframe) {
Shader geom(Version::GL330, Shader::Type::Geometry);
geom.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("MeshVisualizer.geom"));
CORRADE_INTERNAL_ASSERT_OUTPUT(geom.compile());
attachShader(geom);
}
attachShader(Shader(Version::GL330, Shader::Type::Fragment)
.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
Shader frag(Version::GL330, Shader::Type::Fragment);
frag.addSource(flags & Flag::Wireframe ? "#define WIREFRAME_RENDERING\n" : "")
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("MeshVisualizer.frag")));
.addSource(rs.get("MeshVisualizer.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
link();
}

20
src/Shaders/Phong.cpp

@ -40,13 +40,17 @@ Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), norm
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
attachShader(Shader(v, Shader::Type::Vertex)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.vert")));
attachShader(Shader(v, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.frag")));
Shader vert(v, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
Shader frag(v, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Phong.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
@ -59,7 +63,7 @@ Phong::Phong(): transformationMatrixUniform(0), projectionMatrixUniform(1), norm
bindAttributeLocation(Normal::Location, "normal");
}
link();
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())

20
src/Shaders/Vector.cpp

@ -47,13 +47,17 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
AbstractShaderProgram::attachShader(Shader(v, Shader::Type::Vertex)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())));
AbstractShaderProgram::attachShader(Shader(v, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Vector.frag")));
Shader vert(v, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
AbstractShaderProgram::attachShader(vert);
Shader frag(v, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("Vector.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
AbstractShaderProgram::attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
@ -66,7 +70,7 @@ template<UnsignedInt dimensions> Vector<dimensions>::Vector(): transformationPro
AbstractShaderProgram::bindAttributeLocation(AbstractVector<dimensions>::TextureCoordinates::Location, "textureCoordinates");
}
AbstractShaderProgram::link();
CORRADE_INTERNAL_ASSERT_OUTPUT(AbstractShaderProgram::link());
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())

20
src/Shaders/VertexColor.cpp

@ -46,13 +46,17 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
Version v = Context::current()->supportedVersion({Version::GLES300, Version::GLES200});
#endif
attachShader(Shader(v, Shader::Type::Vertex)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>())));
attachShader(Shader(v, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("VertexColor.frag")));
Shader vert(v, Shader::Type::Vertex);
vert.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get(vertexShaderName<dimensions>()));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
Shader frag(v, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("VertexColor.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_attrib_location>() ||
@ -65,7 +69,7 @@ template<UnsignedInt dimensions> VertexColor<dimensions>::VertexColor(): transfo
bindAttributeLocation(Color::Location, "color");
}
link();
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
#ifndef MAGNUM_TARGET_GLES
if(!Context::current()->isExtensionSupported<Extensions::GL::ARB::explicit_uniform_location>())

20
src/TextureTools/DistanceField.cpp

@ -70,14 +70,18 @@ DistanceFieldShader::DistanceFieldShader() {
Corrade::Utility::Resource rs("MagnumTextureTools");
attachShader(Shader(Version::GL330, Shader::Type::Vertex)
.addSource(rs.get("DistanceFieldShader.vert")));
attachShader(Shader(Version::GL330, Shader::Type::Fragment)
.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldShader.frag")));
link();
Shader vert(Version::GL330, Shader::Type::Vertex);
vert.addSource(rs.get("DistanceFieldShader.vert"));
CORRADE_INTERNAL_ASSERT_OUTPUT(vert.compile());
attachShader(vert);
Shader frag(Version::GL330, Shader::Type::Fragment);
frag.addSource(rs.get("compatibility.glsl"))
.addSource(rs.get("DistanceFieldShader.frag"));
CORRADE_INTERNAL_ASSERT_OUTPUT(frag.compile());
attachShader(frag);
CORRADE_INTERNAL_ASSERT_OUTPUT(link());
}
}

Loading…
Cancel
Save