|
5 | 5 | numTexels *= dimensions[i]; |
6 | 6 | } |
7 | 7 |
|
8 | | - if (opt.floatTextures && !output) { |
| 8 | + if (opt.floatTextures && (!output || opt.floatOutput)) { |
9 | 9 | numTexels = Math.ceil(numTexels / 4); |
10 | 10 | } |
11 | 11 |
|
|
133 | 133 | var programUniformLocationCache = []; |
134 | 134 |
|
135 | 135 | function ret() { |
136 | | - if (opt.floatTextures && !gpu.OES_texture_float) { |
| 136 | + if (opt.floatTextures === true && !GPUUtils.OES_texture_float) { |
137 | 137 | throw "Float textures are not supported on this browser"; |
| 138 | + } else if (opt.floatTextures === undefined && GPUUtils.OES_texture_float) { |
| 139 | + opt.floatTextures = true; |
138 | 140 | } |
139 | 141 |
|
140 | 142 | if (!opt.dimensions || opt.dimensions.length === 0) { |
|
152 | 154 | } |
153 | 155 | } |
154 | 156 |
|
155 | | - var texSize = dimToTexSize(gpu, opt.dimensions, true); |
156 | | - |
| 157 | + var texSize = dimToTexSize(opt, opt.dimensions, true); |
| 158 | + |
157 | 159 | if (opt.graphical) { |
158 | 160 | if (opt.dimensions.length != 2) { |
159 | 161 | throw "Output must have 2 dimensions on graphical mode"; |
160 | 162 | } |
161 | 163 |
|
| 164 | + if (opt.floatOutput) { |
| 165 | + throw "Cannot use graphical mode and float output at the same time"; |
| 166 | + } |
| 167 | + |
162 | 168 | texSize = GPUUtils.clone(opt.dimensions); |
| 169 | + } else if (opt.floatOutput === undefined && GPUUtils.OES_texture_float) { |
| 170 | + opt.floatOutput = true; |
163 | 171 | } |
164 | 172 |
|
165 | 173 | canvas.width = texSize[0]; |
|
387 | 395 | '', |
388 | 396 | 'void main(void) {', |
389 | 397 | ' index = floor(vTexCoord.s * float(uTexSize.x)) + floor(vTexCoord.t * float(uTexSize.y)) * uTexSize.x;', |
| 398 | + (opt.floatOutput ? 'index *= 4.0;' : ''), |
390 | 399 | ' threadId = indexTo3D(index, uOutputDim);', |
391 | 400 | ' kernel();', |
392 | 401 | ' if (outputToColor == true) {', |
393 | 402 | ' gl_FragColor = actualColor;', |
394 | 403 | ' } else {', |
395 | | - ' gl_FragColor = encode32(kernelResult);', |
| 404 | + (opt.floatOutput ? '' : 'gl_FragColor = encode32(kernelResult);'), |
| 405 | + (opt.floatOutput ? 'gl_FragColor.r = kernelResult;' : ''), |
| 406 | + (opt.floatOutput ? 'index += 1.0; threadId = indexTo3D(index, uOutputDim); kernel();' : ''), |
| 407 | + (opt.floatOutput ? 'gl_FragColor.g = kernelResult;' : ''), |
| 408 | + (opt.floatOutput ? 'index += 1.0; threadId = indexTo3D(index, uOutputDim); kernel();' : ''), |
| 409 | + (opt.floatOutput ? 'gl_FragColor.b = kernelResult;' : ''), |
| 410 | + (opt.floatOutput ? 'index += 1.0; threadId = indexTo3D(index, uOutputDim); kernel();' : ''), |
| 411 | + (opt.floatOutput ? 'gl_FragColor.a = kernelResult;' : ''), |
396 | 412 | ' }', |
397 | 413 | '}' |
398 | 414 | ].join('\n'); |
|
407 | 423 | gl.compileShader(fragShader); |
408 | 424 |
|
409 | 425 | if (!gl.getShaderParameter(vertShader, gl.COMPILE_STATUS)) { |
410 | | - console.error("An error occurred compiling the shaders: " + gl.getShaderInfoLog(vertShader)); |
411 | 426 | console.log(vertShaderSrc); |
| 427 | + console.error("An error occurred compiling the shaders: " + gl.getShaderInfoLog(vertShader)); |
412 | 428 | throw "Error compiling vertex shader"; |
413 | 429 | } |
414 | 430 | if (!gl.getShaderParameter(fragShader, gl.COMPILE_STATUS)) { |
415 | | - console.error("An error occurred compiling the shaders: " + gl.getShaderInfoLog(fragShader)); |
416 | 431 | console.log(fragShaderSrc); |
| 432 | + console.error("An error occurred compiling the shaders: " + gl.getShaderInfoLog(fragShader)); |
417 | 433 | throw "Error compiling fragment shader"; |
418 | 434 | } |
419 | 435 |
|
420 | 436 | if (opt.debug) { |
| 437 | + console.log('Options:'); |
| 438 | + console.dir(opt); |
| 439 | + console.log('GLSL Shader Output:'); |
421 | 440 | console.log(fragShaderSrc); |
422 | 441 | } |
423 | 442 |
|
|
470 | 489 | var argType = GPUUtils.getArgumentType(arguments[textureCount]); |
471 | 490 | if (argType == "Array") { |
472 | 491 | paramDim = getDimensions(arguments[textureCount], true); |
473 | | - paramSize = dimToTexSize(gpu, paramDim); |
| 492 | + paramSize = dimToTexSize(opt, paramDim); |
474 | 493 |
|
475 | 494 | texture = gl.createTexture(); |
476 | 495 | gl.activeTexture(gl["TEXTURE"+textureCount]); |
|
531 | 550 | throw "Input type not supported (GPU): " + arguments[textureCount]; |
532 | 551 | } |
533 | 552 | } |
534 | | - |
535 | | - if (opt.outputToTexture) { |
536 | | - var outputTexture = gl.createTexture(); |
537 | | - gl.activeTexture(gl["TEXTURE"+textureCount]); |
538 | | - gl.bindTexture(gl.TEXTURE_2D, outputTexture); |
539 | | - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
540 | | - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
541 | | - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
542 | | - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); |
| 553 | + |
| 554 | + var outputTexture = gl.createTexture(); |
| 555 | + gl.activeTexture(gl["TEXTURE"+textureCount]); |
| 556 | + gl.bindTexture(gl.TEXTURE_2D, outputTexture); |
| 557 | + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
| 558 | + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
| 559 | + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
| 560 | + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); |
| 561 | + if (opt.floatOutput) { |
| 562 | + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.FLOAT, null); |
| 563 | + } else { |
543 | 564 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, texSize[0], texSize[1], 0, gl.RGBA, gl.UNSIGNED_BYTE, null); |
| 565 | + } |
544 | 566 |
|
545 | | - var framebuffer = gl.createFramebuffer(); |
546 | | - framebuffer.width = texSize[0]; |
547 | | - framebuffer.height = texSize[1]; |
548 | | - gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); |
549 | | - gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0); |
550 | | - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); |
| 567 | + var framebuffer = gl.createFramebuffer(); |
| 568 | + framebuffer.width = texSize[0]; |
| 569 | + framebuffer.height = texSize[1]; |
| 570 | + gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); |
| 571 | + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, outputTexture, 0); |
| 572 | + |
| 573 | + gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); |
| 574 | + |
| 575 | + if (opt.outputToTexture) { |
551 | 576 | return new GPUTexture(gpu, outputTexture, texSize, opt.dimensions); |
552 | 577 | } else { |
553 | | - gl.bindRenderbuffer(gl.RENDERBUFFER, null); |
554 | | - gl.bindFramebuffer(gl.FRAMEBUFFER, null); |
555 | | - |
556 | | - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); |
557 | | - |
558 | 578 | if (opt.graphical) { |
559 | 579 | return; |
560 | 580 | } |
561 | 581 |
|
562 | | - var bytes = new Uint8Array(texSize[0]*texSize[1]*4); |
563 | | - gl.readPixels(0, 0, texSize[0], texSize[1], gl.RGBA, gl.UNSIGNED_BYTE, bytes); |
564 | | - var result = Array.prototype.slice.call(new Float32Array(bytes.buffer)); |
565 | | - result.length = threadDim[0] * threadDim[1] * threadDim[2]; |
| 582 | + var result; |
| 583 | + if (opt.floatOutput) { |
| 584 | + result = new Float32Array(texSize[0]*texSize[1]*4); |
| 585 | + gl.readPixels(0, 0, texSize[0], texSize[1], gl.RGBA, gl.FLOAT, result); |
| 586 | + } else { |
| 587 | + var bytes = new Uint8Array(texSize[0]*texSize[1]*4); |
| 588 | + gl.readPixels(0, 0, texSize[0], texSize[1], gl.RGBA, gl.UNSIGNED_BYTE, bytes); |
| 589 | + result = Float32Array.prototype.slice.call(new Float32Array(bytes.buffer)); |
| 590 | + } |
| 591 | + |
| 592 | + result = result.subarray(0, threadDim[0] * threadDim[1] * threadDim[2]); |
566 | 593 |
|
567 | 594 | if (opt.dimensions.length == 1) { |
568 | 595 | return result; |
|
0 commit comments