diff options
author | Sven Gothel <[email protected]> | 2014-04-04 02:30:00 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-04-04 02:30:00 +0200 |
commit | 9c71f276d1fcc87b69b413847fd1da34b30d0932 (patch) | |
tree | 71f738861036221827062450a9d7d4cff5a9f766 /src/jogl/classes/com/jogamp/graph/curve | |
parent | abc833631e0ab30a06c7aff47a39a551544fd735 (diff) |
Bug 801: Cleanup shader-program location/data update ; Add COLORTEXTURE + TextureSequence to Region (Demo: TextureButton)
Cleanup shader-program location/data update
- GLUniformData:
- Allow lazy data setup, as used for
RenderState.ProgramLocal, see below
- RenderState
- Separate data (pmv, weight, colorStatic) from
program-local uniforms -> add class ProgramLocal.
Reduces uniform location lookups, since
ProgramLocal is bound to Region impl.
- ProgramLocal.update(..) needs to write uniform data always,
since data is being used in multiple programs!
- No 'dirty' tracking possible, removed - see above.
- RegionRenderer
- Fix shader-selection: 2-pass programs differ from 1-pass!
- No shader-setup at init
+++
Add COLORTEXTURE + TextureSequence to Region
- Create color-texture coords in vertex-shader via region's bounding box (pass-1)
- Use color-texture unit in pass-1 if enabled (own shader program)
- Use TextureSequence in Region impl. providing all required data (unit + texture-name)
- Demo: TextureButton (a UIShape)
Diffstat (limited to 'src/jogl/classes/com/jogamp/graph/curve')
5 files changed, 172 insertions, 112 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/curve/Region.java b/src/jogl/classes/com/jogamp/graph/curve/Region.java index 7edd2f572..230fa324d 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/Region.java +++ b/src/jogl/classes/com/jogamp/graph/curve/Region.java @@ -37,6 +37,7 @@ import com.jogamp.graph.geom.Triangle; import com.jogamp.graph.geom.Vertex; import com.jogamp.opengl.math.geom.AABBox; import com.jogamp.opengl.math.geom.Frustum; +import com.jogamp.opengl.util.texture.TextureSequence; /** * Abstract Outline shape representation define the method an OutlineShape(s) @@ -102,7 +103,7 @@ public abstract class Region { /** Default maximum {@link #getQuality() quality}, {@value}. */ public static final int MAX_QUALITY = 1; - public static final int TWO_PASS_DEFAULT_TEXTURE_UNIT = 0; + public static final int DEFAULT_TWO_PASS_TEXTURE_UNIT = 0; private final int renderModes; private int quality; @@ -175,7 +176,7 @@ public abstract class Region { protected abstract void pushIndex(int idx); /** - * Return bit-field of render modes, see {@link #create(int)}. + * Return bit-field of render modes, see {@link #create(int, TextureSequence)}. */ public final int getRenderModes() { return renderModes; } @@ -369,19 +370,33 @@ public abstract class Region { return box; } - /** Check if this region is dirty. A region is marked dirty when new - * Vertices, Triangles, and or Lines are added after a call to update() + /** + * Check if this region is dirty. A region is marked dirty when new + * Vertices, Triangles, and or Lines are added after a call to update(). + * <p> + * A region is also dirty if other render attributes or parameters are changed! + * </p> * * @return true if region is Dirty, false otherwise * - * @see update(GL2ES2) */ + * @see update(GL2ES2) + */ public final boolean isDirty() { return dirty; } + /** + * See {@link #isDirty()}. + */ protected final void setDirty(boolean v) { dirty = v; } + /** + * See {@link #isDirty()}. + */ + public final void markDirty() { + dirty = true; + } public String toString() { return "Region["+getRenderModeString(this.renderModes)+", q "+quality+", dirty "+dirty+", vertices "+numVertices+", box "+box+"]"; diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java index 9505f2a9d..3c6045a1f 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/GLRegion.java @@ -35,6 +35,7 @@ import jogamp.graph.curve.opengl.VBORegion2PVBAAES2; import jogamp.graph.curve.opengl.VBORegionSPES2;
import com.jogamp.opengl.util.PMVMatrix;
+import com.jogamp.opengl.util.texture.TextureSequence;
import com.jogamp.graph.curve.Region;
/** A GLRegion is the OGL binding of one or more OutlineShapes
@@ -53,23 +54,31 @@ public abstract class GLRegion extends Region { * Create a GLRegion using the passed render mode
*
* <p> In case {@link Region#VBAA_RENDERING_BIT} is being requested the default texture unit
- * {@link Region#TWO_PASS_DEFAULT_TEXTURE_UNIT} is being used.</p>
- *
- * @param rs the RenderState to be used
+ * {@link Region#DEFAULT_TWO_PASS_TEXTURE_UNIT} is being used.</p>
* @param renderModes bit-field of modes, e.g. {@link Region#VARWEIGHT_RENDERING_BIT}, {@link Region#VBAA_RENDERING_BIT}
+ * @param colorTexSeq TODO
+ * @param rs the RenderState to be used
*/
- public static GLRegion create(int renderModes) {
+ public static GLRegion create(int renderModes, final TextureSequence colorTexSeq) {
+ if( null != colorTexSeq ) {
+ renderModes |= Region.COLORTEXTURE_RENDERING_BIT;
+ } else if( Region.hasColorTexture(renderModes) ) {
+ throw new IllegalArgumentException("COLORTEXTURE_RENDERING_BIT set but null TextureSequence");
+ }
if( isVBAA(renderModes) ) {
- return new VBORegion2PVBAAES2(renderModes, Region.TWO_PASS_DEFAULT_TEXTURE_UNIT);
+ return new VBORegion2PVBAAES2(renderModes, colorTexSeq, Region.DEFAULT_TWO_PASS_TEXTURE_UNIT);
} else if( isMSAA(renderModes) ) {
- return new VBORegion2PMSAAES2(renderModes, Region.TWO_PASS_DEFAULT_TEXTURE_UNIT);
+ return new VBORegion2PMSAAES2(renderModes, colorTexSeq, Region.DEFAULT_TWO_PASS_TEXTURE_UNIT);
} else {
- return new VBORegionSPES2(renderModes);
+ return new VBORegionSPES2(renderModes, colorTexSeq);
}
}
- protected GLRegion(int renderModes) {
+ protected final TextureSequence colorTexSeq;
+
+ protected GLRegion(int renderModes, TextureSequence colorTexSeq) {
super(renderModes);
+ this.colorTexSeq = colorTexSeq;
}
/**
diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java index ade6098e1..8724baff8 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RegionRenderer.java @@ -139,9 +139,6 @@ public class RegionRenderer { public final int getHeight() { return vp_height; } public final PMVMatrix getMatrix() { return rs.getMatrix(); } - public final PMVMatrix getMatrixMutable() { return rs.getMatrixMutable(); } - public final void setMatrixDirty() { rs.setMatrixDirty(); } - public final boolean isMatrixDirty() { return rs.isMatrixDirty(); } ////////////////////////////////////// @@ -190,12 +187,6 @@ public class RegionRenderer { if( null != enableCallback ) { enableCallback.run(gl, this); } - - useShaderProgram(gl, renderModes, true, 0, 0); - initialized = rs.update(gl, true, renderModes, true); - if(!initialized) { - throw new GLException("Shader initialization failed"); - } } public final void destroy(GL2ES2 gl) { @@ -247,14 +238,13 @@ public class RegionRenderer { public final void reshapeNotify(int width, int height) { this.vp_width = width; this.vp_height = height; - rs.setMatrixDirty(); } public final void reshapePerspective(float angle, int width, int height, float near, float far) { this.vp_width = width; this.vp_height = height; final float ratio = (float)width/(float)height; - final PMVMatrix p = rs.getMatrixMutable(); + final PMVMatrix p = rs.getMatrix(); p.glMatrixMode(GLMatrixFunc.GL_PROJECTION); p.glLoadIdentity(); p.gluPerspective(angle, ratio, near, far); @@ -263,7 +253,7 @@ public class RegionRenderer { public final void reshapeOrtho(int width, int height, float near, float far) { this.vp_width = width; this.vp_height = height; - final PMVMatrix p = rs.getMatrixMutable(); + final PMVMatrix p = rs.getMatrix(); p.glMatrixMode(GLMatrixFunc.GL_PROJECTION); p.glLoadIdentity(); p.glOrthof(0, width, 0, height, near, far); @@ -368,6 +358,7 @@ public class RegionRenderer { private final IntObjectHashMap shaderPrograms = new IntObjectHashMap(); private static final int HIGH_MASK = Region.COLORCHANNEL_RENDERING_BIT | Region.COLORTEXTURE_RENDERING_BIT; + private static final int TWO_PASS_BIT = 1 << 31; /** * @param gl @@ -382,7 +373,8 @@ public class RegionRenderer { final boolean pass1, final int quality, final int sampleCount) { final ShaderModeSelector1 sel1 = pass1 ? ShaderModeSelector1.selectPass1(renderModes) : ShaderModeSelector1.selectPass2(renderModes, quality, sampleCount); - final int shaderKey = sel1.ordinal() | ( HIGH_MASK & renderModes ); + final boolean isTwoPass = Region.isTwoPass( renderModes ); + final int shaderKey = sel1.ordinal() | ( HIGH_MASK & renderModes ) | ( isTwoPass ? TWO_PASS_BIT : 0 ); /** if(DEBUG) { @@ -395,14 +387,16 @@ public class RegionRenderer { final boolean spChanged = getRenderState().setShaderProgram(gl, sp); if(DEBUG) { if( spChanged ) { - System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X (changed)%n", Region.getRenderModeString(renderModes), sel1, shaderKey); + System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); + } else { + System.err.printf("RegionRendererImpl01.useShaderProgram.X1: GOT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (keep)%n", Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); } } return spChanged; } final String versionedBaseName = getVersionedShaderName(); final String vertexShaderName; - if( Region.isTwoPass( renderModes ) ) { + if( isTwoPass ) { vertexShaderName = versionedBaseName+"-pass"+(pass1?1:2); } else { vertexShaderName = versionedBaseName+"-single"; @@ -453,6 +447,7 @@ public class RegionRenderer { if( !sp.init(gl) ) { throw new GLException("RegionRenderer: Couldn't init program: "+sp); } + if( !sp.link(gl, System.err) ) { throw new GLException("could not link program: "+sp); } @@ -460,8 +455,8 @@ public class RegionRenderer { shaderPrograms.put(shaderKey, sp); if(DEBUG) { - System.err.printf("RegionRendererImpl01.useShaderProgram.X1: PUT renderModes %s, sel1 %s, key 0x%X -> SP %s (changed)%n", - Region.getRenderModeString(renderModes), sel1, shaderKey, sp); + System.err.printf("RegionRendererImpl01.useShaderProgram.X1: PUT renderModes %s, sel1 %s, key 0x%X -> sp %d / %d (changed)%n", + Region.getRenderModeString(renderModes), sel1, shaderKey, sp.program(), sp.id()); } return true; } diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java index c7083a41b..818526cd7 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/RenderState.java @@ -31,6 +31,7 @@ import java.nio.FloatBuffer; import javax.media.opengl.GL; import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLException; import javax.media.opengl.GLUniformData; import jogamp.graph.curve.opengl.shader.UniformNames; @@ -78,25 +79,109 @@ public class RenderState { private final Vertex.Factory<? extends Vertex> vertexFactory; private final PMVMatrix pmvMatrix; - private final GLUniformData gcu_PMVMatrix01; - private final GLUniformData gcu_Weight; - private final GLUniformData gcu_ColorStatic; - private boolean gcu_PMVMatrix01_dirty = true; - private boolean gcu_Weight_dirty = true; - private boolean gcu_ColorStatic_dirty = true; + private final float[] weight; + private final FloatBuffer weightBuffer; + private final float[] colorStatic; + private final FloatBuffer colorStaticBuffer; private ShaderProgram sp; private int hintBitfield; + private final int id; + private static synchronized int getNextID() { + return nextID++; + } + private static int nextID = 1; + + /** + * Representation of {@link RenderState} data for one {@link ShaderProgram} + * as {@link GLUniformData}. + * <p> + * FIXME: Utilize 'ARB_Uniform_Buffer_Object' where available! + * </p> + */ + public static class ProgramLocal { + public final GLUniformData gcu_PMVMatrix01; + public final GLUniformData gcu_Weight; + public final GLUniformData gcu_ColorStatic; + private int rsId = -1; + + public ProgramLocal() { + gcu_PMVMatrix01 = GLUniformData.creatEmptyMatrix(UniformNames.gcu_PMVMatrix01, 4, 4); + gcu_Weight = GLUniformData.creatEmptyVector(UniformNames.gcu_Weight, 1); + gcu_ColorStatic = GLUniformData.creatEmptyVector(UniformNames.gcu_ColorStatic, 4); + } + + public final int getRenderStateId() { return rsId; } + + /** + * <p> + * Since {@link RenderState} data is being used in multiple + * {@link ShaderProgram}s the data must always be written. + * </p> + * @param gl + * @param updateLocation + * @param renderModes + * @param throwOnError TODO + * @return true if no error occurred, i.e. all locations found, otherwise false. + */ + public final boolean update(final GL2ES2 gl, final RenderState rs, final boolean updateLocation, final int renderModes, final boolean pass1, final boolean throwOnError) { + if( rs.id() != rsId ) { + gcu_PMVMatrix01.setData(rs.pmvMatrix.glGetPMvMatrixf()); + gcu_Weight.setData(rs.weightBuffer); + gcu_ColorStatic.setData(rs.colorStaticBuffer); + rsId = rs.id(); + } + boolean res = true; + if( null != rs.sp && rs.sp.inUse() ) { + if( !Region.isTwoPass(renderModes) || !pass1 ) { + final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_PMVMatrix01, throwOnError); + res = res && r0; + } + if( pass1 ) { + if( Region.hasVariableWeight( renderModes ) ) { + final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_Weight, throwOnError); + res = res && r0; + } + { + final boolean r0 = rs.updateUniformDataLoc(gl, updateLocation, true, gcu_ColorStatic, throwOnError); + res = res && r0; + } + } + } + return res; + } + + public StringBuilder toString(StringBuilder sb, boolean alsoUnlocated) { + if(null==sb) { + sb = new StringBuilder(); + } + sb.append("ProgramLocal[rsID ").append(rsId).append(Platform.NEWLINE); + // pmvMatrix.toString(sb, "%.2f"); + sb.append(gcu_PMVMatrix01).append(", ").append(Platform.NEWLINE); + sb.append(gcu_ColorStatic).append(", "); + sb.append(gcu_Weight).append("]"); + return sb; + } + + @Override + public String toString() { + return toString(null, false).toString(); + } + } + protected RenderState(Vertex.Factory<? extends Vertex> vertexFactory, PMVMatrix pmvMatrix) { + this.id = getNextID(); this.sp = null; this.vertexFactory = vertexFactory; this.pmvMatrix = null != pmvMatrix ? pmvMatrix : new PMVMatrix(); - this.gcu_PMVMatrix01 = new GLUniformData(UniformNames.gcu_PMVMatrix01, 4, 4, this.pmvMatrix.glGetPMvMatrixf()); - this.gcu_Weight = new GLUniformData(UniformNames.gcu_Weight, 1.0f); - this.gcu_ColorStatic = new GLUniformData(UniformNames.gcu_ColorStatic, 4, FloatBuffer.allocate(4)); + this.weight = new float[1]; + this.weightBuffer = FloatBuffer.wrap(weight); + this.colorStatic = new float[4]; + this.colorStaticBuffer = FloatBuffer.wrap(colorStatic); this.hintBitfield = 0; } + public final int id() { return id; } public final ShaderProgram getShaderProgram() { return sp; } public final boolean isShaderProgramInUse() { return null != sp ? sp.inUse() : false; } @@ -124,42 +209,28 @@ public class RenderState { public final Vertex.Factory<? extends Vertex> getVertexFactory() { return vertexFactory; } public final PMVMatrix getMatrix() { return pmvMatrix; } - public final PMVMatrix getMatrixMutable() { - gcu_PMVMatrix01_dirty = true; - return pmvMatrix; - } - public final GLUniformData getMatrixUniform() { return gcu_PMVMatrix01; } - public final void setMatrixDirty() { gcu_PMVMatrix01_dirty = true; } - public final boolean isMatrixDirty() { return gcu_PMVMatrix01_dirty;} public static boolean isWeightValid(float v) { return 0.0f <= v && v <= 1.9f ; } - public final float getWeight() { return gcu_Weight.floatValue(); } + public final float getWeight() { return weight[0]; } public final void setWeight(float v) { if( !isWeightValid(v) ) { throw new IllegalArgumentException("Weight out of range"); } - gcu_Weight_dirty = true; - gcu_Weight.setData(v); + weight[0] = v; } public final float[] getColorStatic(float[] rgbaColor) { - FloatBuffer fb = (FloatBuffer) gcu_ColorStatic.getBuffer(); - rgbaColor[0] = fb.get(0); - rgbaColor[1] = fb.get(1); - rgbaColor[2] = fb.get(2); - rgbaColor[3] = fb.get(3); + System.arraycopy(colorStatic, 0, rgbaColor, 0, 4); return rgbaColor; } public final void setColorStatic(float r, float g, float b, float a){ - final FloatBuffer fb = (FloatBuffer) gcu_ColorStatic.getBuffer(); - fb.put(0, r); - fb.put(1, g); - fb.put(2, b); - fb.put(3, a); - gcu_ColorStatic_dirty = true; + colorStatic[0] = r; + colorStatic[1] = g; + colorStatic[2] = b; + colorStatic[3] = a; } @@ -167,43 +238,17 @@ public class RenderState { * * @param gl * @param updateLocation - * @param renderModes - * @return true if no error occurred, i.e. all locations found, otherwise false. - */ - public final boolean update(GL2ES2 gl, final boolean updateLocation, final int renderModes, final boolean pass1) { - boolean res = true; - if( null != sp && sp.inUse() ) { - if( ( !Region.isTwoPass(renderModes) || !pass1 ) && ( gcu_PMVMatrix01_dirty || updateLocation ) ) { - final boolean r0 = updateUniformDataLoc(gl, updateLocation, gcu_PMVMatrix01_dirty, gcu_PMVMatrix01); - res = res && r0; - gcu_PMVMatrix01_dirty = !r0; - } - if( pass1 ) { - if( Region.hasVariableWeight( renderModes ) && ( gcu_Weight_dirty || updateLocation ) ) { - final boolean r0 = updateUniformDataLoc(gl, updateLocation, gcu_Weight_dirty, gcu_Weight); - res = res && r0; - gcu_Weight_dirty = !r0; - } - if( gcu_ColorStatic_dirty || updateLocation ) { - final boolean r0 = updateUniformDataLoc(gl, updateLocation, gcu_ColorStatic_dirty, gcu_ColorStatic); - res = res && r0; - gcu_ColorStatic_dirty = false; - } - } - } - return res; - } - - /** - * - * @param gl - * @param updateLocation * @param data + * @param throwOnError TODO * @return true if no error occured, i.e. all locations found, otherwise false. */ - public final boolean updateUniformLoc(final GL2ES2 gl, final boolean updateLocation, final GLUniformData data) { + public final boolean updateUniformLoc(final GL2ES2 gl, final boolean updateLocation, final GLUniformData data, final boolean throwOnError) { if( updateLocation || 0 > data.getLocation() ) { - return 0 <= data.setLocation(gl, sp.program()); + final boolean ok = 0 <= data.setLocation(gl, sp.program()); + if( throwOnError && !ok ) { + throw new GLException("Could not locate "+data); + } + return ok; } else { return true; } @@ -215,12 +260,16 @@ public class RenderState { * @param updateLocation * @param updateData TODO * @param data + * @param throwOnError TODO * @return true if no error occured, i.e. all locations found, otherwise false. */ - public final boolean updateUniformDataLoc(final GL2ES2 gl, boolean updateLocation, boolean updateData, final GLUniformData data) { + public final boolean updateUniformDataLoc(final GL2ES2 gl, boolean updateLocation, boolean updateData, final GLUniformData data, final boolean throwOnError) { updateLocation = updateLocation || 0 > data.getLocation(); if( updateLocation ) { updateData = 0 <= data.setLocation(gl, sp.program()); + if( throwOnError && !updateData ) { + throw new GLException("Could not locate "+data); + } } if( updateData ){ gl.glUniform(data); @@ -233,11 +282,16 @@ public class RenderState { /** * @param gl * @param data + * @param throwOnError TODO * @return true if no error occured, i.e. all locations found, otherwise false. */ - public final boolean updateAttributeLoc(final GL2ES2 gl, final boolean updateLocation, final GLArrayDataServer data) { + public final boolean updateAttributeLoc(final GL2ES2 gl, final boolean updateLocation, final GLArrayDataServer data, boolean throwOnError) { if( updateLocation || 0 > data.getLocation() ) { - return 0 <= data.setLocation(gl, sp.program()); + final boolean ok = 0 <= data.setLocation(gl, sp.program()); + if( throwOnError && !ok ) { + throw new GLException("Could not locate "+data); + } + return ok; } else { return true; } @@ -274,21 +328,8 @@ public class RenderState { return false; } - public StringBuilder toString(StringBuilder sb, boolean alsoUnlocated) { - if(null==sb) { - sb = new StringBuilder(); - } - sb.append("RenderState[").append(sp).append(Platform.NEWLINE); - // pmvMatrix.toString(sb, "%.2f"); - sb.append(", dirty[pmv "+gcu_PMVMatrix01_dirty+", color "+gcu_ColorStatic_dirty+", weight "+gcu_Weight_dirty+"], ").append(Platform.NEWLINE); - sb.append(gcu_PMVMatrix01).append(", ").append(Platform.NEWLINE); - sb.append(gcu_ColorStatic).append(", "); - sb.append(gcu_Weight).append("]"); - return sb; - } - @Override public String toString() { - return toString(null, false).toString(); + return "RenderState["+sp+"]"; } } diff --git a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java index f944843e9..aadbecc91 100644 --- a/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java +++ b/src/jogl/classes/com/jogamp/graph/curve/opengl/TextRegionUtil.java @@ -178,7 +178,7 @@ public class TextRegionUtil { final int special = 0; GLRegion region = getCachedRegion(font, str, pixelSize, special); if(null == region) { - region = GLRegion.create(renderModes); + region = GLRegion.create(renderModes, null); addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, tempT1, tempT2); addCachedRegion(gl, font, str, pixelSize, special, region); } @@ -213,7 +213,7 @@ public class TextRegionUtil { if(!renderer.isInitialized()){ throw new GLException("TextRendererImpl01: not initialized!"); } - final GLRegion region = GLRegion.create(renderModes); + final GLRegion region = GLRegion.create(renderModes, null); addStringToRegion(region, renderer.getRenderState().getVertexFactory(), font, pixelSize, str, rgbaColor, temp1, temp2); region.draw(gl, renderer, sampleCount); region.destroy(gl); |