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:
parent
1fef7a8408
commit
6427e11ae3
5 changed files with 122 additions and 11 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue