private void begin(Writer writer, IndWriter indexer, int mode, int blockSize) { mDraw.checkErr(); mActiveWriter = writer; mActiveIndexer = indexer; mActiveMode = mode; mVertBuf.clear(); int bytes = mVertBuf.capacity(); int vertBytes = writer.mVertWriter.bytesPerElem(); mActiveCap = (bytes / (vertBytes * blockSize)) * blockSize; mActivePos = 0; writer.mProgram.bind(mDraw); writer.mVao.bind(mDraw); mVbo.bind(mDraw); if (indexer != null) { indexer.reset(); mIndBuf.clear(); mIbo.bind(mDraw); } DrawUtil.checkErr(); }
public void init(DrawEnv d) { mDraw = d; if (mVbo.id() != 0) { return; } mVbo.alloc(mVertBuf.capacity()); mVbo.init(d); mIbo.alloc(mIndBuf.capacity()); mIbo.init(d); d.checkErr(); }
/** * Emulates the old OpenGL immediate mode rendering. Meant largely to help transition old code to * new GL versions. * * @author Philip DeCamp */ public class DrawStream { private static final int DEFAULT_BUF_SIZE = 64 * 1024; private final Bo mVbo = Bo.createArrayBuffer(GL_STREAM_DRAW); private final Bo mIbo = Bo.createElementBuffer(GL_STREAM_DRAW); private final ByteBuffer mVertBuf; private final ByteBuffer mIndBuf; private final DrawVert mVert = new DrawVert(new Vec3(), new float[4], new Vec3(), new Vec4(0, 0, 0, 1)); private final BasicShaderConfig mConfig = new BasicShaderConfig(); private BasicShaderConfig mChosenConfig = new BasicShaderConfig(); private Object mOverrideConfig = null; private final Map<Object, Writer> mWriters = new HashMap<>(); private final IndWriter mQuadIndexer = new QuadIndWriter(); private DrawEnv mDraw; private Writer mActiveWriter = null; private IndWriter mActiveIndexer = null; private int mActiveCap = 0; private int mActivePos = 0; private int mActiveMode = 0; public DrawStream() { this(DEFAULT_BUF_SIZE); } public DrawStream(int bufSize) { mVertBuf = DrawUtil.alloc(bufSize); // 12 is smallest possible vert size. // 6/4 is the max ration between indices and verts (for drawing quads) // 4 at the end is bytes per index. mIndBuf = DrawUtil.alloc(bufSize / 12 * 6 / 4 * 4); } public void init(DrawEnv d) { mDraw = d; if (mVbo.id() != 0) { return; } mVbo.alloc(mVertBuf.capacity()); mVbo.init(d); mIbo.alloc(mIndBuf.capacity()); mIbo.init(d); d.checkErr(); } /** * Configures the rendering program for the draw stream. Some version of {@code config()} or * {@code configCustom()} must be called prior to any {@code begin*()}. * * @param color Enables color information. * @param tex Enables texture information. * @param norm Enables normal information. */ public void config(boolean color, boolean tex, boolean norm) { config(color, tex, norm, false); } /** * Configures the rendering program for the draw stream. Some version of {@code config()} or * {@code configCustom()} must be called prior to any {@code begin*()}. * * @param color Enables color information. * @param tex Enables texture information. * @param norm Enables normal information. * @param fog Enables fog information. */ public void config(boolean color, boolean tex, boolean norm, boolean fog) { mOverrideConfig = null; mConfig.texComponentNum(tex ? 4 : 0); mConfig.color(color); mConfig.normals(norm); mConfig.fog(fog); } /** * Specifies that a custom configuration object will be used for rendering. * * @param key Unique object that identifies configuration. */ public void configCustom(Object key) { mOverrideConfig = key; } /** * Enables user to provide a custom configuration that can be used with this DrawStream. * * @param key Unique object used to identify the configuration. * @param prog Program to use in configuration. * @param vertWriter BoWriter to serialize data in configuration. */ public void createCustomConfig(Object key, Program prog, BoWriter<? super DrawVert> vertWriter) { Writer writer = new Writer(prog, vertWriter); Writer prev = mWriters.put(key, writer); if (prev != null) { prev.deref(); } } /** * Disposes previously created configuration. * * @param key Unique object used to identify the configuration. */ public boolean disposeCustomConfig(Object key) { Writer prev = mWriters.remove(key); if (prev != null) { prev.deref(); return true; } return false; } public void beginPoints() { mConfig.geomMode(GL_POINTS); begin(getWriter(), null, GL_POINTS, 1); } public void beginLines() { mConfig.geomMode(GL_LINES); begin(getWriter(), null, GL_LINES, 2); } public void beginLineStrip() { mConfig.geomMode(GL_LINE_STRIP); begin(getWriter(), null, GL_LINE_STRIP, 2); } public void beginLineLoop() { mConfig.geomMode(GL_LINE_LOOP); begin(getWriter(), null, GL_LINE_LOOP, 2); } public void beginTris() { mConfig.geomMode(GL_TRIANGLES); begin(getWriter(), null, GL_TRIANGLES, 3); } public void beginTriStrip() { mConfig.geomMode(GL_TRIANGLE_STRIP); begin(getWriter(), null, GL_TRIANGLE_STRIP, 3); } public void beginQuads() { mConfig.geomMode(GL_TRIANGLES); begin(getWriter(), mQuadIndexer, GL_TRIANGLES, 4); } public void beginQuadStrip() { mConfig.geomMode(GL_TRIANGLE_STRIP); begin(getWriter(), null, GL_TRIANGLE_STRIP, 4); } private void begin(Writer writer, IndWriter indexer, int mode, int blockSize) { mDraw.checkErr(); mActiveWriter = writer; mActiveIndexer = indexer; mActiveMode = mode; mVertBuf.clear(); int bytes = mVertBuf.capacity(); int vertBytes = writer.mVertWriter.bytesPerElem(); mActiveCap = (bytes / (vertBytes * blockSize)) * blockSize; mActivePos = 0; writer.mProgram.bind(mDraw); writer.mVao.bind(mDraw); mVbo.bind(mDraw); if (indexer != null) { indexer.reset(); mIndBuf.clear(); mIbo.bind(mDraw); } DrawUtil.checkErr(); } public void end() { if (mActiveWriter == null) { return; } if (mActivePos > 0) { flush(); } if (mActiveIndexer != null) { GLES30.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); mActiveIndexer = null; } mActiveWriter.mVao.unbind(mDraw); mActiveWriter.mProgram.unbind(mDraw); DrawUtil.checkErr(); } public void colorub(int red, int green, int blue) { colorub(red, green, blue, 0xFF); } public void colorub(int red, int green, int blue, int alpha) { Vec4 c = mVert.mColor; c.x = red / 255f; c.y = green / 255f; c.z = blue / 255f; c.w = alpha / 255f; } public void color(float red, float green, float blue) { color(red, green, blue, 1f); } public void color(float red, float green, float blue, float alpha) { Vec4 c = mVert.mColor; c.x = red; c.y = green; c.z = blue; c.w = alpha; } public void color(Vec3 v) { color(v.x, v.y, v.z, 1f); } public void color(Vec4 v) { color(v.x, v.y, v.z, v.w); } public void norm(int x, int y, int z) { norm((float) x, (float) y, (float) z); } public void norm(float x, float y, float z) { Vec3 v = mVert.mNorm; v.x = x; v.y = y; v.z = z; } public void norm(float[] v) { tex(v[0], v[1], v[2], 1f); } public void tex(int x, int y) { this.tex((float) x, (float) y, 0f, 1f); } public void tex(float x, float y) { tex(x, y, 0f, 1f); } public void tex(int x, int y, int z) { tex((float) x, (float) y, (float) z, 1f); } public void tex(float x, float y, float z) { tex(x, y, z, 1); } public void tex(int x, int y, int z, int w) { tex((float) x, (float) y, (float) z, (float) w); } public void tex(float x, float y, float z, float w) { float[] v = mVert.mTex; v[0] = x; v[1] = y; v[2] = z; v[3] = w; } public void tex(Vec2 v) { tex(v.x, v.y, 0f, 1f); } public void tex(Vec3 v) { tex(v.x, v.y, v.z, 1f); } public void tex(Vec4 v) { Vec.put(v, mVert.mTex); } public void vert(int x, int y) { vert((float) x, (float) y, 0f); } public void vert(float x, float y) { vert(x, y, 0f); } public void vert(int x, int y, int z) { vert((float) x, (float) y, (float) z); } public void vert(float x, float y, float z) { Vec.put(x, y, z, mVert.mPos); mActiveWriter.mVertWriter.write(mVert, mVertBuf); if (mActiveIndexer != null) { mActiveIndexer.write(mActivePos, mIndBuf); } if (++mActivePos < mActiveCap) { return; } flush(); } public void vert(Vec3 v) { vert(v.x, v.y, v.z); } public void pointSize(float f) { mDraw.mPointSize.apply(f); } private Writer getWriter() { if (mOverrideConfig != null) { Writer ret = mWriters.get(mOverrideConfig); if (ret != null) { return ret; } throw new IllegalStateException("DrawStream configuration not found."); } mConfig.lineWidth(mDraw.mLineWidth.mValue); mConfig.chooseAvailable(mChosenConfig); Writer writer = mWriters.get(mChosenConfig); if (writer != null) { return writer; } BoProgram<DrawVert, ?> prog = BasicShaders.createProgram(mChosenConfig, mDraw.mShaderMan); writer = new Writer(prog.mProgram, prog.mVertWriter); mWriters.put(new BasicShaderConfig(mChosenConfig), writer); return writer; } private class Writer extends AbstractRefable { public Object mParent; public Program mProgram; public BoWriter<? super DrawVert> mVertWriter; public Vao mVao; public Writer(Program program, BoWriter<? super DrawVert> writer) { mProgram = program; mVertWriter = writer; mVao = new Vao(mVbo, null); program.init(mDraw); writer.attributes(mVao); } @Override protected void freeObject() { mProgram.dispose(mDraw); mVao.dispose(mDraw); } } private void flush() { DrawEnv d = mDraw; mVertBuf.flip(); GLES30.glBufferSubData(GL_ARRAY_BUFFER, 0, mVertBuf.remaining(), mVertBuf); mVertBuf.clear(); if (mActiveIndexer == null) { GLES30.glDrawArrays(mActiveMode, 0, mActivePos); } else { mIndBuf.flip(); GLES30.glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, mIndBuf.remaining(), mIndBuf); GLES30.glDrawElements(mActiveMode, mActiveIndexer.count(), GL_UNSIGNED_INT, 0); mIndBuf.clear(); } mActivePos = 0; } public interface IndWriter { void reset(); void write(int ind, ByteBuffer out); int count(); } private static class QuadIndWriter implements IndWriter { int mCount = 0; int mPos = 0; int[] mV = {0, 0, 0, 0}; public void reset() { mPos = 0; mCount = 0; } public void write(int ind, ByteBuffer out) { mV[mPos++] = ind; if (mPos == 4) { out.putInt(mV[0]); out.putInt(mV[1]); out.putInt(mV[2]); out.putInt(mV[0]); out.putInt(mV[2]); out.putInt(mV[3]); mPos = 0; mCount += 6; } } public int count() { return mCount; } } }