OpenGL ES SDK for Android ARM Developer Center
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Native.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2014-2017, ARM Limited and Contributors
2  *
3  * SPDX-License-Identifier: MIT
4  *
5  * Permission is hereby granted, free of charge,
6  * to any person obtaining a copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
16  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
17  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  */
20 
41 #include <jni.h>
42 #include <android/log.h>
43 
44 #include <cstdlib>
45 #include <cmath>
46 #include <iostream>
47 #include <sstream>
48 #include <string>
49 
50 #include "Common.h"
51 #include "Matrix.h"
52 #include "Native.h"
53 #include "Texture.h"
54 #include "Timer.h"
55 #include "Shader.h"
56 
57 using namespace std;
58 using namespace MaliSDK;
59 
60 /* Asset directories and filenames */
61 const string resourceDirectory = "/data/data/com.arm.malideveloper.openglessdk.minMaxBlending/files/";
62 const string imagesFilename = "MRbrain";
63 
64 /* Number of images in resourceDirectory. */
65 const int imagesCount = 109;
66 
67 /* Generic framework timer used to count the time interval for switch of blending equations. */
69 
70 /* Dimensions of window. */
71 int windowWidth = 0;
72 int windowHeight = 0;
73 
74 /* 3D texture dimensions. Although there are 109 images in resourceDirectory, texture depth is extended to 128 for 2 reasons:
75  * 1) We require some layers in the front and behind the original ones, to avoid errors while rotating texture coordinates.
76  * 2) Setting depth as a half of the other dimensions slightly improves the effect of blending. */
77 const GLint textureWidth = 256;
78 const GLint textureHeight = 256;
79 const GLint textureDepth = 128;
80 
81 /* Emprically determined value of threshold used for min blending. */
83 /* Color value of a 3D texture layer. */
84 const short fillerLuminance = 4;
85 
86 /* ID of a 3D texture rendered on the screen. Filled by OpenGL ES. */
88 
89 /* ID of a program assigned by OpenGL ES. */
91 
92 /* ID of a buffer object storing vertices of a square. */
94 /* ID of a buffer object storing U/V/W texture coordinates. */
96 
97 /* ID of a vertex array object. */
99 
100 /* Locations of changable uniforms. */
103 
104 /* Since there are additional layers in the front and in the back of original texture images, there
105  * are two different functions used to load them. That is why we need this variable to indicate which
106  * layer of 3D texture should be filled at the moment. */
107 GLint textureZOffset = 0;
108 
109 /* Flag passed to shaders indicating current blending equation. */
111 
112 /* Amount of time in seconds used by a timer to switch blending equations. */
113 const float resetTimeInterval = 5.0f;
114 
115 /* Array storing vertices of a square built from 2 triangles moved in the negative Z direction.
116  *
117  * 2-3----------------5
118  * | \\ |
119  * | \\ |
120  * | \\ |
121  * | \\ |
122  * | \\ |
123  * | \\ |
124  * | \\ |
125  * | \\ |
126  * 0----------------1-4 */
127 const float squareVertices[] =
128 {
129  -1.0f, 1.0f, -1.0f, 1.0f,
130  1.0f, 1.0f, -1.0f, 1.0f,
131  -1.0f, -1.0f, -1.0f, 1.0f,
132  -1.0f, -1.0f, -1.0f, 1.0f,
133  1.0f, 1.0f, -1.0f, 1.0f,
134  1.0f, -1.0f, -1.0f, 1.0f,
135 };
136 
137 /* Array storing 3D texture coordinates corresponding to vertices of a square. */
138 const float uvwCoordinates[] =
139 {
140  0.0f, 0.0f, 1.0f,
141  1.0f, 0.0f, 1.0f,
142  0.0f, 1.0f, 1.0f,
143  0.0f, 1.0f, 1.0f,
144  1.0f, 0.0f, 1.0f,
145  1.0f, 1.0f, 1.0f,
146 };
147 
148 /* Please look into header for the specification. */
150 {
151  /* Generate and bind 3D texture. */
152  /* [Generate texture ID] */
153  GL_CHECK(glGenTextures(1, &textureID));
154  /* [Generate texture ID] */
155  /* [Bind texture object] */
156  GL_CHECK(glBindTexture(GL_TEXTURE_3D, textureID));
157  /* [Bind texture object] */
158 
159  /* [Initialize texture storage] */
160  /* Initialize storage space for texture data. */
161  GL_CHECK(glTexStorage3D(GL_TEXTURE_3D,
162  1,
163  GL_R16I,
164  textureWidth,
166  textureDepth));
167  /* [Initialize texture storage] */
168 
169  /* [Set texture object parameters] */
170  /* Set texture parameters. */
171  GL_CHECK(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
172  GL_CHECK(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
173  GL_CHECK(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
174  GL_CHECK(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
175  GL_CHECK(glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
176  /* [Set texture object parameters] */
177 
178  /* Try loading image data. */
180 }
181 
182 /* Please look into header for the specification. */
184 {
185  /* Location of input variables in vertex shader. */
186  GLint positionLocation = GL_CHECK(glGetAttribLocation(programID, "inputPosition"));
187  GLint inputUVWCoordinatesLocation = GL_CHECK(glGetAttribLocation(programID, "inputUVWCoordinates"));
188 
189  ASSERT(positionLocation != -1, "Could not find attribute location for: inputPosition");
190  ASSERT(inputUVWCoordinatesLocation != -1, "Could not find attribute location for: inputUVWCoordinates");
191 
192  /* Generate and bind a vertex array object. */
193  GL_CHECK(glGenVertexArrays(1, &vaoID));
194  GL_CHECK(glBindVertexArray(vaoID));
195 
196  /* Generate and bind a buffer object storing vertices of a single quad. */
197  GL_CHECK(glGenBuffers(1, &verticesBufferID));
198  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, verticesBufferID));
199 
200  /* Put data into the buffer. */
201  GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertices), squareVertices, GL_STATIC_DRAW));
202 
203  /* Set a vertex attribute pointer at the beginnig of the buffer. */
204  GL_CHECK(glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, 0));
205  GL_CHECK(glEnableVertexAttribArray(positionLocation));
206 
207  /* Generate and bind a buffer object storing UV texture coordinates. */
208  GL_CHECK(glGenBuffers(1, &uvwBufferID));
209  GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, uvwBufferID));
210 
211  /* Put data into the buffer. */
212  GL_CHECK(glBufferData(GL_ARRAY_BUFFER, sizeof(uvwCoordinates), uvwCoordinates, GL_STATIC_DRAW));
213 
214  /* Set vertex attribute pointer at the beginning of the buffer. */
215  GL_CHECK(glVertexAttribPointer(inputUVWCoordinatesLocation, 3, GL_FLOAT, GL_FALSE, 0, 0));
216  GL_CHECK(glEnableVertexAttribArray(inputUVWCoordinatesLocation));
217 }
218 
219 /* Please look into header for the specification. */
221 {
222  /* Path to vertex shader source. */
223  const string vertexShaderPath = resourceDirectory + "Min_Max_Blending_shader.vert";
224  /* Path to fragment shader source. */
225  const string fragmentShaderPath = resourceDirectory + "Min_Max_Blending_shader.frag";
226 
227  /* IDs of shaders. */
230 
231  /* Compile shaders and handle possible compilation errors. */
232  Shader::processShader(&vertexShaderID, vertexShaderPath.c_str(), GL_VERTEX_SHADER);
233  Shader::processShader(&fragmentShaderID, fragmentShaderPath.c_str(), GL_FRAGMENT_SHADER);
234 
235  /* Generate ID for a program. */
236  programID = GL_CHECK(glCreateProgram());
237 
238  /* Attach shaders to the program. */
239  GL_CHECK(glAttachShader(programID, vertexShaderID));
240  GL_CHECK(glAttachShader(programID, fragmentShaderID));
241 
242  /* Link the program. */
243  GL_CHECK(glLinkProgram(programID));
244 
245  /* Since there is only one program, it is enough to make it current at this stage. */
246  GL_CHECK(glUseProgram(programID));
247 }
248 
249 /* Please look into header for the specification. */
251 {
252  /* Number of layers added at the front of a 3D texture. */
253  const int frontLayersCount = (textureDepth - imagesCount) / 2;
254  /* Number of layers added at the back of a 3D texture. */
255  const int backLayersCount = textureDepth - frontLayersCount - imagesCount;
256 
257  /* Check if both numbers of additional layers are not negative. */
258  ASSERT(frontLayersCount >= 0 && backLayersCount >= 0,
259  "Too low textureDepth value or too many images have been tried to be loaded.");
260 
261  /* Load front layers. */
262  loadUniformTextures(frontLayersCount);
263  /* Load imagesCount images. */
264  loadImages();
265  /* Load back layers. */
266  loadUniformTextures(backLayersCount);
267 
268  /* Make sure the 3D texture is fully loaded. */
270  "3D texture not completely loaded.");
271 }
272 
273 /* Please look into header for the specification. */
275 {
276  /* Locations in shaders of uniform variables whose values are set only once. */
277  GLint cameraMatrixLocation = GL_CHECK(glGetUniformLocation(programID, "cameraMatrix"));
278  GLint projectionMatrixLocation = GL_CHECK(glGetUniformLocation(programID, "projectionMatrix"));
279  /* [Get 3D sampler uniform location] */
280  GLint textureSamplerLocation = GL_CHECK(glGetUniformLocation(programID, "textureSampler"));
281  /* [Get 3D sampler uniform location] */
282  GLint instancesCountLocation = GL_CHECK(glGetUniformLocation(programID, "instancesCount"));
283  GLint minBlendingThresholdLocation = GL_CHECK(glGetUniformLocation(programID, "minBlendingThreshold"));
284 
285  /* Locations in shaders of uniform variables whose values are going to be modified. */
286  isMinBlendingLocation = GL_CHECK(glGetUniformLocation(programID, "isMinBlending"));
287  rotationVectorLocation = GL_CHECK(glGetUniformLocation(programID, "rotationVector"));
288 
289  ASSERT(cameraMatrixLocation != -1, "Could not find location for uniform: cameraMatrix");
290  ASSERT(projectionMatrixLocation != -1, "Could not find location for uniform: projectionMatrix");
291  /* [Verify 3D sampler uniform location value] */
292  ASSERT(textureSamplerLocation != -1, "Could not find location for uniform: textureSampler");
293  /* [Verify 3D sampler uniform location value] */
294  ASSERT(instancesCountLocation != -1, "Could not find location for uniform: instancesCount");
295  ASSERT(minBlendingThresholdLocation != -1, "Could not find location for uniform: minBlendingThreshold");
296  ASSERT(isMinBlendingLocation != -1, "Could not find location for uniform: isMinBlending");
297  ASSERT(rotationVectorLocation != -1, "Could not find location for uniform: rotationVector");
298 
299  /* Value of translation of camera in Z axis. */
300  const float cameraTranslation = -2.0f;
301  /* Matrix representing translation of camera. */
302  Matrix cameraMatrix = Matrix::createTranslation(0.0f,
303  0.0f,
304  cameraTranslation);
305  /* Perspective matrix used as projection matrix. */
307  (float) windowWidth / (float) windowHeight,
308  0.01f,
309  10.0f);
310 
311  /* Pass matrix to the program. */
312  GL_CHECK(glUniformMatrix4fv(cameraMatrixLocation,
313  1,
314  GL_FALSE,
315  cameraMatrix.getAsArray()));
316  /* Pass matrix to the program. */
317  GL_CHECK(glUniformMatrix4fv(projectionMatrixLocation,
318  1,
319  GL_FALSE,
320  projectionMatrix.getAsArray()));
321 
322  /* Pass default texture unit ID to the program. */
323  GL_CHECK(glUniform1i(textureSamplerLocation, 0));
324 
325  /* Pass the number of instances to be drawn, which is equal to the depth of texture. */
326  GL_CHECK(glUniform1i(instancesCountLocation, textureDepth));
327 
328  /* Pass the value of threshold used for min blending. */
329  GL_CHECK(glUniform1f(minBlendingThresholdLocation, minBlendingThreshold));
330 }
331 
332 /* Please look into header for the specification. */
334 {
335  /* Indices of images start with 1. */
336  for (int currentImageIndex = 1; currentImageIndex <= imagesCount; ++currentImageIndex)
337  {
338  GLvoid* textureData = 0;
339  /* Maximum number of digits representing extensions. */
340  const int digitsCount = 3;
341 
342  /* Convert index of the current image, to a string. */
343  std::stringstream stringStream;
344  stringStream << currentImageIndex;
345  string numericExtension = stringStream.str();
346 
347  /* Path to the image. */
348  const string filePath = resourceDirectory + imagesFilename + "." + numericExtension;
349 
350  /* Load data from a file. */
351  Texture::loadData(filePath.c_str(), (unsigned char**) &textureData);
352 
353  /* Push loaded data to the next layer of a 3D texture that has not been filled yet. */
354  setNextTextureImage(textureData);
355 
356  /* Free allocated memory space. */
357  free(textureData);
358  }
359 }
360 
361 /* Please look into header for the specification. */
363 {
364  GLvoid* textureData = 0;
365 
366  /* Create texture with short data type. */
370  (short**) &textureData);
371 
372  /* Load created texture count times. */
373  for (int i = 0; i < count; ++i)
374  {
375  setNextTextureImage(textureData);
376  }
377 
378  /* Free allocated memory space. */
379  delete [] (unsigned char *)textureData;
380 }
381 
386 {
387  /* Switch blending each resetTimeInterval seconds passed. */
389  {
391 
393 
394  timer.reset();
395  }
396 
397  /* Rotation angles. */
398  static float angleX = 0.0f;
399  static float angleY = 0.0f;
400  static float angleZ = 0.0f;
401 
402  /* Arbitrary angle incremental values. */
403  const float angleXIncrement = 0.75f;
404  const float angleYIncrement = 1.0f;
405  const float angleZIncrement = 0.5f;
406 
407  /* Vector storing rotation angles that is going to be passed to shader. */
408  float rotationVector[] = {angleX, angleY, angleZ};
409 
410  /* Clear the screen. */
411  GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
412 
413  /* Pass the rotation vector to shader. */
414  GL_CHECK(glUniform3fv(rotationVectorLocation, 1, rotationVector));
415 
416  /* [Draw 3D texture] */
417  /* Draw a single square layer consisting of 6 vertices for textureDepth times. */
418  GL_CHECK(glDrawArraysInstanced(GL_TRIANGLES, 0, 6, textureDepth));
419  /* [Draw 3D texture] */
420 
421  /* Increment rotation angles.*/
422  angleX += angleXIncrement;
423  angleY += angleYIncrement;
424  angleZ += angleZIncrement;
425 
426  /* Make sure rotation angles do not go over 360 degrees. */
427  if(angleX >= 360.0f) angleX = 0.0f;
428  if(angleY >= 360.0f) angleY = 0.0f;
429  if(angleZ >= 360.0f) angleZ = 0.0f;
430 }
431 
432 /* Please look into header for the specification. */
434 {
435  if (isMinBlending)
436  {
437  /* [Set new blend equation : GL_MIN] */
438  /* Set new blend equation. */
439  GL_CHECK(glBlendEquation(GL_MIN));
440  /* [Set new blend equation : GL_MIN] */
441  /* Set white color for min blending. */
442  GL_CHECK(glClearColor(1.0f, 1.0f, 1.0f, 1.0f));
443  }
444  else
445  {
446  /* [Set new blend equation : GL_MAX] */
447  /* Set new blend equation. */
448  GL_CHECK(glBlendEquation(GL_MAX));
449  /* [Set new blend equation : GL_MAX] */
450  /* Set black color for max blending. */
451  GL_CHECK(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
452  }
453 
454  /* Pass boolean value informing shader about current blending mode. */
455  GL_CHECK(glUniform1i(isMinBlendingLocation, isMinBlending));
456 }
457 
458 /* Please look into header for the specification. */
460 {
461  /* [Fill texture layer with data] */
462  /* Set 2D image at the current textureZOffset. */
463  GL_CHECK(glTexSubImage3D(GL_TEXTURE_3D,
464  0,
465  0,
466  0,
468  textureWidth,
470  1,
471  GL_RED_INTEGER,
472  GL_SHORT,
473  textureData));
474  /* [Fill texture layer with data] */
475 
476  /* Increment textureZOffset. */
477  textureZOffset++;
478 }
479 
486 void setupGraphics(int width, int height)
487 {
489  windowWidth = width;
490 
492 
493  /* Try initializing 3D texture. Log error if it fails. */
495 
496  /* Try initializing attribute arrays. Log error if it fails. */
498 
500 
501  /* [Enable blending] */
502  /* Enable blending. */
503  GL_CHECK(glEnable(GL_BLEND));
504  /* [Enable blending] */
505 
506  /* Set initial blending equation. */
508 
509  /* Start counting time. */
510  timer.reset();
511 }
512 
518 void uninit()
519 {
520  GL_CHECK(glDeleteTextures (1, &textureID ));
521  GL_CHECK(glDeleteBuffers (1, &verticesBufferID));
522  GL_CHECK(glDeleteBuffers (1, &uvwBufferID ));
523  GL_CHECK(glDeleteVertexArrays(1, &vaoID ));
524  GL_CHECK(glDeleteProgram (programID ));
525 }
526 
527 extern "C"
528 {
529  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_minMaxBlending_NativeLibrary_init(JNIEnv*, jobject, jint width, jint height);
530  JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_minMaxBlending_NativeLibrary_step(JNIEnv*, jobject);
532 };
533 
535 {
536  setupGraphics(width, height);
537 }
538 
540 {
541  renderFrame();
542 }
543 
545 {
546  uninit();
547 }
void setupGraphics(int width, int height)
Definition: Native.cpp:1256
void initializeTextureData()
Fills 3D texture with images.
Definition: Native.cpp:250
GLuint programID
Definition: Native.cpp:90
static float angleZ
Definition: Native.cpp:81
void loadData(const char *filename, unsigned char **textureData)
Load texture data from a file into memory.
Definition: Text.cpp:38
GLuint textureID
Definition: Native.cpp:87
#define GL_CHECK(x)
Definition: Native.cpp:64
float getTime()
Returns the time passed since object creation or since reset() was last called.
Definition: Timer.cpp:109
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_minMaxBlending_NativeLibrary_uninit(JNIEnv *, jobject)
Definition: Native.cpp:544
float projectionMatrix[16]
Definition: Native.cpp:156
void initializeAttribArrays()
Initializes input vertex data for shaders.
Definition: Native.cpp:183
int windowHeight
Definition: Native.cpp:574
const GLint textureDepth
Definition: Native.cpp:79
const string resourceDirectory
Definition: Native.cpp:67
GLint GLsizei GLsizei height
Definition: gl2ext.h:179
GLint positionLocation
Definition: Native.cpp:99
void setNextTextureImage(GLvoid *textureData)
Fills next empty 3D texture layer with textureData.
Definition: Native.cpp:459
#define GL_MAX
Definition: gl2ext.h:299
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_minMaxBlending_NativeLibrary_step(JNIEnv *, jobject)
Definition: Native.cpp:539
Functions for manipulating matrices.
Definition: Matrix.h:31
const float squareVertices[]
Definition: Native.cpp:127
GLuint fragmentShaderID
const GLfloat minBlendingThreshold
Definition: Native.cpp:82
Provides a platform independent high resolution timer.
Definition: Timer.h:37
GLenum GLenum GLsizei count
Definition: gl2ext.h:133
void matrixPerspective(float *matrix, float fieldOfView, float aspectRatio, float zNear, float zFar)
Create a perspective projection matrix and store the results in the first parameter.
Definition: Matrix.cpp:96
float * getAsArray(void)
Get the matrix elements as a column major order array.
Definition: Matrix.cpp:78
void loadImages()
Loads imagesCount images located in resourceDirectory.
Definition: Native.cpp:333
const string imagesFilename
Definition: Native.cpp:62
void initializeProgram()
Creates program and attaches shaders to it.
Definition: Native.cpp:220
void initializeUniformData()
Initializes uniform variables in program.
Definition: Native.cpp:274
GLuint uvwBufferID
Definition: Native.cpp:95
GLuint vaoID
Definition: Native.cpp:98
const GLint textureHeight
Definition: Native.cpp:78
void reset()
Resets the timer to 0.0f.
Definition: Timer.cpp:100
typedef GLboolean(GL_APIENTRYP PFNGLISENABLEDIOESPROC)(GLenum target
void uninit()
Delete created objects and free allocated memory.
Definition: Native.cpp:1706
const float resetTimeInterval
Definition: Native.cpp:113
const int imagesCount
Definition: Native.cpp:65
JNIEXPORT void JNICALL Java_com_arm_malideveloper_openglessdk_minMaxBlending_NativeLibrary_init(JNIEnv *, jobject, jint width, jint height)
Definition: Native.cpp:534
void loadUniformTextures(int count)
Creates and loads count unicolor layers to a 3D texture.
Definition: Native.cpp:362
GLfloat GLfloat f
Definition: gl2ext.h:2707
void renderFrame(void)
Definition: Native.cpp:1536
const GLint textureWidth
Definition: Native.cpp:77
GLuint verticesBufferID
Definition: Native.cpp:93
unsigned char * textureData
Definition: ThreadSync.cpp:109
GLint textureZOffset
Definition: Native.cpp:107
#define GL_TEXTURE_3D
Definition: gl2ext.h:1613
float angleY
Definition: Native.cpp:118
GLint isMinBlendingLocation
Definition: Native.cpp:101
Timer timer
Definition: Native.cpp:1059
int windowWidth
Definition: Native.cpp:575
void initialize3DTexture()
Initializes OpenGL ES texture components.
Definition: Native.cpp:149
bool createTexture(std::string filename, GLuint *textureLocation)
Definition: Native.cpp:445
static float angleX
Definition: Native.cpp:79
void setBlendEquation(GLboolean isMinBlending)
Sets current blending equation.
Definition: Native.cpp:433
GLint rotationVectorLocation
Definition: Native.cpp:102
GLboolean isMinBlending
Definition: Native.cpp:110
GLuint vertexShaderID
#define ASSERT(x, s)
Definition: common.h:45
const short fillerLuminance
Definition: Native.cpp:84
GLint GLsizei width
Definition: gl2ext.h:179
typedef GLfloat(GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC)(GLuint path
#define GL_MIN
Definition: gl2ext.h:298
typedef GLuint(GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC)(GLuint count
const float uvwCoordinates[]
Definition: Native.cpp:138