138 lines
3.8 KiB
JavaScript
138 lines
3.8 KiB
JavaScript
var check = require('./util/check')
|
|
var isTypedArray = require('./util/is-typed-array')
|
|
|
|
var GL_RGBA = 6408
|
|
var GL_UNSIGNED_BYTE = 5121
|
|
var GL_PACK_ALIGNMENT = 0x0D05
|
|
var GL_FLOAT = 0x1406 // 5126
|
|
|
|
module.exports = function wrapReadPixels (
|
|
gl,
|
|
framebufferState,
|
|
reglPoll,
|
|
context,
|
|
glAttributes,
|
|
extensions,
|
|
limits) {
|
|
function readPixelsImpl (input) {
|
|
var type
|
|
if (framebufferState.next === null) {
|
|
check(
|
|
glAttributes.preserveDrawingBuffer,
|
|
'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer')
|
|
type = GL_UNSIGNED_BYTE
|
|
} else {
|
|
check(
|
|
framebufferState.next.colorAttachments[0].texture !== null,
|
|
'You cannot read from a renderbuffer')
|
|
type = framebufferState.next.colorAttachments[0].texture._texture.type
|
|
|
|
check.optional(function () {
|
|
if (extensions.oes_texture_float) {
|
|
check(
|
|
type === GL_UNSIGNED_BYTE || type === GL_FLOAT,
|
|
'Reading from a framebuffer is only allowed for the types \'uint8\' and \'float\'')
|
|
|
|
if (type === GL_FLOAT) {
|
|
check(limits.readFloat, 'Reading \'float\' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float')
|
|
}
|
|
} else {
|
|
check(
|
|
type === GL_UNSIGNED_BYTE,
|
|
'Reading from a framebuffer is only allowed for the type \'uint8\'')
|
|
}
|
|
})
|
|
}
|
|
|
|
var x = 0
|
|
var y = 0
|
|
var width = context.framebufferWidth
|
|
var height = context.framebufferHeight
|
|
var data = null
|
|
|
|
if (isTypedArray(input)) {
|
|
data = input
|
|
} else if (input) {
|
|
check.type(input, 'object', 'invalid arguments to regl.read()')
|
|
x = input.x | 0
|
|
y = input.y | 0
|
|
check(
|
|
x >= 0 && x < context.framebufferWidth,
|
|
'invalid x offset for regl.read')
|
|
check(
|
|
y >= 0 && y < context.framebufferHeight,
|
|
'invalid y offset for regl.read')
|
|
width = (input.width || (context.framebufferWidth - x)) | 0
|
|
height = (input.height || (context.framebufferHeight - y)) | 0
|
|
data = input.data || null
|
|
}
|
|
|
|
// sanity check input.data
|
|
if (data) {
|
|
if (type === GL_UNSIGNED_BYTE) {
|
|
check(
|
|
data instanceof Uint8Array,
|
|
'buffer must be \'Uint8Array\' when reading from a framebuffer of type \'uint8\'')
|
|
} else if (type === GL_FLOAT) {
|
|
check(
|
|
data instanceof Float32Array,
|
|
'buffer must be \'Float32Array\' when reading from a framebuffer of type \'float\'')
|
|
}
|
|
}
|
|
|
|
check(
|
|
width > 0 && width + x <= context.framebufferWidth,
|
|
'invalid width for read pixels')
|
|
check(
|
|
height > 0 && height + y <= context.framebufferHeight,
|
|
'invalid height for read pixels')
|
|
|
|
// Update WebGL state
|
|
reglPoll()
|
|
|
|
// Compute size
|
|
var size = width * height * 4
|
|
|
|
// Allocate data
|
|
if (!data) {
|
|
if (type === GL_UNSIGNED_BYTE) {
|
|
data = new Uint8Array(size)
|
|
} else if (type === GL_FLOAT) {
|
|
data = data || new Float32Array(size)
|
|
}
|
|
}
|
|
|
|
// Type check
|
|
check.isTypedArray(data, 'data buffer for regl.read() must be a typedarray')
|
|
check(data.byteLength >= size, 'data buffer for regl.read() too small')
|
|
|
|
// Run read pixels
|
|
gl.pixelStorei(GL_PACK_ALIGNMENT, 4)
|
|
gl.readPixels(x, y, width, height, GL_RGBA,
|
|
type,
|
|
data)
|
|
|
|
return data
|
|
}
|
|
|
|
function readPixelsFBO (options) {
|
|
var result
|
|
framebufferState.setFBO({
|
|
framebuffer: options.framebuffer
|
|
}, function () {
|
|
result = readPixelsImpl(options)
|
|
})
|
|
return result
|
|
}
|
|
|
|
function readPixels (options) {
|
|
if (!options || !('framebuffer' in options)) {
|
|
return readPixelsImpl(options)
|
|
} else {
|
|
return readPixelsFBO(options)
|
|
}
|
|
}
|
|
|
|
return readPixels
|
|
}
|