Add and use a simple shader to make the current color more bluish


#1

Hi everyone

I'm working on a project in windows using Juce and VS 2010 and in my project I draw a map using an external library called geofusion.

what I'm trying to do is to add a shader on top of the map to make it a little more blue.

As I'm new to both juce and shaders, I tried copying and changing the code from the openGlDemo in juce examples.

the problem I have is when I use both vertex and fragment shaders and link them, I see nothing, But if I only use fragment shader, I can change the color of the map to pink for example, but then everything is pink and it just draws a pink layer on top of the map and the map is not shown.

so in short, I want to use vertex shader only for passing the original colour to fragment shader so I can add more blue to it.

I've created a shader class to make things easier to read.

Here are my .h and .cpp files for shader class :

shader.h file :

 



#ifndef __SHADER_H__
#define __SHADER_H__


#include <list>
#include <utility>
#include <vector>
#include <map>

#include <JuceHeader.h>
#include "GmxTypeDefs.h"

#include "../Core/Globals.h"
#include "math/Vector2D.h"
#include "math/Vector3D.h"
#include "Animations/AnimationManager.h"
#include "JuceHeader.h"
#include "Window.h"


//========================================================================================================================================================
/** \class Shader Shader.h
*    \brief ...
*/
//========================================================================================================================================================

class Shader :public juce::OpenGLShaderProgram
{
public:

        
    struct Vertex
    {
        float position[3];
        float normal[3];
        float colour[4];
        float texCoord[2];
    };

    //=============================================ATTRIBUTES===========================================================================================================
    // This class just manages the attributes that the demo shaders use.
    struct Attributes
    {
        //! Constructor
        Attributes (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader);

        //! TODO
        void enable (juce::OpenGLContext& openGLContext);
        //! TODO
        void disable (juce::OpenGLContext& openGLContext);
        
        
    private:

        //! TODO
        static juce::OpenGLShaderProgram::Attribute* createAttribute (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader, const char* attributeName);
        
    public:

        typedef juce::ScopedPointer<juce::OpenGLShaderProgram::Attribute> AttributePointer; ///< scoped pointer to Attribute object
        
        AttributePointer    m_position;            ///< TODO
        AttributePointer    m_normal;            ///< TODO
        AttributePointer    m_sourceColour;        ///< TODO
        AttributePointer    m_texureCoordIn;    ///< TODO
    
    };

    //=============================================UNIFORM===========================================================================================================
    // This class just manages the uniform values that the demo shaders use.
    struct Uniforms
    {
        //! Constructor
        Uniforms (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader);

    private:

        //! TODO
        static juce::OpenGLShaderProgram::Uniform* createUniform (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader, const char* uniformName);

    public:

        typedef juce::ScopedPointer<juce::OpenGLShaderProgram::Uniform> UniformPointer; ///< scoped pointer to Uniform object
        
        UniformPointer    m_projectionMatrix;    ///< TODO
        UniformPointer    m_viewMatrix;        ///< TODO
        UniformPointer    m_texture;            ///< TODO
        UniformPointer    m_lightPosition;    ///< TODO
        UniformPointer    m_bouncingNumber;    ///< TODO
    };
    //========================================================================================================================================================
    

    
    //! Constructor
    Shader(juce::OpenGLContext& openGLContext);
    //! Destructor.
    ~Shader();

    void release() noexcept;

    //========================================================================================================================================================
    void linkShaders(juce::OpenGLContext& openGLContext, const juce::String& vertexShaderCode, const juce::String& fragmentShaderCode);
    //========================================================================================================================================================
};

#endif

