void Texture::setRepeated(bool repeated) { if (repeated != m_isRepeated) { m_isRepeated = repeated; if (m_texture) { ensureGlContext(); // Make sure that the current texture binding will be preserved priv::TextureSaver save; if (!m_isRepeated && !GLEXT_texture_edge_clamp) { static bool warned = false; if (!warned) { err() << "OpenGL extension SGIS_texture_edge_clamp unavailable" << std::endl; err() << "Artifacts may occur along texture edges" << std::endl; err() << "Ensure that hardware acceleration is enabled if available" << std::endl; warned = true; } } glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : (GLEXT_texture_edge_clamp ? GLEXT_GL_CLAMP_TO_EDGE : GLEXT_GL_CLAMP))); } } }
void Shader::bind(const Shader* shader) { ensureGlContext(); // Make sure that we can use shaders if (!isAvailable()) { err() << "Failed to bind or unbind shader: your system doesn't support shaders " << "(you should test Shader::isAvailable() before trying to use the Shader class)" << std::endl; return; } if (shader && shader->m_shaderProgram) { // Enable the program glCheck(GLEXT_glUseProgramObject(castToGlHandle(shader->m_shaderProgram))); // Bind the textures shader->bindTextures(); // Bind the current texture if (shader->m_currentTexture != -1) glCheck(GLEXT_glUniform1i(shader->m_currentTexture, 0)); } else { // Bind no shader glCheck(GLEXT_glUseProgramObject(0)); } }
void Shader::setParameter(const std::string& name, const Texture& texture) { if (m_shaderProgram) { ensureGlContext(); // Find the location of the variable in the shader int location = glGetUniformLocationARB(m_shaderProgram, name.c_str()); if (location == -1) { err() << "Texture \"" << name << "\" not found in shader" << std::endl; return; } // Store the location -> texture mapping TextureTable::iterator it = m_textures.find(location); if (it == m_textures.end()) { // New entry, make sure there are enough texture units static const GLint maxUnits = getMaxTextureUnits(); if (m_textures.size() + 1 >= static_cast<std::size_t>(maxUnits)) { err() << "Impossible to use texture \"" << name << "\" for shader: all available texture units are used" << std::endl; return; } m_textures[location] = &texture; } else { // Location already used, just replace the texture it->second = &texture; } } }
Shader::~Shader() { ensureGlContext(); // Destroy effect program if (m_shaderProgram) glCheck(glDeleteObjectARB(m_shaderProgram)); }
Shader::~Shader() { ensureGlContext(); // Destroy effect program if (m_shaderProgram) glCheck(GLEXT_glDeleteObject(castToGlHandle(m_shaderProgram))); }
bool RenderTextureImplFBO::isAvailable() { ensureGlContext(); // Make sure that GLEW is initialized priv::ensureGlewInit(); return GLEW_EXT_framebuffer_object != 0; }
bool RenderTextureImplFBO::isAvailable() { ensureGlContext(); // Make sure that extensions are initialized priv::ensureExtensionsInit(); return GLEXT_framebuffer_object != 0; }
unsigned int Texture::getMaximumSize() { ensureGlContext(); GLint size; glCheck(glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size)); return static_cast<unsigned int>(size); }
Image Texture::copyToImage() const { // Easy case: empty texture if (!m_texture) return Image(); ensureGlContext(); // Make sure that the current texture binding will be preserved priv::TextureSaver save; // Create an array of pixels std::vector<Uint8> pixels(m_size.x * m_size.y * 4); if ((m_size == m_actualSize) && !m_pixelsFlipped) { // Texture is not padded nor flipped, we can use a direct copy glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0])); } else { // Texture is either padded or flipped, we have to use a slower algorithm // All the pixels will first be copied to a temporary array std::vector<Uint8> allPixels(m_actualSize.x * m_actualSize.y * 4); glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, &allPixels[0])); // Then we copy the useful pixels from the temporary array to the final one const Uint8* src = &allPixels[0]; Uint8* dst = &pixels[0]; int srcPitch = m_actualSize.x * 4; int dstPitch = m_size.x * 4; // Handle the case where source pixels are flipped vertically if (m_pixelsFlipped) { src += srcPitch * (m_size.y - 1); srcPitch = -srcPitch; } for (unsigned int i = 0; i < m_size.y; ++i) { std::memcpy(dst, src, dstPitch); src += srcPitch; dst += dstPitch; } } // Create the image Image image; image.create(m_size.x, m_size.y, &pixels[0]); return image; }
void Shader::setUniform(const std::string& name, CurrentTextureType) { if (m_shaderProgram) { ensureGlContext(); // Find the location of the variable in the shader m_currentTexture = getUniformLocation(name); } }
bool Texture::create(unsigned int width, unsigned int height) { // Check if texture parameters are valid before creating it if ((width == 0) || (height == 0)) { err() << "Failed to create texture, invalid size (" << width << "x" << height << ")" << std::endl; return false; } // Compute the internal texture dimensions depending on NPOT textures support Vector2u actualSize(getValidSize(width), getValidSize(height)); // Check the maximum texture size unsigned int maxSize = getMaximumSize(); if ((actualSize.x > maxSize) || (actualSize.y > maxSize)) { err() << "Failed to create texture, its internal size is too high " << "(" << actualSize.x << "x" << actualSize.y << ", " << "maximum is " << maxSize << "x" << maxSize << ")" << std::endl; return false; } // All the validity checks passed, we can store the new texture settings m_size.x = width; m_size.y = height; m_actualSize = actualSize; m_pixelsFlipped = false; ensureGlContext(); // Create the OpenGL texture if it doesn't exist yet if (!m_texture) { GLuint texture; glCheck(glGenTextures(1, &texture)); m_texture = static_cast<unsigned int>(texture); } // Make sure that the current texture binding will be preserved priv::TextureSaver save; // Initialize the texture glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_actualSize.x, m_actualSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE)); glCheck(glTexEnvi(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, -1)); m_cacheId = getUniqueId(); return true; }
Texture::~Texture() { // Destroy the OpenGL texture if (m_texture) { ensureGlContext(); GLuint texture = static_cast<GLuint>(m_texture); glCheck(glDeleteTextures(1, &texture)); } }
void Texture::bind(const Texture* texture, CoordinateType coordinateType) { ensureGlContext(); if (texture && texture->m_texture) { // Bind the texture glCheck(glBindTexture(GL_TEXTURE_2D, texture->m_texture)); // Check if we need to define a special texture matrix if ((coordinateType == Pixels) || texture->m_pixelsFlipped) { GLfloat matrix[16] = {1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f, 0.f, 1.f }; // If non-normalized coordinates (= pixels) are requested, we need to // setup scale factors that convert the range [0 .. size] to [0 .. 1] if (coordinateType == Pixels) { matrix[0] = 1.f / texture->m_actualSize.x; matrix[5] = 1.f / texture->m_actualSize.y; } // If pixels are flipped we must invert the Y axis if (texture->m_pixelsFlipped) { matrix[5] = -matrix[5]; matrix[13] = static_cast<float>(texture->m_size.y) / texture->m_actualSize.y; } // Load the matrix glCheck(glMatrixMode(GL_TEXTURE)); glCheck(glLoadMatrixf(matrix)); // Go back to model-view mode (sf::RenderTarget relies on it) glCheck(glMatrixMode(GL_MODELVIEW)); } } else { // Bind no texture glCheck(glBindTexture(GL_TEXTURE_2D, 0)); // Reset the texture matrix glCheck(glMatrixMode(GL_TEXTURE)); glCheck(glLoadIdentity()); // Go back to model-view mode (sf::RenderTarget relies on it) glCheck(glMatrixMode(GL_MODELVIEW)); } }
bool Shader::isAvailable() { ensureGlContext(); // Make sure that GLEW is initialized priv::ensureGlewInit(); return GLEW_ARB_shading_language_100 && GLEW_ARB_shader_objects && GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader; }
void Shader::setParameter(const std::string& name, CurrentTextureType) { if (m_shaderProgram) { ensureGlContext(); // Find the location of the variable in the shader m_currentTexture = glGetUniformLocationARB(m_shaderProgram, name.c_str()); if (m_currentTexture == -1) err() << "Texture \"" << name << "\" not found in shader" << std::endl; } }
void Shader::bindAttribute(int location, const std::string& name) { if (m_shaderProgram) { ensureGlContext(); GLint n; glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &n); if (location < n) { glCheck(glBindAttribLocationARB(m_shaderProgram,location,name.c_str())); m_currentAttrib = getVertexAttribLocation(name); } else { err() << "Invalid attribute location " << location << " in vertex." << std::endl; } } }
void Shader::bind() const { if (m_shaderProgram) { ensureGlContext(); // Enable the program glCheck(glUseProgramObjectARB(m_shaderProgram)); // Bind the textures bindTextures(); // Bind the current texture if (m_currentTexture != -1) glCheck(glUniform1iARB(m_currentTexture, 0)); } }
void Shader::setParameter(const std::string& name, float x, float y, float z, float w) { if (m_shaderProgram) { ensureGlContext(); // Enable program GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); glCheck(glUseProgramObjectARB(m_shaderProgram)); // Get parameter location and assign it new values GLint location = getParamLocation(name); if (location != -1) glCheck(glUniform4fARB(location, x, y, z, w)); // Disable program glCheck(glUseProgramObjectARB(program)); } }
//////////////////////////////////////////////////////////// /// \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); } }
void Texture::setRepeated(bool repeated) { if (repeated != m_isRepeated) { m_isRepeated = repeated; if (m_texture) { ensureGlContext(); // Make sure that the current texture binding will be preserved priv::TextureSaver save; glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_isRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_isRepeated ? GL_REPEAT : GL_CLAMP_TO_EDGE)); } } }
void Shader::setParameter(const std::string& name, const sf::Transform& transform) { if (m_shaderProgram) { ensureGlContext(); // Enable program GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); glCheck(glUseProgramObjectARB(m_shaderProgram)); // Get parameter location and assign it new values GLint location = getParamLocation(name); if (location != -1) glCheck(glUniformMatrix4fvARB(location, 1, GL_FALSE, transform.getMatrix())); // Disable program glCheck(glUseProgramObjectARB(program)); } }
void Texture::update(const Uint8* pixels, unsigned int width, unsigned int height, unsigned int x, unsigned int y) { assert(x + width <= m_size.x); assert(y + height <= m_size.y); if (pixels && m_texture) { ensureGlContext(); // Make sure that the current texture binding will be preserved priv::TextureSaver save; // Copy pixels from the given array to the texture glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels)); m_pixelsFlipped = false; m_cacheId = getUniqueId(); } }
void Shader::setParameter(const std::string& name, math::Matrix4f matrix) { if (m_shaderProgram) { ensureGlContext(); // Enable program GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); glCheck(glUseProgramObjectARB(m_shaderProgram)); // Get parameter location and assign it new values GLint location = getParamLocation(name); if (location != -1) { std::array<float, 16> glmatrix = matrix.toGlMatrix(); glCheck(glUniformMatrix4fvARB(location, 1, GL_FALSE, glmatrix.data())); } // Disable program glCheck(glUseProgramObjectARB(program)); } }
void Texture::setSmooth(bool smooth) { if (smooth != m_isSmooth) { m_isSmooth = smooth; if (m_texture) { ensureGlContext(); // Make sure that the current texture binding will be preserved priv::TextureSaver save; glCheck(glBindTexture(GL_TEXTURE_2D, m_texture)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); glCheck(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_isSmooth ? GL_LINEAR : GL_NEAREST)); } } }
void Shader::setParameter(const std::string& name, float x, float y, float z, float w) { if (m_shaderProgram) { ensureGlContext(); // Enable program GLhandleARB program = glGetHandleARB(GL_PROGRAM_OBJECT_ARB); glCheck(glUseProgramObjectARB(m_shaderProgram)); // Get parameter location and assign it new values GLint location = glGetUniformLocationARB(m_shaderProgram, name.c_str()); if (location != -1) glCheck(glUniform4fARB(location, x, y, z, w)); else err() << "Parameter \"" << name << "\" not found in shader" << std::endl; // Disable program glCheck(glUseProgramObjectARB(program)); } }
RenderTextureImplFBO::~RenderTextureImplFBO() { ensureGlContext(); // Destroy the depth buffer if (m_depthBuffer) { GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer); glCheck(glDeleteRenderbuffersEXT(1, &depthBuffer)); } // Destroy the frame buffer if (m_frameBuffer) { GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer); glCheck(glDeleteFramebuffersEXT(1, &frameBuffer)); } // Delete the context delete m_context; }
void Shader::setParameter(const std::string& name, const Transform& transform) { if (m_shaderProgram) { ensureGlContext(); // 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())); } // Disable program glCheck(GLEXT_glUseProgramObject(program)); } }
unsigned int Texture::getValidSize(unsigned int size) { ensureGlContext(); // Make sure that GLEW is initialized priv::ensureGlewInit(); if (GLEW_ARB_texture_non_power_of_two) { // If hardware supports NPOT textures, then just return the unmodified size return size; } else { // If hardware doesn't support NPOT textures, we calculate the nearest power of two unsigned int powerOfTwo = 1; while (powerOfTwo < size) powerOfTwo *= 2; return powerOfTwo; } }
void Shader::bind(const Shader* shader) { ensureGlContext(); if (shader && shader->m_shaderProgram) { // Enable the program glCheck(glUseProgramObjectARB(shader->m_shaderProgram)); // Bind the textures shader->bindTextures(); // Bind the current texture if (shader->m_currentTexture != -1) glCheck(glUniform1iARB(shader->m_currentTexture, 0)); } else { // Bind no shader glCheck(glUseProgramObjectARB(0)); } }
void Shader::setParameter(const std::string& name, float x, float y, float z, float w) { if (m_shaderProgram) { ensureGlContext(); // 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)); } // Disable program glCheck(GLEXT_glUseProgramObject(program)); } }