Skip to content

Instantly share code, notes, and snippets.

@sergeystoma
Created April 23, 2022 03:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sergeystoma/1b9bf7fce6e58ef8ae0f6a99a1c5a49f to your computer and use it in GitHub Desktop.
Save sergeystoma/1b9bf7fce6e58ef8ae0f6a99a1c5a49f to your computer and use it in GitHub Desktop.
// eslint-disable-next-line func-names, no-underscore-dangle
this.engine._readTexturePixelsSync = function (texture, width, height, faceIndex, level, buffer, flushRenderer, noDataConversion) {
if (texture._hardwareTexture
&& texture._hardwareTexture.underlyingResource
&& texture._hardwareTexture.underlyingResource.__SPECTOR_Object_CustomData) {
const t = texture._hardwareTexture.underlyingResource;
// eslint-disable-next-line
console.log(`Exporting texture id ${t.__SPECTOR_Object_TAG.id}, format ${t.__SPECTOR_Object_CustomData.format}, compressed ${t.__SPECTOR_Object_CustomData.isCompressed}`);
}
if (faceIndex === 0) {
// eslint-disable-next-line no-param-reassign
faceIndex = -1;
}
if (level === 0) {
// eslint-disable-next-line no-param-reassign
level = 0;
}
if (buffer === 0) {
// eslint-disable-next-line no-param-reassign
buffer = null;
}
if (flushRenderer === 0) {
// eslint-disable-next-line no-param-reassign
flushRenderer = true;
}
if (noDataConversion === 0) {
// eslint-disable-next-line no-param-reassign
noDataConversion = false;
}
// eslint-disable-next-line no-underscore-dangle
const gl = this._gl;
if (!gl) {
throw new Error('Engine does not have gl rendering context.');
}
if (flushRenderer) {
this.flushFramebuffer();
}
// Make a new framebuffer texture.
const colorTarget = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, colorTarget);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
// Setup new framebuffer instead of BJS dummy framebuffer since that may be used elsewhere.
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorTarget, 0);
// Old state.
const previousProgram = gl.getParameter(gl.CURRENT_PROGRAM);
const previousViewport = gl.getParameter(gl.VIEWPORT);
// Viewport.
gl.viewport(0, 0, width, height);
// Shaders.
const vertShaderSource = `#version 300 es
in vec2 aVertex;
in vec2 aTexture;
out vec2 vTexture;
void main(void) {
gl_Position = vec4(aVertex, 0.0, 1.0);
vTexture = aTexture;
}
`;
const fragShaderSource = `#version 300 es
precision mediump float;
in vec2 vTexture;
out vec4 fragmentColor;
uniform sampler2D uSampler;
void main(void) {
fragmentColor = texture(uSampler, vTexture);
}
`;
const vertShader = gl.createShader(gl.VERTEX_SHADER);
const fragShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertShader, vertShaderSource);
gl.shaderSource(fragShader, fragShaderSource);
gl.compileShader(vertShader);
// const vertLog = gl.getShaderInfoLog(vertShader);
// // eslint-disable-next-line
// console.log(`Vertex shader: ${vertLog}`);
gl.compileShader(fragShader);
// const fragLog = gl.getShaderInfoLog(fragShader);
// // eslint-disable-next-line
// console.log(`Fragment shader: ${fragLog}`);
const program = gl.createProgram();
gl.attachShader(program, vertShader);
gl.attachShader(program, fragShader);
gl.linkProgram(program);
gl.useProgram(program);
const vertLocation = gl.getAttribLocation(program, 'aVertex');
const textLocation = gl.getAttribLocation(program, 'aTexture');
const samplerLocation = gl.getUniformLocation(program, 'uSampler');
// Quad.
const vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, 1, -1, -1, 1, -1, 1, 1]), gl.STATIC_DRAW);
const textBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, textBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 1, 0, 0, 1, 0, 1, 1]), gl.STATIC_DRAW);
// Draw quad.
gl.enableVertexAttribArray(vertLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.vertexAttribPointer(vertLocation, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(textLocation);
gl.bindBuffer(gl.ARRAY_BUFFER, textBuffer);
gl.vertexAttribPointer(textLocation, 2, gl.FLOAT, false, 0, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture._hardwareTexture == null ? null : texture._hardwareTexture.underlyingResource);
const magFilter = gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER);
const minFilter = gl.getTexParameter(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_ANISOTROPY_EXT, 1);
gl.uniform1i(samplerLocation, 0);
gl.disable(gl.DEPTH_TEST);
gl.depthMask(false);
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
gl.disableVertexAttribArray(vertLocation);
gl.disableVertexAttribArray(textLocation);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
// Get pixels.
const readBuffer = new Uint8Array(4 * width * height);
gl.flush();
gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readBuffer);
// Clean up.
gl.depthMask(true);
gl.deleteBuffer(vertBuffer);
gl.deleteBuffer(textBuffer);
gl.deleteShader(vertShader);
gl.deleteShader(fragShader);
gl.deleteProgram(program);
gl.deleteFramebuffer(fb);
gl.deleteTexture(colorTarget);
gl.useProgram(previousProgram);
gl.viewport(previousViewport[0], previousViewport[1], previousViewport[2], previousViewport[3]);
gl.bindFramebuffer(gl.FRAMEBUFFER, this._currentFramebuffer);
return readBuffer;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment