Revision 75f3272e
Added by Leszek Koltunski 6 months ago
| src/main/java/org/distorted/library/program/DistortedProgram.java | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
| 6 | // This library is free software; you can redistribute it and/or // | |
| 7 | // modify it under the terms of the GNU Lesser General Public // | |
| 8 | // License as published by the Free Software Foundation; either // | |
| 9 | // version 2.1 of the License, or (at your option) any later version. // | |
| 10 | // // | |
| 11 | // This library is distributed in the hope that it will be useful, // | |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // | |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // | |
| 14 | // Lesser General Public License for more details. // | |
| 15 | // // | |
| 16 | // You should have received a copy of the GNU Lesser General Public // | |
| 17 | // License along with this library; if not, write to the Free Software // | |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // | |
| 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 20 |  | |
| 21 | package org.distorted.library.program; | |
| 22 |  | |
| 23 | import android.opengl.GLES30; | |
| 24 |  | |
| 25 | import org.distorted.library.main.DistortedLibrary; | |
| 26 |  | |
| 27 | import java.io.BufferedReader; | |
| 28 | import java.io.IOException; | |
| 29 | import java.io.InputStream; | |
| 30 | import java.io.InputStreamReader; | |
| 31 |  | |
| 32 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 33 | /** | |
| 34 | * An object which encapsulates a vertex/fragment shader combo, aka Shader Program. | |
| 35 | */ | |
| 36 | public class DistortedProgram | |
| 37 |   {
 | |
| 38 | public static final int ATTR_LAYOUT_PNTC = 0; | |
| 39 | public static final int ATTR_LAYOUT_PTC = 1; | |
| 40 | public static final int ATTR_LAYOUT_PNT = 2; | |
| 41 | public static final int ATTR_LAYOUT_PNC = 3; | |
| 42 | public static final int ATTR_LAYOUT_PT = 4; | |
| 43 | public static final int ATTR_LAYOUT_P = 5; | |
| 44 | public static final int ATTR_LAYOUT_UNK = 6; | |
| 45 |  | |
| 46 | private String mAttributeStr, mUniformStr, mUniList; | |
| 47 | private int mAttributeLen, mUniformLen; | |
| 48 | private int mNumAttributes; | |
| 49 | private int mNumUniforms; | |
| 50 | private String[] mAttributeName; | |
| 51 | private final int mProgramHandle; | |
| 52 |  | |
| 53 | /** | |
| 54 | * Various programs have different attributes (because even if the source is the same, some of them might | |
| 55 | * be unused). | |
| 56 | * Main, Full have 4 attributes in the order (position,normal,texcoord, component) | |
| 57 | * Pre has 3 attributes (position,texcoord,component) | |
| 58 | * Maybe there are other possibilities (only position and normal? 3- position,normal,texcoord?) | |
| 59 | */ | |
| 60 | public int mAttributeLayout; | |
| 61 | /** | |
| 62 | * List of Attributes (OpenGL ES 3.0: 'in' variables), in the same order as declared in the shader source. | |
| 63 | */ | |
| 64 | public int[] mAttribute; | |
| 65 | /** | |
| 66 | * List of Uniforms, in the same order as declared in the shader source. | |
| 67 | */ | |
| 68 | public int[] mUniform; | |
| 69 |  | |
| 70 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 71 |  | |
| 72 | private int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes, final String[] feedbackVaryings) | |
| 73 | throws LinkingException | |
| 74 |     {
 | |
| 75 | int programHandle = GLES30.glCreateProgram(); | |
| 76 |  | |
| 77 | if (programHandle != 0) | |
| 78 |       {
 | |
| 79 | GLES30.glAttachShader(programHandle, vertexShaderHandle); | |
| 80 | GLES30.glAttachShader(programHandle, fragmentShaderHandle); | |
| 81 |  | |
| 82 | if( feedbackVaryings!=null ) | |
| 83 |         {
 | |
| 84 | GLES30.glTransformFeedbackVaryings(programHandle, feedbackVaryings, GLES30.GL_INTERLEAVED_ATTRIBS); | |
| 85 | } | |
| 86 |  | |
| 87 | if (attributes != null) | |
| 88 |         {
 | |
| 89 | final int size = attributes.length; | |
| 90 |  | |
| 91 | for(int i=0; i<size; i++) | |
| 92 |           {
 | |
| 93 | GLES30.glBindAttribLocation(programHandle, i, attributes[i]); | |
| 94 | } | |
| 95 | } | |
| 96 |  | |
| 97 | GLES30.glLinkProgram(programHandle); | |
| 98 |  | |
| 99 | final int[] linkStatus = new int[1]; | |
| 100 | GLES30.glGetProgramiv(programHandle, GLES30.GL_LINK_STATUS, linkStatus, 0); | |
| 101 |  | |
| 102 | if (linkStatus[0] != GLES30.GL_TRUE ) | |
| 103 |         {
 | |
| 104 | String error = GLES30.glGetProgramInfoLog(programHandle); | |
| 105 | GLES30.glDeleteProgram(programHandle); | |
| 106 | throw new LinkingException(error); | |
| 107 | } | |
| 108 |  | |
| 109 | //final int[] numberOfUniforms = new int[1]; | |
| 110 | //GLES30.glGetProgramiv(programHandle, GLES30.GL_ACTIVE_UNIFORMS, numberOfUniforms, 0); | |
| 111 |       //DistortedLibrary.logMessage("DistortedProgram: number of active uniforms="+numberOfUniforms[0]);
 | |
| 112 | } | |
| 113 |  | |
| 114 | return programHandle; | |
| 115 | } | |
| 116 |  | |
| 117 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 118 |  | |
| 119 | private void init(int glslVersion) | |
| 120 |     {
 | |
| 121 | mAttributeStr = (glslVersion == 100 ? "attribute " : "in "); | |
| 122 | mAttributeLen = mAttributeStr.length(); | |
| 123 | mNumAttributes = 0; | |
| 124 | mUniformStr = "uniform "; | |
| 125 | mUniformLen = mUniformStr.length(); | |
| 126 | mNumUniforms = 0; | |
| 127 | mUniList = ""; | |
| 128 | } | |
| 129 |  | |
| 130 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 131 |  | |
| 132 | private String parseOutUniform(final String line) | |
| 133 |     {
 | |
| 134 | int len = line.length(); | |
| 135 | int whiteSpace, semicolon, nameBegin; | |
| 136 | char currChar; | |
| 137 |  | |
| 138 | for(whiteSpace=0; whiteSpace<len; whiteSpace++) | |
| 139 |       {
 | |
| 140 | currChar = line.charAt(whiteSpace); | |
| 141 | if( currChar!=' ' && currChar!='\t') break; | |
| 142 | } | |
| 143 |  | |
| 144 | for(semicolon=whiteSpace; semicolon<len; semicolon++) | |
| 145 |       {
 | |
| 146 | currChar = line.charAt(semicolon); | |
| 147 | if( currChar==';') break; | |
| 148 | } | |
| 149 |  | |
| 150 | if( semicolon<len && semicolon-whiteSpace>=mUniformLen+1 ) | |
| 151 |       {
 | |
| 152 | String subline = line.substring(whiteSpace,semicolon); | |
| 153 | int subLen = semicolon-whiteSpace; | |
| 154 |  | |
| 155 | if( subline.startsWith(mUniformStr)) | |
| 156 |         {
 | |
| 157 |         //DistortedLibrary.logMessage("DistortedProgram: GOOD LINE: " +subline+" subLen="+subLen);
 | |
| 158 |  | |
| 159 | for(nameBegin=subLen-1; nameBegin>mUniformLen-2; nameBegin--) | |
| 160 |           {
 | |
| 161 | currChar=subline.charAt(nameBegin); | |
| 162 |  | |
| 163 | if( currChar==' ' || currChar=='\t' ) | |
| 164 |             {
 | |
| 165 | mNumUniforms++; | |
| 166 | String uniform = subline.substring(nameBegin+1,subLen); | |
| 167 |             int brace = uniform.indexOf("[");
 | |
| 168 |  | |
| 169 | return brace>=0 ? uniform.substring(0,brace) : uniform; | |
| 170 | } | |
| 171 | } | |
| 172 | } | |
| 173 | } | |
| 174 |  | |
| 175 | return null; | |
| 176 | } | |
| 177 |  | |
| 178 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 179 |  | |
| 180 | private String parseOutAttribute(final String line) | |
| 181 |     {
 | |
| 182 | int len = line.length(); | |
| 183 | int whiteSpace, semicolon, nameBegin; | |
| 184 | char currChar; | |
| 185 |  | |
| 186 | for(whiteSpace=0; whiteSpace<len; whiteSpace++) | |
| 187 |       {
 | |
| 188 | currChar = line.charAt(whiteSpace); | |
| 189 | if( currChar!=' ' && currChar!='\t') break; | |
| 190 | } | |
| 191 |  | |
| 192 | for(semicolon=whiteSpace; semicolon<len; semicolon++) | |
| 193 |       {
 | |
| 194 | currChar = line.charAt(semicolon); | |
| 195 | if( currChar==';') break; | |
| 196 | } | |
| 197 |  | |
| 198 | if( semicolon<len && semicolon-whiteSpace>=mAttributeLen+1 ) | |
| 199 |       {
 | |
| 200 | String subline = line.substring(whiteSpace,semicolon); | |
| 201 | int subLen = semicolon-whiteSpace; | |
| 202 |  | |
| 203 | if( subline.startsWith(mAttributeStr)) | |
| 204 |         {
 | |
| 205 | for(nameBegin=subLen-1; nameBegin>mAttributeLen-2; nameBegin--) | |
| 206 |           {
 | |
| 207 | currChar=subline.charAt(nameBegin); | |
| 208 |  | |
| 209 | if( currChar==' ' || currChar=='\t' ) | |
| 210 |             {
 | |
| 211 | return subline.substring(nameBegin+1,subLen); | |
| 212 | } | |
| 213 | } | |
| 214 | } | |
| 215 | } | |
| 216 |  | |
| 217 | return null; | |
| 218 | } | |
| 219 |  | |
| 220 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 221 |  | |
| 222 | private void doAttributes(final String shader, boolean doAttributes) | |
| 223 |     {
 | |
| 224 | String attribute, attrList="", uniform; | |
| 225 |     String[] lines = shader.split("\n");
 | |
| 226 |  | |
| 227 | for (String line : lines) | |
| 228 |       {
 | |
| 229 | if( doAttributes ) | |
| 230 |         {
 | |
| 231 | attribute = parseOutAttribute(line); | |
| 232 |  | |
| 233 | if (attribute != null) | |
| 234 |           {
 | |
| 235 | if( !attrList.isEmpty() ) attrList += " "; | |
| 236 | attrList += attribute; | |
| 237 | } | |
| 238 | } | |
| 239 |  | |
| 240 | uniform = parseOutUniform(line); | |
| 241 |  | |
| 242 | if (uniform != null) | |
| 243 |         {
 | |
| 244 | if( !mUniList.isEmpty() ) mUniList += " "; | |
| 245 | mUniList += uniform; | |
| 246 | } | |
| 247 | } | |
| 248 |  | |
| 249 | if( doAttributes ) | |
| 250 |       {
 | |
| 251 |       mAttributeName = attrList.split(" ");
 | |
| 252 | mNumAttributes = mAttributeName.length; | |
| 253 | } | |
| 254 | } | |
| 255 |  | |
| 256 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 257 |  | |
| 258 | private String readTextFileFromRawResource(final InputStream inputStream, boolean doAttributes) | |
| 259 |     {
 | |
| 260 | final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); | |
| 261 | final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); | |
| 262 |  | |
| 263 | String nextLine, attribute, attrList=""; | |
| 264 | final StringBuilder body = new StringBuilder(); | |
| 265 |  | |
| 266 | try | |
| 267 |       {
 | |
| 268 | while ((nextLine = bufferedReader.readLine()) != null) | |
| 269 |         {
 | |
| 270 | body.append(nextLine); | |
| 271 |         body.append('\n');
 | |
| 272 |  | |
| 273 | if( doAttributes ) | |
| 274 |           {
 | |
| 275 | attribute = parseOutAttribute(nextLine); | |
| 276 |  | |
| 277 | if( attribute!=null ) | |
| 278 |             {
 | |
| 279 |             //DistortedLibrary.logMessage("DistortedProgram: new attribute: "+attribute);
 | |
| 280 | if( !attrList.isEmpty() ) attrList += " "; | |
| 281 | attrList += attribute; | |
| 282 | } | |
| 283 | } | |
| 284 | } | |
| 285 | } | |
| 286 | catch (IOException e) | |
| 287 |       {
 | |
| 288 | return null; | |
| 289 | } | |
| 290 |  | |
| 291 | if( doAttributes ) | |
| 292 |       {
 | |
| 293 |       mAttributeName = attrList.split(" ");
 | |
| 294 | mNumAttributes = mAttributeName.length; | |
| 295 | } | |
| 296 |  | |
| 297 | return body.toString(); | |
| 298 | } | |
| 299 |  | |
| 300 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 301 |  | |
| 302 | private static int compileShader(final int shaderType, final String shaderSource) | |
| 303 | throws FragmentCompilationException,VertexCompilationException | |
| 304 |     {
 | |
| 305 | int shaderHandle = GLES30.glCreateShader(shaderType); | |
| 306 |  | |
| 307 | if (shaderHandle != 0) | |
| 308 |       {
 | |
| 309 | GLES30.glShaderSource(shaderHandle, shaderSource); | |
| 310 | GLES30.glCompileShader(shaderHandle); | |
| 311 | final int[] compileStatus = new int[1]; | |
| 312 | GLES30.glGetShaderiv(shaderHandle, GLES30.GL_COMPILE_STATUS, compileStatus, 0); | |
| 313 |  | |
| 314 | if (compileStatus[0] != GLES30.GL_TRUE) | |
| 315 |         {
 | |
| 316 | String error = GLES30.glGetShaderInfoLog(shaderHandle); | |
| 317 |  | |
| 318 | GLES30.glDeleteShader(shaderHandle); | |
| 319 |  | |
| 320 | switch (shaderType) | |
| 321 |           {
 | |
| 322 | case GLES30.GL_VERTEX_SHADER: throw new VertexCompilationException(error); | |
| 323 | case GLES30.GL_FRAGMENT_SHADER: throw new FragmentCompilationException(error); | |
| 324 | default: throw new RuntimeException(error); | |
| 325 | } | |
| 326 | } | |
| 327 | } | |
| 328 |  | |
| 329 | return shaderHandle; | |
| 330 | } | |
| 331 |  | |
| 332 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 333 |  | |
| 334 | private static String insertEnabledEffects(String code, final String effects) | |
| 335 |     {
 | |
| 336 | final String marker = "// ENABLED EFFECTS WILL BE INSERTED HERE"; | |
| 337 | int length = marker.length(); | |
| 338 |  | |
| 339 | int place = code.indexOf(marker); | |
| 340 |  | |
| 341 | if( place>=0 ) | |
| 342 |       {
 | |
| 343 | String begin = code.substring(0,place-1); | |
| 344 | String end = code.substring(place+length); | |
| 345 |  | |
| 346 | return begin + effects + end; | |
| 347 | } | |
| 348 | else | |
| 349 |       {
 | |
| 350 |       DistortedLibrary.logMessage("DistortedProgram: Error: marker string not found in SHADER!");
 | |
| 351 | } | |
| 352 |  | |
| 353 | return null; | |
| 354 | } | |
| 355 |  | |
| 356 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 357 |  | |
| 358 | private void setUpAttributes() | |
| 359 |     {
 | |
| 360 | int[] att = new int[mNumAttributes]; | |
| 361 |  | |
| 362 | for(int i=0; i<mNumAttributes; i++) | |
| 363 |       {
 | |
| 364 | att[i] = GLES30.glGetAttribLocation( mProgramHandle, mAttributeName[i]); | |
| 365 | } | |
| 366 |  | |
| 367 | int emptyAttrs = 0; | |
| 368 |  | |
| 369 | for(int i=0; i<mNumAttributes-emptyAttrs; i++) | |
| 370 |       {
 | |
| 371 | if( att[i] < 0 ) | |
| 372 |         {
 | |
| 373 | emptyAttrs++; | |
| 374 |  | |
| 375 | for(int j=i; j<mNumAttributes-emptyAttrs; j++) | |
| 376 |           {
 | |
| 377 | att[j] = att[j+1]; | |
| 378 | mAttributeName[j] = mAttributeName[j+1]; | |
| 379 | } | |
| 380 | } | |
| 381 | } | |
| 382 |  | |
| 383 | if( emptyAttrs>0 ) | |
| 384 |       {
 | |
| 385 | mNumAttributes -= emptyAttrs; | |
| 386 | mAttribute = new int[mNumAttributes]; | |
| 387 | System.arraycopy(att, 0, mAttribute, 0, mNumAttributes); | |
| 388 | } | |
| 389 | else | |
| 390 |       {
 | |
| 391 | mAttribute = att; | |
| 392 | } | |
| 393 |  | |
| 394 | setUpAttributeLayout(); | |
| 395 | } | |
| 396 |  | |
| 397 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 398 |  | |
| 399 | private void setUpAttributeLayout() | |
| 400 |     {
 | |
| 401 | switch(mNumAttributes) | |
| 402 |       {
 | |
| 403 | case 4: mAttributeLayout = ATTR_LAYOUT_PNTC; | |
| 404 | break; | |
| 405 |       case 3: if( mAttributeName[2].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PNT;
 | |
| 406 |               else if( mAttributeName[2].equals("a_Component") )
 | |
| 407 |                 {
 | |
| 408 |                 if( mAttributeName[1].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PTC;
 | |
| 409 |                 else if( mAttributeName[1].equals("a_Normal"  ) ) mAttributeLayout = ATTR_LAYOUT_PNC;
 | |
| 410 | else | |
| 411 |                   {
 | |
| 412 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 413 |                   DistortedLibrary.logMessage("DistortedProgram: 1 Error in attribute layout: "+mAttributeName[1]);
 | |
| 414 | } | |
| 415 | } | |
| 416 | else | |
| 417 |                 {
 | |
| 418 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 419 |                 DistortedLibrary.logMessage("DistortedProgram: 2 Error in attribute layout: "+mAttributeName[2]);
 | |
| 420 | } | |
| 421 | break; | |
| 422 |       case 2: if( mAttributeName[1].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PT;
 | |
| 423 | else | |
| 424 |                 {
 | |
| 425 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 426 |                 DistortedLibrary.logMessage("DistortedProgram: 3 Error in attribute layout: "+mAttributeName[1]);
 | |
| 427 | } | |
| 428 | break; | |
| 429 |       case 1: if( mAttributeName[0].equals("a_Position") ) mAttributeLayout = ATTR_LAYOUT_P;
 | |
| 430 | else | |
| 431 |                 {
 | |
| 432 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 433 |                 DistortedLibrary.logMessage("DistortedProgram: 4 Error in attribute layout: "+mAttributeName[0]);
 | |
| 434 | } | |
| 435 | break; | |
| 436 | default:mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 437 |               DistortedLibrary.logMessage("DistortedProgram: 5 Error in attribute layout: "+mNumAttributes);
 | |
| 438 | } | |
| 439 | } | |
| 440 |  | |
| 441 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 442 |  | |
| 443 | private void setUpUniforms() | |
| 444 |     {
 | |
| 445 | if( mNumUniforms>0 ) | |
| 446 |       {
 | |
| 447 | mUniform = new int[mNumUniforms]; | |
| 448 |       String[] uniformName = mUniList.split(" ");
 | |
| 449 |  | |
| 450 | for(int i=0; i<mNumUniforms; i++) | |
| 451 |         {
 | |
| 452 | mUniform[i] = GLES30.glGetUniformLocation( mProgramHandle, uniformName[i]); | |
| 453 | } | |
| 454 | } | |
| 455 | else mUniform = null; | |
| 456 | } | |
| 457 |  | |
| 458 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 459 | /** | |
| 460 | * Only for use by the library itself. | |
| 461 | * | |
| 462 | * @y.exclude | |
| 463 | */ | |
| 464 | public DistortedProgram(final InputStream vert, final InputStream frag, final String vertHeader, final String fragHeader, | |
| 465 | int glslVersion, final String[] feedback ) | |
| 466 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 467 |     {
 | |
| 468 | init(glslVersion); | |
| 469 |  | |
| 470 | final String vertShader = readTextFileFromRawResource(vert, true ); | |
| 471 | final String fragShader = readTextFileFromRawResource(frag, false); | |
| 472 |  | |
| 473 | final int vertShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertHeader + vertShader); | |
| 474 | final int fragShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragHeader + fragShader); | |
| 475 |  | |
| 476 | mProgramHandle = createAndLinkProgram(vertShaderHandle, fragShaderHandle, mAttributeName, glslVersion>= 300 ? feedback:null ); | |
| 477 |  | |
| 478 | setUpAttributes(); | |
| 479 | setUpUniforms(); | |
| 480 | } | |
| 481 |  | |
| 482 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 483 | /** | |
| 484 | * Only for use by the library itself. | |
| 485 | * | |
| 486 | * @y.exclude | |
| 487 | */ | |
| 488 | public DistortedProgram(final InputStream vert, final InputStream frag, final String vertHeader, final String fragHeader, | |
| 489 | final String enabledVert, final String enabledFrag, int glslVersion, final String[] feedback ) | |
| 490 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 491 |     {
 | |
| 492 | init(glslVersion); | |
| 493 |  | |
| 494 | String vertShader = readTextFileFromRawResource( vert, true ); | |
| 495 | String fragShader = readTextFileFromRawResource( frag, false); | |
| 496 |  | |
| 497 | if( enabledVert!=null ) vertShader = insertEnabledEffects(vertShader,enabledVert); | |
| 498 | if( enabledFrag!=null ) fragShader = insertEnabledEffects(fragShader,enabledFrag); | |
| 499 |  | |
| 500 | final int vertShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertHeader + vertShader); | |
| 501 | final int fragShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragHeader + fragShader); | |
| 502 |  | |
| 503 | mProgramHandle = createAndLinkProgram(vertShaderHandle, fragShaderHandle, mAttributeName, glslVersion>= 300 ? feedback:null ); | |
| 504 |  | |
| 505 | setUpAttributes(); | |
| 506 | setUpUniforms(); | |
| 507 | } | |
| 508 |  | |
| 509 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 510 | /** | |
| 511 | * Only for use by the library itself. | |
| 512 | * | |
| 513 | * @y.exclude | |
| 514 | */ | |
| 515 | public DistortedProgram(final InputStream vertex, final InputStream fragment, final String vertexHeader, final String fragmentHeader, int glslVersion ) | |
| 516 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 517 |     {
 | |
| 518 | this(vertex,fragment,vertexHeader,fragmentHeader,glslVersion,null); | |
| 519 | } | |
| 520 |  | |
| 521 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 522 | // PUBLIC API | |
| 523 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 524 | /** | |
| 525 | * Create a new Shader Program from two source strings. | |
| 526 | * <p> | |
| 527 | * Needs to be called from a thread holding the OpenGL context. | |
| 528 | * | |
| 529 | * @param vertex Vertex shader code. | |
| 530 | * @param fragment Fragment shader code. | |
| 531 | * @throws FragmentCompilationException fragment shader failed to compile | |
| 532 | * @throws VertexCompilationException vertex shader failed to compile | |
| 533 | * @throws LinkingException shaders failed to link | |
| 534 | */ | |
| 535 | public DistortedProgram(final String vertex, final String fragment) | |
| 536 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 537 |     {
 | |
| 538 | init(300); | |
| 539 |  | |
| 540 | doAttributes(vertex , true ); | |
| 541 | doAttributes(fragment, false); | |
| 542 |  | |
| 543 | final int vertexShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertex ); | |
| 544 | final int fragmentShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragment); | |
| 545 |  | |
| 546 | mProgramHandle = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, mAttributeName, null ); | |
| 547 |  | |
| 548 | setUpAttributes(); | |
| 549 | setUpUniforms(); | |
| 550 | } | |
| 551 |  | |
| 552 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 553 | /** | |
| 554 | * Return the handle of the created program so that we can later, say, call glUseProgram. | |
| 555 | */ | |
| 556 | public int getProgramHandle() | |
| 557 |     {
 | |
| 558 | return mProgramHandle; | |
| 559 | } | |
| 560 |  | |
| 561 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 562 | /** | |
| 563 | * Use the program and enable all vertex attribute arrays. | |
| 564 | * Needs to be called from a thread holding the OpenGL context. | |
| 565 | */ | |
| 566 | public void useProgram() | |
| 567 |     {
 | |
| 568 | GLES30.glUseProgram(mProgramHandle); | |
| 569 |  | |
| 570 | for(int i=0; i<mNumAttributes; i++) | |
| 571 |       {
 | |
| 572 | GLES30.glEnableVertexAttribArray(mAttribute[i]); | |
| 573 | } | |
| 574 | } | |
| 575 |  | |
| 576 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 577 | /** | |
| 578 | * Disable all vertex attribute arrays. | |
| 579 | * Needs to be called from a thread holding the OpenGL context. | |
| 580 | */ | |
| 581 | public void stopUsingProgram() | |
| 582 |     {
 | |
| 583 | GLES30.glUseProgram(0); | |
| 584 |  | |
| 585 | for(int i=0; i<mNumAttributes; i++) | |
| 586 |       {
 | |
| 587 | GLES30.glDisableVertexAttribArray(mAttribute[i]); | |
| 588 | } | |
| 589 | } | |
| 590 | } | |
| 591 |  | |
| 592 |  | |
| src/main/java/org/distorted/library/program/DistortedProgram.kt | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
| 6 | // This library is free software; you can redistribute it and/or // | |
| 7 | // modify it under the terms of the GNU Lesser General Public // | |
| 8 | // License as published by the Free Software Foundation; either // | |
| 9 | // version 2.1 of the License, or (at your option) any later version. // | |
| 10 | // // | |
| 11 | // This library is distributed in the hope that it will be useful, // | |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // | |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // | |
| 14 | // Lesser General Public License for more details. // | |
| 15 | // // | |
| 16 | // You should have received a copy of the GNU Lesser General Public // | |
| 17 | // License along with this library; if not, write to the Free Software // | |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // | |
| 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 20 |  | |
| 21 | package org.distorted.library.program; | |
| 22 |  | |
| 23 | import android.opengl.GLES30; | |
| 24 |  | |
| 25 | import org.distorted.library.main.DistortedLibrary; | |
| 26 |  | |
| 27 | import java.io.BufferedReader; | |
| 28 | import java.io.IOException; | |
| 29 | import java.io.InputStream; | |
| 30 | import java.io.InputStreamReader; | |
| 31 |  | |
| 32 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 33 | /** | |
| 34 | * An object which encapsulates a vertex/fragment shader combo, aka Shader Program. | |
| 35 | */ | |
| 36 | public class DistortedProgram | |
| 37 |   {
 | |
| 38 | public static final int ATTR_LAYOUT_PNTC = 0; | |
| 39 | public static final int ATTR_LAYOUT_PTC = 1; | |
| 40 | public static final int ATTR_LAYOUT_PNT = 2; | |
| 41 | public static final int ATTR_LAYOUT_PNC = 3; | |
| 42 | public static final int ATTR_LAYOUT_PT = 4; | |
| 43 | public static final int ATTR_LAYOUT_P = 5; | |
| 44 | public static final int ATTR_LAYOUT_UNK = 6; | |
| 45 |  | |
| 46 | private String mAttributeStr, mUniformStr, mUniList; | |
| 47 | private int mAttributeLen, mUniformLen; | |
| 48 | private int mNumAttributes; | |
| 49 | private int mNumUniforms; | |
| 50 | private String[] mAttributeName; | |
| 51 | private final int mProgramHandle; | |
| 52 |  | |
| 53 | /** | |
| 54 | * Various programs have different attributes (because even if the source is the same, some of them might | |
| 55 | * be unused). | |
| 56 | * Main, Full have 4 attributes in the order (position,normal,texcoord, component) | |
| 57 | * Pre has 3 attributes (position,texcoord,component) | |
| 58 | * Maybe there are other possibilities (only position and normal? 3- position,normal,texcoord?) | |
| 59 | */ | |
| 60 | public int mAttributeLayout; | |
| 61 | /** | |
| 62 | * List of Attributes (OpenGL ES 3.0: 'in' variables), in the same order as declared in the shader source. | |
| 63 | */ | |
| 64 | public int[] mAttribute; | |
| 65 | /** | |
| 66 | * List of Uniforms, in the same order as declared in the shader source. | |
| 67 | */ | |
| 68 | public int[] mUniform; | |
| 69 |  | |
| 70 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 71 |  | |
| 72 | private int createAndLinkProgram(final int vertexShaderHandle, final int fragmentShaderHandle, final String[] attributes, final String[] feedbackVaryings) | |
| 73 | throws LinkingException | |
| 74 |     {
 | |
| 75 | int programHandle = GLES30.glCreateProgram(); | |
| 76 |  | |
| 77 | if (programHandle != 0) | |
| 78 |       {
 | |
| 79 | GLES30.glAttachShader(programHandle, vertexShaderHandle); | |
| 80 | GLES30.glAttachShader(programHandle, fragmentShaderHandle); | |
| 81 |  | |
| 82 | if( feedbackVaryings!=null ) | |
| 83 |         {
 | |
| 84 | GLES30.glTransformFeedbackVaryings(programHandle, feedbackVaryings, GLES30.GL_INTERLEAVED_ATTRIBS); | |
| 85 | } | |
| 86 |  | |
| 87 | if (attributes != null) | |
| 88 |         {
 | |
| 89 | final int size = attributes.length; | |
| 90 |  | |
| 91 | for(int i=0; i<size; i++) | |
| 92 |           {
 | |
| 93 | GLES30.glBindAttribLocation(programHandle, i, attributes[i]); | |
| 94 | } | |
| 95 | } | |
| 96 |  | |
| 97 | GLES30.glLinkProgram(programHandle); | |
| 98 |  | |
| 99 | final int[] linkStatus = new int[1]; | |
| 100 | GLES30.glGetProgramiv(programHandle, GLES30.GL_LINK_STATUS, linkStatus, 0); | |
| 101 |  | |
| 102 | if (linkStatus[0] != GLES30.GL_TRUE ) | |
| 103 |         {
 | |
| 104 | String error = GLES30.glGetProgramInfoLog(programHandle); | |
| 105 | GLES30.glDeleteProgram(programHandle); | |
| 106 | throw new LinkingException(error); | |
| 107 | } | |
| 108 |  | |
| 109 | //final int[] numberOfUniforms = new int[1]; | |
| 110 | //GLES30.glGetProgramiv(programHandle, GLES30.GL_ACTIVE_UNIFORMS, numberOfUniforms, 0); | |
| 111 |       //DistortedLibrary.logMessage("DistortedProgram: number of active uniforms="+numberOfUniforms[0]);
 | |
| 112 | } | |
| 113 |  | |
| 114 | return programHandle; | |
| 115 | } | |
| 116 |  | |
| 117 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 118 |  | |
| 119 | private void init(int glslVersion) | |
| 120 |     {
 | |
| 121 | mAttributeStr = (glslVersion == 100 ? "attribute " : "in "); | |
| 122 | mAttributeLen = mAttributeStr.length(); | |
| 123 | mNumAttributes = 0; | |
| 124 | mUniformStr = "uniform "; | |
| 125 | mUniformLen = mUniformStr.length(); | |
| 126 | mNumUniforms = 0; | |
| 127 | mUniList = ""; | |
| 128 | } | |
| 129 |  | |
| 130 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 131 |  | |
| 132 | private String parseOutUniform(final String line) | |
| 133 |     {
 | |
| 134 | int len = line.length(); | |
| 135 | int whiteSpace, semicolon, nameBegin; | |
| 136 | char currChar; | |
| 137 |  | |
| 138 | for(whiteSpace=0; whiteSpace<len; whiteSpace++) | |
| 139 |       {
 | |
| 140 | currChar = line.charAt(whiteSpace); | |
| 141 | if( currChar!=' ' && currChar!='\t') break; | |
| 142 | } | |
| 143 |  | |
| 144 | for(semicolon=whiteSpace; semicolon<len; semicolon++) | |
| 145 |       {
 | |
| 146 | currChar = line.charAt(semicolon); | |
| 147 | if( currChar==';') break; | |
| 148 | } | |
| 149 |  | |
| 150 | if( semicolon<len && semicolon-whiteSpace>=mUniformLen+1 ) | |
| 151 |       {
 | |
| 152 | String subline = line.substring(whiteSpace,semicolon); | |
| 153 | int subLen = semicolon-whiteSpace; | |
| 154 |  | |
| 155 | if( subline.startsWith(mUniformStr)) | |
| 156 |         {
 | |
| 157 |         //DistortedLibrary.logMessage("DistortedProgram: GOOD LINE: " +subline+" subLen="+subLen);
 | |
| 158 |  | |
| 159 | for(nameBegin=subLen-1; nameBegin>mUniformLen-2; nameBegin--) | |
| 160 |           {
 | |
| 161 | currChar=subline.charAt(nameBegin); | |
| 162 |  | |
| 163 | if( currChar==' ' || currChar=='\t' ) | |
| 164 |             {
 | |
| 165 | mNumUniforms++; | |
| 166 | String uniform = subline.substring(nameBegin+1,subLen); | |
| 167 |             int brace = uniform.indexOf("[");
 | |
| 168 |  | |
| 169 | return brace>=0 ? uniform.substring(0,brace) : uniform; | |
| 170 | } | |
| 171 | } | |
| 172 | } | |
| 173 | } | |
| 174 |  | |
| 175 | return null; | |
| 176 | } | |
| 177 |  | |
| 178 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 179 |  | |
| 180 | private String parseOutAttribute(final String line) | |
| 181 |     {
 | |
| 182 | int len = line.length(); | |
| 183 | int whiteSpace, semicolon, nameBegin; | |
| 184 | char currChar; | |
| 185 |  | |
| 186 | for(whiteSpace=0; whiteSpace<len; whiteSpace++) | |
| 187 |       {
 | |
| 188 | currChar = line.charAt(whiteSpace); | |
| 189 | if( currChar!=' ' && currChar!='\t') break; | |
| 190 | } | |
| 191 |  | |
| 192 | for(semicolon=whiteSpace; semicolon<len; semicolon++) | |
| 193 |       {
 | |
| 194 | currChar = line.charAt(semicolon); | |
| 195 | if( currChar==';') break; | |
| 196 | } | |
| 197 |  | |
| 198 | if( semicolon<len && semicolon-whiteSpace>=mAttributeLen+1 ) | |
| 199 |       {
 | |
| 200 | String subline = line.substring(whiteSpace,semicolon); | |
| 201 | int subLen = semicolon-whiteSpace; | |
| 202 |  | |
| 203 | if( subline.startsWith(mAttributeStr)) | |
| 204 |         {
 | |
| 205 | for(nameBegin=subLen-1; nameBegin>mAttributeLen-2; nameBegin--) | |
| 206 |           {
 | |
| 207 | currChar=subline.charAt(nameBegin); | |
| 208 |  | |
| 209 | if( currChar==' ' || currChar=='\t' ) | |
| 210 |             {
 | |
| 211 | return subline.substring(nameBegin+1,subLen); | |
| 212 | } | |
| 213 | } | |
| 214 | } | |
| 215 | } | |
| 216 |  | |
| 217 | return null; | |
| 218 | } | |
| 219 |  | |
| 220 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 221 |  | |
| 222 | private void doAttributes(final String shader, boolean doAttributes) | |
| 223 |     {
 | |
| 224 | String attribute, attrList="", uniform; | |
| 225 |     String[] lines = shader.split("\n");
 | |
| 226 |  | |
| 227 | for (String line : lines) | |
| 228 |       {
 | |
| 229 | if( doAttributes ) | |
| 230 |         {
 | |
| 231 | attribute = parseOutAttribute(line); | |
| 232 |  | |
| 233 | if (attribute != null) | |
| 234 |           {
 | |
| 235 | if( !attrList.isEmpty() ) attrList += " "; | |
| 236 | attrList += attribute; | |
| 237 | } | |
| 238 | } | |
| 239 |  | |
| 240 | uniform = parseOutUniform(line); | |
| 241 |  | |
| 242 | if (uniform != null) | |
| 243 |         {
 | |
| 244 | if( !mUniList.isEmpty() ) mUniList += " "; | |
| 245 | mUniList += uniform; | |
| 246 | } | |
| 247 | } | |
| 248 |  | |
| 249 | if( doAttributes ) | |
| 250 |       {
 | |
| 251 |       mAttributeName = attrList.split(" ");
 | |
| 252 | mNumAttributes = mAttributeName.length; | |
| 253 | } | |
| 254 | } | |
| 255 |  | |
| 256 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 257 |  | |
| 258 | private String readTextFileFromRawResource(final InputStream inputStream, boolean doAttributes) | |
| 259 |     {
 | |
| 260 | final InputStreamReader inputStreamReader = new InputStreamReader(inputStream); | |
| 261 | final BufferedReader bufferedReader = new BufferedReader(inputStreamReader); | |
| 262 |  | |
| 263 | String nextLine, attribute, attrList=""; | |
| 264 | final StringBuilder body = new StringBuilder(); | |
| 265 |  | |
| 266 | try | |
| 267 |       {
 | |
| 268 | while ((nextLine = bufferedReader.readLine()) != null) | |
| 269 |         {
 | |
| 270 | body.append(nextLine); | |
| 271 |         body.append('\n');
 | |
| 272 |  | |
| 273 | if( doAttributes ) | |
| 274 |           {
 | |
| 275 | attribute = parseOutAttribute(nextLine); | |
| 276 |  | |
| 277 | if( attribute!=null ) | |
| 278 |             {
 | |
| 279 |             //DistortedLibrary.logMessage("DistortedProgram: new attribute: "+attribute);
 | |
| 280 | if( !attrList.isEmpty() ) attrList += " "; | |
| 281 | attrList += attribute; | |
| 282 | } | |
| 283 | } | |
| 284 | } | |
| 285 | } | |
| 286 | catch (IOException e) | |
| 287 |       {
 | |
| 288 | return null; | |
| 289 | } | |
| 290 |  | |
| 291 | if( doAttributes ) | |
| 292 |       {
 | |
| 293 |       mAttributeName = attrList.split(" ");
 | |
| 294 | mNumAttributes = mAttributeName.length; | |
| 295 | } | |
| 296 |  | |
| 297 | return body.toString(); | |
| 298 | } | |
| 299 |  | |
| 300 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 301 |  | |
| 302 | private static int compileShader(final int shaderType, final String shaderSource) | |
| 303 | throws FragmentCompilationException,VertexCompilationException | |
| 304 |     {
 | |
| 305 | int shaderHandle = GLES30.glCreateShader(shaderType); | |
| 306 |  | |
| 307 | if (shaderHandle != 0) | |
| 308 |       {
 | |
| 309 | GLES30.glShaderSource(shaderHandle, shaderSource); | |
| 310 | GLES30.glCompileShader(shaderHandle); | |
| 311 | final int[] compileStatus = new int[1]; | |
| 312 | GLES30.glGetShaderiv(shaderHandle, GLES30.GL_COMPILE_STATUS, compileStatus, 0); | |
| 313 |  | |
| 314 | if (compileStatus[0] != GLES30.GL_TRUE) | |
| 315 |         {
 | |
| 316 | String error = GLES30.glGetShaderInfoLog(shaderHandle); | |
| 317 |  | |
| 318 | GLES30.glDeleteShader(shaderHandle); | |
| 319 |  | |
| 320 | switch (shaderType) | |
| 321 |           {
 | |
| 322 | case GLES30.GL_VERTEX_SHADER: throw new VertexCompilationException(error); | |
| 323 | case GLES30.GL_FRAGMENT_SHADER: throw new FragmentCompilationException(error); | |
| 324 | default: throw new RuntimeException(error); | |
| 325 | } | |
| 326 | } | |
| 327 | } | |
| 328 |  | |
| 329 | return shaderHandle; | |
| 330 | } | |
| 331 |  | |
| 332 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 333 |  | |
| 334 | private static String insertEnabledEffects(String code, final String effects) | |
| 335 |     {
 | |
| 336 | final String marker = "// ENABLED EFFECTS WILL BE INSERTED HERE"; | |
| 337 | int length = marker.length(); | |
| 338 |  | |
| 339 | int place = code.indexOf(marker); | |
| 340 |  | |
| 341 | if( place>=0 ) | |
| 342 |       {
 | |
| 343 | String begin = code.substring(0,place-1); | |
| 344 | String end = code.substring(place+length); | |
| 345 |  | |
| 346 | return begin + effects + end; | |
| 347 | } | |
| 348 | else | |
| 349 |       {
 | |
| 350 |       DistortedLibrary.logMessage("DistortedProgram: Error: marker string not found in SHADER!");
 | |
| 351 | } | |
| 352 |  | |
| 353 | return null; | |
| 354 | } | |
| 355 |  | |
| 356 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 357 |  | |
| 358 | private void setUpAttributes() | |
| 359 |     {
 | |
| 360 | int[] att = new int[mNumAttributes]; | |
| 361 |  | |
| 362 | for(int i=0; i<mNumAttributes; i++) | |
| 363 |       {
 | |
| 364 | att[i] = GLES30.glGetAttribLocation( mProgramHandle, mAttributeName[i]); | |
| 365 | } | |
| 366 |  | |
| 367 | int emptyAttrs = 0; | |
| 368 |  | |
| 369 | for(int i=0; i<mNumAttributes-emptyAttrs; i++) | |
| 370 |       {
 | |
| 371 | if( att[i] < 0 ) | |
| 372 |         {
 | |
| 373 | emptyAttrs++; | |
| 374 |  | |
| 375 | for(int j=i; j<mNumAttributes-emptyAttrs; j++) | |
| 376 |           {
 | |
| 377 | att[j] = att[j+1]; | |
| 378 | mAttributeName[j] = mAttributeName[j+1]; | |
| 379 | } | |
| 380 | } | |
| 381 | } | |
| 382 |  | |
| 383 | if( emptyAttrs>0 ) | |
| 384 |       {
 | |
| 385 | mNumAttributes -= emptyAttrs; | |
| 386 | mAttribute = new int[mNumAttributes]; | |
| 387 | System.arraycopy(att, 0, mAttribute, 0, mNumAttributes); | |
| 388 | } | |
| 389 | else | |
| 390 |       {
 | |
| 391 | mAttribute = att; | |
| 392 | } | |
| 393 |  | |
| 394 | setUpAttributeLayout(); | |
| 395 | } | |
| 396 |  | |
| 397 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 398 |  | |
| 399 | private void setUpAttributeLayout() | |
| 400 |     {
 | |
| 401 | switch(mNumAttributes) | |
| 402 |       {
 | |
| 403 | case 4: mAttributeLayout = ATTR_LAYOUT_PNTC; | |
| 404 | break; | |
| 405 |       case 3: if( mAttributeName[2].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PNT;
 | |
| 406 |               else if( mAttributeName[2].equals("a_Component") )
 | |
| 407 |                 {
 | |
| 408 |                 if( mAttributeName[1].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PTC;
 | |
| 409 |                 else if( mAttributeName[1].equals("a_Normal"  ) ) mAttributeLayout = ATTR_LAYOUT_PNC;
 | |
| 410 | else | |
| 411 |                   {
 | |
| 412 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 413 |                   DistortedLibrary.logMessage("DistortedProgram: 1 Error in attribute layout: "+mAttributeName[1]);
 | |
| 414 | } | |
| 415 | } | |
| 416 | else | |
| 417 |                 {
 | |
| 418 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 419 |                 DistortedLibrary.logMessage("DistortedProgram: 2 Error in attribute layout: "+mAttributeName[2]);
 | |
| 420 | } | |
| 421 | break; | |
| 422 |       case 2: if( mAttributeName[1].equals("a_TexCoordinate") ) mAttributeLayout = ATTR_LAYOUT_PT;
 | |
| 423 | else | |
| 424 |                 {
 | |
| 425 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 426 |                 DistortedLibrary.logMessage("DistortedProgram: 3 Error in attribute layout: "+mAttributeName[1]);
 | |
| 427 | } | |
| 428 | break; | |
| 429 |       case 1: if( mAttributeName[0].equals("a_Position") ) mAttributeLayout = ATTR_LAYOUT_P;
 | |
| 430 | else | |
| 431 |                 {
 | |
| 432 | mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 433 |                 DistortedLibrary.logMessage("DistortedProgram: 4 Error in attribute layout: "+mAttributeName[0]);
 | |
| 434 | } | |
| 435 | break; | |
| 436 | default:mAttributeLayout = ATTR_LAYOUT_UNK; | |
| 437 |               DistortedLibrary.logMessage("DistortedProgram: 5 Error in attribute layout: "+mNumAttributes);
 | |
| 438 | } | |
| 439 | } | |
| 440 |  | |
| 441 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 442 |  | |
| 443 | private void setUpUniforms() | |
| 444 |     {
 | |
| 445 | if( mNumUniforms>0 ) | |
| 446 |       {
 | |
| 447 | mUniform = new int[mNumUniforms]; | |
| 448 |       String[] uniformName = mUniList.split(" ");
 | |
| 449 |  | |
| 450 | for(int i=0; i<mNumUniforms; i++) | |
| 451 |         {
 | |
| 452 | mUniform[i] = GLES30.glGetUniformLocation( mProgramHandle, uniformName[i]); | |
| 453 | } | |
| 454 | } | |
| 455 | else mUniform = null; | |
| 456 | } | |
| 457 |  | |
| 458 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 459 | /** | |
| 460 | * Only for use by the library itself. | |
| 461 | * | |
| 462 | * @y.exclude | |
| 463 | */ | |
| 464 | public DistortedProgram(final InputStream vert, final InputStream frag, final String vertHeader, final String fragHeader, | |
| 465 | int glslVersion, final String[] feedback ) | |
| 466 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 467 |     {
 | |
| 468 | init(glslVersion); | |
| 469 |  | |
| 470 | final String vertShader = readTextFileFromRawResource(vert, true ); | |
| 471 | final String fragShader = readTextFileFromRawResource(frag, false); | |
| 472 |  | |
| 473 | final int vertShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertHeader + vertShader); | |
| 474 | final int fragShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragHeader + fragShader); | |
| 475 |  | |
| 476 | mProgramHandle = createAndLinkProgram(vertShaderHandle, fragShaderHandle, mAttributeName, glslVersion>= 300 ? feedback:null ); | |
| 477 |  | |
| 478 | setUpAttributes(); | |
| 479 | setUpUniforms(); | |
| 480 | } | |
| 481 |  | |
| 482 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 483 | /** | |
| 484 | * Only for use by the library itself. | |
| 485 | * | |
| 486 | * @y.exclude | |
| 487 | */ | |
| 488 | public DistortedProgram(final InputStream vert, final InputStream frag, final String vertHeader, final String fragHeader, | |
| 489 | final String enabledVert, final String enabledFrag, int glslVersion, final String[] feedback ) | |
| 490 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 491 |     {
 | |
| 492 | init(glslVersion); | |
| 493 |  | |
| 494 | String vertShader = readTextFileFromRawResource( vert, true ); | |
| 495 | String fragShader = readTextFileFromRawResource( frag, false); | |
| 496 |  | |
| 497 | if( enabledVert!=null ) vertShader = insertEnabledEffects(vertShader,enabledVert); | |
| 498 | if( enabledFrag!=null ) fragShader = insertEnabledEffects(fragShader,enabledFrag); | |
| 499 |  | |
| 500 | final int vertShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertHeader + vertShader); | |
| 501 | final int fragShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragHeader + fragShader); | |
| 502 |  | |
| 503 | mProgramHandle = createAndLinkProgram(vertShaderHandle, fragShaderHandle, mAttributeName, glslVersion>= 300 ? feedback:null ); | |
| 504 |  | |
| 505 | setUpAttributes(); | |
| 506 | setUpUniforms(); | |
| 507 | } | |
| 508 |  | |
| 509 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 510 | /** | |
| 511 | * Only for use by the library itself. | |
| 512 | * | |
| 513 | * @y.exclude | |
| 514 | */ | |
| 515 | public DistortedProgram(final InputStream vertex, final InputStream fragment, final String vertexHeader, final String fragmentHeader, int glslVersion ) | |
| 516 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 517 |     {
 | |
| 518 | this(vertex,fragment,vertexHeader,fragmentHeader,glslVersion,null); | |
| 519 | } | |
| 520 |  | |
| 521 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 522 | // PUBLIC API | |
| 523 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 524 | /** | |
| 525 | * Create a new Shader Program from two source strings. | |
| 526 | * <p> | |
| 527 | * Needs to be called from a thread holding the OpenGL context. | |
| 528 | * | |
| 529 | * @param vertex Vertex shader code. | |
| 530 | * @param fragment Fragment shader code. | |
| 531 | * @throws FragmentCompilationException fragment shader failed to compile | |
| 532 | * @throws VertexCompilationException vertex shader failed to compile | |
| 533 | * @throws LinkingException shaders failed to link | |
| 534 | */ | |
| 535 | public DistortedProgram(final String vertex, final String fragment) | |
| 536 | throws FragmentCompilationException,VertexCompilationException,LinkingException | |
| 537 |     {
 | |
| 538 | init(300); | |
| 539 |  | |
| 540 | doAttributes(vertex , true ); | |
| 541 | doAttributes(fragment, false); | |
| 542 |  | |
| 543 | final int vertexShaderHandle = compileShader(GLES30.GL_VERTEX_SHADER , vertex ); | |
| 544 | final int fragmentShaderHandle = compileShader(GLES30.GL_FRAGMENT_SHADER, fragment); | |
| 545 |  | |
| 546 | mProgramHandle = createAndLinkProgram(vertexShaderHandle, fragmentShaderHandle, mAttributeName, null ); | |
| 547 |  | |
| 548 | setUpAttributes(); | |
| 549 | setUpUniforms(); | |
| 550 | } | |
| 551 |  | |
| 552 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 553 | /** | |
| 554 | * Return the handle of the created program so that we can later, say, call glUseProgram. | |
| 555 | */ | |
| 556 | public int getProgramHandle() | |
| 557 |     {
 | |
| 558 | return mProgramHandle; | |
| 559 | } | |
| 560 |  | |
| 561 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 562 | /** | |
| 563 | * Use the program and enable all vertex attribute arrays. | |
| 564 | * Needs to be called from a thread holding the OpenGL context. | |
| 565 | */ | |
| 566 | public void useProgram() | |
| 567 |     {
 | |
| 568 | GLES30.glUseProgram(mProgramHandle); | |
| 569 |  | |
| 570 | for(int i=0; i<mNumAttributes; i++) | |
| 571 |       {
 | |
| 572 | GLES30.glEnableVertexAttribArray(mAttribute[i]); | |
| 573 | } | |
| 574 | } | |
| 575 |  | |
| 576 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 577 | /** | |
| 578 | * Disable all vertex attribute arrays. | |
| 579 | * Needs to be called from a thread holding the OpenGL context. | |
| 580 | */ | |
| 581 | public void stopUsingProgram() | |
| 582 |     {
 | |
| 583 | GLES30.glUseProgram(0); | |
| 584 |  | |
| 585 | for(int i=0; i<mNumAttributes; i++) | |
| 586 |       {
 | |
| 587 | GLES30.glDisableVertexAttribArray(mAttribute[i]); | |
| 588 | } | |
| 589 | } | |
| 590 | } | |
| 591 |  | |
| 592 |  | |
| src/main/java/org/distorted/library/program/FragmentCompilationException.java | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
| 6 | // This library is free software; you can redistribute it and/or // | |
| 7 | // modify it under the terms of the GNU Lesser General Public // | |
| 8 | // License as published by the Free Software Foundation; either // | |
| 9 | // version 2.1 of the License, or (at your option) any later version. // | |
| 10 | // // | |
| 11 | // This library is distributed in the hope that it will be useful, // | |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // | |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // | |
| 14 | // Lesser General Public License for more details. // | |
| 15 | // // | |
| 16 | // You should have received a copy of the GNU Lesser General Public // | |
| 17 | // License along with this library; if not, write to the Free Software // | |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // | |
| 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 20 |  | |
| 21 | package org.distorted.library.program; | |
| 22 |  | |
| 23 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 24 |  | |
| 25 | /** | |
| 26 | * Thrown asynchronously by the library whenever shader compilation fails. | |
| 27 | * If compilation of the fragment shader fails for some other reason than too many uniforms. | |
| 28 | * <p> | |
| 29 | * This can happen on older OpenGL ES 2.0 devices if they, say, do not support variable loops in the shaders. | |
| 30 | * Theoretically should never happen on devices supporting at least OpenGL ES 3.0. | |
| 31 | */ | |
| 32 |  | |
| 33 | @SuppressWarnings("serial")
 | |
| 34 | public class FragmentCompilationException extends Exception | |
| 35 |   {
 | |
| 36 |  | |
| 37 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 38 | /** | |
| 39 | * Default empty constructor | |
| 40 | */ | |
| 41 | public FragmentCompilationException() | |
| 42 |     {
 | |
| 43 |  | |
| 44 | } | |
| 45 |  | |
| 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 47 | /** | |
| 48 | * Constructor with a message describing why compilation failed. | |
| 49 | * | |
| 50 | * @param detailMessage Message describing why compilation failed | |
| 51 | */ | |
| 52 | public FragmentCompilationException(String detailMessage) | |
| 53 |     {
 | |
| 54 | super(detailMessage); | |
| 55 | } | |
| 56 |  | |
| 57 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 58 | /** | |
| 59 | * Constructor necessary to make Chained Exceptions working. | |
| 60 | * | |
| 61 | * @param throwable The parent Throwable. | |
| 62 | */ | |
| 63 | public FragmentCompilationException(Throwable throwable) | |
| 64 |     {
 | |
| 65 | super(throwable); | |
| 66 | } | |
| 67 |  | |
| 68 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 69 | /** | |
| 70 | * Constructor necessary to make Chained Exceptions working. | |
| 71 | * | |
| 72 | * @param detailMessage Message describing why compilation failed | |
| 73 | * @param throwable The parent Throwable. | |
| 74 | */ | |
| 75 | public FragmentCompilationException(String detailMessage, Throwable throwable) | |
| 76 |     {
 | |
| 77 | super(detailMessage, throwable); | |
| 78 | } | |
| 79 |  | |
| 80 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 81 | } | |
| src/main/java/org/distorted/library/program/FragmentCompilationException.kt | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
| 6 | // This library is free software; you can redistribute it and/or // | |
| 7 | // modify it under the terms of the GNU Lesser General Public // | |
| 8 | // License as published by the Free Software Foundation; either // | |
| 9 | // version 2.1 of the License, or (at your option) any later version. // | |
| 10 | // // | |
| 11 | // This library is distributed in the hope that it will be useful, // | |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // | |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // | |
| 14 | // Lesser General Public License for more details. // | |
| 15 | // // | |
| 16 | // You should have received a copy of the GNU Lesser General Public // | |
| 17 | // License along with this library; if not, write to the Free Software // | |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // | |
| 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 20 |  | |
| 21 | package org.distorted.library.program; | |
| 22 |  | |
| 23 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 24 |  | |
| 25 | /** | |
| 26 | * Thrown asynchronously by the library whenever shader compilation fails. | |
| 27 | * If compilation of the fragment shader fails for some other reason than too many uniforms. | |
| 28 | * <p> | |
| 29 | * This can happen on older OpenGL ES 2.0 devices if they, say, do not support variable loops in the shaders. | |
| 30 | * Theoretically should never happen on devices supporting at least OpenGL ES 3.0. | |
| 31 | */ | |
| 32 |  | |
| 33 | @SuppressWarnings("serial")
 | |
