mirror of https://github.com/buggins/dlangui.git
new batching implementation
This commit is contained in:
parent
34172b8a31
commit
e288e6fd40
|
@ -65,7 +65,7 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
glSupport.setOrthoProjection(Rect(0, 0, _dx, _dy), Rect(0, 0, _dx, _dy));
|
||||
}
|
||||
|
||||
/// reserved for hardware-accelerated drawing - begins drawing batch
|
||||
/// reserved for hardware-accelerated drawing - begins drawing queue
|
||||
override void beforeDrawing() {
|
||||
_alpha = 0;
|
||||
if (_scene !is null) {
|
||||
|
@ -74,11 +74,12 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
_scene = new Scene(this);
|
||||
}
|
||||
|
||||
/// reserved for hardware-accelerated drawing - ends drawing batch
|
||||
/// reserved for hardware-accelerated drawing - ends drawing queue
|
||||
override void afterDrawing() {
|
||||
glSupport.setOrthoProjection(Rect(0, 0, _dx, _dy), Rect(0, 0, _dx, _dy));
|
||||
glSupport.beforeRenderGUI();
|
||||
_scene.draw();
|
||||
glSupport.batch.flush();
|
||||
glSupport.queue.flush();
|
||||
GLProgram.unbind();
|
||||
glSupport.destroyBuffers();
|
||||
glSupport.flushGL();
|
||||
|
@ -142,7 +143,6 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
assert(_scene !is null);
|
||||
Rect dstrect = Rect(x,y, x + glyph.correctedBlackBoxX, y + glyph.blackBoxY);
|
||||
Rect srcrect = Rect(0, 0, glyph.correctedBlackBoxX, glyph.blackBoxY);
|
||||
//Log.v("GLDrawBuf.drawGlyph dst=", dstrect, " src=", srcrect, " color=", color);
|
||||
color = applyAlpha(color);
|
||||
if (!isFullyTransparentColor(color) && applyClipping(dstrect, srcrect)) {
|
||||
if (!glGlyphCache.isInCache(glyph.id))
|
||||
|
@ -158,7 +158,7 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
if (applyClipping(dstrect, srcrect)) {
|
||||
if (!glImageCache.isInCache(src.id))
|
||||
glImageCache.put(src);
|
||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, applyAlpha(0xFFFFFF), 0, null, 0));
|
||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, applyAlpha(0xFFFFFF), 0, null));
|
||||
}
|
||||
}
|
||||
/// draw source buffer rectangle contents to destination buffer rectangle applying rescaling
|
||||
|
@ -168,7 +168,7 @@ class GLDrawBuf : DrawBuf, GLConfigCallback {
|
|||
if (applyClipping(dstrect, srcrect)) {
|
||||
if (!glImageCache.isInCache(src.id))
|
||||
glImageCache.put(src);
|
||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, applyAlpha(0xFFFFFF), 0, null, 0));
|
||||
_scene.add(new TextureSceneItem(src.id, dstrect, srcrect, applyAlpha(0xFFFFFF), 0, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -545,17 +545,12 @@ private class GLImageCache : GLCache
|
|||
_needUpdateTexture = true;
|
||||
return cacheItem;
|
||||
}
|
||||
void drawItem(GLCacheItem item, Rect dstrc, Rect srcrc, uint color, uint options, Rect * clip, int rotationAngle) {
|
||||
void drawItem(GLCacheItem item, Rect dstrc, Rect srcrc, uint color, uint options, Rect * clip) {
|
||||
if (_needUpdateTexture)
|
||||
updateTexture();
|
||||
if (_texture && _texture.ID != 0) {
|
||||
//rotationAngle = 0;
|
||||
int rx = dstrc.middlex;
|
||||
int ry = dstrc.middley;
|
||||
if (rotationAngle) {
|
||||
//rotationAngle = 0;
|
||||
//setRotation(rx, ry, rotationAngle);
|
||||
}
|
||||
// convert coordinates to cached texture
|
||||
srcrc.offset(item._rc.left, item._rc.top);
|
||||
if (clip) {
|
||||
|
@ -577,17 +572,7 @@ private class GLImageCache : GLCache
|
|||
dstrc.bottom -= clip.bottom;
|
||||
}
|
||||
if (!dstrc.empty)
|
||||
glSupport.batch.addTexturedRect(_texture, _tdx, _tdy, color, color, color, color, srcrc, dstrc, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
|
||||
//glSupport.drawColorAndTextureRects(_texture, _tdx, _tdy, [srcrc], [dstrc], [color, color, color, color], srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
|
||||
//drawColorAndTextureRect(vertices, texcoords, color, _texture);
|
||||
|
||||
if (rotationAngle) {
|
||||
// unset rotation
|
||||
glSupport.setRotation(rx, ry, 0);
|
||||
// glMatrixMode(GL_PROJECTION);
|
||||
// checkgl!glPopMatrix();
|
||||
}
|
||||
|
||||
glSupport.queue.addTexturedRect(_texture, _tdx, _tdy, color, color, color, color, srcrc, dstrc, srcrc.width() != dstrc.width() || srcrc.height() != dstrc.height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -619,11 +604,11 @@ private class GLImageCache : GLCache
|
|||
_map[img.id] = res;
|
||||
}
|
||||
/// draw cached item
|
||||
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, int options, Rect * clip, int rotationAngle) {
|
||||
void drawItem(uint objectId, Rect dstrc, Rect srcrc, uint color, int options, Rect * clip) {
|
||||
GLCacheItem* item = objectId in _map;
|
||||
if (item) {
|
||||
auto page = (cast(GLImageCachePage)item.page);
|
||||
page.drawItem(*item, dstrc, srcrc, color, options, clip, rotationAngle);
|
||||
page.drawItem(*item, dstrc, srcrc, color, options, clip);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -673,9 +658,7 @@ private class GLGlyphCache : GLCache
|
|||
}
|
||||
if (!dstrc.empty) {
|
||||
//Log.d("drawing glyph with color ", color);
|
||||
//glSupport.drawColorAndTextureRect(_texture, _tdx, _tdy, srcrc, dstrc, color, false);
|
||||
//glSupport.drawColorAndTextureRects(_texture, _tdx, _tdy, [srcrc], [dstrc], [color, color, color, color], false);
|
||||
glSupport.batch.addTexturedRect(_texture, _tdx, _tdy, color, color, color, color, srcrc, dstrc, false);
|
||||
glSupport.queue.addTexturedRect(_texture, _tdx, _tdy, color, color, color, color, srcrc, dstrc, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -723,8 +706,7 @@ public:
|
|||
_color = color;
|
||||
}
|
||||
override void draw() {
|
||||
//glSupport.drawLines([Rect(_p1, _p2)], [_color, _color]);
|
||||
glSupport.batch.addLine(Rect(_p1, _p2), _color, _color);
|
||||
glSupport.queue.addLine(Rect(_p1, _p2), _color, _color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -743,7 +725,7 @@ public:
|
|||
_color = color;
|
||||
}
|
||||
override void draw() {
|
||||
glSupport.batch.addTriangle(_p1, _p2, _p3, _color, _color, _color);
|
||||
glSupport.queue.addTriangle(_p1, _p2, _p3, _color, _color, _color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,8 +740,7 @@ public:
|
|||
_color = color;
|
||||
}
|
||||
override void draw() {
|
||||
glSupport.batch.addSolidRect(_rc, _color);
|
||||
//glSupport.drawSolidFillRects([_rc], [_color, _color, _color, _color]);
|
||||
glSupport.queue.addSolidRect(_rc, _color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,9 +762,7 @@ public:
|
|||
for (int y = _rc.top; y < _rc.bottom; y++) {
|
||||
for (int x = _rc.left; x < _rc.right; x++)
|
||||
if ((x ^ y) & 1) {
|
||||
//glSupport.drawSolidFillRect(Rect(x, y, x + 1, y + 1), _color, _color, _color, _color);
|
||||
//glSupport.drawSolidFillRects([Rect(x, y, x + 1, y + 1)], [_color, _color, _color, _color]);
|
||||
glSupport.batch.addSolidRect(Rect(x, y, x + 1, y + 1), _color);
|
||||
glSupport.queue.addSolidRect(Rect(x, y, x + 1, y + 1), _color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -798,15 +777,14 @@ private:
|
|||
uint color;
|
||||
uint options;
|
||||
Rect * clip;
|
||||
int rotationAngle;
|
||||
|
||||
public:
|
||||
override void draw() {
|
||||
if (glImageCache)
|
||||
glImageCache.drawItem(objectId, dstrc, srcrc, color, options, clip, rotationAngle);
|
||||
glImageCache.drawItem(objectId, dstrc, srcrc, color, options, clip);
|
||||
}
|
||||
|
||||
this(uint _objectId, Rect _dstrc, Rect _srcrc, uint _color, uint _options, Rect * _clip, int _rotationAngle)
|
||||
this(uint _objectId, Rect _dstrc, Rect _srcrc, uint _color, uint _options, Rect * _clip)
|
||||
{
|
||||
objectId = _objectId;
|
||||
dstrc = _dstrc;
|
||||
|
@ -814,7 +792,6 @@ public:
|
|||
color = _color;
|
||||
options = _options;
|
||||
clip = _clip;
|
||||
rotationAngle = _rotationAngle;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -856,13 +833,12 @@ public:
|
|||
}
|
||||
override void draw() {
|
||||
if (_handler) {
|
||||
glSupport.batch.flush();
|
||||
glSupport.queue.flush();
|
||||
glSupport.setOrthoProjection(_windowRect, _rc);
|
||||
glSupport.clearDepthBuffer();
|
||||
//glEnable(GL_BLEND);
|
||||
//checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
_handler(_windowRect, _rc);
|
||||
glSupport.batch.flush();
|
||||
glSupport.setOrthoProjection(_windowRect, _windowRect);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ version (Android) {
|
|||
public import EGL.egl;
|
||||
//public import GLES2.gl2;
|
||||
public import GLES3.gl3;
|
||||
|
||||
|
||||
static if (SUPPORT_LEGACY_OPENGL) {
|
||||
public import GLES.gl : glEnableClientState, glLightfv, glColor4f, GL_ALPHA_TEST, GL_VERTEX_ARRAY,
|
||||
GL_COLOR_ARRAY, glVertexPointer, glColorPointer, glDisableClientState,
|
||||
|
@ -268,7 +268,7 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect {
|
|||
|
||||
/// override to init shader code locations
|
||||
abstract bool initLocations();
|
||||
|
||||
|
||||
~this() {
|
||||
// TODO: cleanup
|
||||
if (program)
|
||||
|
@ -499,88 +499,50 @@ class SolidFillProgram : GLProgram {
|
|||
}
|
||||
|
||||
VAO vao;
|
||||
VBO vbo;
|
||||
EBO ebo;
|
||||
|
||||
protected void createVAO(float[] vertices, float[] colors) {
|
||||
if (!vao) {
|
||||
vao = new VAO;
|
||||
vbo = new VBO;
|
||||
ebo = new EBO;
|
||||
}
|
||||
vbo.bind();
|
||||
ebo.bind();
|
||||
vao.bind();
|
||||
protected void beforeExecute() {
|
||||
bind();
|
||||
setUniform(DefaultUniform.u_worldViewProjectionMatrix, glSupport.projectionMatrix);
|
||||
}
|
||||
|
||||
protected void createVAO(size_t verticesBufferLength) {
|
||||
vao = new VAO;
|
||||
|
||||
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
|
||||
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * float.sizeof));
|
||||
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (verticesBufferLength * float.sizeof));
|
||||
|
||||
glEnableVertexAttribArray(vertexLocation);
|
||||
glEnableVertexAttribArray(colAttrLocation);
|
||||
}
|
||||
|
||||
protected void beforeExecute() {
|
||||
glEnable(GL_BLEND);
|
||||
checkgl!glDisable(GL_CULL_FACE);
|
||||
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
bind();
|
||||
setUniform(DefaultUniform.u_worldViewProjectionMatrix, glSupport.projectionMatrix);
|
||||
//checkgl!glUniformMatrix4fv(matrixLocation, 1, false, glSupport.projectionMatrix.m.ptr);
|
||||
}
|
||||
|
||||
bool execute(float[] vertices, float[] colors, int[] indexes) {
|
||||
bool drawBatch(int length, int start) {
|
||||
if(!check())
|
||||
return false;
|
||||
beforeExecute();
|
||||
|
||||
createVAO(vertices, colors);
|
||||
|
||||
vbo.bind();
|
||||
vbo.fill([vertices, colors]);
|
||||
|
||||
ebo.bind();
|
||||
ebo.fill(indexes);
|
||||
|
||||
vao.bind();
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)null);
|
||||
|
||||
vao.unbind();
|
||||
vbo.unbind();
|
||||
ebo.unbind();
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(start * 4));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void destroyBuffers() {
|
||||
destroy(vao);
|
||||
destroy(vbo);
|
||||
destroy(ebo);
|
||||
vao = null;
|
||||
vbo = null;
|
||||
ebo = null;
|
||||
}
|
||||
}
|
||||
|
||||
class LineProgram : SolidFillProgram {
|
||||
override bool execute(float[] vertices, float[] colors, int[] indexes) {
|
||||
override bool drawBatch(int length, int start) {
|
||||
if(!check())
|
||||
return false;
|
||||
beforeExecute();
|
||||
|
||||
createVAO(vertices, colors);
|
||||
|
||||
vbo.bind();
|
||||
vbo.fill([vertices, colors]);
|
||||
|
||||
ebo.bind();
|
||||
ebo.fill(indexes);
|
||||
|
||||
vao.bind();
|
||||
checkgl!glDrawElements(GL_LINES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)null);
|
||||
|
||||
vao.unbind();
|
||||
vbo.unbind();
|
||||
ebo.unbind();
|
||||
checkgl!glDrawElements(GL_LINES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(start * 4));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -624,33 +586,26 @@ class TextureProgram : SolidFillProgram {
|
|||
/// get location for vertex attribute
|
||||
override int getVertexElementLocation(VertexElementType type) {
|
||||
switch(type) with(VertexElementType) {
|
||||
case TEXCOORD0:
|
||||
case TEXCOORD0:
|
||||
return texCoordLocation;
|
||||
default:
|
||||
return super.getVertexElementLocation(type);
|
||||
}
|
||||
}
|
||||
|
||||
protected void createVAO(float[] vertices, float[] colors, float[] texcoords) {
|
||||
if (!vao) {
|
||||
vao = new VAO;
|
||||
vbo = new VBO;
|
||||
ebo = new EBO;
|
||||
}
|
||||
vbo.bind();
|
||||
ebo.bind();
|
||||
vao.bind();
|
||||
protected void createVAO(size_t verticesBufferLength, size_t colorsBufferLength) {
|
||||
vao = new VAO;
|
||||
|
||||
glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 0, cast(void*) 0);
|
||||
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (vertices.length * float.sizeof));
|
||||
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) ((vertices.length + colors.length) * float.sizeof));
|
||||
glVertexAttribPointer(colAttrLocation, 4, GL_FLOAT, GL_FALSE, 0, cast(void*) (verticesBufferLength * float.sizeof));
|
||||
glVertexAttribPointer(texCoordLocation, 2, GL_FLOAT, GL_FALSE, 0, cast(void*) ((verticesBufferLength + colorsBufferLength) * float.sizeof));
|
||||
|
||||
glEnableVertexAttribArray(vertexLocation);
|
||||
glEnableVertexAttribArray(colAttrLocation);
|
||||
glEnableVertexAttribArray(texCoordLocation);
|
||||
}
|
||||
|
||||
bool execute(float[] vertices, float[] colors, float[] texcoords, Tex2D texture, bool linear, int[] indexes) {
|
||||
bool drawBatch(Tex2D texture, bool linear, int length, int start) {
|
||||
if(!check())
|
||||
return false;
|
||||
beforeExecute();
|
||||
|
@ -658,21 +613,9 @@ class TextureProgram : SolidFillProgram {
|
|||
texture.setup();
|
||||
texture.setSamplerParams(linear);
|
||||
|
||||
createVAO(vertices, colors, texcoords);
|
||||
|
||||
vbo.bind();
|
||||
vbo.fill([vertices, colors, texcoords]);
|
||||
|
||||
ebo.bind();
|
||||
ebo.fill(indexes);
|
||||
|
||||
vao.bind();
|
||||
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)null);
|
||||
|
||||
vao.unbind();
|
||||
vbo.unbind();
|
||||
ebo.unbind();
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(start * 4));
|
||||
|
||||
texture.unbind();
|
||||
return true;
|
||||
|
@ -699,6 +642,24 @@ private void FillColor(uint color, Color[] buf_slice) {
|
|||
}
|
||||
}
|
||||
|
||||
private float[] convertColors(uint[] cols) {
|
||||
float[] colors;
|
||||
colors.assumeSafeAppend();
|
||||
colors.length = cols.length * 4;
|
||||
for (uint i = 0; i < cols.length; i++) {
|
||||
uint color = cols[i];
|
||||
float r = ((color >> 16) & 255) / 255.0;
|
||||
float g = ((color >> 8) & 255) / 255.0;
|
||||
float b = ((color >> 0) & 255) / 255.0;
|
||||
float a = (((color >> 24) & 255) ^ 255) / 255.0;
|
||||
colors[i * 4 + 0] = r;
|
||||
colors[i * 4 + 1] = g;
|
||||
colors[i * 4 + 2] = b;
|
||||
colors[i * 4 + 3] = a;
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
__gshared GLSupport _glSupport;
|
||||
@property GLSupport glSupport() {
|
||||
if (!_glSupport) {
|
||||
|
@ -794,10 +755,10 @@ final class GLSupport {
|
|||
|
||||
private bool _legacyMode;
|
||||
@property bool legacyMode() { return _legacyMode; }
|
||||
@property batch() { return _batch; }
|
||||
@property queue() { return _queue; }
|
||||
|
||||
this(bool legacy = false) {
|
||||
_batch = new OpenGLBatch();
|
||||
_queue = new OpenGLQueue;
|
||||
version (Android) {
|
||||
Log.d("creating GLSupport");
|
||||
} else {
|
||||
|
@ -809,7 +770,7 @@ final class GLSupport {
|
|||
_legacyMode = legacy;
|
||||
}
|
||||
|
||||
OpenGLBatch _batch;
|
||||
OpenGLQueue _queue;
|
||||
|
||||
SolidFillProgram _solidFillProgram;
|
||||
LineProgram _lineProgram;
|
||||
|
@ -860,67 +821,48 @@ final class GLSupport {
|
|||
return true;
|
||||
}
|
||||
|
||||
void beforeRenderGUI() {
|
||||
glEnable(GL_BLEND);
|
||||
checkgl!glDisable(GL_CULL_FACE);
|
||||
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
VBO vbo;
|
||||
EBO ebo;
|
||||
|
||||
void fillBuffers(float[] vertices, float[] colors, float[] texcoords, int[] indices) {
|
||||
vbo = new VBO;
|
||||
ebo = new EBO;
|
||||
|
||||
vbo.bind();
|
||||
vbo.fill([vertices, colors, texcoords]);
|
||||
|
||||
ebo.bind();
|
||||
ebo.fill(indices);
|
||||
|
||||
// create vertex array objects and bind vertex buffers to them
|
||||
_solidFillProgram.createVAO(vertices.length);
|
||||
vbo.bind();
|
||||
ebo.bind();
|
||||
_lineProgram.vao = _solidFillProgram.vao;
|
||||
_textureProgram.createVAO(vertices.length, colors.length);
|
||||
vbo.bind();
|
||||
ebo.bind();
|
||||
}
|
||||
|
||||
void destroyBuffers() {
|
||||
if (_solidFillProgram)
|
||||
_solidFillProgram.destroyBuffers();
|
||||
if (_lineProgram)
|
||||
_lineProgram.destroyBuffers();
|
||||
if (_textureProgram)
|
||||
_textureProgram.destroyBuffers();
|
||||
|
||||
destroy(vbo);
|
||||
destroy(ebo);
|
||||
vbo = null;
|
||||
ebo = null;
|
||||
}
|
||||
|
||||
void setRotation(int x, int y, int rotationAngle) {
|
||||
/*
|
||||
this->rotationAngle = rotationAngle;
|
||||
rotationX = x;
|
||||
rotationY = y;
|
||||
if (!currentFramebufferId) {
|
||||
rotationY = bufferDy - rotationY;
|
||||
}
|
||||
|
||||
QMatrix4x4 matrix2;
|
||||
matrix2.ortho(0, bufferDx, 0, bufferDy, 0.5f, 5.0f);
|
||||
if (rotationAngle) {
|
||||
matrix2.translate(rotationX, rotationY, 0);
|
||||
matrix2.rotate(rotationAngle, 0, 0, 1);
|
||||
matrix2.translate(-rotationX, -rotationY, 0);
|
||||
}
|
||||
matrix2.copyDataTo(m);
|
||||
*/
|
||||
}
|
||||
|
||||
/// one rect is one line (left, top) - (right, bottom); for one line there are two color items
|
||||
void drawLines(Rect[] lines, uint[] vertexColors) {
|
||||
Color[] colors;
|
||||
colors.length = vertexColors.length;
|
||||
for (uint i = 0; i < vertexColors.length; i++)
|
||||
FillColor(vertexColors[i], colors[i .. i + 1]);
|
||||
|
||||
float[] vertexArray;
|
||||
vertexArray.assumeSafeAppend();
|
||||
for (uint i = 0; i < lines.length; i++) {
|
||||
Rect rc = lines[i];
|
||||
|
||||
float x0 = cast(float)(rc.left);
|
||||
float y0 = cast(float)(bufferDy-rc.top);
|
||||
float x1 = cast(float)(rc.right);
|
||||
float y1 = cast(float)(bufferDy-rc.bottom);
|
||||
|
||||
// don't flip for framebuffer
|
||||
if (currentFBO) {
|
||||
y0 = cast(float)(rc.top);
|
||||
y1 = cast(float)(rc.bottom);
|
||||
}
|
||||
|
||||
vertexArray ~= x0;
|
||||
vertexArray ~= y0;
|
||||
vertexArray ~= Z_2D;
|
||||
vertexArray ~= x1;
|
||||
vertexArray ~= y1;
|
||||
vertexArray ~= Z_2D;
|
||||
}
|
||||
|
||||
int[] indexes = makeLineIndexesArray(lines.length);
|
||||
void drawLines(int length, int start) {
|
||||
|
||||
if (_legacyMode) {
|
||||
static if (SUPPORT_LEGACY_OPENGL) {
|
||||
|
@ -931,10 +873,10 @@ final class GLSupport {
|
|||
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
|
||||
checkgl!glEnableClientState(GL_COLOR_ARRAY);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)vertexArray.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
|
||||
|
||||
checkgl!glDrawElements(GL_LINES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)indexes.ptr);
|
||||
checkgl!glDrawElements(GL_LINES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -943,83 +885,13 @@ final class GLSupport {
|
|||
}
|
||||
} else {
|
||||
if (_lineProgram !is null) {
|
||||
_lineProgram.execute(vertexArray, cast(float[])colors, indexes);
|
||||
_lineProgram.drawBatch(length, start);
|
||||
} else
|
||||
Log.e("No program");
|
||||
}
|
||||
}
|
||||
|
||||
static immutable float Z_2D = -2.0f;
|
||||
|
||||
/// make indexes for rectangle TRIANGLES (2 triangles == 6 vertexes per rect)
|
||||
protected int[] makeRectangleIndexesArray(size_t rectCount) {
|
||||
int[] indexes;
|
||||
indexes.assumeSafeAppend();
|
||||
for (uint i = 0; i < rectCount; i++) {
|
||||
indexes ~= i * 4 + 0;
|
||||
indexes ~= i * 4 + 1;
|
||||
indexes ~= i * 4 + 2;
|
||||
indexes ~= i * 4 + 1;
|
||||
indexes ~= i * 4 + 2;
|
||||
indexes ~= i * 4 + 3;
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/// make indexes for rectangle TRIANGLES (2 triangles == 6 vertexes per rect)
|
||||
protected int[] makeTriangleIndexesArray(size_t pointCount) {
|
||||
int[] indexes;
|
||||
indexes.assumeSafeAppend();
|
||||
for (uint i = 0; i + 2 < pointCount; i += 3) {
|
||||
indexes ~= i + 0;
|
||||
indexes ~= i + 1;
|
||||
indexes ~= i + 2;
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
/// make indexes for LINES
|
||||
protected int[] makeLineIndexesArray(size_t lineCount) {
|
||||
int[] indexes;
|
||||
indexes.assumeSafeAppend();
|
||||
for (uint i = 0; i < lineCount; i++) {
|
||||
indexes ~= i * 2 + 0;
|
||||
indexes ~= i * 2 + 1;
|
||||
}
|
||||
return indexes;
|
||||
}
|
||||
|
||||
void drawSolidFillRects(Rect[] rects, uint[] vertexColors) {
|
||||
//Log.v("drawSolidFillRects rects:", rects.length, " colors:", vertexColors.length);
|
||||
float[] colors = convertColors(vertexColors);
|
||||
|
||||
float[] vertexArray;
|
||||
vertexArray.assumeSafeAppend();
|
||||
|
||||
for (uint i = 0; i < rects.length; i++) {
|
||||
Rect rc = rects[i];
|
||||
|
||||
float x0 = cast(float)(rc.left);
|
||||
float y0 = cast(float)(bufferDy-rc.top);
|
||||
float x1 = cast(float)(rc.right);
|
||||
float y1 = cast(float)(bufferDy-rc.bottom);
|
||||
|
||||
// don't flip for framebuffer
|
||||
if (currentFBO) {
|
||||
y0 = cast(float)(rc.top);
|
||||
y1 = cast(float)(rc.bottom);
|
||||
}
|
||||
|
||||
float[3 * 4] vertices = [
|
||||
x0,y0,Z_2D,
|
||||
x0,y1,Z_2D,
|
||||
x1,y0,Z_2D,
|
||||
x1,y1,Z_2D];
|
||||
|
||||
vertexArray ~= vertices;
|
||||
}
|
||||
|
||||
int[] indexes = makeRectangleIndexesArray(rects.length);
|
||||
void drawSolidFillTriangles(int length, int start) {
|
||||
|
||||
if (_legacyMode) {
|
||||
static if (SUPPORT_LEGACY_OPENGL) {
|
||||
|
@ -1030,10 +902,10 @@ final class GLSupport {
|
|||
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
|
||||
checkgl!glEnableClientState(GL_COLOR_ARRAY);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)vertexArray.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
|
||||
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)indexes.ptr);
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -1042,121 +914,13 @@ final class GLSupport {
|
|||
}
|
||||
} else {
|
||||
if (_solidFillProgram !is null) {
|
||||
_solidFillProgram.execute(vertexArray, colors, indexes);
|
||||
_solidFillProgram.drawBatch(length, start);
|
||||
} else
|
||||
Log.e("No program");
|
||||
}
|
||||
}
|
||||
|
||||
void drawSolidFillTriangles(PointF[] points, uint[] vertexColors) {
|
||||
//Log.v("drawSolidFillRects rects:", rects.length, " colors:", vertexColors.length);
|
||||
float[] colors = convertColors(vertexColors);
|
||||
|
||||
float[] vertexArray;
|
||||
vertexArray.assumeSafeAppend();
|
||||
|
||||
for (uint i = 0; i + 2 < points.length; i += 3) {
|
||||
float x0 = points[i+0].x;
|
||||
float y0 = currentFBO ? points[i+0].y : (bufferDy - points[i+0].y);
|
||||
float x1 = points[i+1].x;
|
||||
float y1 = currentFBO ? points[i+1].y : (bufferDy - points[i+1].y);
|
||||
float x2 = points[i+2].x;
|
||||
float y2 = currentFBO ? points[i+2].y : (bufferDy - points[i+2].y);
|
||||
|
||||
float[3 * 3] vertices = [
|
||||
x0,y0,Z_2D,
|
||||
x1,y1,Z_2D,
|
||||
x2,y2,Z_2D];
|
||||
|
||||
vertexArray ~= vertices;
|
||||
}
|
||||
|
||||
int[] indexes = makeTriangleIndexesArray(points.length);
|
||||
|
||||
if (_legacyMode) {
|
||||
static if (SUPPORT_LEGACY_OPENGL) {
|
||||
glColor4f(1,1,1,1);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
checkgl!glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
|
||||
checkgl!glEnableClientState(GL_COLOR_ARRAY);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)vertexArray.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr);
|
||||
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)indexes.ptr);
|
||||
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
} else {
|
||||
if (_solidFillProgram !is null) {
|
||||
_solidFillProgram.execute(vertexArray, colors, indexes);
|
||||
} else
|
||||
Log.e("No program");
|
||||
}
|
||||
}
|
||||
|
||||
float[] convertColors(uint[] cols) {
|
||||
float[] colors;
|
||||
colors.assumeSafeAppend();
|
||||
colors.length = cols.length * 4;
|
||||
for (uint i = 0; i < cols.length; i++) {
|
||||
uint color = cols[i];
|
||||
float r = ((color >> 16) & 255) / 255.0;
|
||||
float g = ((color >> 8) & 255) / 255.0;
|
||||
float b = ((color >> 0) & 255) / 255.0;
|
||||
float a = (((color >> 24) & 255) ^ 255) / 255.0;
|
||||
colors[i * 4 + 0] = r;
|
||||
colors[i * 4 + 1] = g;
|
||||
colors[i * 4 + 2] = b;
|
||||
colors[i * 4 + 3] = a;
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
|
||||
void drawColorAndTextureRects(Tex2D texture, int tdx, int tdy, Rect[] srcRects, Rect[] dstRects, uint[] vertexColors, bool linear) {
|
||||
float[] colors = convertColors(vertexColors);
|
||||
|
||||
float[] vertexArray;
|
||||
vertexArray.assumeSafeAppend();
|
||||
float[] txcoordArray;
|
||||
txcoordArray.assumeSafeAppend();
|
||||
|
||||
for (uint i = 0; i < srcRects.length; i++) {
|
||||
Rect srcrc = srcRects[i];
|
||||
Rect dstrc = dstRects[i];
|
||||
|
||||
float dstx0 = cast(float)dstrc.left;
|
||||
float dsty0 = cast(float)(bufferDy - (dstrc.top));
|
||||
float dstx1 = cast(float)dstrc.right;
|
||||
float dsty1 = cast(float)(bufferDy - (dstrc.bottom));
|
||||
|
||||
// don't flip for framebuffer
|
||||
if (currentFBO) {
|
||||
dsty0 = cast(float)(dstrc.top);
|
||||
dsty1 = cast(float)(dstrc.bottom);
|
||||
}
|
||||
|
||||
float srcx0 = srcrc.left / cast(float)tdx;
|
||||
float srcy0 = srcrc.top / cast(float)tdy;
|
||||
float srcx1 = srcrc.right / cast(float)tdx;
|
||||
float srcy1 = srcrc.bottom / cast(float)tdy;
|
||||
float[3 * 4] vertices = [
|
||||
dstx0,dsty0,Z_2D,
|
||||
dstx0,dsty1,Z_2D,
|
||||
dstx1,dsty0,Z_2D,
|
||||
dstx1,dsty1,Z_2D];
|
||||
float[2 * 4] texcoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy0, srcx1,srcy1];
|
||||
vertexArray ~= vertices;
|
||||
txcoordArray ~= texcoords;
|
||||
}
|
||||
|
||||
int[] indexes = makeRectangleIndexesArray(srcRects.length);
|
||||
//Log.v("drawColorAndTextureRects srcrects:", srcRects.length, " dstrects:", dstRects.length, " colors:", vertexColors.length, " indexes: ", indexes);
|
||||
void drawColorAndTextureTriangles(Tex2D texture, bool linear, int length, int start) {
|
||||
|
||||
if (_legacyMode) {
|
||||
static if (SUPPORT_LEGACY_OPENGL) {
|
||||
|
@ -1174,11 +938,11 @@ final class GLSupport {
|
|||
checkgl!glEnableClientState(GL_COLOR_ARRAY);
|
||||
checkgl!glEnableClientState(GL_VERTEX_ARRAY);
|
||||
checkgl!glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)vertexArray.ptr);
|
||||
checkgl!glTexCoordPointer(2, GL_FLOAT, 0, cast(void*)txcoordArray.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)colors.ptr);
|
||||
checkgl!glVertexPointer(3, GL_FLOAT, 0, cast(void*)_queue._vertices.ptr);
|
||||
checkgl!glTexCoordPointer(2, GL_FLOAT, 0, cast(void*)_queue._texCoords.ptr);
|
||||
checkgl!glColorPointer(4, GL_FLOAT, 0, cast(void*)_queue._colors.ptr);
|
||||
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)indexes.length, GL_UNSIGNED_INT, cast(void*)indexes.ptr);
|
||||
checkgl!glDrawElements(GL_TRIANGLES, cast(int)length, GL_UNSIGNED_INT, cast(void*)(_queue._indices.ptr + start * 4));
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
@ -1188,7 +952,7 @@ final class GLSupport {
|
|||
glDisable(GL_TEXTURE_2D);
|
||||
}
|
||||
} else {
|
||||
_textureProgram.execute(vertexArray, colors, txcoordArray, texture, linear, indexes);
|
||||
_textureProgram.drawBatch(texture, linear, length, start);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1412,7 +1176,7 @@ class GLObject(GLObjectTypes type, GLuint target = 0) {
|
|||
else
|
||||
mixin("checkgl!glBind" ~ to!string(type) ~ "(0);");
|
||||
}
|
||||
|
||||
|
||||
static if(type == GLObjectTypes.Buffer)
|
||||
{
|
||||
void fill(float[][] buffs) {
|
||||
|
@ -1422,7 +1186,7 @@ class GLObject(GLObjectTypes type, GLuint target = 0) {
|
|||
checkgl!glBufferData(target,
|
||||
length * float.sizeof,
|
||||
null,
|
||||
GL_STREAM_DRAW);
|
||||
GL_STATIC_DRAW);
|
||||
int offset;
|
||||
foreach(b; buffs) {
|
||||
checkgl!glBufferSubData(target,
|
||||
|
@ -1435,7 +1199,7 @@ class GLObject(GLObjectTypes type, GLuint target = 0) {
|
|||
|
||||
static if (target == GL_ELEMENT_ARRAY_BUFFER) {
|
||||
void fill(int[] indexes) {
|
||||
checkgl!glBufferData(target, cast(int)(indexes.length * int.sizeof), indexes.ptr, GL_STREAM_DRAW);
|
||||
checkgl!glBufferData(target, cast(int)(indexes.length * int.sizeof), indexes.ptr, GL_STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1678,95 +1442,234 @@ GLenum primitiveTypeToGL(PrimitiveType type) {
|
|||
}
|
||||
|
||||
|
||||
/// OpenGL batch buffer - to draw several triangles in single OpenGL call
|
||||
class OpenGLBatch {
|
||||
private Tex2D _currentTexture;
|
||||
private int _currentTextureDx;
|
||||
private int _currentTextureDy;
|
||||
private bool _currentTextureLinear;
|
||||
private Rect[] _srcRects;
|
||||
private Rect[] _dstRects;
|
||||
private uint[] _colors;
|
||||
/// clear buffers
|
||||
void reset() {
|
||||
_colors.length = 0;
|
||||
_colors.assumeSafeAppend();
|
||||
_srcRects.length = 0;
|
||||
_srcRects.assumeSafeAppend();
|
||||
_dstRects.length = 0;
|
||||
_dstRects.assumeSafeAppend();
|
||||
_currentTexture = null;
|
||||
_currentTextureDx = 0;
|
||||
_currentTextureDy = 0;
|
||||
_currentTextureLinear = false;
|
||||
|
||||
/// OpenGL GUI rendering queue. It collects gui draw calls, fills a big buffer for vertex data and draws everything
|
||||
private final class OpenGLQueue {
|
||||
|
||||
OpenGLBatch[] batches;
|
||||
|
||||
/// OpenGL batch structure - to draw several triangles in single OpenGL call
|
||||
private struct OpenGLBatch {
|
||||
|
||||
enum BatchType { Line = 0, Rect, Triangle, TexturedRect }
|
||||
BatchType type;
|
||||
Tex2D texture;
|
||||
int textureDx;
|
||||
int textureDy;
|
||||
bool textureLinear;
|
||||
|
||||
// length of batch in indices
|
||||
int length;
|
||||
// offset in index buffer
|
||||
int start;
|
||||
}
|
||||
/// draw buffered items
|
||||
|
||||
// a big buffer
|
||||
float[] _vertices;
|
||||
float[] _colors;
|
||||
float[] _texCoords;
|
||||
int[] _indices;
|
||||
|
||||
|
||||
/// draw all
|
||||
void flush() {
|
||||
if (_dstRects.length == 0)
|
||||
return; // nothing to draw
|
||||
if (_currentTexture) {
|
||||
// draw with texture
|
||||
//Log.v("flush ", _dstRects.length, " texture rectangles");
|
||||
glSupport.drawColorAndTextureRects(_currentTexture, _currentTextureDx, _currentTextureDy, _srcRects, _dstRects, _colors, _currentTextureLinear);
|
||||
} else {
|
||||
// draw solid fill
|
||||
//Log.v("flush ", _dstRects.length, " solid rectangles");
|
||||
glSupport.drawSolidFillRects(_dstRects, _colors);
|
||||
glSupport.fillBuffers(_vertices, _colors, _texCoords, _indices);
|
||||
foreach(b; batches) {
|
||||
switch(b.type) with(OpenGLBatch.BatchType)
|
||||
{
|
||||
case Line: glSupport.drawLines(b.length, b.start); break;
|
||||
case Rect: glSupport.drawSolidFillTriangles(b.length, b.start); break;
|
||||
case Triangle: glSupport.drawSolidFillTriangles(b.length, b.start); break;
|
||||
case TexturedRect: glSupport.drawColorAndTextureTriangles(b.texture, b.textureLinear, b.length, b.start); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
reset();
|
||||
//Log.d(batches.length, " ", _vertices.length, " ", _colors.length, " ", _texCoords.length, " ", _indices.length);
|
||||
destroy(batches);
|
||||
destroy(_vertices);
|
||||
destroy(_colors);
|
||||
destroy(_texCoords);
|
||||
destroy(_indices);
|
||||
batches = null;
|
||||
_vertices = null;
|
||||
_colors = null;
|
||||
_texCoords = null;
|
||||
_indices = null;
|
||||
}
|
||||
/// add textured rect
|
||||
void addTexturedRect(Tex2D texture, int textureDx, int textureDy, uint color1, uint color2, uint color3, uint color4, Rect srcRect, Rect dstRect, bool linear) {
|
||||
if (!_currentTexture
|
||||
|| _currentTexture.ID != texture.ID
|
||||
|| _currentTextureLinear != linear
|
||||
//|| (textureDx != _currentTextureDx)
|
||||
//|| (textureDy != _currentTextureDy)
|
||||
//|| true
|
||||
)
|
||||
|
||||
static immutable float Z_2D = -2.0f;
|
||||
|
||||
/// add textured rectangle to queue
|
||||
void addTexturedRect(Tex2D texture, int textureDx, int textureDy, uint color1, uint color2, uint color3, uint color4, Rect srcrc, Rect dstrc, bool linear) {
|
||||
if (batches is null
|
||||
|| batches[$-1].type != OpenGLBatch.BatchType.TexturedRect
|
||||
|| batches[$-1].texture.ID != texture.ID
|
||||
|| batches[$-1].textureLinear != linear)
|
||||
{
|
||||
flush();
|
||||
_currentTexture = texture;
|
||||
_currentTextureDx = textureDx;
|
||||
_currentTextureDy = textureDy;
|
||||
_currentTextureLinear = linear;
|
||||
batches ~= OpenGLBatch();
|
||||
batches[$-1].type = OpenGLBatch.BatchType.TexturedRect;
|
||||
batches[$-1].texture = texture;
|
||||
batches[$-1].textureDx = textureDx;
|
||||
batches[$-1].textureDy = textureDy;
|
||||
batches[$-1].textureLinear = linear;
|
||||
if(batches.length > 1)
|
||||
batches[$-1].start = batches[$-2].start + batches[$-2].length;
|
||||
}
|
||||
if (_currentTexture) {
|
||||
_srcRects ~= srcRect;
|
||||
}
|
||||
_dstRects ~= dstRect;
|
||||
_colors ~= color1;
|
||||
_colors ~= color2;
|
||||
_colors ~= color3;
|
||||
_colors ~= color4;
|
||||
|
||||
float[] colors = convertColors([color1, color2, color3, color4]);
|
||||
|
||||
float dstx0 = cast(float)dstrc.left;
|
||||
float dsty0 = cast(float)(glSupport.currentFBO ? dstrc.top : (glSupport.bufferDy - dstrc.top));
|
||||
float dstx1 = cast(float)dstrc.right;
|
||||
float dsty1 = cast(float)(glSupport.currentFBO ? dstrc.bottom : (glSupport.bufferDy - dstrc.bottom));
|
||||
|
||||
float srcx0 = srcrc.left / cast(float)textureDx;
|
||||
float srcy0 = srcrc.top / cast(float)textureDy;
|
||||
float srcx1 = srcrc.right / cast(float)textureDx;
|
||||
float srcy1 = srcrc.bottom / cast(float)textureDy;
|
||||
|
||||
float[3 * 4] vertices = [
|
||||
dstx0,dsty0,Z_2D,
|
||||
dstx0,dsty1,Z_2D,
|
||||
dstx1,dsty0,Z_2D,
|
||||
dstx1,dsty1,Z_2D ];
|
||||
|
||||
float[2 * 4] texCoords = [srcx0,srcy0, srcx0,srcy1, srcx1,srcy0, srcx1,srcy1];
|
||||
|
||||
int[] indices = makeRectangleIndicesArray(cast(int)_vertices.length / 3);
|
||||
|
||||
mixin(calcLengthAndAppendAllToBuffer);
|
||||
}
|
||||
/// add solid rect
|
||||
|
||||
/// add solid rectangle to queue
|
||||
void addSolidRect(Rect dstRect, uint color) {
|
||||
addGradientRect(dstRect, color, color, color, color);
|
||||
}
|
||||
|
||||
/// add gradient rect
|
||||
void addGradientRect(Rect dstRect, uint color1, uint color2, uint color3, uint color4) {
|
||||
if (_currentTexture)
|
||||
flush();
|
||||
_dstRects ~= dstRect;
|
||||
_colors ~= color1;
|
||||
_colors ~= color2;
|
||||
_colors ~= color3;
|
||||
_colors ~= color4;
|
||||
/// add gradient rectangle to queue
|
||||
void addGradientRect(Rect rc, uint color1, uint color2, uint color3, uint color4) {
|
||||
if (batches is null || batches[$-1].type != OpenGLBatch.BatchType.Rect) {
|
||||
batches ~= OpenGLBatch();
|
||||
batches[$-1].type = OpenGLBatch.BatchType.Rect;
|
||||
if(batches.length > 1)
|
||||
batches[$-1].start = batches[$-2].start + batches[$-2].length;
|
||||
}
|
||||
|
||||
float[] colors = convertColors([color1, color2, color3, color4]);
|
||||
|
||||
float x0 = cast(float)(rc.left);
|
||||
float y0 = cast(float)(glSupport.currentFBO ? rc.top : (glSupport.bufferDy - rc.top));
|
||||
float x1 = cast(float)(rc.right);
|
||||
float y1 = cast(float)(glSupport.currentFBO ? rc.bottom : (glSupport.bufferDy - rc.bottom));
|
||||
|
||||
float[3 * 4] vertices = [
|
||||
x0,y0,Z_2D,
|
||||
x0,y1,Z_2D,
|
||||
x1,y0,Z_2D,
|
||||
x1,y1,Z_2D ];
|
||||
// fill texture coords buffer with zeros
|
||||
float[2 * 4] texCoords = 0;
|
||||
|
||||
int[] indices = makeRectangleIndicesArray(cast(int)_vertices.length / 3);
|
||||
|
||||
mixin(calcLengthAndAppendAllToBuffer);
|
||||
}
|
||||
|
||||
/// add triangle to queue
|
||||
void addTriangle(PointF p1, PointF p2, PointF p3, uint color1, uint color2, uint color3) {
|
||||
flush();
|
||||
// TODO: batch triangles
|
||||
glSupport.drawSolidFillTriangles([p1, p2, p3], [color1, color2, color3]);
|
||||
if (batches is null || batches[$-1].type != OpenGLBatch.BatchType.Triangle) {
|
||||
batches ~= OpenGLBatch();
|
||||
batches[$-1].type = OpenGLBatch.BatchType.Triangle;
|
||||
if(batches.length > 1)
|
||||
batches[$-1].start = batches[$-2].start + batches[$-2].length;
|
||||
}
|
||||
|
||||
float[] colors = convertColors([color1, color2, color3]);
|
||||
|
||||
float x0 = p1.x;
|
||||
float y0 = glSupport.currentFBO ? p1.y : (glSupport.bufferDy - p1.y);
|
||||
float x1 = p2.x;
|
||||
float y1 = glSupport.currentFBO ? p2.y : (glSupport.bufferDy - p2.y);
|
||||
float x2 = p3.x;
|
||||
float y2 = glSupport.currentFBO ? p3.y : (glSupport.bufferDy - p3.y);
|
||||
|
||||
float[3 * 3] vertices = [
|
||||
x0,y0,Z_2D,
|
||||
x1,y1,Z_2D,
|
||||
x2,y2,Z_2D ];
|
||||
// fill texture coords buffer with zeros
|
||||
float[2 * 3] texCoords = 0;
|
||||
|
||||
int[] indices = makeTriangleIndicesArray(cast(int)_vertices.length / 3);
|
||||
|
||||
mixin(calcLengthAndAppendAllToBuffer);
|
||||
}
|
||||
|
||||
/// add gradient rect
|
||||
void addLine(Rect dstRect, uint color1, uint color2) {
|
||||
flush();
|
||||
// TODO: batch lines, too
|
||||
glSupport.drawLines([dstRect], [color1, color2]);
|
||||
/// add line to queue
|
||||
/// rc is a line (left, top) - (right, bottom)
|
||||
void addLine(Rect rc, uint color1, uint color2) {
|
||||
if (batches is null || batches[$-1].type != OpenGLBatch.BatchType.Line) {
|
||||
batches ~= OpenGLBatch();
|
||||
batches[$-1].type = OpenGLBatch.BatchType.Line;
|
||||
if(batches.length > 1)
|
||||
batches[$-1].start = batches[$-2].start + batches[$-2].length;
|
||||
}
|
||||
|
||||
float[] colors = convertColors([color1, color2]);
|
||||
|
||||
float x0 = cast(float)(rc.left);
|
||||
float y0 = cast(float)(glSupport.currentFBO ? rc.top : (glSupport.bufferDy - rc.top));
|
||||
float x1 = cast(float)(rc.right);
|
||||
float y1 = cast(float)(glSupport.currentFBO ? rc.bottom : (glSupport.bufferDy - rc.bottom));
|
||||
|
||||
float[3 * 2] vertices = [
|
||||
x0, y0, Z_2D,
|
||||
x1, y1, Z_2D ];
|
||||
// fill texture coords buffer with zeros
|
||||
float[2 * 2] texCoords = 0;
|
||||
|
||||
int[] indices = makeLineIndicesArray(cast(int)_vertices.length / 3);
|
||||
|
||||
mixin(calcLengthAndAppendAllToBuffer);
|
||||
}
|
||||
|
||||
enum calcLengthAndAppendAllToBuffer = q{
|
||||
batches[$-1].length += cast(int)indices.length;
|
||||
|
||||
_vertices ~= vertices;
|
||||
_colors ~= colors;
|
||||
_texCoords ~= texCoords;
|
||||
_indices ~= indices;
|
||||
};
|
||||
|
||||
/// make indices for rectangle (2 triangles == 6 vertexes per rect)
|
||||
int[6] makeRectangleIndicesArray(int offset) {
|
||||
int[6] indices;
|
||||
indices[0] = offset + 0;
|
||||
indices[1] = offset + 1;
|
||||
indices[2] = offset + 2;
|
||||
indices[3] = offset + 1;
|
||||
indices[4] = offset + 2;
|
||||
indices[5] = offset + 3;
|
||||
|
||||
return indices;
|
||||
}
|
||||
|
||||
/// make indices for triangles
|
||||
int[3] makeTriangleIndicesArray(int offset) {
|
||||
int[3] indices;
|
||||
indices[0] = offset + 0;
|
||||
indices[1] = offset + 1;
|
||||
indices[2] = offset + 2;
|
||||
return indices;
|
||||
}
|
||||
|
||||
/// make indices for lines
|
||||
int[2] makeLineIndicesArray(int offset) {
|
||||
int[2] indices;
|
||||
indices[0] = offset + 0;
|
||||
indices[1] = offset + 1;
|
||||
|
||||
return indices;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue