use GLState for depth and stencil test

This commit is contained in:
Hannes Janetzek 2013-01-05 07:59:55 +01:00
parent e50ea0c2ba
commit 7cc32f1572
8 changed files with 99 additions and 109 deletions

View File

@ -16,7 +16,6 @@ package org.oscim.renderer;
import static android.opengl.GLES20.GL_ARRAY_BUFFER; import static android.opengl.GLES20.GL_ARRAY_BUFFER;
import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_BLEND;
import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL; import static android.opengl.GLES20.GL_POLYGON_OFFSET_FILL;
import static org.oscim.generator.JobTile.STATE_READY; import static org.oscim.generator.JobTile.STATE_READY;
@ -51,9 +50,7 @@ public class BaseLayer {
Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, pos.viewMatrix, 0); Matrix.multiplyMM(mVPMatrix, 0, mfProjMatrix, 0, pos.viewMatrix, 0);
/* draw base layer */ /* draw base layer */
GLES20.glEnable(GL_DEPTH_TEST);
GLES20.glEnable(GL_POLYGON_OFFSET_FILL); GLES20.glEnable(GL_POLYGON_OFFSET_FILL);
// mDrawCount = 0;
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
MapTile t = tiles[i]; MapTile t = tiles[i];
@ -72,7 +69,7 @@ public class BaseLayer {
} }
GLES20.glDisable(GL_POLYGON_OFFSET_FILL); GLES20.glDisable(GL_POLYGON_OFFSET_FILL);
GLES20.glDisable(GL_DEPTH_TEST);
mDrawSerial++; mDrawSerial++;
} }
@ -116,7 +113,8 @@ public class BaseLayer {
PolygonRenderer.draw(pos, null, mvp, true, true); PolygonRenderer.draw(pos, null, mvp, true, true);
clipped = true; clipped = true;
} }
// clip lines to quad in depth buffer
GLState.test(true, false);
GLES20.glEnable(GL_BLEND); GLES20.glEnable(GL_BLEND);
l = LineRenderer.draw(pos, l, mvp, div, simpleShader, l = LineRenderer.draw(pos, l, mvp, div, simpleShader,
tile.layers.lineOffset); tile.layers.lineOffset);

View File

@ -34,39 +34,42 @@ public class GLState {
blend = false; blend = false;
depth = false; depth = false;
stencil = false; stencil = false;
GLES20.glDisable(GLES20.GL_STENCIL_TEST);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
} }
// public static void blend(boolean enable) { public static void blend(boolean enable) {
// if (blend == enable) if (blend == enable)
// return; return;
//
// if (blend) if (blend)
// GLES20.glEnable(GLES20.GL_BLEND); GLES20.glEnable(GLES20.GL_BLEND);
// else else
// GLES20.glDisable(GLES20.GL_BLEND); GLES20.glDisable(GLES20.GL_BLEND);
// } }
//
// public static void test(boolean depthTest, boolean stencilTest) { public static void test(boolean depthTest, boolean stencilTest) {
// if (depth != depthTest) { if (depth != depthTest) {
//
// if (depthTest) if (depthTest)
// GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// else else
// GLES20.glDisable(GLES20.GL_DEPTH_TEST); GLES20.glDisable(GLES20.GL_DEPTH_TEST);
//
// depth = depthTest; depth = depthTest;
// } }
//
// if (stencil != stencilTest) { if (stencil != stencilTest) {
//
// if (stencilTest) if (stencilTest)
// GLES20.glEnable(GLES20.GL_STENCIL_TEST); GLES20.glEnable(GLES20.GL_STENCIL_TEST);
// else else
// GLES20.glDisable(GLES20.GL_STENCIL_TEST); GLES20.glDisable(GLES20.GL_STENCIL_TEST);
//
// stencil = stencilTest; stencil = stencilTest;
// } }
// } }
public static void enableVertexArrays(int va1, int va2) { public static void enableVertexArrays(int va1, int va2) {
if (va1 > 1 || va2 > 1) if (va1 > 1 || va2 > 1)

View File

@ -16,12 +16,10 @@ package org.oscim.renderer;
import static android.opengl.GLES20.GL_ALWAYS; import static android.opengl.GLES20.GL_ALWAYS;
import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_BLEND;
import static android.opengl.GLES20.GL_DEPTH_TEST;
import static android.opengl.GLES20.GL_EQUAL; import static android.opengl.GLES20.GL_EQUAL;
import static android.opengl.GLES20.GL_INVERT; import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_LESS; import static android.opengl.GLES20.GL_LESS;
import static android.opengl.GLES20.GL_SHORT; import static android.opengl.GLES20.GL_SHORT;
import static android.opengl.GLES20.GL_STENCIL_TEST;
import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.GL_TRIANGLE_FAN;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP; import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
import static android.opengl.GLES20.GL_ZERO; import static android.opengl.GLES20.GL_ZERO;
@ -167,8 +165,25 @@ public final class PolygonRenderer {
// stencil buffer index to start fill // stencil buffer index to start fill
private static int mStart; private static int mStart;
/**
* draw polygon layers (unil layer.next is not polygon layer)
* using stencil buffer method
* @param pos
* used to fade layers accorind to 'fade'
* in layer.area.
* @param layer
* layer to draw (referencing vertices in current vbo)
* @param matrix
* mvp matrix
* @param first
* pass true to clear stencil buffer region
* @param drawClipped
* clip to first quad in current vbo
* @return
* next layer
*/
public static Layer draw(MapPosition pos, Layer layer, public static Layer draw(MapPosition pos, Layer layer,
float[] matrix, boolean first, boolean drawClip) { float[] matrix, boolean first, boolean drawClipped) {
int zoom = pos.zoomLevel; int zoom = pos.zoomLevel;
float scale = pos.scale; float scale = pos.scale;
@ -182,9 +197,11 @@ public final class PolygonRenderer {
glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0); glUniformMatrix4fv(hPolygonMatrix, 1, false, matrix, 0);
// use stencilbuffer method for polygon drawing // reset start when only two layer left in stencil buffer
glEnable(GL_STENCIL_TEST); // if (mCount > 5) {
//GLState.stencilTest(true); // mCount = 0;
// mStart = 0;
// }
if (first) { if (first) {
mCount = 0; mCount = 0;
@ -202,7 +219,8 @@ public final class PolygonRenderer {
continue; continue;
if (mCount == mStart) { if (mCount == mStart) {
// clear stencilbuffer (tile region) // clear stencilbuffer (tile region) by drawing
// a quad with func 'always' and op 'zero'
// disable drawing to framebuffer // disable drawing to framebuffer
glColorMask(false, false, false, false); glColorMask(false, false, false, false);
@ -210,55 +228,38 @@ public final class PolygonRenderer {
// never pass the test: always apply fail op // never pass the test: always apply fail op
glStencilFunc(GL_ALWAYS, 0, 0xFF); glStencilFunc(GL_ALWAYS, 0, 0xFF);
glStencilMask(0xFF); glStencilMask(0xFF);
glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
if (drawClip) { if (drawClipped) {
GLState.test(true, true);
// draw clip-region into depth buffer: // draw clip-region into depth buffer:
// this is used for lines and polygons // this is used for lines and polygons
// write to depth buffer // write to depth buffer
glDepthMask(true); glDepthMask(true);
// to prevent overdraw gl_less restricts // to prevent overdraw gl_less restricts the
// the clip to the area where no other // clip to the area where no other tile has drawn
// tile has drawn
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
} }
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (drawClip) { if (drawClipped) {
first = false; first = false;
drawClip = false; drawClipped = false;
// dont modify depth buffer // do not modify depth buffer anymore
glDepthMask(false); glDepthMask(false);
// only draw to this tile // only draw to this tile
glDepthFunc(GL_EQUAL); glDepthFunc(GL_EQUAL);
} }
// stencil op for stencil method polygon drawing // op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
// no need for depth test while drawing stencil
if (drawClip)
glDisable(GL_DEPTH_TEST);
} }
// else if (mCount == mStart) {
// // disable drawing to framebuffer // no need for depth test while drawing stencil
// glColorMask(false, false, false, false); GLState.test(false, true);
//
// // never pass the test: always apply fail op
// glStencilFunc(GL_ALWAYS, 0, 0xFF);
//
// // stencil op for stencil method polygon drawing
// glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
//
// // no need for depth test while drawing stencil
// if (clip)
// glDisable(GL_DEPTH_TEST);
// }
mFillPolys[mCount] = pl; mFillPolys[mCount] = pl;
@ -270,8 +271,8 @@ public final class PolygonRenderer {
// draw up to 8 layers into stencil buffer // draw up to 8 layers into stencil buffer
if (mCount == STENCIL_BITS) { if (mCount == STENCIL_BITS) {
/* only draw where nothing was drawn yet */ /* only draw where nothing was drawn yet */
if (drawClip) if (drawClipped)
glEnable(GL_DEPTH_TEST); GLState.test(true, true);
fillPolygons(zoom, scale); fillPolygons(zoom, scale);
mCount = 0; mCount = 0;
@ -281,35 +282,38 @@ public final class PolygonRenderer {
if (mCount > 0) { if (mCount > 0) {
/* only draw where nothing was drawn yet */ /* only draw where nothing was drawn yet */
if (drawClip) if (drawClipped)
glEnable(GL_DEPTH_TEST); GLState.test(true, true);
fillPolygons(zoom, scale); fillPolygons(zoom, scale);
} }
// maybe reset start when only few layers left in stencil buffer
// if (mCount > 5){
// mCount = 0;
// mStart = 0;
// }
glDisable(GL_STENCIL_TEST); if (drawClipped && first) {
GLState.test(true, false);
GLES20.glColorMask(false, false, false, false);
GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS);
if (drawClip && first) GLES20.glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
drawDepthClip();
GLES20.glDepthMask(false);
GLES20.glColorMask(true, true, true, true);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
}
return l; return l;
} }
private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f }; private static float[] debugFillColor = { 0.3f, 0.0f, 0.0f, 0.3f };
private static float[] debugFillColor2 = { 0.0f, 0.3f, 0.0f, 0.3f }; private static float[] debugFillColor2 = { 0.0f, 0.3f, 0.0f, 0.3f };
private static FloatBuffer mDebugFill;
private static ByteBuffer mDebugFill;
static void debugDraw(float[] matrix, float[] coords, int color) { static void debugDraw(float[] matrix, float[] coords, int color) {
GLState.test(false, false);
if (mDebugFill == null)
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder())
.asFloatBuffer();
mDebugFill = ByteBuffer.allocateDirect(32).order(ByteOrder.nativeOrder()); mDebugFill.put(coords);
FloatBuffer buf = mDebugFill.asFloatBuffer();
buf.put(coords);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
@ -330,18 +334,5 @@ public final class PolygonRenderer {
glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GlUtils.checkGlError("draw debug"); GlUtils.checkGlError("draw debug");
// GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
}
static void drawDepthClip() {
glColorMask(false, false, false, false);
GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDepthMask(false);
glColorMask(true, true, true, true);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
} }
} }

View File

@ -90,7 +90,7 @@ public final class TextureRenderer {
} }
public static Layer draw(Layer layer, float scale, float[] projection, float matrix[]) { public static Layer draw(Layer layer, float scale, float[] projection, float matrix[]) {
GLState.test(false, false);
// GlUtils.checkGlError("draw texture >"); // GlUtils.checkGlError("draw texture >");
GLES20.glUseProgram(mTextureProgram); GLES20.glUseProgram(mTextureProgram);

View File

@ -373,10 +373,8 @@ public class BuildingOverlay extends RenderOverlay {
GLES20.glUniform1i(hBuildingMode, 0); GLES20.glUniform1i(hBuildingMode, 0);
GLES20.glColorMask(false, false, false, false); GLES20.glColorMask(false, false, false, false);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLState.test(true, false);
GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glEnable(GLES20.GL_CULL_FACE);
//GLES20.glCullFace(GLES20.GL_CW);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);

View File

@ -200,13 +200,12 @@ public class ExtrusionOverlay extends RenderOverlay {
} }
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);
GLState.test(true, false);
GLES20.glUseProgram(extrusionProgram); GLES20.glUseProgram(extrusionProgram);
GLState.enableVertexArrays(hExtrusionVertexPosition, -1); GLState.enableVertexArrays(hExtrusionVertexPosition, -1);
GLES20.glEnable(GLES20.GL_CULL_FACE); GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glCullFace(GLES20.GL_FRONT); GLES20.glCullFace(GLES20.GL_FRONT);
GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL); GLES20.glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glColorMask(false, false, false, false); GLES20.glColorMask(false, false, false, false);
@ -291,7 +290,6 @@ public class ExtrusionOverlay extends RenderOverlay {
} }
GLES20.glDisable(GLES20.GL_CULL_FACE); GLES20.glDisable(GLES20.GL_CULL_FACE);
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL); GLES20.glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);

View File

@ -188,7 +188,7 @@ public class ModelOverlay extends RenderOverlay {
// draw to depth buffer // draw to depth buffer
GLES20.glColorMask(false, false, false, false); GLES20.glColorMask(false, false, false, false);
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT); GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT);
GLES20.glEnable(GLES20.GL_DEPTH_TEST); GLState.test(true, false);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS); GLES20.glDepthFunc(GLES20.GL_LESS);

View File

@ -18,6 +18,7 @@ import org.oscim.core.MapPosition;
import org.oscim.core.Tile; import org.oscim.core.Tile;
import org.oscim.renderer.BufferObject; import org.oscim.renderer.BufferObject;
import org.oscim.renderer.GLRenderer; import org.oscim.renderer.GLRenderer;
import org.oscim.renderer.GLState;
import org.oscim.renderer.LineRenderer; import org.oscim.renderer.LineRenderer;
import org.oscim.renderer.PolygonRenderer; import org.oscim.renderer.PolygonRenderer;
import org.oscim.renderer.TextureRenderer; import org.oscim.renderer.TextureRenderer;
@ -104,6 +105,7 @@ public abstract class RenderOverlay {
Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0); Matrix.multiplyMM(mvp, 0, proj, 0, mv, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo.id);
GLState.test(false, false);
for (Layer l = layers.layers; l != null;) { for (Layer l = layers.layers; l != null;) {
if (l.type == Layer.POLYGON) { if (l.type == Layer.POLYGON) {