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.