1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

New class: OpenGLGraphicsContextCustomShader, which allows custom fragment shaders to be applied to a rectangular area during a normal 2D paint routine, to achieve per-pixel effects.

This commit is contained in:
jules 2014-02-24 11:04:38 +00:00
parent 1fef7a8408
commit 6427e11ae3
5 changed files with 122 additions and 11 deletions

View file

@ -104,14 +104,6 @@ void OpenGLExtensionFunctions::initialise()
#undef JUCE_GL_EXTENSION_FUNCTIONS
#if JUCE_OPENGL_ES
#define JUCE_MEDIUMP "mediump"
#define JUCE_HIGHP "highp"
#else
#define JUCE_MEDIUMP
#define JUCE_HIGHP
#endif
#if JUCE_DEBUG && ! defined (JUCE_CHECK_OPENGL_ERROR)
static const char* getGLErrorMessage (const GLenum e)
{

View file

@ -64,6 +64,31 @@
#include <GLES2/gl2.h>
#endif
//=============================================================================
#if JUCE_OPENGL_ES || defined (DOXYGEN)
/** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
these macros define the various precision keywords only on GLES.
*/
#define JUCE_MEDIUMP "mediump"
/** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
these macros define the various precision keywords only on GLES.
*/
#define JUCE_HIGHP "highp"
/** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL.
Since it's mandatory in GLES to mark a variable with a precision, but the keywords don't exist in normal GLSL,
these macros define the various precision keywords only on GLES.
*/
#define JUCE_LOWP "lowp"
#else
#define JUCE_MEDIUMP
#define JUCE_HIGHP
#define JUCE_LOWP
#endif
//=============================================================================
namespace juce
{

View file

@ -1631,6 +1631,13 @@ public:
state->shaderQuadQueue.add (iter, fillType.colour.getPixelARGB());
}
void fillRectWithCustomShader (OpenGLRendering::ShaderPrograms::ShaderBase& shader, const Rectangle<int>& area, Colour colour)
{
state->setShader (shader);
state->shaderQuadQueue.add (area, colour.getPixelARGB());
state->currentShader.clearShader (state->shaderQuadQueue);
}
//==============================================================================
Font font;
GLState* state;
@ -1644,7 +1651,7 @@ private:
//==============================================================================
class ShaderContext : public RenderingHelpers::StackBasedLowLevelGraphicsContext <SavedState>
class ShaderContext : public RenderingHelpers::StackBasedLowLevelGraphicsContext<SavedState>
{
public:
ShaderContext (const Target& target) : glState (target)
@ -1652,7 +1659,11 @@ public:
stack.initialise (new SavedState (&glState));
}
private:
void fillRectWithCustomShader (ShaderPrograms::ShaderBase& shader, const Rectangle<int>& area, Colour colour)
{
static_cast<SavedState&> (*stack).fillRectWithCustomShader (shader, area, colour);
}
GLState glState;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ShaderContext)
@ -1736,3 +1747,42 @@ void clearOpenGLGlyphCache()
{
OpenGLRendering::SavedState::GlyphCacheType::getInstance().reset();
}
//==============================================================================
struct OpenGLGraphicsContextCustomShader::Pimpl : public OpenGLRendering::ShaderPrograms::ShaderBase
{
Pimpl (OpenGLRendering::ShaderContext& c, const String& fragmentShader)
: ShaderBase (c.glState.target.context, fragmentShader.toRawUTF8())
{
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pimpl)
};
OpenGLGraphicsContextCustomShader::OpenGLGraphicsContextCustomShader (Pimpl* p) : pimpl (p) {}
OpenGLGraphicsContextCustomShader::~OpenGLGraphicsContextCustomShader() {}
OpenGLGraphicsContextCustomShader* OpenGLGraphicsContextCustomShader::create (LowLevelGraphicsContext& gc, StringRef fragmentShaderCode)
{
if (OpenGLRendering::ShaderContext* sc = dynamic_cast<OpenGLRendering::ShaderContext*> (&gc))
{
ScopedPointer<Pimpl> p (new Pimpl (*sc, String (JUCE_DECLARE_VARYING_COLOUR JUCE_DECLARE_VARYING_PIXELPOS "\n") + fragmentShaderCode));
if (! p->program.isLinked())
return nullptr;
return new OpenGLGraphicsContextCustomShader (p.release());
}
jassertfalse; // You've passed-in a non-GL context!
return nullptr;
}
void OpenGLGraphicsContextCustomShader::fillRect (LowLevelGraphicsContext& gc, const Rectangle<int>& area, Colour colour) const
{
jassert (pimpl != nullptr);
if (OpenGLRendering::ShaderContext* sc = dynamic_cast<OpenGLRendering::ShaderContext*> (&gc))
sc->fillRectWithCustomShader (*pimpl, area, colour);
}

View file

@ -46,4 +46,45 @@ LowLevelGraphicsContext* createOpenGLGraphicsContext (OpenGLContext& context,
int width, int height);
//==============================================================================
/**
Used to create custom shaders for use with an openGL 2D rendering context.
Given a GL-based rendering context, you can write a fragment shader that applies some
kind of per-pixel effect.
*/
struct JUCE_API OpenGLGraphicsContextCustomShader
{
/** Destructor. */
~OpenGLGraphicsContextCustomShader();
/** Attempts to compile and return a new shader object.
This must be called only when an openGL context is active. It'll return nullptr
if the code fails to compile or some other error occurs.
The shader code should be a normal fragment shader. As well as the usual variables, there
will be some extra ones: "frontColour", which is the colour that gets passed into the fillRect
method, and "pixelPos", which is a vec2 indicating the pixel position within the graphics context
of the pixel being drawn.
*/
static OpenGLGraphicsContextCustomShader* create (LowLevelGraphicsContext&,
StringRef fragmentShaderCode);
/** Applies the shader to a rectangle within the graphics context.
NB: This will ignore any clip region that is active.
*/
void fillRect (LowLevelGraphicsContext&, const Rectangle<int>& area, Colour colour) const;
private:
struct Pimpl;
friend struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
OpenGLGraphicsContextCustomShader (Pimpl*);
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLGraphicsContextCustomShader)
};
#endif // JUCE_OPENGLGRAPHICSCONTEXT_H_INCLUDED

View file

@ -80,7 +80,10 @@ public:
bool link() noexcept;
/** Get the output for the last shader compilation or link that failed. */
const String& getLastError() const noexcept { return errorLog; }
const String& getLastError() const noexcept { return errorLog; }
/** Returns true if the program is linked and ready for use. */
bool isLinked() const noexcept { return programID != 0; }
/** Selects this program into the current context. */
void use() const noexcept;