shader.cpp file : (sorry for the long code, for some unknown reason I coudn't attach the files to this post)




#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>

#include <algorithm>
#include <exception>
#include <TraceLog.h>

#include "../Core/EventSystem/EventManager.h"
#include "../Core/InputSystem/InputManager.h"
#include "../Core/Core.h"
#include "../Core/ConfigSystem/ConfigDataSets.h"
#include "../Core/ConfigSystem/ConfigManager.h"
#include "../Data/Shapefile/Shapefile.h"
#include "../Scenes/Scene.h"

#include "OpenGLCanvas.h"
#include "Window.h"
#include "Visuals/Visual.h"
#include "Visuals/ImageSprite.h"
#include "Visuals/GraphVisual.h"
#include "Visuals/PolygonVisual.h"
#include "Resources/ResourceManager.h"
#include "Animations/AnimationManager.h"
#include "ParticleSystem/ParticleManager.h"

#include "ViewManager.h"

#include "Shader.h"

#include "Resources/FontHandle.h"

//==========================================ATTRIBUTES==============================================================================================================
Shader::Attributes::Attributes (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader)
{
    m_position      = createAttribute (openGLContext, shader, "position");
    m_normal        = createAttribute (openGLContext, shader, "normal");
    m_sourceColour  = createAttribute (openGLContext, shader, "sourceColour");
    m_texureCoordIn = createAttribute (openGLContext, shader, "texureCoordIn");
}
//========================================================================================================================================================
void Shader::Attributes::enable(juce::OpenGLContext& openGLContext)
{
    if (m_position != nullptr)
    {
        openGLContext.extensions.glVertexAttribPointer (m_position->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), 0);
        openGLContext.extensions.glEnableVertexAttribArray (m_position->attributeID);
    }

    if (m_normal != nullptr)
    {
        openGLContext.extensions.glVertexAttribPointer (m_normal->attributeID, 3, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 3));
        openGLContext.extensions.glEnableVertexAttribArray (m_normal->attributeID);
    }

    if (m_sourceColour != nullptr)
    {
        openGLContext.extensions.glVertexAttribPointer (m_sourceColour->attributeID, 4, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 6));
        openGLContext.extensions.glEnableVertexAttribArray (m_sourceColour->attributeID);
    }

    if (m_texureCoordIn != nullptr)
    {
        openGLContext.extensions.glVertexAttribPointer (m_texureCoordIn->attributeID, 2, GL_FLOAT, GL_FALSE, sizeof (Vertex), (GLvoid*) (sizeof (float) * 10));
        openGLContext.extensions.glEnableVertexAttribArray (m_texureCoordIn->attributeID);
    }
};
//========================================================================================================================================================    
void Shader::Attributes::disable (juce::OpenGLContext& openGLContext)
{
    if (m_position != nullptr)       openGLContext.extensions.glDisableVertexAttribArray (m_position->attributeID);
    if (m_normal != nullptr)         openGLContext.extensions.glDisableVertexAttribArray (m_normal->attributeID);
    if (m_sourceColour != nullptr)   openGLContext.extensions.glDisableVertexAttribArray (m_sourceColour->attributeID);
    if (m_texureCoordIn != nullptr)  openGLContext.extensions.glDisableVertexAttribArray (m_texureCoordIn->attributeID);
}
//========================================================================================================================================================
juce::OpenGLShaderProgram::Attribute* Shader::Attributes::createAttribute (juce::OpenGLContext& openGLContext,     juce::OpenGLShaderProgram& shader, const char* attributeName)
{
    if (openGLContext.extensions.glGetAttribLocation (shader.getProgramID(), attributeName) < 0)
        return nullptr;

    return new juce::OpenGLShaderProgram::Attribute (shader, attributeName);
}
//=========================================UNIFORMS===============================================================================================================
Shader::Uniforms::Uniforms (juce::OpenGLContext& openGLContext, juce::OpenGLShaderProgram& shader)
{
    m_projectionMatrix = createUniform (openGLContext, shader, "projectionMatrix");
    m_viewMatrix       = createUniform (openGLContext, shader, "viewMatrix");
    m_texture          = createUniform (openGLContext, shader, "demoTexture");
    m_lightPosition    = createUniform (openGLContext, shader, "lightPosition");
    m_bouncingNumber   = createUniform (openGLContext, shader, "bouncingNumber");
}

//========================================================================================================================================================
juce::OpenGLShaderProgram::Uniform* Shader::Uniforms::createUniform (juce::OpenGLContext& openGLContext,
    juce::OpenGLShaderProgram& shader,
    const char* uniformName)
{
    if (openGLContext.extensions.glGetUniformLocation (shader.getProgramID(), uniformName) < 0)
        return nullptr;

    return new juce::OpenGLShaderProgram::Uniform (shader, uniformName);
}

//==================================================================================================================================================================================================================================
Shader::Shader(juce::OpenGLContext& openGLContext): juce::OpenGLShaderProgram(openGLContext)
{
    
    //INTENTIONALY ...

}
//========================================================================================================================================================

Shader::~Shader()
{
    release();
}

//========================================================================================================================================================

void Shader::linkShaders(juce::OpenGLContext& openGLContext, const juce::String& vertexShaderCode, const juce::String& fragmentShaderCode)
{
    if (vertexShaderCode.isNotEmpty() || fragmentShaderCode.isNotEmpty())
    {

        juce::String statusText;
        juce::ScopedPointer<Shader::Attributes> attributes = NULL;
        juce::ScopedPointer<Shader::Uniforms> uniforms = NULL;
        if (addVertexShader (juce::OpenGLHelpers::translateVertexShaderToV3 (vertexShaderCode)) &&
            addFragmentShader (juce::OpenGLHelpers::translateFragmentShaderToV3 (fragmentShaderCode)) &&
            link())
        {

            //use();

            //shape      = new Shape (openGLContext);
            attributes = new Attributes (openGLContext, *this);
            uniforms   = new Uniforms (openGLContext, *this);

            statusText = "GLSL: v" + juce::String (juce::OpenGLShaderProgram::getLanguageVersion(), 2);
        }
        else
        {
            statusText = getLastError();
        }

        LOG_VAL(statusText);

        //controlsOverlay->statusLabel.setText (statusText, dontSendNotification);

    }
}

void Shader::release() noexcept
{
    OpenGLShaderProgram::release();
    //context.extensions.glUseProgram(0);
}

//========================================================================================================================================================

This is the fragment and vertex shader codes:

juce::String newVertexShader=

    "attribute vec4 position;\n"
    "attribute vec4 sourceColour;\n"
    "attribute vec2 texureCoordIn;\n"
    "\n"
    "uniform mat4 projectionMatrix;\n"
    "uniform mat4 viewMatrix;\n"
    "\n"
    "varying vec4 destinationColour;\n"
    "varying vec2 textureCoordOut;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    destinationColour = sourceColour;\n"
    "    textureCoordOut = texureCoordIn;\n"
    "    gl_Position = projectionMatrix * viewMatrix * position;\n"
    "}\n"
    ;

juce::String newFragmentShader =
    #if JUCE_OPENGL_ES
        "varying lowp vec4 destinationColour;\n"
        "varying lowp vec2 textureCoordOut;\n"
    #else
        "varying vec4 destinationColour;\n"
        "varying vec2 textureCoordOut;\n"
    #endif
    "void main()\n"
    "{\n"
    "    vec4 colour1 = vec4 (1.0, 0.4, 0.6, 0.1);\n"
    "    gl_FragColor = destinationColour+ vec4(0.0, 0.0, 0.4, 1.0);\n"
    "}\n"

    ;
juce::OpenGLContext& openGLContext = m_window->getContext();
Shader* shader = new Shader (openGLContext);
shader->linkShaders(openGLContext, newVertexShader, newFragmentShader);

And here's the part of code where I use the shader :

shader->use();

     renderMap();

shader->release();

 

Can someone guide me in the right direction please?

Thanks in advance.