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.
