Skip to content

Commit

Permalink
Merge 4d97bc2 into 27f24d3
Browse files Browse the repository at this point in the history
  • Loading branch information
Jongmoon Yoon committed Dec 21, 2017
2 parents 27f24d3 + 4d97bc2 commit 0264bca
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 116 deletions.
61 changes: 23 additions & 38 deletions src/PanoImageRenderer/PanoImageRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export default class PanoImageRenderer extends Component {

this._image = null;
this._imageIsReady = false;
this._keepUpdate = false; // Flag to specify 'continuous update' on video even when still.

this._onContentLoad = this._onContentLoad.bind(this);
this._onContentError = this._onContentError.bind(this);
Expand All @@ -91,8 +92,10 @@ export default class PanoImageRenderer extends Component {

if (isVideo) {
this._contentLoader = new VideoLoader();
this._keepUpdate = true;
} else {
this._contentLoader = new ImageLoader();
this._keepUpdate = false;
}

// img element or img url
Expand Down Expand Up @@ -169,7 +172,8 @@ export default class PanoImageRenderer extends Component {
}

isImageLoaded() {
return !!this._image && this._imageIsReady;
return !!this._image && this._imageIsReady &&
(!this._isVideo || this._image.readyState >= 2 /* HAVE_CURRENT_DATA */);
}

cancelLoadImage() {
Expand Down Expand Up @@ -312,6 +316,9 @@ export default class PanoImageRenderer extends Component {
if (!this.shaderProgram) {
throw new Error(`Failed to intialize shaders: ${WebGLUtils.getErrorNameFromWebGLErrorCode(this.context.getError())}`);
}

// Buffers for shader
this._initBuffers();
} catch (e) {
this.trigger(EVENTS.ERROR, {
type: ERROR_TYPE.NO_WEBGL,
Expand Down Expand Up @@ -389,14 +396,16 @@ export default class PanoImageRenderer extends Component {
const gl = this.context;

this.vertexBuffer = WebGLUtils.initBuffer(
gl, gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), 3);
gl, gl.ARRAY_BUFFER, new Float32Array(vertexPositionData), 3,
this.shaderProgram.vertexPositionAttribute);

this.indexBuffer = WebGLUtils.initBuffer(
gl, gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexData), 1);

if (textureCoordData !== null) {
this.textureCoordBuffer = WebGLUtils.initBuffer(
gl, gl.ARRAY_BUFFER, new Float32Array(textureCoordData), 2);
gl, gl.ARRAY_BUFFER, new Float32Array(textureCoordData), 2,
this.shaderProgram.textureCoordAttribute);
}
}

Expand All @@ -408,7 +417,7 @@ export default class PanoImageRenderer extends Component {
}

renderWithQuaternion(quaternion, fieldOfView) {
if (!this.isImageLoaded() || !this.hasRenderingContext()) {
if (!this.isImageLoaded()) {
return;
}

Expand Down Expand Up @@ -447,16 +456,17 @@ export default class PanoImageRenderer extends Component {
}
}

keepUpdate(doUpdate) {
this._keepUpdate = doUpdate;
}

render(yaw, pitch, fieldOfView) {
if (!this.isImageLoaded() || !this.hasRenderingContext()) {
if (!this.isImageLoaded()) {
return;
}

if (this._isVideo) { /* TODO: && Check if isPlaying */
this._bindTexture();
}

if (this._lastYaw !== null && this._lastYaw === yaw &&
if (this._keepUpdate === false &&
this._lastYaw !== null && this._lastYaw === yaw &&
this._lastPitch !== null && this._lastPitch === pitch &&
this.fieldOfView && this.fieldOfView === fieldOfView &&
this._shouldForceDraw === false) {
Expand Down Expand Up @@ -485,45 +495,20 @@ export default class PanoImageRenderer extends Component {
_draw() {
const gl = this.context;

gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.activeTexture(gl.TEXTURE0);
if (this._isCubeStrip) {
gl.bindTexture(gl.TEXTURE_CUBE_MAP, this.texture);
} else {
gl.bindTexture(gl.TEXTURE_2D, this.texture);
}

if (this.vertexBuffer === null || this.indexBuffer === null) {
this._initBuffers();
}
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);

// gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.uniform1i(this.shaderProgram.samplerUniform, 0);
gl.uniformMatrix4fv(this.shaderProgram.pMatrixUniform, false, this.pMatrix);
gl.uniformMatrix4fv(this.shaderProgram.mvMatrixUniform, false, this.mvMatrix);

// textureCoordBuffer is used in sphere
if (this.textureCoordBuffer) {
WebGLUtils.bindBufferToAttribute(
gl, this.textureCoordBuffer, this.shaderProgram.textureCoordAttribute);
}

if (this.vertexBuffer) {
WebGLUtils.bindBufferToAttribute(
gl, this.vertexBuffer, this.shaderProgram.vertexPositionAttribute);
if (this._isVideo) {
this._renderer.texImage2D(this.context, this._image);
}

if (this.indexBuffer) {
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
gl.drawElements(
gl.TRIANGLES, this.indexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
}

if (this._isCubeStrip) {
gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
} else {
gl.bindTexture(gl.TEXTURE_2D, null);
}
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/PanoImageRenderer/WebGLUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default class WebGLUtils {
return null;
}

static initBuffer(gl, target /* bind point */, data, itemSize) {
static initBuffer(gl, target /* bind point */, data, itemSize, attr) {
const buffer = gl.createBuffer();

gl.bindBuffer(target, buffer);
Expand All @@ -53,6 +53,11 @@ export default class WebGLUtils {
buffer.numItems = data.length / itemSize;
}

if (attr !== undefined) {
gl.enableVertexAttribArray(attr);
gl.vertexAttribPointer(attr, buffer.itemSize, gl.FLOAT, false, 0, 0);
}

return buffer;
}

Expand Down
112 changes: 57 additions & 55 deletions src/PanoImageRenderer/renderer/CubeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,74 +99,76 @@ export default class CubeRenderer extends Renderer {
return;
}

try {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);

this.texImage2D(gl, image);
} catch (e) {

}
}

static texImage2D(gl, image) {
const agent = Agent();
const width = image.naturalWidth || image.videoWidth;
const height = image.naturalHeight || image.videoHeight;
const hasDrawImageBug = CubeRenderer.hasDrawImageBug(agent);
const maxCubeMapTextureSize = CubeRenderer.getMaxCubeMapTextureSize(gl, image, agent);
const heightScale = CubeRenderer.getHightScale(width, agent);

try {
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);

if (!hasDrawImageBug) {
const canvas = document.createElement("canvas");
if (!hasDrawImageBug) {
const canvas = document.createElement("canvas");

canvas.width = maxCubeMapTextureSize;
canvas.height = maxCubeMapTextureSize;
const context = canvas.getContext("2d");
canvas.width = maxCubeMapTextureSize;
canvas.height = maxCubeMapTextureSize;
const context = canvas.getContext("2d");

for (let surfaceIdx = 0; surfaceIdx < 6; surfaceIdx++) {
context.drawImage(
image, 0, surfaceIdx * (width * heightScale),
width, width * heightScale, 0, 0, maxCubeMapTextureSize, maxCubeMapTextureSize);
for (let surfaceIdx = 0; surfaceIdx < 6; surfaceIdx++) {
context.drawImage(
image, 0, surfaceIdx * (width * heightScale),
width, width * heightScale, 0, 0, maxCubeMapTextureSize, maxCubeMapTextureSize);
gl.texImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + surfaceIdx, 0, gl.RGBA,
gl.RGBA, gl.UNSIGNED_BYTE, canvas);
}
} else {
// #288, drawImage bug
const halfCanvas = document.createElement("canvas");
const context = halfCanvas.getContext("2d");

halfCanvas.width = maxCubeMapTextureSize * 3;
halfCanvas.height = maxCubeMapTextureSize;

const tileCanvas = document.createElement("canvas");
const tileContext = tileCanvas.getContext("2d");

tileCanvas.width = maxCubeMapTextureSize;
tileCanvas.height = maxCubeMapTextureSize;

for (let i = 0; i < 2; i++) {
context.save();
context.translate(0, maxCubeMapTextureSize);
context.rotate(-Math.PI / 2);
context.scale(1 / 3, 3);
context.drawImage(
image, 0, width * 3 * i * heightScale, width, height / 2 * heightScale,
0, 0, halfCanvas.width, halfCanvas.height);
context.restore();
for (let j = 0; j < 3; j++) {
tileContext.save();
tileContext.translate(maxCubeMapTextureSize, 0);
tileContext.rotate(Math.PI / 2);
tileContext.drawImage(
halfCanvas, j * width, 0, width, width, 0, 0, maxCubeMapTextureSize, maxCubeMapTextureSize);
tileContext.restore();
gl.texImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + surfaceIdx, 0, gl.RGBA,
gl.RGBA, gl.UNSIGNED_BYTE, canvas);
}
} else {
// #288, drawImage bug
const halfCanvas = document.createElement("canvas");
const context = halfCanvas.getContext("2d");

halfCanvas.width = maxCubeMapTextureSize * 3;
halfCanvas.height = maxCubeMapTextureSize;

const tileCanvas = document.createElement("canvas");
const tileContext = tileCanvas.getContext("2d");

tileCanvas.width = maxCubeMapTextureSize;
tileCanvas.height = maxCubeMapTextureSize;

for (let i = 0; i < 2; i++) {
context.save();
context.translate(0, maxCubeMapTextureSize);
context.rotate(-Math.PI / 2);
context.scale(1 / 3, 3);
context.drawImage(
image, 0, width * 3 * i * heightScale, width, height / 2 * heightScale,
0, 0, halfCanvas.width, halfCanvas.height);
context.restore();
for (let j = 0; j < 3; j++) {
tileContext.save();
tileContext.translate(maxCubeMapTextureSize, 0);
tileContext.rotate(Math.PI / 2);
tileContext.drawImage(
halfCanvas, j * width, 0, width, width, 0, 0, maxCubeMapTextureSize, maxCubeMapTextureSize);
tileContext.restore();
gl.texImage2D(
gl.TEXTURE_CUBE_MAP_POSITIVE_X + i * 3 + j, 0,
gl.RGBA, maxCubeMapTextureSize, maxCubeMapTextureSize, 0,
gl.RGBA, gl.UNSIGNED_BYTE, tileCanvas);
}
gl.TEXTURE_CUBE_MAP_POSITIVE_X + i * 3 + j, 0,
gl.RGBA, maxCubeMapTextureSize, maxCubeMapTextureSize, 0,
gl.RGBA, gl.UNSIGNED_BYTE, tileCanvas);
}
}
} catch (e) {

}

gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
}

static getMaxCubeMapTextureSize(gl, image, agent) {
Expand Down
40 changes: 18 additions & 22 deletions src/PanoImageRenderer/renderer/SphereRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,32 +55,28 @@ export default class SphereRenderer extends Renderer {
return;
}

const maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
const width = image.naturalWidth || image.videoWidth;// imageWidth;
const height = image.naturalHeight || image.videoHeight;// imageHeight;
const aspectRatio = height / width;
const canvas = document.createElement("canvas");

if (aspectRatio <= 1) {
canvas.width = Math.min(width, maxTextureSize);
canvas.height = canvas.width * aspectRatio;
} else {
canvas.height = Math.min(height, maxTextureSize);
canvas.width = canvas.height / aspectRatio;
// Make sure image isn't too big
const width = Math.max(image.width, image.height);
const maxWidth = gl.getParameter(gl.MAX_TEXTURE_SIZE);

if (width > maxWidth) {
console.warn(`Image width(${width}) exceeds device limit(${maxWidth}))`);
return;
}
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);

const context = canvas.getContext("2d");
gl.activeTexture(gl.TEXTURE0);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.bindTexture(gl.TEXTURE_2D, texture);

context.drawImage(image, 0, 0, width, height, 0, 0, canvas.width, canvas.height);
const data = new Uint8Array(context.getImageData(0, 0, canvas.width, canvas.height).data);
// Draw first frame
this.texImage2D(gl, image);
}

gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA,
canvas.width, canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
// this.trigger(EVENTS.BIND_TEXTURE);
gl.bindTexture(gl.TEXTURE_2D, null);
/**
* https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glTexImage2D.xml
*/
static texImage2D(gl, image) {
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
}

static _initData() {
Expand Down
5 changes: 5 additions & 0 deletions src/PanoViewer/PanoViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,11 @@ export default class PanoViewer extends Component {
return this;
}

keepUpdate(doUpdate) {
this._photoSphereRenderer.keepUpdate(doUpdate);
return this;
}

/**
* Get projection type (equirectangular/cube)
* @ko 프로젝션 타입(Equirectangular 혹은 Cube)을 반환한다.
Expand Down

0 comments on commit 0264bca

Please sign in to comment.