| 34 | public class FragmentCompilationException extends Exception | |
| 35 |   {
 | |
| 36 |  | |
| 37 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 38 | /** | |
| 39 | * Default empty constructor | |
| 40 | */ | |
| 41 | public FragmentCompilationException() | |
| 42 |     {
 | |
| 43 |  | |
| 44 | } | |
| 45 |  | |
| 46 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 47 | /** | |
| 48 | * Constructor with a message describing why compilation failed. | |
| 49 | * | |
| 50 | * @param detailMessage Message describing why compilation failed | |
| 51 | */ | |
| 52 | public FragmentCompilationException(String detailMessage) | |
| 53 |     {
 | |
| 54 | super(detailMessage); | |
| 55 | } | |
| 56 |  | |
| 57 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 58 | /** | |
| 59 | * Constructor necessary to make Chained Exceptions working. | |
| 60 | * | |
| 61 | * @param throwable The parent Throwable. | |
| 62 | */ | |
| 63 | public FragmentCompilationException(Throwable throwable) | |
| 64 |     {
 | |
| 65 | super(throwable); | |
| 66 | } | |
| 67 |  | |
| 68 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 69 | /** | |
| 70 | * Constructor necessary to make Chained Exceptions working. | |
| 71 | * | |
| 72 | * @param detailMessage Message describing why compilation failed | |
| 73 | * @param throwable The parent Throwable. | |
| 74 | */ | |
| 75 | public FragmentCompilationException(String detailMessage, Throwable throwable) | |
| 76 |     {
 | |
| 77 | super(detailMessage, throwable); | |
| 78 | } | |
| 79 |  | |
| 80 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 81 | } | |
| src/main/java/org/distorted/library/program/FragmentUniformsException.java | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
| 6 | // This library is free software; you can redistribute it and/or // | |
| 7 | // modify it under the terms of the GNU Lesser General Public // | |
| 8 | // License as published by the Free Software Foundation; either // | |
| 9 | // version 2.1 of the License, or (at your option) any later version. // | |
| 10 | // // | |
| 11 | // This library is distributed in the hope that it will be useful, // | |
| 12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of // | |
| 13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // | |
| 14 | // Lesser General Public License for more details. // | |
| 15 | // // | |
| 16 | // You should have received a copy of the GNU Lesser General Public // | |
| 17 | // License along with this library; if not, write to the Free Software // | |
| 18 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // | |
| 19 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 20 |  | |
| 21 | package org.distorted.library.program; | |
| 22 |  | |
| 23 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 24 |  | |
| 25 | import org.distorted.library.main.DistortedLibrary; | |
| 26 |  | |
| 27 | /** | |
| 28 | * Thrown asynchronously by the library whenever shader compilation fails. | |
| 29 | * If compilation of the fragment shader fails because of too many uniforms there, i.e. because | |
| 30 |  *  we have set {@link DistortedLibrary#setMax(org.distorted.library.effect.EffectType, int)}
 | |
| 31 | * to too high value. | |
| 32 | */ | |
| 33 |  | |
| 34 | @SuppressWarnings("serial")
 | |
| 35 | public class FragmentUniformsException extends Exception | |
| 36 |   {
 | |
| 37 | private int max=0; | |
| 38 |  | |
| 39 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 40 | /** | |
| 41 | * Default empty constructor | |
| 42 | */ | |
| 43 | public FragmentUniformsException() | |
| 44 |     {
 | |
| 45 |  | |
| 46 | } | |
| 47 |  | |
| 48 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 49 | /** | |
| 50 | * Constructor with a message describing why compilation failed. | |
| 51 | * | |
| 52 | * @param detailMessage Message describing why compilation failed | |
| 53 | */ | |
| 54 | public FragmentUniformsException(String detailMessage) | |
| 55 |     {
 | |
| 56 | super(detailMessage); | |
| 57 | } | |
| 58 |  | |
| 59 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 60 | /** | |
| 61 | * Constructor necessary to make Chained Exceptions working. | |
| 62 | * | |
| 63 | * @param throwable The parent Throwable. | |
| 64 | */ | |
| 65 | public FragmentUniformsException(Throwable throwable) | |
| 66 |     {
 | |
| 67 | super(throwable); | |
| 68 | } | |
| 69 |  | |
| 70 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 71 | /** | |
| 72 | * Constructor necessary to make Chained Exceptions working. | |
| 73 | * | |
| 74 | * @param detailMessage Message describing why compilation failed | |
| 75 | * @param throwable The parent Throwable. | |
| 76 | */ | |
| 77 | public FragmentUniformsException(String detailMessage, Throwable throwable) | |
| 78 |     {
 | |
| 79 | super(detailMessage, throwable); | |
| 80 | } | |
| 81 |  | |
| 82 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 83 | /** | |
| 84 | * Constructor with a message describing why compilation failed and integer holding the maximum | |
| 85 | * number of uniforms in Fragment Shader supported by current hardware. | |
| 86 | * | |
| 87 | * @param detailMessage Message describing why compilation failed | |
| 88 | * @param m maximum number of uniforms in Fragment Shader supported by current hardware. | |
| 89 | */ | |
| 90 | public FragmentUniformsException(String detailMessage, int m) | |
| 91 |     {
 | |
| 92 | super(detailMessage); | |
| 93 | max = m; | |
| 94 | } | |
| 95 |  | |
| 96 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 97 | /** | |
| 98 | * Gets the maximum number of uniforms in fragment shader supported by current hardware. | |
| 99 | * | |
| 100 | * @return Maximum number of uniforms in fragment shader supported by current hardware. | |
| 101 | */ | |
| 102 | public int getMax() | |
| 103 |     {
 | |
| 104 | return max; | |
| 105 | } | |
| 106 |  | |
| 107 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 108 | } | |
| src/main/java/org/distorted/library/program/FragmentUniformsException.kt | ||
|---|---|---|
| 1 | /////////////////////////////////////////////////////////////////////////////////////////////////// | |
| 2 | // Copyright 2016 Leszek Koltunski leszek@koltunski.pl // | |
| 3 | // // | |
| 4 | // This file is part of Distorted. // | |
| 5 | // // | |
Also available in: Unified diff
Rename .java to .kt