Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GraphRenderer.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11#ifndef JAU_GAMP_GRAPH_GL_GRAPHRENDERER_HPP_
12#define JAU_GAMP_GRAPH_GL_GRAPHRENDERER_HPP_
13
18#include <jau/debug.hpp>
19
20namespace gamp::graph::gl {
21
22 /** \addtogroup Gamp_Graph
23 *
24 * @{
25 */
26
27 using namespace jau::math;
28 using namespace jau::math::geom;
29 using namespace gamp::graph;
30 using namespace gamp::render::gl;
31
32 /**
33 * OpenGL {@link Region} renderer
34 *
35 * All {@link Region} rendering operations utilize a RegionRenderer.
36 *
37 * The RegionRenderer owns its {@link RenderState}, a composition.
38 *
39 * The RegionRenderer manages and own all used {@link ShaderProgram}s, a composition.
40 *
41 * At its {@link #destroy(GL2ES2) destruction}, all {@link ShaderProgram}s and its {@link RenderState}
42 * will be destroyed and released.
43 */
45 protected:
46 protected static const bool DEBUG = Region.DEBUG;
47 protected static const bool DEBUG_ALL_EVENT = Region.DEBUG_ALL_EVENT;
48 protected static const bool DEBUG_INSTANCE = Region.DEBUG_INSTANCE;
49 private static const bool DEBUG_SHADER_MAP = DEBUG;
50
51 /**
52 * May be passed to
53 * {@link RegionRenderer#create(Vertex.Factory<? extends Vertex>, RenderState, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback, com.jogamp.graph.curve.opengl.RegionRenderer.GLCallback) RegionRenderer ctor},
54 * e.g.
55 * <ul>
56 * <li>{@link RegionRenderer#defaultBlendEnable}</li>
57 * <li>{@link RegionRenderer#defaultBlendDisable}</li>
58 * </ul>
59 */
60 public interface GLCallback {
61 /**
62 * @param gl a current GL object
63 * @param renderer {@link RegionRenderer} calling this method.
64 */
65 void run(GL gl, RegionRenderer renderer);
66 }
67
68 /**
69 * Default {@link GL#GL_BLEND} <i>enable</i> {@link GLCallback},
70 * turning-off depth writing via {@link GL#glDepthMask(bool)} if {@link RenderState#BITHINT_GLOBAL_DEPTH_TEST_ENABLED} is set
71 * and turning-on the {@link GL#GL_BLEND} state.
72 * <p>
73 * Implementation also sets {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint},
74 * which will cause {@link GLRegion#draw(GL2ES2, RegionRenderer) GLRegion's draw-method}
75 * to set the proper {@link GL#glBlendFuncSeparate(int, int, int, int) blend-function}
76 * and the clear-color to <i>transparent-black</i> in case of {@link Region#isTwoPass(int) multipass} FBO rendering.
77 * </p>
78 * @see #create(GLCallback, GLCallback)
79 * @see #enable(GL2ES2, bool)
80 */
81 public static const GLCallback defaultBlendEnable = new GLCallback() {
82 @Override
83 public void run(const GL gl, const RegionRenderer renderer) {
84 if( renderer.hintBitsSet(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
85 gl.glDepthMask(false);
86 // gl.glDisable(GL.GL_DEPTH_TEST);
87 // gl.glDepthFunc(GL.GL_ALWAYS);
88 }
89 gl.glEnable(GL.GL_BLEND);
90 gl.glBlendEquation(GL.GL_FUNC_ADD); // default
91 renderer.setHintBits(RenderState.BITHINT_BLENDING_ENABLED);
92 }
93 };
94
95 /**
96 * Default {@link GL#GL_BLEND} <i>disable</i> {@link GLCallback},
97 * simply turning-off the {@link GL#GL_BLEND} state
98 * and turning-on depth writing via {@link GL#glDepthMask(bool)} if {@link RenderState#BITHINT_GLOBAL_DEPTH_TEST_ENABLED} is set.
99 * <p>
100 * Implementation also clears {@link RegionRenderer#getRenderState() RenderState}'s {@link RenderState#BITHINT_BLENDING_ENABLED blending bit-hint}.
101 * </p>
102 * @see #create(GLCallback, GLCallback)
103 * @see #enable(GL2ES2, bool)
104 */
105 public static const GLCallback defaultBlendDisable = new GLCallback() {
106 @Override
107 public void run(const GL gl, const RegionRenderer renderer) {
108 renderer.clearHintBits(RenderState.BITHINT_BLENDING_ENABLED);
109 gl.glDisable(GL.GL_BLEND);
110 if( renderer.hintBitsSet(RenderState.BITHINT_GLOBAL_DEPTH_TEST_ENABLED) ) {
111 // gl.glEnable(GL.GL_DEPTH_TEST);
112 // gl.glDepthFunc(GL.GL_LESS);
113 gl.glDepthMask(true);
114 }
115 }
116 };
117
118 /**
119 * Create a hardware accelerated RegionRenderer including its {@link RenderState} composition.
120 * <p>
121 * The optional {@link GLCallback}s <code>enableCallback</code> and <code>disableCallback</code>
122 * maybe used to issue certain tasks at {@link #enable(GL2ES2, bool)}.<br/>
123 * For example, instances {@link #defaultBlendEnable} and {@link #defaultBlendDisable}
124 * can be utilized to enable and disable {@link GL#GL_BLEND}.
125 * </p>
126 * @return an instance of Region Renderer
127 * @see #enable(GL2ES2, bool)
128 */
129 public static RegionRenderer create() {
130 return new RegionRenderer(null, null, null);
131 }
132
133 /**
134 * Create a hardware accelerated RegionRenderer including its {@link RenderState} composition.
135 * <p>
136 * The optional {@link GLCallback}s <code>enableCallback</code> and <code>disableCallback</code>
137 * maybe used to issue certain tasks at {@link #enable(GL2ES2, bool)}.<br/>
138 * For example, instances {@link #defaultBlendEnable} and {@link #defaultBlendDisable}
139 * can be utilized to enable and disable {@link GL#GL_BLEND}.
140 * </p>
141 * @param enableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
142 * {@link #init(GL2ES2) init(gl)} and {@link #enable(GL2ES2, bool) enable(gl, true)}.
143 * @param disableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
144 * {@link #enable(GL2ES2, bool) enable(gl, false)}.
145 * @return an instance of Region Renderer
146 * @see #enable(GL2ES2, bool)
147 */
148 public static RegionRenderer create(const GLCallback enableCallback, const GLCallback disableCallback) {
149 return new RegionRenderer(enableCallback, disableCallback);
150 }
151
152 /**
153 * Create a hardware accelerated RegionRenderer including its {@link RenderState} composition.
154 * <p>
155 * The optional {@link GLCallback}s <code>enableCallback</code> and <code>disableCallback</code>
156 * maybe used to issue certain tasks at {@link #enable(GL2ES2, bool)}.<br/>
157 * For example, instances {@link #defaultBlendEnable} and {@link #defaultBlendDisable}
158 * can be utilized to enable and disable {@link GL#GL_BLEND}.
159 * </p>
160 * @param sharedPMVMatrix optional shared {@link PMVMatrix4f} to be used for the {@link RenderState} composition.
161 * @param enableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
162 * {@link #init(GL2ES2) init(gl)} and {@link #enable(GL2ES2, bool) enable(gl, true)}.
163 * @param disableCallback optional {@link GLCallback}, if not <code>null</code> will be issued at
164 * {@link #enable(GL2ES2, bool) enable(gl, false)}.
165 * @return an instance of Region Renderer
166 * @see #enable(GL2ES2, bool)
167 */
168 public static RegionRenderer create(const PMVMatrix4f sharedPMVMatrix,
169 const GLCallback enableCallback, const GLCallback disableCallback) {
170 return new RegionRenderer(sharedPMVMatrix, enableCallback, disableCallback);
171 }
172
173 private const RenderState rs;
174
175 private const GLCallback enableCallback;
176 private const GLCallback disableCallback;
177
178 private const Recti viewport = new Recti();
179 private bool initialized;
180 private bool vboSupported = false;
181
182 public const bool isInitialized() { return initialized; }
183
184 /** Copies the current Rect4i viewport in given target and returns it for chaining. */
185 public const Recti getViewport(const Recti target) {
186 target.set(viewport);
187 return target;
188 }
189 /** Borrows the current Rect4i viewport w/o copying. */
190 public const Recti getViewport() {
191 return viewport;
192 }
193 /** Return width of current viewport */
194 public const int getWidth() { return viewport.width(); }
195 /** Return height of current viewport */
196 public const int getHeight() { return viewport.height(); }
197
198 //////////////////////////////////////
199
200 protected RegionRenderer(const GLCallback enableCallback, const GLCallback disableCallback) {
201 this(null, enableCallback, disableCallback);
202 }
203
204 protected RegionRenderer(const PMVMatrix4f sharedPMVMatrix,
205 const GLCallback enableCallback, const GLCallback disableCallback)
206 {
207 this.rs = new RenderState(sharedPMVMatrix);
208 this.enableCallback = enableCallback;
209 this.disableCallback = disableCallback;
210 if( UseShaderPrograms0 ) {
211 shaderPrograms0 = new LongObjectHashMap();
212 shaderPrograms1 = null;
213 } else {
214 shaderPrograms0 = null;
215 shaderPrograms1 = new HashMap<ShaderKey, ShaderProgram>();
216 }
217 }
218
219 public const bool isVBOSupported() { return vboSupported; }
220
221 /**
222 * Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext
223 * if not initialized yet.
224 * <p>Disables the renderer via {@link #enable(GL2ES2, bool)} to remove any side-effects, ie ShaderState incl. shader program.</p>
225 * <p>Shall be called once before at initialization before a {@code draw()} method, e.g. {@link RegionRenderer#draw(GL2ES2, Region)}</p>
226 *
227 * @param gl referencing the current GLContext to which the ShaderState is bound to
228 * @throws GLException if initialization failed
229 */
230 public const void init(const GL2ES2 gl) throws GLException {
231 if(initialized){
232 return;
233 }
234 vboSupported = gl.isFunctionAvailable("glGenBuffers") &&
235 gl.isFunctionAvailable("glBindBuffer") &&
236 gl.isFunctionAvailable("glBufferData") &&
237 gl.isFunctionAvailable("glDrawElements") &&
238 gl.isFunctionAvailable("glVertexAttribPointer") &&
239 gl.isFunctionAvailable("glDeleteBuffers");
240
241 if(DEBUG) {
242 System.err.println("TextRendererImpl01: VBO Supported = " + isVBOSupported());
243 }
244
245 if(!vboSupported){
246 throw new GLException("VBO not supported");
247 }
248
249 rs.attachTo(gl);
250
251 initialized = true;
252 enable(gl, false);
253 }
254
255 /** Deletes all {@link ShaderProgram}s and nullifies its references including {@link RenderState#destroy(GL2ES2)}. */
256 public const void destroy(const GL2ES2 gl) {
257 if(!initialized){
258 if(DEBUG_INSTANCE) {
259 System.err.println("TextRenderer: Not initialized!");
260 }
261 return;
262 }
263 if( UseShaderPrograms0 ) {
264 for(const Iterator<LongObjectHashMap.Entry> i = shaderPrograms0.iterator(); i.hasNext(); ) {
265 const ShaderProgram sp = (ShaderProgram) i.next().getValue();
266 sp.destroy(gl);
267 }
268 shaderPrograms0.clear();
269 } else {
270 for(const Iterator<ShaderProgram> i = shaderPrograms1.values().iterator(); i.hasNext(); ) {
271 const ShaderProgram sp = i.next();
272 sp.destroy(gl);
273 }
274 shaderPrograms1.clear();
275 }
276 rs.detachFrom(gl);
277 rs.destroy();
278 initialized = false;
279 }
280
281 /** Return the {@link RenderState} composition. */
282 public const RenderState getRenderState() { return rs; }
283
284 //
285 // RenderState forwards
286 //
287
288 /** Borrow the current {@link PMVMatrix4f}. */
289 public const PMVMatrix4f getMatrix() { return rs.getMatrix(); }
290
291 public const float getWeight() { return rs.getWeight(); }
292
293 public const void setWeight(const float v) { rs.setWeight(v); }
294
295 public const Vec4f getColorStatic(const Vec4f rgbaColor) { return rs.getColorStatic(rgbaColor); }
296
297 public const void setColorStatic(const Vec4f rgbaColor){ rs.setColorStatic(rgbaColor); }
298
299 public const void setColorStatic(const float r, const float g, const float b, const float a){ rs.setColorStatic(r, g, b, a); }
300
301 /** Sets pass2 AA-quality rendering value clipped to the range [{@link Region#MIN_AA_QUALITY}..{@link Region#MAX_AA_QUALITY}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}. */
302 public const int setAAQuality(const int v) { return rs.setAAQuality(v); }
303 /** Returns pass2 AA-quality rendering value for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link Region#VBAA_RENDERING_BIT}. */
304 public const int getAAQuality() { return rs.getAAQuality(); }
305
306 /** Sets pass2 AA sample count clipped to the range [{@link Region#MIN_AA_SAMPLE_COUNT}..{@link Region#MAX_AA_SAMPLE_COUNT}] for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
307 public const int setSampleCount(const int v) { return rs.setSampleCount(v); }
308 /** Returns pass2 AA sample count for Graph Region AA {@link Region#getRenderModes() render-modes}: {@link #VBAA_RENDERING_BIT} or {@link Region#MSAA_RENDERING_BIT}. */
309 public const int getSampleCount() { return rs.getSampleCount(); }
310
311 /** Set the optional clipping {@link Frustum}, which shall be pre-multiplied with the Mv-matrix or null to disable. */
312 public const void setClipFrustum(const Frustum clipFrustum) { rs.setClipFrustum(clipFrustum); }
313 /** Returns the optional Mv-premultiplied clipping {@link Frustum} or null if unused. */
314 public const Frustum getClipFrustum() { return rs.getClipFrustum(); }
315
316 public const bool hintBitsSet(const int mask) { return rs.hintBitsSet(mask); }
317
318 public const void setHintBits(const int mask) { rs.setHintBits(mask); }
319
320 public const void clearHintBits(const int mask) { rs.clearHintBits(mask); }
321
322 /**
323 * Enabling or disabling the {@link #getRenderState() RenderState}'s
324 * current {@link RenderState#getShaderProgram() shader program}.
325 * <p>
326 * {@link #useShaderProgram(GL2ES2, int, bool, TextureSequence)}
327 * generates, selects and caches the desired Curve-Graph {@link ShaderProgram}
328 * and {@link RenderState#setShaderProgram(GL2ES2, ShaderProgram) sets it current} in the {@link RenderState} composition.
329 * </p>
330 * <p>
331 * In case enable and disable {@link GLCallback}s are setup via {@link #create(Vertex.Factory<? extends Vertex>, RenderState, GLCallback, GLCallback)},
332 * they will be called before toggling the shader program.
333 * </p>
334 * @param gl current GL object
335 * @param enable if true enable the current {@link ShaderProgram}, otherwise disable.
336 * @see #create(Vertex.Factory<? extends Vertex>, RenderState, GLCallback, GLCallback)
337 * @see #useShaderProgram(GL2ES2, int, bool, TextureSequence)
338 * @see RenderState#setShaderProgram(GL2ES2, ShaderProgram)
339 * @see RenderState#getShaderProgram()
340 */
341 public const void enable(const GL2ES2 gl, const bool enable) {
342 enable(gl, enable, enableCallback, disableCallback);
343 }
344
345 /**
346 * Same as {@link #enable(GL2ES2, bool)} but allowing to force {@link GLCallback}s off.
347 * @param gl current GL object
348 * @param enable if true enable the current {@link ShaderProgram}, otherwise disable.
349 * @param enableCB explicit {@link GLCallback} for enable
350 * @param disableCB explicit {@link GLCallback} for disable
351 * @see #enable(GL2ES2, bool)
352 */
353 public const void enable(const GL2ES2 gl, const bool enable, const GLCallback enableCB, const GLCallback disableCB) {
354 if( enable ) {
355 if( null != enableCB ) {
356 enableCB.run(gl, this);
357 }
358 } else {
359 if( null != disableCB ) {
360 disableCB.run(gl, this);
361 }
362 const ShaderProgram sp = rs.getShaderProgram();
363 if( null != sp ) {
364 sp.useProgram(gl, false);
365 }
366 }
367 }
368
369 /**
370 * No PMVMatrix4f operation is performed here.
371 */
372 public const void reshapeNotify(const int x, const int y, const int width, const int height) {
373 viewport.set(x, y, width, height);
374 }
375
376 /**
377 * Perspective projection, method also calls {@link #reshapeNotify(int, int, int, int)}.
378 * @param angle_rad perspective angle in radians
379 * @param width viewport width
380 * @param height viewport height
381 * @param near projection z-near
382 * @param far projection z-far
383 */
384 public const void reshapePerspective(const float angle_rad, const int width, const int height, const float near, const float far) {
385 reshapeNotify(0, 0, width, height);
386 const float ratio = (float)width/(float)height;
387 const PMVMatrix4f p = getMatrix();
388 p.loadPIdentity();
389 p.perspectiveP(angle_rad, ratio, near, far);
390 }
391
392 /**
393 * Orthogonal projection, method also calls {@link #reshapeNotify(int, int, int, int)}.
394 * @param width viewport width
395 * @param height viewport height
396 * @param near projection z-near
397 * @param far projection z-far
398 */
399 public const void reshapeOrtho(const int width, const int height, const float near, const float far) {
400 reshapeNotify(0, 0, width, height);
401 const PMVMatrix4f p = getMatrix();
402 p.loadPIdentity();
403 p.orthoP(0, width, 0, height, near, far);
404 }
405
406 //
407 // Shader Management
408 //
409
410 private static const String SHADER_SRC_SUB = "";
411 private static const String SHADER_BIN_SUB = "bin";
412 private static const String GLSL_PARAM_COMMENT_START = "\n// JogAmp Graph Parameter Start\n";
413 private static const String GLSL_PARAM_COMMENT_END = "// JogAmp Graph Parameter End\n\n";
414 private static const String GLSL_USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n";
415 private static const String GLSL_USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n";
416 private static const String GLSL_USE_FRUSTUM_CLIPPING = "#define USE_FRUSTUM_CLIPPING 1\n";
417 private static const String GLSL_DEF_SAMPLE_COUNT = "#define SAMPLE_COUNT ";
418 private static const String GLSL_CONST_SAMPLE_COUNT = "const float sample_count = ";
419 private static const String GLSL_MAIN_BEGIN = "void main (void)\n{\n";
420 private static const String gcuTexture2D = "gcuTexture2D";
421 private static const String GLSL_USE_DISCARD = "#define USE_DISCARD 1\n";
422
423 private String getVersionedShaderName() {
424 return "curverenderer01";
425 }
426
427 // FIXME: Really required to have sampler2D def. precision ? If not, we can drop getFragmentShaderPrecision(..) and use default ShaderCode ..
428 private static const String es2_precision_fp = "\nprecision mediump float;\nprecision mediump int;\nprecision mediump sampler2D;\n";
429
430 private const String getFragmentShaderPrecision(const GL2ES2 gl) {
431 if( gl.isGLES() ) {
432 return es2_precision_fp;
433 }
434 if( ShaderCode.requiresGL3DefaultPrecision(gl) ) {
435 return ShaderCode.gl3_default_precision_fp;
436 }
437 return null;
438 }
439
440 private static enum ShaderModeSelector1 {
441 /** Pass-1: Curve Simple */
442 PASS1_SIMPLE("curve", "_simple", 0),
443 /** Pass-1: Curve Varying Weight */
444 PASS1_WEIGHT("curve", "_weight", 0),
445 /** Pass-2: MSAA */
446 PASS2_MSAA("msaa", "", 0),
447 /** Pass-2: VBAA Flipquad3, 1 sample */
448 PASS2_VBAA_QUAL0_SAMPLES1("vbaa", "_flipquad3", 1),
449 /** Pass-2: VBAA Flipquad3, 2 samples */
450 PASS2_VBAA_QUAL0_SAMPLES2("vbaa", "_flipquad3", 2),
451 /** Pass-2: VBAA Flipquad3, 4 samples */
452 PASS2_VBAA_QUAL0_SAMPLES4("vbaa", "_flipquad3", 4),
453 /** Pass-2: VBAA Flipquad3, 8 samples */
454 PASS2_VBAA_QUAL0_SAMPLES8("vbaa", "_flipquad3", 8),
455
456 /** Pass-2: VBAA Brute-Force, Odd, 1 samples */
457 PASS2_VBAA_QUAL1_SAMPLES1("vbaa", "_bforce_odd", 1),
458 /** Pass-2: VBAA Brute-Force, Even, 2 samples */
459 PASS2_VBAA_QUAL1_SAMPLES2("vbaa", "_bforce_even", 2),
460 /** Pass-2: VBAA Brute-Force, Odd, 3 samples */
461 PASS2_VBAA_QUAL1_SAMPLES3("vbaa", "_bforce_odd", 3),
462 /** Pass-2: VBAA Brute-Force, Even, 4 samples */
463 PASS2_VBAA_QUAL1_SAMPLES4("vbaa", "_bforce_even", 4),
464 /** Pass-2: VBAA Brute-Force, Odd, 5 samples */
465 PASS2_VBAA_QUAL1_SAMPLES5("vbaa", "_bforce_odd", 5),
466 /** Pass-2: VBAA Brute-Force, Even, 6 samples */
467 PASS2_VBAA_QUAL1_SAMPLES6("vbaa", "_bforce_even", 6),
468 /** Pass-2: VBAA Brute-Force, Odd, 7 samples */
469 PASS2_VBAA_QUAL1_SAMPLES7("vbaa", "_bforce_odd", 7),
470 /** Pass-2: VBAA Brute-Force, Even, 8 samples */
471 PASS2_VBAA_QUAL1_SAMPLES8("vbaa", "_bforce_even", 8);
472
473 public const String tech;
474 public const String sub;
475 public const int sampleCount;
476
477 ShaderModeSelector1(const String tech, const String sub, const int sampleCount) {
478 this.tech = tech;
479 this.sub= sub;
480 this.sampleCount = sampleCount;
481 }
482
483 public static ShaderModeSelector1 selectPass1(const int renderModes) {
484 return Region.hasVariableWeight(renderModes) ? PASS1_WEIGHT : PASS1_SIMPLE;
485 }
486
487 public static ShaderModeSelector1 selectPass2(const int renderModes, const int quality, const int sampleCount) {
488 if( Region.isVBAA(renderModes) ) {
489 if( 0 == quality ) {
490 if( sampleCount < 2 ) {
491 return PASS2_VBAA_QUAL0_SAMPLES1;
492 } else if( sampleCount < 4 ) {
493 return PASS2_VBAA_QUAL0_SAMPLES2;
494 } else if( sampleCount < 8 ) {
495 return PASS2_VBAA_QUAL0_SAMPLES4;
496 } else {
497 return PASS2_VBAA_QUAL0_SAMPLES8;
498 }
499 } else {
500 switch( sampleCount ) {
501 case 0: // Fall through intended
502 case 1: return PASS2_VBAA_QUAL1_SAMPLES1;
503 case 2: return PASS2_VBAA_QUAL1_SAMPLES2;
504 case 3: return PASS2_VBAA_QUAL1_SAMPLES3;
505 case 4: return PASS2_VBAA_QUAL1_SAMPLES4;
506 case 5: return PASS2_VBAA_QUAL1_SAMPLES5;
507 case 6: return PASS2_VBAA_QUAL1_SAMPLES6;
508 case 7: return PASS2_VBAA_QUAL1_SAMPLES7;
509 default: return PASS2_VBAA_QUAL1_SAMPLES8;
510 }
511 }
512 } else {
513 return PASS2_MSAA; // Region.isMSAA(renderModes) and default
514 }
515 }
516 }
517
518 private static class ShaderKey {
519 const bool isTwoPass;
520 const bool pass1;
521 const ShaderModeSelector1 sms;
522 const bool hasFrustumClipping; // pass1 or pass2
523 const bool hasColorChannel; // pass1 only
524 const bool hasColorTexture; // pass1 only
525 const String colorTexSeqID;
526
527 const int hashValue;
528
529 ShaderKey(const bool isTwoPass, const bool pass1, const ShaderModeSelector1 sms,
530 const bool hasFrustumClipping, const bool hasColorChannel,
531 const bool hasColorTexture, const TextureSequence colorTexSeq, const int colorTexSeqHash)
532 {
533 this.isTwoPass = isTwoPass;
534 this.pass1 = pass1;
535 this.sms = sms;
536 this.hasFrustumClipping = hasFrustumClipping;
537 this.hasColorChannel = hasColorChannel;
538 this.hasColorTexture = hasColorTexture;
539 if( hasColorTexture ) {
540 this.colorTexSeqID = colorTexSeq.getTextureFragmentShaderHashID();
541 } else {
542 this.colorTexSeqID = "";
543 }
544 hashValue = getShaderKey1(isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms, colorTexSeqHash);
545 }
546 @Override
547 public const int hashCode() { return hashValue; }
548 @Override
549 public const bool equals(const Object other) {
550 if( this == other ) { return true; }
551 if( !(other instanceof ShaderKey) ) {
552 return false;
553 }
554 const ShaderKey o = (ShaderKey)other;
555 return isTwoPass == o.isTwoPass &&
556 pass1 == o.pass1 &&
557 // pass2Quality == o.pass2Quality && // included in sms
558 // sampleCount == o.sampleCount && // included in sms
559 sms.ordinal() == o.sms.ordinal() &&
560 hasFrustumClipping == o.hasFrustumClipping &&
561 hasColorChannel == o.hasColorChannel &&
562 hasColorTexture == o.hasColorTexture &&
563 colorTexSeqID.equals(o.colorTexSeqID);
564 }
565 @Override
566 public String toString() {
567 return shaderHashToString(hashValue, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms);
568 }
569 }
570 private static const bool UseShaderPrograms0 = true;
571 private const LongObjectHashMap shaderPrograms0;
572 private const HashMap<ShaderKey, ShaderProgram> shaderPrograms1;
573
574 private static String shaderHashToString(const int hashCode, const bool isTwoPass, const bool pass1,
575 const bool hasFrustumClipping, const bool hasColorChannel, const bool hasColorTexture,
576 const ShaderModeSelector1 sms) {
577 return "ShaderHash[hash 0x"+Integer.toHexString(hashCode)+", is2Pass "+isTwoPass+", pass1 "+pass1+
578 ", has[clip "+hasFrustumClipping+", colChan "+hasColorChannel+", colTex "+hasColorTexture+"], "+sms+"]";
579 }
580 private static String shaderKeyToString(const long key, const bool isTwoPass, const bool pass1,
581 const bool hasFrustumClipping, const bool hasColorChannel, const bool hasColorTexture,
582 const ShaderModeSelector1 sms) {
583 return "ShaderKey[key 0x"+Long.toHexString(key)+", is2Pass "+isTwoPass+", pass1 "+pass1+
584 ", has[clip "+hasFrustumClipping+", colChan "+hasColorChannel+", colTex "+hasColorTexture+"], "+sms+"]";
585 }
586
587 private static long getShaderKey0(const bool isTwoPass, const bool pass1,
588 const bool hasFrustumClipping, const bool hasColorChannel, const bool hasColorTexture,
589 const ShaderModeSelector1 sms, const long colorTexSeqHash) {
590 // # | s |
591 // 0 | 1 | isTwoPass
592 // 1 | 1 | pass1
593 // 2 | 5 | ShaderModeSelector1
594 // 7 | 1 | hasFrustumClipping
595 // 8 | 1 | hasColorChannel
596 // 9 | 1 | hasColorTexture
597 // 32 | 32 | colorTexSeqHash
598 long hash = isTwoPass ? 1L : 0L;
599 hash |= ( pass1 ? 1L : 0L ) << 1;
600 hash |= (long)( sms.ordinal() & 0b11111 ) << 2; // incl. pass2Quality + sampleCount
601 hash |= ( hasFrustumClipping ? 1L : 0L ) << 7;
602 hash |= ( hasColorChannel ? 1L : 0L ) << 8;
603 hash |= ( hasColorTexture ? 1L : 0L ) << 9;
604 hash |= ( colorTexSeqHash & 0xFFFFFFL ) << 32;
605 return hash;
606 }
607 private static int getShaderKey1(const bool isTwoPass, const bool pass1,
608 const bool hasFrustumClipping, const bool hasColorChannel, const bool hasColorTexture,
609 const ShaderModeSelector1 sms, const int colorTexSeqHash) {
610 // 31 * x == (x << 5) - x
611 int hash = 31 * ( isTwoPass ? 1 : 0 );
612 hash = ((hash << 5) - hash) + ( pass1 ? 1 : 0 ) ;
613 // hash = ((hash << 5) - hash) + pass2Quality; // included in sms
614 // hash = ((hash << 5) - hash) + sampleCount; // included in sms
615 hash = ((hash << 5) - hash) + sms.ordinal();
616 hash = ((hash << 5) - hash) + ( hasFrustumClipping ? 1 : 0 );
617 hash = ((hash << 5) - hash) + ( hasColorChannel ? 1 : 0 );
618 hash = ((hash << 5) - hash) + ( hasColorTexture ? 1 : 0 );
619 hash = ((hash << 5) - hash) + colorTexSeqHash;
620 return hash;
621 }
622
623 /**
624 * Generate, selects and caches the desired Curve-Graph {@link ShaderProgram} according to the given parameters.
625 *
626 * The newly generated or cached {@link ShaderProgram} is {@link RenderState#setShaderProgram(GL2ES2, ShaderProgram) set current} in the {@link RenderState} composition
627 * and can be retrieved via {@link RenderState#getShaderProgram()}.
628 *
629 * @param gl
630 * @param renderModes
631 * @param pass1
632 * @param colorTexSeq
633 * @return true if a new shader program is being used and hence external uniform-data and -location,
634 * as well as the attribute-location must be updated, otherwise false.
635 * @see #enable(GL2ES2, bool)
636 * @see RenderState#setShaderProgram(GL2ES2, ShaderProgram)
637 * @see RenderState#getShaderProgram()
638 */
639 public const bool useShaderProgram(const GL2ES2 gl, const int renderModes, const bool pass1, const TextureSequence colorTexSeq) {
640 const bool isTwoPass = Region.isTwoPass( renderModes );
641 const ShaderModeSelector1 sms = pass1 ? ShaderModeSelector1.selectPass1(renderModes) :
642 ShaderModeSelector1.selectPass2(renderModes, getAAQuality(), getSampleCount());
643 const bool hasFrustumClipping = ( null != getClipFrustum() ) && ( ( !isTwoPass && pass1 ) || ( isTwoPass && !pass1 ) );
644 const bool hasColorChannel = pass1 && Region.hasColorChannel( renderModes );
645 const bool hasColorTexture = pass1 && Region.hasColorTexture( renderModes ) && null != colorTexSeq;
646 const int colorTexSeqHash;
647 const String colTexLookupFuncName;
648 if( hasColorTexture ) {
649 colTexLookupFuncName = colorTexSeq.setTextureLookupFunctionName(gcuTexture2D);
650 colorTexSeqHash = colorTexSeq.getTextureFragmentShaderHashCode();
651 } else {
652 colTexLookupFuncName = "";
653 colorTexSeqHash = 0;
654 }
655
656 if( UseShaderPrograms0 ) {
657 return useShaderProgram0(gl, renderModes, isTwoPass, pass1, sms, hasFrustumClipping, hasColorChannel,
658 hasColorTexture, colorTexSeq, colTexLookupFuncName, colorTexSeqHash);
659 } else {
660 return useShaderProgram1(gl, renderModes, isTwoPass, pass1, sms, hasFrustumClipping, hasColorChannel,
661 hasColorTexture, colorTexSeq, colTexLookupFuncName, colorTexSeqHash);
662 }
663 }
664 private const bool useShaderProgram0(const GL2ES2 gl, const int renderModes,
665 const bool isTwoPass, const bool pass1, const ShaderModeSelector1 sms,
666 const bool hasFrustumClipping, const bool hasColorChannel,
667 const bool hasColorTexture, const TextureSequence colorTexSeq,
668 const String colTexLookupFuncName, const int colorTexSeqHash)
669 {
670 const long shaderKey = getShaderKey0(isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms, colorTexSeqHash);
671 /**
672 if(DEBUG) {
673 System.err.println("XXX "+Region.getRenderModeString(renderModes, getAAQuality(), getSampleCount(), 0)+", "+
674 shaderKeyToString(shaderHashCode, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms));
675 } */
676
677 ShaderProgram sp = (ShaderProgram) shaderPrograms0.get( shaderKey );
678 if( null != sp ) {
679 const bool spChanged = rs.setShaderProgram(gl, sp);
680 if( DEBUG_SHADER_MAP ) {
681 if( spChanged ) {
682 System.err.printf("RegionRenderer.useShaderProgram0.X1: GOT renderModes %s, %s -> sp %d / %d (changed)%n",
683 Region.getRenderModeString(renderModes),
684 shaderKeyToString(shaderKey, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms), sp.program(), sp.id());
685 } else if( DEBUG_ALL_EVENT ) {
686 System.err.printf("RegionRenderer.useShaderProgram0.X1: GOT renderModes %s, %s -> sp %d / %d (keep)%n",
687 Region.getRenderModeString(renderModes),
688 shaderKeyToString(shaderKey, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms), sp.program(), sp.id());
689 }
690 }
691 return spChanged;
692 }
693 sp = createShaderProgram(gl, renderModes, isTwoPass, pass1, sms, hasFrustumClipping, hasColorChannel,
694 hasColorTexture, colorTexSeq, colTexLookupFuncName, colorTexSeqHash);
695 rs.setShaderProgram(gl, sp);
696
697 if( DEBUG_SHADER_MAP ) {
698 System.err.printf("RegionRenderer.useShaderProgram0.X2: NEW renderModes %s, %s -> sp %d / %d (new)%n",
699 Region.getRenderModeString(renderModes),
700 shaderKeyToString(shaderKey, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms), sp.program(), sp.id());
701 // sp.dumpSource(System.err);
702 }
703 const ShaderProgram spOld = (ShaderProgram) shaderPrograms0.put(shaderKey, sp);
704 if( null != spOld ) {
705 // COLLISION!
706 const String msg = String.format((Locale)null,
707 "RegionRenderer.useShaderProgram0: WARNING Shader-HashCode Collision: hash 0x%s: %s, %s -> sp %d / %d (new)%n",
708 Long.toHexString(shaderKey), Region.getRenderModeString(renderModes),
709 shaderKeyToString(shaderKey, isTwoPass, pass1, hasFrustumClipping, hasColorChannel, hasColorTexture, sms), sp.program(), sp.id());
710 throw new RuntimeException(msg);
711 }
712 return true;
713 }
714 private const bool useShaderProgram1(const GL2ES2 gl, const int renderModes,
715 const bool isTwoPass, const bool pass1, const ShaderModeSelector1 sms,
716 const bool hasFrustumClipping, const bool hasColorChannel,
717 const bool hasColorTexture, const TextureSequence colorTexSeq,
718 const String colTexLookupFuncName, const int colorTexSeqHash) {
719 const ShaderKey shaderKey = new ShaderKey(isTwoPass, pass1, sms, hasFrustumClipping, hasColorChannel,
720 hasColorTexture, colorTexSeq, colorTexSeqHash);
721 /**
722 if(DEBUG) {
723 System.err.println("XXX "+Region.getRenderModeString(renderModes, getAAQuality(), getSampleCount(), 0)+", "+shaderKey);
724 } */
725
726 ShaderProgram sp = shaderPrograms1.get( shaderKey );
727 if( null != sp ) {
728 const bool spChanged = rs.setShaderProgram(gl, sp);
729 if( DEBUG_SHADER_MAP ) {
730 if( spChanged ) {
731 System.err.printf("RegionRenderer.useShaderProgram1.X1: GOT renderModes %s, %s -> sp %d / %d (changed)%n",
732 Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id());
733 } else if( DEBUG_ALL_EVENT ) {
734 System.err.printf("RegionRenderer.useShaderProgram1.X1: GOT renderModes %s, %s -> sp %d / %d (keep)%n",
735 Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id());
736 }
737 }
738 return spChanged;
739 }
740 sp = createShaderProgram(gl, renderModes, isTwoPass, pass1, sms, hasFrustumClipping, hasColorChannel,
741 hasColorTexture, colorTexSeq, colTexLookupFuncName, colorTexSeqHash);
742 rs.setShaderProgram(gl, sp);
743
744 if( DEBUG_SHADER_MAP ) {
745 System.err.printf("RegionRenderer.useShaderProgram1.X2: NEW renderModes %s, %s -> sp %d / %d (new)%n",
746 Region.getRenderModeString(renderModes), shaderKey, sp.program(), sp.id());
747 // sp.dumpSource(System.err);
748 }
749
750 shaderPrograms1.put(shaderKey, sp);
751 return true;
752 }
753 @SuppressWarnings("unused")
754 private const ShaderProgram createShaderProgram(const GL2ES2 gl, const int renderModes,
755 const bool isTwoPass, const bool pass1, const ShaderModeSelector1 sms,
756 const bool hasFrustumClipping, const bool hasColorChannel,
757 const bool hasColorTexture, const TextureSequence colorTexSeq,
758 const String colTexLookupFuncName, const int colorTexSeqHash)
759 {
760 const String versionedBaseName = getVersionedShaderName();
761 const String vertexShaderName;
762 if( isTwoPass ) {
763 vertexShaderName = versionedBaseName+"-pass"+(pass1?1:2);
764 } else {
765 vertexShaderName = versionedBaseName+"-single";
766 }
767 const ShaderCode rsVp = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, vertexShaderName, true);
768 const ShaderCode rsFp = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, AttributeNames.class, SHADER_SRC_SUB, SHADER_BIN_SUB, versionedBaseName+"-segment-head", true);
769
770 if( hasColorTexture && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
771 if( !gl.isExtensionAvailable(GLExtensions.OES_EGL_image_external) ) {
772 throw new GLException(GLExtensions.OES_EGL_image_external+" requested but not available");
773 }
774 }
775 bool preludeGLSLVersion = true;
776 if( hasColorTexture && GLES2.GL_TEXTURE_EXTERNAL_OES == colorTexSeq.getTextureTarget() ) {
777 if( Platform.OSType.ANDROID == Platform.getOSType() && gl.isGLES3() ) {
778 // Bug on Nexus 10, ES3 - Android 4.3, where
779 // GL_OES_EGL_image_external extension directive leads to a failure _with_ '#version 300 es' !
780 // P0003: Extension 'GL_OES_EGL_image_external' not supported
781 preludeGLSLVersion = false;
782 }
783 }
784 //
785 // GLSL customization at top
786 //
787 int posVp = rsVp.defaultShaderCustomization(gl, preludeGLSLVersion, true);
788 // rsFp.defaultShaderCustomization(gl, true, true);
789 int posFp = preludeGLSLVersion ? rsFp.addGLSLVersion(gl) : 0;
790 if( hasColorTexture ) {
791 posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getRequiredExtensionsShaderStub());
792 }
793 if( pass1 && !preludeGLSLVersion || ( gl.isGLES2() && !gl.isGLES3() ) ) {
794 posFp = rsFp.insertShaderSource(0, posFp, ShaderCode.createExtensionDirective(GLExtensions.OES_standard_derivatives, ShaderCode.ENABLE));
795 }
796 if( false ) {
797 const String rsFpDefPrecision = getFragmentShaderPrecision(gl);
798 if( null != rsFpDefPrecision ) {
799 posFp = rsFp.insertShaderSource(0, posFp, rsFpDefPrecision);
800 }
801 } else {
802 posFp = rsFp.addDefaultShaderPrecision(gl, posFp);
803 }
804
805 //
806 // GLSL append from here on
807 posFp = -1;
808
809 posVp = rsVp.insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_START);
810 posFp = rsFp.insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_START);
811
812 if( !gl.getContext().hasRendererQuirk(GLRendererQuirks.GLSLBuggyDiscard) ) {
813 posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_DISCARD);
814 }
815
816 if( hasFrustumClipping ) {
817 posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_FRUSTUM_CLIPPING);
818 posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_FRUSTUM_CLIPPING);
819 }
820
821 if( hasColorChannel ) {
822 posVp = rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_CHANNEL);
823 posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_CHANNEL);
824 }
825 if( hasColorTexture ) {
826 rsVp.insertShaderSource(0, posVp, GLSL_USE_COLOR_TEXTURE);
827 posFp = rsFp.insertShaderSource(0, posFp, GLSL_USE_COLOR_TEXTURE);
828 }
829 if( !pass1 ) {
830 posFp = rsFp.insertShaderSource(0, posFp, GLSL_DEF_SAMPLE_COUNT+sms.sampleCount+"\n");
831 posFp = rsFp.insertShaderSource(0, posFp, GLSL_CONST_SAMPLE_COUNT+sms.sampleCount+".0;\n");
832 }
833
834 posVp = rsVp.insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_END);
835 posFp = rsFp.insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_END);
836
837 try {
838 posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "uniforms.glsl");
839 posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "varyings.glsl");
840 if( hasColorTexture || hasFrustumClipping ) {
841 posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, "functions.glsl");
842 }
843 } catch (const IOException ioe) {
844 throw new RuntimeException("Failed to read: includes", ioe);
845 }
846 if( 0 > posFp ) {
847 throw new RuntimeException("Failed to read: includes");
848 }
849
850 if( hasColorTexture ) {
851 posFp = rsFp.insertShaderSource(0, posFp, "uniform "+colorTexSeq.getTextureSampler2DType()+" "+UniformNames.gcu_ColorTexUnit+";\n");
852 posFp = rsFp.insertShaderSource(0, posFp, colorTexSeq.getTextureLookupFragmentShaderImpl());
853 }
854
855 posFp = rsFp.insertShaderSource(0, posFp, GLSL_MAIN_BEGIN);
856
857 const String passS = pass1 ? "-pass1-" : "-pass2-";
858 const String shaderSegment = versionedBaseName+passS+sms.tech+sms.sub+".glsl";
859 if(DEBUG) {
860 System.err.printf("RegionRenderer.createShaderProgram.1: segment %s%n", shaderSegment);
861 }
862 try {
863 posFp = rsFp.insertShaderSource(0, posFp, AttributeNames.class, shaderSegment);
864 } catch (const IOException ioe) {
865 throw new RuntimeException("Failed to read: "+shaderSegment, ioe);
866 }
867 if( 0 > posFp ) {
868 throw new RuntimeException("Failed to read: "+shaderSegment);
869 }
870 posFp = rsFp.insertShaderSource(0, posFp, "}\n");
871
872 if( hasColorTexture ) {
873 rsFp.replaceInShaderSource(gcuTexture2D, colTexLookupFuncName);
874 }
875
876 const ShaderProgram sp = new ShaderProgram();
877 sp.add(rsVp);
878 sp.add(rsFp);
879
880 if( !sp.init(gl) ) {
881 throw new GLException("RegionRenderer: Couldn't init program: "+sp);
882 }
883
884 if( !sp.link(gl, System.err) ) {
885 throw new GLException("could not link program: "+sp);
886 }
887 return sp;
888 }
889 };
890
891
892 /**@}*/
893
894} // namespace gamp::graph::gl
895
896#endif /* JAU_GAMP_GRAPH_GL_GRAPHRENDERER_HPP_ */
897
898
const void destroy(const GL2ES2 gl)
Deletes all ShaderPrograms and nullifies its references including RenderState#destroy(GL2ES2).
const PMVMatrix4f getMatrix()
Borrow the current PMVMatrix4f.
const void setClipFrustum(const Frustum clipFrustum)
Set the optional clipping Frustum, which shall be pre-multiplied with the Mv-matrix or null to disabl...
static RegionRenderer create()
Create a hardware accelerated RegionRenderer including its RenderState composition.
const void setWeight(const float v)
const bool equals(const Object other)
const void reshapeOrtho(const int width, const int height, const float near, const float far)
Orthogonal projection, method also calls reshapeNotify(int, int, int, int).
const void enable(const GL2ES2 gl, const bool enable, const GLCallback enableCB, const GLCallback disableCB)
Same as enable(GL2ES2, bool) but allowing to force GLCallbacks off.
const Recti getViewport(const Recti target)
Copies the current Rect4i viewport in given target and returns it for chaining.
const bool hintBitsSet(const int mask)
RegionRenderer(const PMVMatrix4f sharedPMVMatrix, const GLCallback enableCallback, const GLCallback disableCallback)
const Vec4f getColorStatic(const Vec4f rgbaColor)
const void setColorStatic(const Vec4f rgbaColor)
const int setSampleCount(const int v)
Sets pass2 AA sample count clipped to the range [Region#MIN_AA_SAMPLE_COUNT..Region#MAX_AA_SAMPLE_COU...
const int getAAQuality()
Returns pass2 AA-quality rendering value for Graph Region AA render-modes: Region#VBAA_RENDERING_BIT.
const void reshapeNotify(const int x, const int y, const int width, const int height)
No PMVMatrix4f operation is performed here.
RegionRenderer(const GLCallback enableCallback, const GLCallback disableCallback)
const void init(const GL2ES2 gl)
Initialize shader and bindings for GPU based rendering bound to the given GL object's GLContext if no...
const int setAAQuality(const int v)
Sets pass2 AA-quality rendering value clipped to the range [Region#MIN_AA_QUALITY....
const Recti getViewport()
Borrows the current Rect4i viewport w/o copying.
const RenderState getRenderState()
Return the RenderState composition.
const void enable(const GL2ES2 gl, const bool enable)
Enabling or disabling the RenderState's current shader program.
const void setColorStatic(const float r, const float g, const float b, const float a)
const Frustum getClipFrustum()
Returns the optional Mv-premultiplied clipping Frustum or null if unused.
const int getHeight()
Return height of current viewport.
const bool useShaderProgram(const GL2ES2 gl, const int renderModes, const bool pass1, const TextureSequence colorTexSeq)
Generate, selects and caches the desired Curve-Graph ShaderProgram according to the given parameters.
const int getWidth()
Return width of current viewport.
const int getSampleCount()
Returns pass2 AA sample count for Graph Region AA render-modes: VBAA_RENDERING_BIT or Region#MSAA_REN...
static const GLCallback defaultBlendDisable
Default GL#GL_BLEND disable GLCallback, simply turning-off the GL#GL_BLEND state and turning-on depth...
static RegionRenderer create(const PMVMatrix4f sharedPMVMatrix, const GLCallback enableCallback, const GLCallback disableCallback)
Create a hardware accelerated RegionRenderer including its RenderState composition.
static const GLCallback defaultBlendEnable
Default GL#GL_BLEND enable GLCallback, turning-off depth writing via GL#glDepthMask(bool) if RenderSt...
const void reshapePerspective(const float angle_rad, const int width, const int height, const float near, const float far)
Perspective projection, method also calls reshapeNotify(int, int, int, int).
const void setHintBits(const int mask)
static RegionRenderer create(const GLCallback enableCallback, const GLCallback disableCallback)
Create a hardware accelerated RegionRenderer including its RenderState composition.
const void clearHintBits(const int mask)
constexpr RectI & set(const Vector2I< value_type > &pos, const Vector2I< value_type > &size) noexcept
TODO constexpr std::strong_ordering operator<=>(const Recti_t& rhs) const noexcept { return ....
Definition recti.hpp:95
Providing frustum planes derived by different inputs (P*MV, ..) used to classify objects.
Definition frustum.hpp:78
Vector4F< float > Vec4f
Definition vec4f.hpp:375
RectI< int > Recti
Definition recti.hpp:139