diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 3869a39..9d2aa67 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -1,4 +1,11 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; +import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; +const temp = [0,0,0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -22,9 +29,19 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY) + constructor(texture, verticesX, verticesY, data) { - super(texture); + const geometry = new Geometry(); + + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + geometry.addAttribute('aVertexPosition', new Float32Array(2), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(2), 2) + geometry.addIndex(new Uint16Array(2)) + + super(geometry, meshShader, 4); + + this.texture = texture; /** * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can @@ -35,11 +52,24 @@ */ this._ready = true; - this.verticesX = verticesX || 10; - this.verticesY = verticesY || 10; + this.segmentsX = this.verticesX = verticesX || 10; + this.segmentsY = this.verticesY = verticesY || 10; - this.drawMode = Mesh.DRAW_MODES.TRIANGLES; + this.meshWidth = data.meshWidth; + this.meshHeight = data.meshHeight; + + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } + this.refresh(); + + this.tint; } /** @@ -58,8 +88,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = texture.width / segmentsX; - const sizeY = texture.height / segmentsY; + const sizeX = this.meshWidth / segmentsX; + const sizeY = this.meshHeight / segmentsY; for (let i = 0; i < total; i++) { @@ -102,12 +132,23 @@ } // console.log(indices) + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.vertices = new Float32Array(verts); this.uvs = new Float32Array(uvs); - this.colors = new Float32Array(colors); this.indices = new Uint16Array(indices); - this.indexDirty = true; + this.geometry.getAttribute('aVertexPosition').data = this.vertices; + this.geometry.getAttribute('aTextureCoord').data = this.uvs; + this.geometry.data.indexBuffer.data = this.indices; + + // ensure that the changes are uploaded + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update();// + } /** @@ -117,8 +158,6 @@ */ _onTextureUpdate() { - Mesh.prototype._onTextureUpdate.call(this); - // wait for the Plane ctor to finish before calling refresh if (this._ready) { @@ -126,4 +165,22 @@ } } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } + + updateTransform() + { + + this.geometry.getAttribute('aVertexPosition').update(); + this.containerUpdateTransform(); + } + + + } diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 3869a39..9d2aa67 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -1,4 +1,11 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; +import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; +const temp = [0,0,0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -22,9 +29,19 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY) + constructor(texture, verticesX, verticesY, data) { - super(texture); + const geometry = new Geometry(); + + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + geometry.addAttribute('aVertexPosition', new Float32Array(2), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(2), 2) + geometry.addIndex(new Uint16Array(2)) + + super(geometry, meshShader, 4); + + this.texture = texture; /** * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can @@ -35,11 +52,24 @@ */ this._ready = true; - this.verticesX = verticesX || 10; - this.verticesY = verticesY || 10; + this.segmentsX = this.verticesX = verticesX || 10; + this.segmentsY = this.verticesY = verticesY || 10; - this.drawMode = Mesh.DRAW_MODES.TRIANGLES; + this.meshWidth = data.meshWidth; + this.meshHeight = data.meshHeight; + + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } + this.refresh(); + + this.tint; } /** @@ -58,8 +88,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = texture.width / segmentsX; - const sizeY = texture.height / segmentsY; + const sizeX = this.meshWidth / segmentsX; + const sizeY = this.meshHeight / segmentsY; for (let i = 0; i < total; i++) { @@ -102,12 +132,23 @@ } // console.log(indices) + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.vertices = new Float32Array(verts); this.uvs = new Float32Array(uvs); - this.colors = new Float32Array(colors); this.indices = new Uint16Array(indices); - this.indexDirty = true; + this.geometry.getAttribute('aVertexPosition').data = this.vertices; + this.geometry.getAttribute('aTextureCoord').data = this.uvs; + this.geometry.data.indexBuffer.data = this.indices; + + // ensure that the changes are uploaded + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update();// + } /** @@ -117,8 +158,6 @@ */ _onTextureUpdate() { - Mesh.prototype._onTextureUpdate.call(this); - // wait for the Plane ctor to finish before calling refresh if (this._ready) { @@ -126,4 +165,22 @@ } } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } + + updateTransform() + { + + this.geometry.getAttribute('aVertexPosition').update(); + this.containerUpdateTransform(); + } + + + } diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js index d713ec1..1b167ee 100644 --- a/src/mesh/Rope.js +++ b/src/mesh/Rope.js @@ -1,5 +1,10 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; /** * The rope allows you to draw a texture across several points and them manipulate these points @@ -24,33 +29,23 @@ */ constructor(texture, points) { - super(texture); + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + const geometry = new Geometry(); + + geometry.addAttribute('aVertexPosition', new Float32Array(points.length * 4), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(points.length * 4), 2) + geometry.addIndex(new Uint16Array(points.length * 2)) + + super(geometry, meshShader, 5); + + this.texture = texture; /* * @member {PIXI.Point[]} An array of points that determine the rope */ this.points = points; - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - /** * Tracker for if the rope is ready to be drawn. Needed because Mesh ctor can * call _onTextureUpdated which could call refresh too early. @@ -60,38 +55,49 @@ */ this._ready = true; - this.refresh(); + this.tint = 0xFFFFFF; + + // wait for the texture to load + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } } /** * Refreshes - * */ refresh() { const points = this.points; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const uvs = this.geometry.getAttribute('aTextureCoord').data; + + //TODO - lets make this more accessable... maybe a getIndx()? + const indices = this.geometry.data.indexBuffer.data; // if too little points, or texture hasn't got UVs set yet just move on. - if (points.length < 1 || !this._texture._uvs) + if (points.length < 1 || !this.texture._uvs) { return; } // if the number of points has changed we will need to recreate the arraybuffers - if (this.vertices.length / 4 !== points.length) + if (vertices.length / 4 !== points.length) { + /* this.vertices = new Float32Array(points.length * 4); this.uvs = new Float32Array(points.length * 4); this.colors = new Float32Array(points.length * 2); this.indices = new Uint16Array(points.length * 2); + */ } - const uvs = this.uvs; - - const indices = this.indices; - const colors = this.colors; - - const textureUvs = this._texture._uvs; + const textureUvs = this.texture._uvs; const offset = new core.Point(textureUvs.x0, textureUvs.y0); const factor = new core.Point(textureUvs.x2 - textureUvs.x0, textureUvs.y2 - textureUvs.y0); @@ -100,9 +106,6 @@ uvs[2] = 0 + offset.x; uvs[3] = Number(factor.y) + offset.y; - colors[0] = 1; - colors[1] = 1; - indices[0] = 0; indices[1] = 1; @@ -121,17 +124,16 @@ uvs[index + 3] = Number(factor.y) + offset.y; index = i * 2; - colors[index] = 1; - colors[index + 1] = 1; - - index = i * 2; indices[index] = index; indices[index + 1] = index + 1; } // ensure that the changes are uploaded - this.dirty++; - this.indexDirty++; + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update(); + + // console.log(this.geometry.data) } /** @@ -141,7 +143,7 @@ */ _onTextureUpdate() { - super._onTextureUpdate(); + //super._onTextureUpdate(); // wait for the Rope ctor to finish before calling refresh if (this._ready) @@ -171,7 +173,8 @@ // this.count -= 0.2; - const vertices = this.vertices; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const total = points.length; for (let i = 0; i < total; i++) @@ -197,9 +200,8 @@ { ratio = 1; } - const perpLength = Math.sqrt((perpX * perpX) + (perpY * perpY)); - const num = this._texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + const num = this.texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; perpX /= perpLength; perpY /= perpLength; @@ -215,7 +217,19 @@ lastPoint = point; } + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.geometry.getAttribute('aVertexPosition').update(); this.containerUpdateTransform(); } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } } diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 3869a39..9d2aa67 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -1,4 +1,11 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; +import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; +const temp = [0,0,0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -22,9 +29,19 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY) + constructor(texture, verticesX, verticesY, data) { - super(texture); + const geometry = new Geometry(); + + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + geometry.addAttribute('aVertexPosition', new Float32Array(2), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(2), 2) + geometry.addIndex(new Uint16Array(2)) + + super(geometry, meshShader, 4); + + this.texture = texture; /** * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can @@ -35,11 +52,24 @@ */ this._ready = true; - this.verticesX = verticesX || 10; - this.verticesY = verticesY || 10; + this.segmentsX = this.verticesX = verticesX || 10; + this.segmentsY = this.verticesY = verticesY || 10; - this.drawMode = Mesh.DRAW_MODES.TRIANGLES; + this.meshWidth = data.meshWidth; + this.meshHeight = data.meshHeight; + + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } + this.refresh(); + + this.tint; } /** @@ -58,8 +88,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = texture.width / segmentsX; - const sizeY = texture.height / segmentsY; + const sizeX = this.meshWidth / segmentsX; + const sizeY = this.meshHeight / segmentsY; for (let i = 0; i < total; i++) { @@ -102,12 +132,23 @@ } // console.log(indices) + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.vertices = new Float32Array(verts); this.uvs = new Float32Array(uvs); - this.colors = new Float32Array(colors); this.indices = new Uint16Array(indices); - this.indexDirty = true; + this.geometry.getAttribute('aVertexPosition').data = this.vertices; + this.geometry.getAttribute('aTextureCoord').data = this.uvs; + this.geometry.data.indexBuffer.data = this.indices; + + // ensure that the changes are uploaded + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update();// + } /** @@ -117,8 +158,6 @@ */ _onTextureUpdate() { - Mesh.prototype._onTextureUpdate.call(this); - // wait for the Plane ctor to finish before calling refresh if (this._ready) { @@ -126,4 +165,22 @@ } } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } + + updateTransform() + { + + this.geometry.getAttribute('aVertexPosition').update(); + this.containerUpdateTransform(); + } + + + } diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js index d713ec1..1b167ee 100644 --- a/src/mesh/Rope.js +++ b/src/mesh/Rope.js @@ -1,5 +1,10 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; /** * The rope allows you to draw a texture across several points and them manipulate these points @@ -24,33 +29,23 @@ */ constructor(texture, points) { - super(texture); + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + const geometry = new Geometry(); + + geometry.addAttribute('aVertexPosition', new Float32Array(points.length * 4), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(points.length * 4), 2) + geometry.addIndex(new Uint16Array(points.length * 2)) + + super(geometry, meshShader, 5); + + this.texture = texture; /* * @member {PIXI.Point[]} An array of points that determine the rope */ this.points = points; - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - /** * Tracker for if the rope is ready to be drawn. Needed because Mesh ctor can * call _onTextureUpdated which could call refresh too early. @@ -60,38 +55,49 @@ */ this._ready = true; - this.refresh(); + this.tint = 0xFFFFFF; + + // wait for the texture to load + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } } /** * Refreshes - * */ refresh() { const points = this.points; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const uvs = this.geometry.getAttribute('aTextureCoord').data; + + //TODO - lets make this more accessable... maybe a getIndx()? + const indices = this.geometry.data.indexBuffer.data; // if too little points, or texture hasn't got UVs set yet just move on. - if (points.length < 1 || !this._texture._uvs) + if (points.length < 1 || !this.texture._uvs) { return; } // if the number of points has changed we will need to recreate the arraybuffers - if (this.vertices.length / 4 !== points.length) + if (vertices.length / 4 !== points.length) { + /* this.vertices = new Float32Array(points.length * 4); this.uvs = new Float32Array(points.length * 4); this.colors = new Float32Array(points.length * 2); this.indices = new Uint16Array(points.length * 2); + */ } - const uvs = this.uvs; - - const indices = this.indices; - const colors = this.colors; - - const textureUvs = this._texture._uvs; + const textureUvs = this.texture._uvs; const offset = new core.Point(textureUvs.x0, textureUvs.y0); const factor = new core.Point(textureUvs.x2 - textureUvs.x0, textureUvs.y2 - textureUvs.y0); @@ -100,9 +106,6 @@ uvs[2] = 0 + offset.x; uvs[3] = Number(factor.y) + offset.y; - colors[0] = 1; - colors[1] = 1; - indices[0] = 0; indices[1] = 1; @@ -121,17 +124,16 @@ uvs[index + 3] = Number(factor.y) + offset.y; index = i * 2; - colors[index] = 1; - colors[index + 1] = 1; - - index = i * 2; indices[index] = index; indices[index + 1] = index + 1; } // ensure that the changes are uploaded - this.dirty++; - this.indexDirty++; + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update(); + + // console.log(this.geometry.data) } /** @@ -141,7 +143,7 @@ */ _onTextureUpdate() { - super._onTextureUpdate(); + //super._onTextureUpdate(); // wait for the Rope ctor to finish before calling refresh if (this._ready) @@ -171,7 +173,8 @@ // this.count -= 0.2; - const vertices = this.vertices; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const total = points.length; for (let i = 0; i < total; i++) @@ -197,9 +200,8 @@ { ratio = 1; } - const perpLength = Math.sqrt((perpX * perpX) + (perpY * perpY)); - const num = this._texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + const num = this.texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; perpX /= perpLength; perpY /= perpLength; @@ -215,7 +217,19 @@ lastPoint = point; } + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.geometry.getAttribute('aVertexPosition').update(); this.containerUpdateTransform(); } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } } diff --git a/src/mesh/index.js b/src/mesh/index.js index 833f39a..30151f2 100644 --- a/src/mesh/index.js +++ b/src/mesh/index.js @@ -9,6 +9,6 @@ export { default as GeometryStyle } from './geometry/GeometryStyle'; export { default as Buffer } from './geometry/Buffer'; export { default as Geometry } from './geometry/Geometry'; -// export { default as Plane } from './Plane'; +export { default as Plane } from './Plane'; // export { default as NineSlicePlane } from './NineSlicePlane'; -// export { default as Rope } from './Rope'; +export { default as Rope } from './Rope'; diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 3869a39..9d2aa67 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -1,4 +1,11 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; +import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; +const temp = [0,0,0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -22,9 +29,19 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY) + constructor(texture, verticesX, verticesY, data) { - super(texture); + const geometry = new Geometry(); + + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + geometry.addAttribute('aVertexPosition', new Float32Array(2), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(2), 2) + geometry.addIndex(new Uint16Array(2)) + + super(geometry, meshShader, 4); + + this.texture = texture; /** * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can @@ -35,11 +52,24 @@ */ this._ready = true; - this.verticesX = verticesX || 10; - this.verticesY = verticesY || 10; + this.segmentsX = this.verticesX = verticesX || 10; + this.segmentsY = this.verticesY = verticesY || 10; - this.drawMode = Mesh.DRAW_MODES.TRIANGLES; + this.meshWidth = data.meshWidth; + this.meshHeight = data.meshHeight; + + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } + this.refresh(); + + this.tint; } /** @@ -58,8 +88,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = texture.width / segmentsX; - const sizeY = texture.height / segmentsY; + const sizeX = this.meshWidth / segmentsX; + const sizeY = this.meshHeight / segmentsY; for (let i = 0; i < total; i++) { @@ -102,12 +132,23 @@ } // console.log(indices) + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.vertices = new Float32Array(verts); this.uvs = new Float32Array(uvs); - this.colors = new Float32Array(colors); this.indices = new Uint16Array(indices); - this.indexDirty = true; + this.geometry.getAttribute('aVertexPosition').data = this.vertices; + this.geometry.getAttribute('aTextureCoord').data = this.uvs; + this.geometry.data.indexBuffer.data = this.indices; + + // ensure that the changes are uploaded + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update();// + } /** @@ -117,8 +158,6 @@ */ _onTextureUpdate() { - Mesh.prototype._onTextureUpdate.call(this); - // wait for the Plane ctor to finish before calling refresh if (this._ready) { @@ -126,4 +165,22 @@ } } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } + + updateTransform() + { + + this.geometry.getAttribute('aVertexPosition').update(); + this.containerUpdateTransform(); + } + + + } diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js index d713ec1..1b167ee 100644 --- a/src/mesh/Rope.js +++ b/src/mesh/Rope.js @@ -1,5 +1,10 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; /** * The rope allows you to draw a texture across several points and them manipulate these points @@ -24,33 +29,23 @@ */ constructor(texture, points) { - super(texture); + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + const geometry = new Geometry(); + + geometry.addAttribute('aVertexPosition', new Float32Array(points.length * 4), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(points.length * 4), 2) + geometry.addIndex(new Uint16Array(points.length * 2)) + + super(geometry, meshShader, 5); + + this.texture = texture; /* * @member {PIXI.Point[]} An array of points that determine the rope */ this.points = points; - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - /** * Tracker for if the rope is ready to be drawn. Needed because Mesh ctor can * call _onTextureUpdated which could call refresh too early. @@ -60,38 +55,49 @@ */ this._ready = true; - this.refresh(); + this.tint = 0xFFFFFF; + + // wait for the texture to load + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } } /** * Refreshes - * */ refresh() { const points = this.points; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const uvs = this.geometry.getAttribute('aTextureCoord').data; + + //TODO - lets make this more accessable... maybe a getIndx()? + const indices = this.geometry.data.indexBuffer.data; // if too little points, or texture hasn't got UVs set yet just move on. - if (points.length < 1 || !this._texture._uvs) + if (points.length < 1 || !this.texture._uvs) { return; } // if the number of points has changed we will need to recreate the arraybuffers - if (this.vertices.length / 4 !== points.length) + if (vertices.length / 4 !== points.length) { + /* this.vertices = new Float32Array(points.length * 4); this.uvs = new Float32Array(points.length * 4); this.colors = new Float32Array(points.length * 2); this.indices = new Uint16Array(points.length * 2); + */ } - const uvs = this.uvs; - - const indices = this.indices; - const colors = this.colors; - - const textureUvs = this._texture._uvs; + const textureUvs = this.texture._uvs; const offset = new core.Point(textureUvs.x0, textureUvs.y0); const factor = new core.Point(textureUvs.x2 - textureUvs.x0, textureUvs.y2 - textureUvs.y0); @@ -100,9 +106,6 @@ uvs[2] = 0 + offset.x; uvs[3] = Number(factor.y) + offset.y; - colors[0] = 1; - colors[1] = 1; - indices[0] = 0; indices[1] = 1; @@ -121,17 +124,16 @@ uvs[index + 3] = Number(factor.y) + offset.y; index = i * 2; - colors[index] = 1; - colors[index + 1] = 1; - - index = i * 2; indices[index] = index; indices[index + 1] = index + 1; } // ensure that the changes are uploaded - this.dirty++; - this.indexDirty++; + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update(); + + // console.log(this.geometry.data) } /** @@ -141,7 +143,7 @@ */ _onTextureUpdate() { - super._onTextureUpdate(); + //super._onTextureUpdate(); // wait for the Rope ctor to finish before calling refresh if (this._ready) @@ -171,7 +173,8 @@ // this.count -= 0.2; - const vertices = this.vertices; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const total = points.length; for (let i = 0; i < total; i++) @@ -197,9 +200,8 @@ { ratio = 1; } - const perpLength = Math.sqrt((perpX * perpX) + (perpY * perpY)); - const num = this._texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + const num = this.texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; perpX /= perpLength; perpY /= perpLength; @@ -215,7 +217,19 @@ lastPoint = point; } + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.geometry.getAttribute('aVertexPosition').update(); this.containerUpdateTransform(); } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } } diff --git a/src/mesh/index.js b/src/mesh/index.js index 833f39a..30151f2 100644 --- a/src/mesh/index.js +++ b/src/mesh/index.js @@ -9,6 +9,6 @@ export { default as GeometryStyle } from './geometry/GeometryStyle'; export { default as Buffer } from './geometry/Buffer'; export { default as Geometry } from './geometry/Geometry'; -// export { default as Plane } from './Plane'; +export { default as Plane } from './Plane'; // export { default as NineSlicePlane } from './NineSlicePlane'; -// export { default as Rope } from './Rope'; +export { default as Rope } from './Rope'; diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index 5913771..db1db74 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -55,6 +55,8 @@ // TODO rename filter to shader this.renderer.bindShader(mesh.shader); + // sync uniforms.. + // now time for geometry.. // bind the geometry... diff --git a/src/core/const.js b/src/core/const.js index 3425b41..f670fd8 100644 --- a/src/core/const.js +++ b/src/core/const.js @@ -104,6 +104,7 @@ SATURATION: 14, COLOR: 15, LUMINOSITY: 16, + NONE: 17 }; /** diff --git a/src/core/renderers/webgl/State.js b/src/core/renderers/webgl/State.js new file mode 100644 index 0000000..046a45c --- /dev/null +++ b/src/core/renderers/webgl/State.js @@ -0,0 +1,131 @@ +const BLEND = 0; +const OFFSET = 1; +const CULLING = 2; +const DEPTH_TEST = 3; +const WINDING = 4; + +export default class State +{ + constructor(data) + { + this.data = 0; + + this.blendMode = 0; + this.polygonOffset = 0; + } + + set blend( value ) + { + if( !!(this.data & (1 << BLEND)) !== value ) + { + this.data ^= (1 << BLEND); + } + } + + get blend() + { + return !!(this.data & (1 << BLEND)) + } + + //////////// + + set offsets( value ) + { + if( !!(this.data & (1 << OFFSET)) !== value ) + { + this.data ^= (1<> 1; + i++; + }*/ + } + + /** + * Sets the current state + * + * @param {*} state - The state to set. + */ + set state(state) + { + // TODO maybe to an object check? ( this.state === state )? + if(this.stateId === state.data)return; + + let diff = this.stateId ^ state.data; + let i = 0; + + // order from least to most common + while(diff) + { + if(diff & 1) + { + // state change! + this.map[i](state.data ^= (1 << i)); + } + + diff = diff >> 1; + i++; + } + + // based on the above settings we check for specific modes.. + // for example if blend is active we check and set the blend modes + // or of polygon offset is active we check the poly depth. + for (let i = 0; i < this.checks.length; i++) + { + this.checks[i](this, state); + }; + } + + + /** + * Enables or disabled blending. + * + * @param {boolean} value - Turn on or off webgl blending. + */ + setBlend(value) + { + this.updateCheck(StateManager.checkBlendMode, value); + + this.gl[value ? 'enable' : 'disable'](this.gl.BLEND); + } + + setPolygonOffset(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.POLYGON_OFFSET_FILL); + } + + /** + * Sets whether to enable or disable depth test. + * + * @param {boolean} value - Turn on or off webgl depth testing. + */ + setDepthTest(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.DEPTH_TEST); + } + + /** + * Sets whether to enable or disable cull face. + * + * @param {boolean} value - Turn on or off webgl cull face. + */ + setCullFace(value) + { + this.gl[value ? 'enable' : 'disable'](this.gl.CULL_FACE); + } + + /** + * Sets the gl front face. + * + * @param {boolean} value - true is clockwise and false is counter-clockwise + */ + setFrontFace(value) + { + this.gl.frontFace(this.gl[value ? 'CW' : 'CCW']); + } + + /** + * Sets the blend mode. + * + * @param {number} value - The blend mode to set to. + */ + setBlendMode(value) + { + if (value === this.blendMode) + { + return; + } + + this.gl.blendFunc(this.blendModes[value][0], this.blendModes[value][1]); + } + + /** + * Sets the polygon offset. + * + * @param {number} value - The blend mode to set to. + */ + setPolygonOffset(value, scale) + { + this.gl.polygonOffset(value, scale); + } + + /** + * Disables all the vaos in use + * + */ + resetAttributes() + { + for (let i = 0; i < this.attribState.tempAttribState.length; i++) + { + this.attribState.tempAttribState[i] = 0; + } + + for (let i = 0; i < this.attribState.attribState.length; i++) + { + this.attribState.attribState[i] = 0; + } + + // im going to assume one is always active for performance reasons. + for (let i = 1; i < this.maxAttribs; i++) + { + this.gl.disableVertexAttribArray(i); + } + } + + // used + /** + * Resets all the logic and disables the vaos + */ + resetToDefault() + { + // unbind any VAO if they exist.. + if (this.nativeVaoExtension) + { + this.nativeVaoExtension.bindVertexArrayOES(null); + } + + // reset all attributes.. + this.resetAttributes(); + + this.gl.pixelStorei(this.gl.UNPACK_FLIP_Y_WEBGL, false); + + //TO DO? + //this.setState(this.defaultState); + } + + updateCheck(func, value) + { + const index = this.checks.indexOf(func); + + if(value && index === -1) + { + this.checks.push(func); + } + else if(!value && index !== -1) + { + this.checks.splice(index, 1); + } + + } + + //static function maintains scope! + static checkBlendMode(manager, state) + { + manager.setBlendMode(state.blendMode); + } + + // TODO - polygon offset? +} diff --git a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js index 53e2111..71b7075 100644 --- a/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js +++ b/src/core/renderers/webgl/utils/mapWebGLBlendModesToPixi.js @@ -31,6 +31,7 @@ array[BLEND_MODES.SATURATION] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.COLOR] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; array[BLEND_MODES.LUMINOSITY] = [gl.ONE, gl.ONE_MINUS_SRC_ALPHA]; + array[BLEND_MODES.NONE] = [0,0]; return array; } diff --git a/src/core/sprites/webgl/SpriteRenderer.js b/src/core/sprites/webgl/SpriteRenderer.js index 633c43f..0c48f61 100644 --- a/src/core/sprites/webgl/SpriteRenderer.js +++ b/src/core/sprites/webgl/SpriteRenderer.js @@ -108,9 +108,10 @@ // step 2: check the maximum number of if statements the shader can have too.. this.MAX_TEXTURES = checkMaxIfStatmentsInShader(this.MAX_TEXTURES, gl); - + console.log(this.MAX_TEXTURE) const shader = this.shader = generateMultiTextureShader(gl, this.MAX_TEXTURES); + console.log(shader) // create a couple of buffers this.indexBuffer = glCore.GLBuffer.createIndexBuffer(gl, this.indices, gl.STATIC_DRAW); @@ -122,7 +123,8 @@ for (let i = 0; i < this.vaoMax; i++) { this.vertexBuffers[i] = glCore.GLBuffer.createVertexBuffer(gl, null, gl.STREAM_DRAW); - + console.log(this.vertexBuffers) + console.log(shader.attributes) /* eslint-disable max-len */ // build the vao object that will render.. @@ -131,8 +133,10 @@ .addAttribute(this.vertexBuffers[i], shader.attributes.aVertexPosition, gl.FLOAT, false, this.vertByteSize, 0) .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureCoord, gl.UNSIGNED_SHORT, true, this.vertByteSize, 2 * 4) .addAttribute(this.vertexBuffers[i], shader.attributes.aColor, gl.UNSIGNED_BYTE, true, this.vertByteSize, 3 * 4) - .addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); - + if(shader.attributes.aTextureId) + { + this.vaos[i].addAttribute(this.vertexBuffers[i], shader.attributes.aTextureId, gl.FLOAT, false, this.vertByteSize, 4 * 4); + } /* eslint-disable max-len */ } diff --git a/src/mesh/Mesh.js b/src/mesh/Mesh.js index 4621235..01a308f 100644 --- a/src/mesh/Mesh.js +++ b/src/mesh/Mesh.js @@ -13,7 +13,7 @@ * @param {PIXI.Shader} shader the shader the mesh will use * @param {number} drawMode the drawMode, can be any of the PIXI.DRAW_MODES consts */ - constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES) + constructor(geometry, shader, drawMode = core.DRAW_MODES.TRIANGLES, uniforms = {}) { super(); /** @@ -41,7 +41,7 @@ */ this.drawMode = drawMode; - this.uniforms = {}; + this.uniforms = uniforms; // geometry// // shader// diff --git a/src/mesh/Plane.js b/src/mesh/Plane.js index 3869a39..9d2aa67 100644 --- a/src/mesh/Plane.js +++ b/src/mesh/Plane.js @@ -1,4 +1,11 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; +import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; +const temp = [0,0,0]; /** * The Plane allows you to draw a texture across several points and them manipulate these points @@ -22,9 +29,19 @@ * @param {number} verticesX - The number of vertices in the x-axis * @param {number} verticesY - The number of vertices in the y-axis */ - constructor(texture, verticesX, verticesY) + constructor(texture, verticesX, verticesY, data) { - super(texture); + const geometry = new Geometry(); + + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + geometry.addAttribute('aVertexPosition', new Float32Array(2), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(2), 2) + geometry.addIndex(new Uint16Array(2)) + + super(geometry, meshShader, 4); + + this.texture = texture; /** * Tracker for if the Plane is ready to be drawn. Needed because Mesh ctor can @@ -35,11 +52,24 @@ */ this._ready = true; - this.verticesX = verticesX || 10; - this.verticesY = verticesY || 10; + this.segmentsX = this.verticesX = verticesX || 10; + this.segmentsY = this.verticesY = verticesY || 10; - this.drawMode = Mesh.DRAW_MODES.TRIANGLES; + this.meshWidth = data.meshWidth; + this.meshHeight = data.meshHeight; + + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } + this.refresh(); + + this.tint; } /** @@ -58,8 +88,8 @@ const segmentsX = this.verticesX - 1; const segmentsY = this.verticesY - 1; - const sizeX = texture.width / segmentsX; - const sizeY = texture.height / segmentsY; + const sizeX = this.meshWidth / segmentsX; + const sizeY = this.meshHeight / segmentsY; for (let i = 0; i < total; i++) { @@ -102,12 +132,23 @@ } // console.log(indices) + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.vertices = new Float32Array(verts); this.uvs = new Float32Array(uvs); - this.colors = new Float32Array(colors); this.indices = new Uint16Array(indices); - this.indexDirty = true; + this.geometry.getAttribute('aVertexPosition').data = this.vertices; + this.geometry.getAttribute('aTextureCoord').data = this.uvs; + this.geometry.data.indexBuffer.data = this.indices; + + // ensure that the changes are uploaded + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update();// + } /** @@ -117,8 +158,6 @@ */ _onTextureUpdate() { - Mesh.prototype._onTextureUpdate.call(this); - // wait for the Plane ctor to finish before calling refresh if (this._ready) { @@ -126,4 +165,22 @@ } } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } + + updateTransform() + { + + this.geometry.getAttribute('aVertexPosition').update(); + this.containerUpdateTransform(); + } + + + } diff --git a/src/mesh/Rope.js b/src/mesh/Rope.js index d713ec1..1b167ee 100644 --- a/src/mesh/Rope.js +++ b/src/mesh/Rope.js @@ -1,5 +1,10 @@ import Mesh from './Mesh'; +import Geometry from './geometry/Geometry'; import * as core from '../core'; +import { readFileSync } from 'fs'; +import { join } from 'path'; + +let meshShader; /** * The rope allows you to draw a texture across several points and them manipulate these points @@ -24,33 +29,23 @@ */ constructor(texture, points) { - super(texture); + if(!meshShader)meshShader = new core.Shader( readFileSync(join(__dirname, './webgl/mesh.vert'), 'utf8'), readFileSync(join(__dirname, './webgl/mesh.frag'), 'utf8')); + + const geometry = new Geometry(); + + geometry.addAttribute('aVertexPosition', new Float32Array(points.length * 4), 2) + geometry.addAttribute('aTextureCoord', new Float32Array(points.length * 4), 2) + geometry.addIndex(new Uint16Array(points.length * 2)) + + super(geometry, meshShader, 5); + + this.texture = texture; /* * @member {PIXI.Point[]} An array of points that determine the rope */ this.points = points; - /* - * @member {Float32Array} An array of vertices used to construct this rope. - */ - this.vertices = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} The WebGL Uvs of the rope. - */ - this.uvs = new Float32Array(points.length * 4); - - /* - * @member {Float32Array} An array containing the color components - */ - this.colors = new Float32Array(points.length * 2); - - /* - * @member {Uint16Array} An array containing the indices of the vertices - */ - this.indices = new Uint16Array(points.length * 2); - /** * Tracker for if the rope is ready to be drawn. Needed because Mesh ctor can * call _onTextureUpdated which could call refresh too early. @@ -60,38 +55,49 @@ */ this._ready = true; - this.refresh(); + this.tint = 0xFFFFFF; + + // wait for the texture to load + if (texture.baseTexture.hasLoaded) + { + this._onTextureUpdate(); + } + else + { + texture.once('update', this._onTextureUpdate, this); + } } /** * Refreshes - * */ refresh() { const points = this.points; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const uvs = this.geometry.getAttribute('aTextureCoord').data; + + //TODO - lets make this more accessable... maybe a getIndx()? + const indices = this.geometry.data.indexBuffer.data; // if too little points, or texture hasn't got UVs set yet just move on. - if (points.length < 1 || !this._texture._uvs) + if (points.length < 1 || !this.texture._uvs) { return; } // if the number of points has changed we will need to recreate the arraybuffers - if (this.vertices.length / 4 !== points.length) + if (vertices.length / 4 !== points.length) { + /* this.vertices = new Float32Array(points.length * 4); this.uvs = new Float32Array(points.length * 4); this.colors = new Float32Array(points.length * 2); this.indices = new Uint16Array(points.length * 2); + */ } - const uvs = this.uvs; - - const indices = this.indices; - const colors = this.colors; - - const textureUvs = this._texture._uvs; + const textureUvs = this.texture._uvs; const offset = new core.Point(textureUvs.x0, textureUvs.y0); const factor = new core.Point(textureUvs.x2 - textureUvs.x0, textureUvs.y2 - textureUvs.y0); @@ -100,9 +106,6 @@ uvs[2] = 0 + offset.x; uvs[3] = Number(factor.y) + offset.y; - colors[0] = 1; - colors[1] = 1; - indices[0] = 0; indices[1] = 1; @@ -121,17 +124,16 @@ uvs[index + 3] = Number(factor.y) + offset.y; index = i * 2; - colors[index] = 1; - colors[index + 1] = 1; - - index = i * 2; indices[index] = index; indices[index + 1] = index + 1; } // ensure that the changes are uploaded - this.dirty++; - this.indexDirty++; + this.geometry.getAttribute('aVertexPosition').update(); + this.geometry.getAttribute('aTextureCoord').update(); + this.geometry.data.indexBuffer.update(); + + // console.log(this.geometry.data) } /** @@ -141,7 +143,7 @@ */ _onTextureUpdate() { - super._onTextureUpdate(); + //super._onTextureUpdate(); // wait for the Rope ctor to finish before calling refresh if (this._ready) @@ -171,7 +173,8 @@ // this.count -= 0.2; - const vertices = this.vertices; + const vertices = this.geometry.getAttribute('aVertexPosition').data; + const total = points.length; for (let i = 0; i < total; i++) @@ -197,9 +200,8 @@ { ratio = 1; } - const perpLength = Math.sqrt((perpX * perpX) + (perpY * perpY)); - const num = this._texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; + const num = this.texture.height / 2; // (20 + Math.abs(Math.sin((i + this.count) * 0.3) * 50) )* ratio; perpX /= perpLength; perpY /= perpLength; @@ -215,7 +217,19 @@ lastPoint = point; } + this.shader.uniforms.alpha = 1; + this.shader.uniforms.uSampler2 = this.texture;// + + this.geometry.getAttribute('aVertexPosition').update(); this.containerUpdateTransform(); } + _renderWebGL(renderer) + { + this.shader.uniforms.tint = core.utils.hex2rgb(this.tint,temp) + this.shader.uniforms.uSampler2 = this.texture;// + + renderer.setObjectRenderer(renderer.plugins.mesh); + renderer.plugins.mesh.render(this); + } } diff --git a/src/mesh/index.js b/src/mesh/index.js index 833f39a..30151f2 100644 --- a/src/mesh/index.js +++ b/src/mesh/index.js @@ -9,6 +9,6 @@ export { default as GeometryStyle } from './geometry/GeometryStyle'; export { default as Buffer } from './geometry/Buffer'; export { default as Geometry } from './geometry/Geometry'; -// export { default as Plane } from './Plane'; +export { default as Plane } from './Plane'; // export { default as NineSlicePlane } from './NineSlicePlane'; -// export { default as Rope } from './Rope'; +export { default as Rope } from './Rope'; diff --git a/src/mesh/webgl/MeshRenderer.js b/src/mesh/webgl/MeshRenderer.js index 5913771..db1db74 100644 --- a/src/mesh/webgl/MeshRenderer.js +++ b/src/mesh/webgl/MeshRenderer.js @@ -55,6 +55,8 @@ // TODO rename filter to shader this.renderer.bindShader(mesh.shader); + // sync uniforms.. + // now time for geometry.. // bind the geometry... diff --git a/src/mesh/webgl/mesh.frag b/src/mesh/webgl/mesh.frag index 9e0b634..de41551 100644 --- a/src/mesh/webgl/mesh.frag +++ b/src/mesh/webgl/mesh.frag @@ -2,9 +2,9 @@ uniform float alpha; uniform vec3 tint; -uniform sampler2D uSampler; +uniform sampler2D uSampler2; void main(void) { - gl_FragColor = texture2D(uSampler, vTextureCoord) * vec4(tint * alpha, alpha); + gl_FragColor = texture2D(uSampler2, vTextureCoord) * vec4(tint * alpha, alpha); }