summaryrefslogtreecommitdiff
path: root/src/SFML/Graphics/Shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/SFML/Graphics/Shader.cpp')
-rw-r--r--src/SFML/Graphics/Shader.cpp751
1 files changed, 637 insertions, 114 deletions
diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp
index ff6a6ff..8010ff2 100644
--- a/src/SFML/Graphics/Shader.cpp
+++ b/src/SFML/Graphics/Shader.cpp
@@ -1,7 +1,7 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
-// Copyright (C) 2007-2015 Laurent Gomila (laurent@sfml-dev.org)
+// Copyright (C) 2007-2016 Laurent Gomila (laurent@sfml-dev.org)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
@@ -28,6 +28,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Graphics/Shader.hpp>
#include <SFML/Graphics/Texture.hpp>
+#include <SFML/Graphics/Transform.hpp>
+#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/InputStream.hpp>
@@ -119,7 +121,21 @@ namespace
// Create a temporary context in case the user checks
// before a GlResource is created, thus initializing
// the shared context
- sf::Context context;
+ if (!sf::Context::getActiveContext())
+ {
+ sf::Context context;
+
+ // Make sure that extensions are initialized
+ sf::priv::ensureExtensionsInit();
+
+ bool available = GLEXT_multitexture &&
+ GLEXT_shading_language_100 &&
+ GLEXT_shader_objects &&
+ GLEXT_vertex_shader &&
+ GLEXT_fragment_shader;
+
+ return available;
+ }
// Make sure that extensions are initialized
sf::priv::ensureExtensionsInit();
@@ -132,6 +148,71 @@ namespace
return available;
}
+ bool checkGeometryShadersAvailable()
+ {
+ // Create a temporary context in case the user checks
+ // before a GlResource is created, thus initializing
+ // the shared context
+ sf::Context context;
+
+ // Make sure that extensions are initialized
+ sf::priv::ensureExtensionsInit();
+
+ bool available = checkShadersAvailable() && GLEXT_geometry_shader4;
+
+ return available;
+ }
+
+ // Transforms an array of 2D vectors into a contiguous array of scalars
+ template <typename T>
+ std::vector<T> flatten(const sf::Vector2<T>* vectorArray, std::size_t length)
+ {
+ const std::size_t vectorSize = 2;
+
+ std::vector<T> contiguous(vectorSize * length);
+ for (std::size_t i = 0; i < length; ++i)
+ {
+ contiguous[vectorSize * i] = vectorArray[i].x;
+ contiguous[vectorSize * i + 1] = vectorArray[i].y;
+ }
+
+ return contiguous;
+ }
+
+ // Transforms an array of 3D vectors into a contiguous array of scalars
+ template <typename T>
+ std::vector<T> flatten(const sf::Vector3<T>* vectorArray, std::size_t length)
+ {
+ const std::size_t vectorSize = 3;
+
+ std::vector<T> contiguous(vectorSize * length);
+ for (std::size_t i = 0; i < length; ++i)
+ {
+ contiguous[vectorSize * i] = vectorArray[i].x;
+ contiguous[vectorSize * i + 1] = vectorArray[i].y;
+ contiguous[vectorSize * i + 2] = vectorArray[i].z;
+ }
+
+ return contiguous;
+ }
+
+ // Transforms an array of 4D vectors into a contiguous array of scalars
+ template <typename T>
+ std::vector<T> flatten(const sf::priv::Vector4<T>* vectorArray, std::size_t length)
+ {
+ const std::size_t vectorSize = 4;
+
+ std::vector<T> contiguous(vectorSize * length);
+ for (std::size_t i = 0; i < length; ++i)
+ {
+ contiguous[vectorSize * i] = vectorArray[i].x;
+ contiguous[vectorSize * i + 1] = vectorArray[i].y;
+ contiguous[vectorSize * i + 2] = vectorArray[i].z;
+ contiguous[vectorSize * i + 3] = vectorArray[i].w;
+ }
+
+ return contiguous;
+ }
}
@@ -142,11 +223,54 @@ Shader::CurrentTextureType Shader::CurrentTexture;
////////////////////////////////////////////////////////////
+struct Shader::UniformBinder : private NonCopyable
+{
+ ////////////////////////////////////////////////////////////
+ /// \brief Constructor: set up state before uniform is set
+ ///
+ ////////////////////////////////////////////////////////////
+ UniformBinder(Shader& shader, const std::string& name) :
+ savedProgram(0),
+ currentProgram(castToGlHandle(shader.m_shaderProgram)),
+ location(-1)
+ {
+ if (currentProgram)
+ {
+ ensureGlContext();
+
+ // Enable program object
+ glCheck(savedProgram = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
+ if (currentProgram != savedProgram)
+ glCheck(GLEXT_glUseProgramObject(currentProgram));
+
+ // Store uniform location for further use outside constructor
+ location = shader.getUniformLocation(name);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor: restore state after uniform is set
+ ///
+ ////////////////////////////////////////////////////////////
+ ~UniformBinder()
+ {
+ // Disable program object
+ if (currentProgram && (currentProgram != savedProgram))
+ glCheck(GLEXT_glUseProgramObject(savedProgram));
+ }
+
+ GLEXT_GLhandle savedProgram; ///< Handle to the previously active program object
+ GLEXT_GLhandle currentProgram; ///< Handle to the program object of the modified sf::Shader instance
+ GLint location; ///< Uniform location, used by the surrounding sf::Shader code
+};
+
+
+////////////////////////////////////////////////////////////
Shader::Shader() :
m_shaderProgram (0),
m_currentTexture(-1),
m_textures (),
-m_params ()
+m_uniforms ()
{
}
@@ -175,9 +299,11 @@ bool Shader::loadFromFile(const std::string& filename, Type type)
// Compile the shader program
if (type == Vertex)
- return compile(&shader[0], NULL);
+ return compile(&shader[0], NULL, NULL);
+ else if (type == Geometry)
+ return compile(NULL, &shader[0], NULL);
else
- return compile(NULL, &shader[0]);
+ return compile(NULL, NULL, &shader[0]);
}
@@ -201,7 +327,39 @@ bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::st
}
// Compile the shader program
- return compile(&vertexShader[0], &fragmentShader[0]);
+ return compile(&vertexShader[0], NULL, &fragmentShader[0]);
+}
+
+
+////////////////////////////////////////////////////////////
+bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& geometryShaderFilename, const std::string& fragmentShaderFilename)
+{
+ // Read the vertex shader file
+ std::vector<char> vertexShader;
+ if (!getFileContents(vertexShaderFilename, vertexShader))
+ {
+ err() << "Failed to open vertex shader file \"" << vertexShaderFilename << "\"" << std::endl;
+ return false;
+ }
+
+ // Read the geometry shader file
+ std::vector<char> geometryShader;
+ if (!getFileContents(geometryShaderFilename, geometryShader))
+ {
+ err() << "Failed to open geometry shader file \"" << geometryShaderFilename << "\"" << std::endl;
+ return false;
+ }
+
+ // Read the fragment shader file
+ std::vector<char> fragmentShader;
+ if (!getFileContents(fragmentShaderFilename, fragmentShader))
+ {
+ err() << "Failed to open fragment shader file \"" << fragmentShaderFilename << "\"" << std::endl;
+ return false;
+ }
+
+ // Compile the shader program
+ return compile(&vertexShader[0], &geometryShader[0], &fragmentShader[0]);
}
@@ -210,9 +368,11 @@ bool Shader::loadFromMemory(const std::string& shader, Type type)
{
// Compile the shader program
if (type == Vertex)
- return compile(shader.c_str(), NULL);
+ return compile(shader.c_str(), NULL, NULL);
+ else if (type == Geometry)
+ return compile(NULL, shader.c_str(), NULL);
else
- return compile(NULL, shader.c_str());
+ return compile(NULL, NULL, shader.c_str());
}
@@ -220,7 +380,15 @@ bool Shader::loadFromMemory(const std::string& shader, Type type)
bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& fragmentShader)
{
// Compile the shader program
- return compile(vertexShader.c_str(), fragmentShader.c_str());
+ return compile(vertexShader.c_str(), NULL, fragmentShader.c_str());
+}
+
+
+////////////////////////////////////////////////////////////
+bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& geometryShader, const std::string& fragmentShader)
+{
+ // Compile the shader program
+ return compile(vertexShader.c_str(), geometryShader.c_str(), fragmentShader.c_str());
}
@@ -237,9 +405,11 @@ bool Shader::loadFromStream(InputStream& stream, Type type)
// Compile the shader program
if (type == Vertex)
- return compile(&shader[0], NULL);
+ return compile(&shader[0], NULL, NULL);
+ else if (type == Geometry)
+ return compile(NULL, &shader[0], NULL);
else
- return compile(NULL, &shader[0]);
+ return compile(NULL, NULL, &shader[0]);
}
@@ -263,165 +433,169 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
}
// Compile the shader program
- return compile(&vertexShader[0], &fragmentShader[0]);
+ return compile(&vertexShader[0], NULL, &fragmentShader[0]);
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, float x)
+bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
{
- if (m_shaderProgram)
+ // Read the vertex shader code from the stream
+ std::vector<char> vertexShader;
+ if (!getStreamContents(vertexShaderStream, vertexShader))
{
- ensureGlContext();
-
- // Enable program
- GLEXT_GLhandle program;
- glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
- glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram)));
+ err() << "Failed to read vertex shader from stream" << std::endl;
+ return false;
+ }
- // Get parameter location and assign it new values
- GLint location = getParamLocation(name);
- if (location != -1)
- {
- glCheck(GLEXT_glUniform1f(location, x));
- }
+ // Read the geometry shader code from the stream
+ std::vector<char> geometryShader;
+ if (!getStreamContents(geometryShaderStream, geometryShader))
+ {
+ err() << "Failed to read geometry shader from stream" << std::endl;
+ return false;
+ }
- // Disable program
- glCheck(GLEXT_glUseProgramObject(program));
+ // Read the fragment shader code from the stream
+ std::vector<char> fragmentShader;
+ if (!getStreamContents(fragmentShaderStream, fragmentShader))
+ {
+ err() << "Failed to read fragment shader from stream" << std::endl;
+ return false;
}
+
+ // Compile the shader program
+ return compile(&vertexShader[0], &geometryShader[0], &fragmentShader[0]);
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, float x, float y)
+void Shader::setUniform(const std::string& name, float x)
{
- if (m_shaderProgram)
- {
- ensureGlContext();
-
- // Enable program
- GLEXT_GLhandle program;
- glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
- glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram)));
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform1f(binder.location, x));
+}
- // Get parameter location and assign it new values
- GLint location = getParamLocation(name);
- if (location != -1)
- {
- glCheck(GLEXT_glUniform2f(location, x, y));
- }
- // Disable program
- glCheck(GLEXT_glUseProgramObject(program));
- }
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Vec2& v)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform2f(binder.location, v.x, v.y));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, float x, float y, float z)
+void Shader::setUniform(const std::string& name, const Glsl::Vec3& v)
{
- if (m_shaderProgram)
- {
- ensureGlContext();
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform3f(binder.location, v.x, v.y, v.z));
+}
- // Enable program
- GLEXT_GLhandle program;
- glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
- glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram)));
- // Get parameter location and assign it new values
- GLint location = getParamLocation(name);
- if (location != -1)
- {
- glCheck(GLEXT_glUniform3f(location, x, y, z));
- }
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Vec4& v)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform4f(binder.location, v.x, v.y, v.z, v.w));
+}
- // Disable program
- glCheck(GLEXT_glUseProgramObject(program));
- }
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, int x)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform1i(binder.location, x));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, float x, float y, float z, float w)
+void Shader::setUniform(const std::string& name, const Glsl::Ivec2& v)
{
- if (m_shaderProgram)
- {
- ensureGlContext();
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform2i(binder.location, v.x, v.y));
+}
- // Enable program
- GLEXT_GLhandle program;
- glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
- glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram)));
- // Get parameter location and assign it new values
- GLint location = getParamLocation(name);
- if (location != -1)
- {
- glCheck(GLEXT_glUniform4f(location, x, y, z, w));
- }
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Ivec3& v)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform3i(binder.location, v.x, v.y, v.z));
+}
- // Disable program
- glCheck(GLEXT_glUseProgramObject(program));
- }
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Ivec4& v)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform4i(binder.location, v.x, v.y, v.z, v.w));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, const Vector2f& v)
+void Shader::setUniform(const std::string& name, bool x)
{
- setParameter(name, v.x, v.y);
+ setUniform(name, static_cast<int>(x));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, const Vector3f& v)
+void Shader::setUniform(const std::string& name, const Glsl::Bvec2& v)
{
- setParameter(name, v.x, v.y, v.z);
+ setUniform(name, Glsl::Ivec2(v));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, const Color& color)
+void Shader::setUniform(const std::string& name, const Glsl::Bvec3& v)
{
- setParameter(name, color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f);
+ setUniform(name, Glsl::Ivec3(v));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, const Transform& transform)
+void Shader::setUniform(const std::string& name, const Glsl::Bvec4& v)
{
- if (m_shaderProgram)
- {
- ensureGlContext();
+ setUniform(name, Glsl::Ivec4(v));
+}
- // Enable program
- GLEXT_GLhandle program;
- glCheck(program = GLEXT_glGetHandle(GLEXT_GL_PROGRAM_OBJECT));
- glCheck(GLEXT_glUseProgramObject(castToGlHandle(m_shaderProgram)));
- // Get parameter location and assign it new values
- GLint location = getParamLocation(name);
- if (location != -1)
- {
- glCheck(GLEXT_glUniformMatrix4fv(location, 1, GL_FALSE, transform.getMatrix()));
- }
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Mat3& matrix)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniformMatrix3fv(binder.location, 1, GL_FALSE, matrix.array));
+}
- // Disable program
- glCheck(GLEXT_glUseProgramObject(program));
- }
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Mat4& matrix)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniformMatrix4fv(binder.location, 1, GL_FALSE, matrix.array));
}
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, const Texture& texture)
+void Shader::setUniform(const std::string& name, const Texture& texture)
{
if (m_shaderProgram)
{
ensureGlContext();
// Find the location of the variable in the shader
- int location = getParamLocation(name);
+ int location = getUniformLocation(name);
if (location != -1)
{
// Store the location -> texture mapping
@@ -449,19 +623,161 @@ void Shader::setParameter(const std::string& name, const Texture& texture)
////////////////////////////////////////////////////////////
-void Shader::setParameter(const std::string& name, CurrentTextureType)
+void Shader::setUniform(const std::string& name, CurrentTextureType)
{
if (m_shaderProgram)
{
ensureGlContext();
// Find the location of the variable in the shader
- m_currentTexture = getParamLocation(name);
+ m_currentTexture = getUniformLocation(name);
}
}
////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const float* scalarArray, std::size_t length)
+{
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform1fv(binder.location, length, scalarArray));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec2* vectorArray, std::size_t length)
+{
+ std::vector<float> contiguous = flatten(vectorArray, length);
+
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform2fv(binder.location, length, &contiguous[0]));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec3* vectorArray, std::size_t length)
+{
+ std::vector<float> contiguous = flatten(vectorArray, length);
+
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform3fv(binder.location, length, &contiguous[0]));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec4* vectorArray, std::size_t length)
+{
+ std::vector<float> contiguous = flatten(vectorArray, length);
+
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniform4fv(binder.location, length, &contiguous[0]));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Mat3* matrixArray, std::size_t length)
+{
+ const std::size_t matrixSize = 3 * 3;
+
+ std::vector<float> contiguous(matrixSize * length);
+ for (std::size_t i = 0; i < length; ++i)
+ priv::copyMatrix(matrixArray[i].array, matrixSize, &contiguous[matrixSize * i]);
+
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniformMatrix3fv(binder.location, length, GL_FALSE, &contiguous[0]));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Mat4* matrixArray, std::size_t length)
+{
+ const std::size_t matrixSize = 4 * 4;
+
+ std::vector<float> contiguous(matrixSize * length);
+ for (std::size_t i = 0; i < length; ++i)
+ priv::copyMatrix(matrixArray[i].array, matrixSize, &contiguous[matrixSize * i]);
+
+ UniformBinder binder(*this, name);
+ if (binder.location != -1)
+ glCheck(GLEXT_glUniformMatrix4fv(binder.location, length, GL_FALSE, &contiguous[0]));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, float x)
+{
+ setUniform(name, x);
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, float x, float y)
+{
+ setUniform(name, Glsl::Vec2(x, y));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, float x, float y, float z)
+{
+ setUniform(name, Glsl::Vec3(x, y, z));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, float x, float y, float z, float w)
+{
+ setUniform(name, Glsl::Vec4(x, y, z, w));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, const Vector2f& v)
+{
+ setUniform(name, v);
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, const Vector3f& v)
+{
+ setUniform(name, v);
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, const Color& color)
+{
+ setUniform(name, Glsl::Vec4(color));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, const Transform& transform)
+{
+ setUniform(name, Glsl::Mat4(transform));
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, const Texture& texture)
+{
+ setUniform(name, texture);
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setParameter(const std::string& name, CurrentTextureType)
+{
+ setUniform(name, CurrentTexture);
+}
+
+
+////////////////////////////////////////////////////////////
unsigned int Shader::getNativeHandle() const
{
return m_shaderProgram;
@@ -514,7 +830,19 @@ bool Shader::isAvailable()
////////////////////////////////////////////////////////////
-bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode)
+bool Shader::isGeometryAvailable()
+{
+ // TODO: Remove this lock when it becomes unnecessary in C++11
+ Lock lock(mutex);
+
+ static bool available = checkGeometryShadersAvailable();
+
+ return available;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
{
ensureGlContext();
@@ -526,6 +854,14 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod
return false;
}
+ // Make sure we can use geometry shaders
+ if (geometryShaderCode && !isGeometryAvailable())
+ {
+ err() << "Failed to create a shader: your system doesn't support geometry shaders "
+ << "(you should test Shader::isGeometryAvailable() before trying to use geometry shaders)" << std::endl;
+ return false;
+ }
+
// Destroy the shader if it was already created
if (m_shaderProgram)
{
@@ -536,7 +872,7 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod
// Reset the internal state
m_currentTexture = -1;
m_textures.clear();
- m_params.clear();
+ m_uniforms.clear();
// Create the program
GLEXT_GLhandle shaderProgram;
@@ -570,6 +906,33 @@ bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCod
glCheck(GLEXT_glDeleteObject(vertexShader));
}
+ // Create the geometry shader if needed
+ if (geometryShaderCode)
+ {
+ // Create and compile the shader
+ GLEXT_GLhandle geometryShader = GLEXT_glCreateShaderObject(GLEXT_GL_GEOMETRY_SHADER);
+ glCheck(GLEXT_glShaderSource(geometryShader, 1, &geometryShaderCode, NULL));
+ glCheck(GLEXT_glCompileShader(geometryShader));
+
+ // Check the compile log
+ GLint success;
+ glCheck(GLEXT_glGetObjectParameteriv(geometryShader, GLEXT_GL_OBJECT_COMPILE_STATUS, &success));
+ if (success == GL_FALSE)
+ {
+ char log[1024];
+ glCheck(GLEXT_glGetInfoLog(geometryShader, sizeof(log), 0, log));
+ err() << "Failed to compile geometry shader:" << std::endl
+ << log << std::endl;
+ glCheck(GLEXT_glDeleteObject(geometryShader));
+ glCheck(GLEXT_glDeleteObject(shaderProgram));
+ return false;
+ }
+
+ // Attach the shader to the program, and delete it (not needed anymore)
+ glCheck(GLEXT_glAttachObject(shaderProgram, geometryShader));
+ glCheck(GLEXT_glDeleteObject(geometryShader));
+ }
+
// Create the fragment shader if needed
if (fragmentShaderCode)
{
@@ -643,11 +1006,11 @@ void Shader::bindTextures() const
////////////////////////////////////////////////////////////
-int Shader::getParamLocation(const std::string& name)
+int Shader::getUniformLocation(const std::string& name)
{
// Check the cache
- ParamTable::const_iterator it = m_params.find(name);
- if (it != m_params.end())
+ UniformTable::const_iterator it = m_uniforms.find(name);
+ if (it != m_uniforms.end())
{
// Already in cache, return it
return it->second;
@@ -656,7 +1019,7 @@ int Shader::getParamLocation(const std::string& name)
{
// Not in cache, request the location from OpenGL
int location = GLEXT_glGetUniformLocation(castToGlHandle(m_shaderProgram), name.c_str());
- m_params.insert(std::make_pair(name, location));
+ m_uniforms.insert(std::make_pair(name, location));
if (location == -1)
err() << "Parameter \"" << name << "\" not found in shader" << std::endl;
@@ -706,6 +1069,13 @@ bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::st
////////////////////////////////////////////////////////////
+bool Shader::loadFromFile(const std::string& vertexShaderFilename, const std::string& geometryShaderFilename, const std::string& fragmentShaderFilename)
+{
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
bool Shader::loadFromMemory(const std::string& shader, Type type)
{
return false;
@@ -720,6 +1090,13 @@ bool Shader::loadFromMemory(const std::string& vertexShader, const std::string&
////////////////////////////////////////////////////////////
+bool Shader::loadFromMemory(const std::string& vertexShader, const std::string& geometryShader, const std::string& fragmentShader)
+{
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
bool Shader::loadFromStream(InputStream& stream, Type type)
{
return false;
@@ -734,6 +1111,145 @@ bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& fragme
////////////////////////////////////////////////////////////
+bool Shader::loadFromStream(InputStream& vertexShaderStream, InputStream& geometryShaderStream, InputStream& fragmentShaderStream)
+{
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, float x)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Vec2& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Vec3& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Vec4& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, int x)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Ivec2& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Ivec3& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Ivec4& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, bool x)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Bvec2& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Bvec3& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Bvec4& v)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Mat3& matrix)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Glsl::Mat4& matrix)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, const Texture& texture)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniform(const std::string& name, CurrentTextureType)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const float* scalarArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec2* vectorArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec3* vectorArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Vec4* vectorArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Mat3* matrixArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+void Shader::setUniformArray(const std::string& name, const Glsl::Mat4* matrixArray, std::size_t length)
+{
+}
+
+
+////////////////////////////////////////////////////////////
void Shader::setParameter(const std::string& name, float x)
{
}
@@ -814,7 +1330,14 @@ bool Shader::isAvailable()
////////////////////////////////////////////////////////////
-bool Shader::compile(const char* vertexShaderCode, const char* fragmentShaderCode)
+bool Shader::isGeometryAvailable()
+{
+ return false;
+}
+
+
+////////////////////////////////////////////////////////////
+bool Shader::compile(const char* vertexShaderCode, const char* geometryShaderCode, const char* fragmentShaderCode)
{
return false;
}