mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
OpenGL gradient rendering. Viewport fix.
This commit is contained in:
parent
b684a99d3a
commit
58580fc792
9 changed files with 242 additions and 69 deletions
|
|
@ -639,7 +639,7 @@ public:
|
|||
private:
|
||||
// Some GL implementations can't take very large triangle lists, so store
|
||||
// the list as a series of blocks containing this max number of triangles.
|
||||
enum { trianglesPerBlock = 2048 };
|
||||
enum { trianglesPerBlock = 256 };
|
||||
|
||||
struct TriangleBlock
|
||||
{
|
||||
|
|
|
|||
|
|
@ -121,4 +121,146 @@ void OpenGLHelpers::drawQuad3D (float x1, float y1, float z1,
|
|||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
namespace OpenGLGradientHelpers
|
||||
{
|
||||
void drawTriangles (GLenum mode, const GLfloat* vertices, const GLfloat* textureCoords, const int numElements)
|
||||
{
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState (GL_COLOR_ARRAY);
|
||||
glDisableClientState (GL_NORMAL_ARRAY);
|
||||
|
||||
glVertexPointer (2, GL_FLOAT, 0, vertices);
|
||||
glTexCoordPointer (2, GL_FLOAT, 0, textureCoords);
|
||||
|
||||
glColor4f (1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glDrawArrays (mode, 0, numElements);
|
||||
}
|
||||
|
||||
void fillWithLinearGradient (const Rectangle<int>& rect,
|
||||
const ColourGradient& grad,
|
||||
const AffineTransform& transform,
|
||||
const int textureSize)
|
||||
{
|
||||
const Point<float> p1 (grad.point1.transformedBy (transform));
|
||||
const Point<float> p2 (grad.point2.transformedBy (transform));
|
||||
const Point<float> p3 (Point<float> (grad.point1.getX() - (grad.point2.getY() - grad.point1.getY()) / textureSize,
|
||||
grad.point1.getY() + (grad.point2.getX() - grad.point1.getX()) / textureSize).transformedBy (transform));
|
||||
|
||||
const AffineTransform textureTransform (AffineTransform::fromTargetPoints (p1.getX(), p1.getY(), 0.0f, 0.0f,
|
||||
p2.getX(), p2.getY(), 1.0f, 0.0f,
|
||||
p3.getX(), p3.getY(), 0.0f, 1.0f));
|
||||
|
||||
const float l = (float) rect.getX();
|
||||
const float r = (float) rect.getRight();
|
||||
const float t = (float) rect.getY();
|
||||
const float b = (float) rect.getBottom();
|
||||
|
||||
const GLfloat vertices[] = { l, t, r, t, l, b, r, b };
|
||||
GLfloat textureCoords[] = { l, t, r, t, l, b, r, b };
|
||||
|
||||
textureTransform.transformPoints (textureCoords[0], textureCoords[1], textureCoords[2], textureCoords[3]);
|
||||
textureTransform.transformPoints (textureCoords[4], textureCoords[5], textureCoords[6], textureCoords[7]);
|
||||
|
||||
drawTriangles (GL_TRIANGLE_STRIP, vertices, textureCoords, 4);
|
||||
}
|
||||
|
||||
void fillWithRadialGradient (const Rectangle<int>& rect,
|
||||
const ColourGradient& grad,
|
||||
const AffineTransform& transform)
|
||||
{
|
||||
const Point<float> centre (grad.point1.transformedBy (transform));
|
||||
|
||||
const float screenRadius = centre.getDistanceFrom (rect.getCentre().toFloat())
|
||||
+ Point<int> (rect.getWidth() / 2,
|
||||
rect.getHeight() / 2).getDistanceFromOrigin()
|
||||
+ 8.0f;
|
||||
|
||||
const AffineTransform inverse (transform.inverted());
|
||||
const float renderingRadius = jmax (Point<float> (screenRadius, 0.0f).transformedBy (inverse).getDistanceFromOrigin(),
|
||||
Point<float> (0.0f, screenRadius).transformedBy (inverse).getDistanceFromOrigin());
|
||||
|
||||
const int numDivisions = 80;
|
||||
GLfloat vertices [6 + numDivisions * 4];
|
||||
GLfloat textureCoords [6 + numDivisions * 4];
|
||||
|
||||
{
|
||||
const float originalRadius = grad.point1.getDistanceFrom (grad.point2);
|
||||
const float texturePos = renderingRadius / originalRadius;
|
||||
|
||||
GLfloat* t = textureCoords;
|
||||
*t++ = 0.0f;
|
||||
*t++ = 0.0f;
|
||||
|
||||
for (int i = numDivisions + 1; --i >= 0;)
|
||||
{
|
||||
*t++ = texturePos;
|
||||
*t++ = 0.0f;
|
||||
*t++ = texturePos;
|
||||
*t++ = 1.0f;
|
||||
}
|
||||
|
||||
jassert (t == textureCoords + numElementsInArray (vertices));
|
||||
}
|
||||
|
||||
{
|
||||
GLfloat* v = vertices;
|
||||
|
||||
*v++ = centre.getX();
|
||||
*v++ = centre.getY();
|
||||
|
||||
const Point<float> first (grad.point1.translated (renderingRadius, -renderingRadius).transformedBy (transform));
|
||||
Point<float> last (first);
|
||||
|
||||
for (int i = 0; i < numDivisions; ++i)
|
||||
{
|
||||
const float angle = (i + 1) * (float_Pi * 4.0f / numDivisions);
|
||||
const Point<float> next (grad.point1.translated (std::sin (angle) * renderingRadius,
|
||||
-std::cos (angle) * renderingRadius)
|
||||
.transformedBy (transform));
|
||||
*v++ = last.getX();
|
||||
*v++ = last.getY();
|
||||
*v++ = next.getX();
|
||||
*v++ = next.getY();
|
||||
last = next;
|
||||
}
|
||||
|
||||
*v++ = last.getX();
|
||||
*v++ = last.getY();
|
||||
*v++ = first.getX();
|
||||
*v++ = first.getY();
|
||||
|
||||
jassert (v == vertices + numElementsInArray (vertices));
|
||||
}
|
||||
|
||||
glEnable (GL_SCISSOR_TEST);
|
||||
glScissor (rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
|
||||
drawTriangles (GL_TRIANGLE_FAN, vertices, textureCoords, numDivisions + 3);
|
||||
glDisable (GL_SCISSOR_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLHelpers::fillRectWithColourGradient (const Rectangle<int>& rect,
|
||||
const ColourGradient& gradient,
|
||||
const AffineTransform& transform)
|
||||
{
|
||||
const int textureSize = 256;
|
||||
OpenGLTexture texture;
|
||||
|
||||
HeapBlock<PixelARGB> lookup (textureSize);
|
||||
gradient.createLookupTable (lookup, textureSize);
|
||||
texture.load (lookup, textureSize, 1);
|
||||
texture.bind();
|
||||
|
||||
if (gradient.isOpaque())
|
||||
glDisable (GL_BLEND);
|
||||
else
|
||||
glEnable (GL_BLEND);
|
||||
|
||||
if (gradient.isRadial)
|
||||
OpenGLGradientHelpers::fillWithRadialGradient (rect, gradient, transform);
|
||||
else
|
||||
OpenGLGradientHelpers::fillWithLinearGradient (rect, gradient, transform, textureSize);
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -60,6 +60,11 @@ public:
|
|||
float x3, float y3, float z3,
|
||||
float x4, float y4, float z4,
|
||||
const Colour& colour);
|
||||
|
||||
/** Fills a rectangle with the specified gradient. */
|
||||
static void fillRectWithColourGradient (const Rectangle<int>& rect,
|
||||
const ColourGradient& gradient,
|
||||
const AffineTransform& transform);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#if JUCE_OPENGL_ES
|
||||
enum { internalGLTextureFormat = GL_RGBA };
|
||||
#else
|
||||
enum { internalGLTextureFormat = 4 };
|
||||
#endif
|
||||
|
||||
|
||||
OpenGLTexture::OpenGLTexture()
|
||||
: textureID (0), width (0), height (0)
|
||||
|
|
@ -36,12 +42,12 @@ OpenGLTexture::~OpenGLTexture()
|
|||
release();
|
||||
}
|
||||
|
||||
void OpenGLTexture::load (const Image& image)
|
||||
void OpenGLTexture::create (const int w, const int h)
|
||||
{
|
||||
release();
|
||||
|
||||
width = image.getWidth();
|
||||
height = image.getHeight();
|
||||
width = w;
|
||||
height = h;
|
||||
|
||||
jassert (BitArray (width).countNumberOfSetBits() == 1); // these dimensions must be a power-of-two
|
||||
jassert (BitArray (height).countNumberOfSetBits() == 1);
|
||||
|
|
@ -57,21 +63,27 @@ void OpenGLTexture::load (const Image& image)
|
|||
glTexParameterf (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
|
||||
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
|
||||
}
|
||||
|
||||
void OpenGLTexture::load (const Image& image)
|
||||
{
|
||||
create (image.getWidth(), image.getHeight());
|
||||
|
||||
Image::BitmapData srcData (image, Image::BitmapData::readOnly);
|
||||
|
||||
#if JUCE_OPENGL_ES
|
||||
enum { internalFormat = GL_RGBA };
|
||||
#else
|
||||
enum { internalFormat = 4 };
|
||||
#endif
|
||||
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internalFormat,
|
||||
width, height, 0,
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internalGLTextureFormat, width, height, 0,
|
||||
image.getFormat() == Image::RGB ? GL_RGB : GL_BGRA_EXT,
|
||||
GL_UNSIGNED_BYTE, srcData.data);
|
||||
}
|
||||
|
||||
void OpenGLTexture::load (const PixelARGB* const pixels, const int w, const int h)
|
||||
{
|
||||
create (w, h);
|
||||
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, internalGLTextureFormat, w, h, 0,
|
||||
GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
||||
void OpenGLTexture::release()
|
||||
{
|
||||
if (textureID != 0)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ public:
|
|||
*/
|
||||
void load (const Image& image);
|
||||
|
||||
/** Creates a texture from a raw array of pixels. */
|
||||
void load (const PixelARGB* pixels, int width, int height);
|
||||
|
||||
/** Frees the texture, if there is one. */
|
||||
void release();
|
||||
|
||||
|
|
@ -67,6 +70,8 @@ private:
|
|||
unsigned int textureID;
|
||||
int width, height;
|
||||
|
||||
void create (int w, int h);
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OpenGLTexture);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue