Faced the same problem. When batching is enabled, the curve effect is canceled. Now is there any solution (elegant or not)?
Is it marked as solved?
playcanvas:master
ā Glidias:master
opened 03:08AM - 08 Jun 18 UTC
All changes in batching.js file....
- Support for batching skinned (animated)ā¦ meshes.
https://github.com/playcanvas/engine/issues/1231
- Custom vertex shader chunk support batched elements.
https://github.com/playcanvas/engine/issues/1227
___________
Other changes to graphics/material files:
- Custom shader chunk support for fog codes. (program-lib.js, standard.js)
- Custom shader chunks support in (basic.js)
I confirm I have signed the [Contributor License Agreement](https://docs.google.com/a/playcanvas.com/forms/d/1Ih69zQfJG-QDLIEpHr6CsaAs6fPORNOVnMv5nuo0cjk/viewform).
Changed code from example
var CurvedWorld = pc.createScript('curvedWorld');
CurvedWorld.attributes.add('curvePower', {
type: 'vec4',
default: [1, -1, 0, 0],
description: 'Determines the amount of curviness to be applied.',
});
CurvedWorld.prototype.initialize = function () {
CurvedWorld.instance = this;
// --- variables
//this.activeCamera = this.app.root.findByName('Camera');
// --- make sure all materials are loaded before calling this
this.materials = this.app.assets.filter(function (asset) {
return asset.type === 'material';
}).map(o => o.resource);
// --- update the material shader
this.materials.forEach(material =>
{
this.updateShader(material);;
material.setParameter('curvePower', [this.curvePower.x * 0.001, this.curvePower.y * 0.001, this.curvePower.z * 0.001, this.curvePower.w * 0.001])
});
// --- events
this.on('attr', () => {
this.materials.forEach(material =>
{
material.setParameter('curvePower', [this.curvePower.x * 0.001, this.curvePower.y * 0.001, this.curvePower.z * 0.001, this.curvePower.w * 0.001]);
this.updateShaderUniforms(material)
});
});
};
CurvedWorld.prototype.postInitialize = function(){
console.log(this.app.batcher._batchList);
};
CurvedWorld.prototype.updateShader = function (material) {
//console.log(material.chunks.transformVS);
material.chunks.transformVS =
//'uniform vec3 curveDirection;\n' +
//'uniform float curvePower;\n' +
'uniform vec4 curvePower;\n' +
'uniform vec3 curveCenterPos;\n' +
//'uniform vec3 curveCameraDirection;\n' +
'#ifdef PIXELSNAP\n' +
'uniform vec4 uScreenSize;\n' +
'#endif\n' +
'#ifdef MORPHING\n' +
'uniform vec4 morph_weights_a;\n' +
'uniform vec4 morph_weights_b;\n' +
'#endif\n' +
'#ifdef MORPHING_TEXTURE_BASED\n' +
'uniform vec4 morph_tex_params;\n' +
'vec2 getTextureMorphCoords() {\n' +
' float vertexId = morph_vertex_id;\n' +
' vec2 textureSize = morph_tex_params.xy;\n' +
' vec2 invTextureSize = morph_tex_params.zw;\n' +
' // turn vertexId into int grid coordinates\n' +
' float morphGridV = floor(vertexId * invTextureSize.x);\n' +
' float morphGridU = vertexId - (morphGridV * textureSize.x);\n' +
' // convert grid coordinates to uv coordinates with half pixel offset\n' +
' return (vec2(morphGridU, morphGridV) * invTextureSize) + (0.5 * invTextureSize);\n' +
'}\n' +
'#endif\n' +
'#ifdef MORPHING_TEXTURE_BASED_POSITION\n' +
'uniform highp sampler2D morphPositionTex;\n' +
'#endif\n' +
'mat4 getModelMatrix() {\n' +
' #ifdef DYNAMICBATCH\n' +
' return getBoneMatrix(vertex_boneIndices);\n' +
' #elif defined(SKIN)\n' +
' return matrix_model * getSkinMatrix(vertex_boneIndices, vertex_boneWeights);\n' +
' #elif defined(INSTANCING)\n' +
' return mat4(instance_line1, instance_line2, instance_line3, instance_line4);\n' +
' #else\n' +
' return matrix_model;\n' +
' #endif\n' +
'}\n' +
'vec4 getPosition() {\n' +
' dModelMatrix = getModelMatrix();\n' +
' vec3 localPos = vertex_position;\n' +
' #ifdef NINESLICED\n' +
' // outer and inner vertices are at the same position, scale both\n' +
' localPos.xz *= outerScale;\n' +
' // offset inner vertices inside\n' +
' // (original vertices must be in [-1;1] range)\n' +
' vec2 positiveUnitOffset = clamp(vertex_position.xz, vec2(0.0), vec2(1.0));\n' +
' vec2 negativeUnitOffset = clamp(-vertex_position.xz, vec2(0.0), vec2(1.0));\n' +
' localPos.xz += (-positiveUnitOffset * innerOffset.xy + negativeUnitOffset * innerOffset.zw) * vertex_texCoord0.xy;\n' +
' vTiledUv = (localPos.xz - outerScale + innerOffset.xy) * -0.5 + 1.0; // uv = local pos - inner corner\n' +
' localPos.xz *= -0.5; // move from -1;1 to -0.5;0.5\n' +
' localPos = localPos.xzy;\n' +
' #endif\n' +
' #ifdef MORPHING\n' +
' #ifdef MORPHING_POS03\n' +
' localPos.xyz += morph_weights_a[0] * morph_pos0;\n' +
' localPos.xyz += morph_weights_a[1] * morph_pos1;\n' +
' localPos.xyz += morph_weights_a[2] * morph_pos2;\n' +
' localPos.xyz += morph_weights_a[3] * morph_pos3;\n' +
' #endif // MORPHING_POS03\n' +
' #ifdef MORPHING_POS47\n' +
' localPos.xyz += morph_weights_b[0] * morph_pos4;\n' +
' localPos.xyz += morph_weights_b[1] * morph_pos5;\n' +
' localPos.xyz += morph_weights_b[2] * morph_pos6;\n' +
' localPos.xyz += morph_weights_b[3] * morph_pos7;\n' +
' #endif // MORPHING_POS47\n' +
' #endif // MORPHING\n' +
' #ifdef MORPHING_TEXTURE_BASED_POSITION\n' +
' // apply morph offset from texture\n' +
' vec2 morphUV = getTextureMorphCoords();\n' +
' vec3 morphPos = texture2D(morphPositionTex, morphUV).xyz;\n' +
' localPos += morphPos;\n' +
' #endif\n' +
' vec4 posW = dModelMatrix * vec4(localPos, 1.0);\n' +
// --- START custom curve code
// ' float amountX = curveCameraDirection.x * pow(posW.x - curveCenterPos.x, 2.0);\n' +
// ' float amountY = curveCameraDirection.y * pow(posW.y - curveCenterPos.y, 2.0);\n' +
// ' float amountZ = curveCameraDirection.z * pow(posW.z - curveCenterPos.z, 2.0);\n' +
// ' float amountSum = (amountX * curveCameraDirection.x + amountY * curveCameraDirection.y + amountZ * curveCameraDirection.z) * curvePower;\n' +
// ' posW = posW + vec4(-amountX * curveCameraDirection.x * curvePower.x,-amountY * curveCameraDirection.y * curvePower.y,-amountZ * curveCameraDirection.z * curvePower.z,0);\n' +
// ' posW.x += -amountSum;\n' +
' float amountX = pow(posW.x - curveCenterPos.x, 2.0);\n' +
//' float amountY = pow(posW.y - curveCenterPos.y, 2.0);\n' +
' float amountZ = pow(posW.z - curveCenterPos.z, 2.0);\n' +
//' float amountSum = amountX + amountY + amountZ;\n' +
' float amountSum = amountX + amountZ;\n' +
' posW += vec4(curvePower.x, curvePower.y, curvePower.z, curvePower.w) * amountSum;\n' +
// --- END custom curve code
' #ifdef SCREENSPACE\n' +
' posW.zw = vec2(0.0, 1.0);\n' +
' #endif\n' +
' dPositionW = posW.xyz;\n' +
' vec4 screenPos;\n' +
' #ifdef UV1LAYOUT\n' +
' screenPos = vec4(vertex_texCoord1.xy * 2.0 - 1.0, 0.5, 1);\n' +
' #else\n' +
' #ifdef SCREENSPACE\n' +
' screenPos = posW;\n' +
' #else\n' +
' screenPos = matrix_viewProjection * posW;\n' +
' #endif\n' +
' #ifdef PIXELSNAP\n' +
' // snap vertex to a pixel boundary\n' +
' screenPos.xy = (screenPos.xy * 0.5) + 0.5;\n' +
' screenPos.xy *= uScreenSize.xy;\n' +
' screenPos.xy = floor(screenPos.xy);\n' +
' screenPos.xy *= uScreenSize.zw;\n' +
' screenPos.xy = (screenPos.xy * 2.0) - 1.0;\n' +
' #endif\n' +
' #endif\n' +
' return screenPos;\n' +
'}\n' +
'vec3 getWorldPosition() {\n' +
' return dPositionW;\n' +
'}\n';
material.update();
//console.log(material.chunks.transformVS);
this.updateShaderUniforms(material);
};
CurvedWorld.prototype.postUpdate = function () {
if (!this.materials) return;
this.materials.forEach(material => this.updateShaderUniforms(material));
};
CurvedWorld.prototype.updateShaderUniforms = function (material) {
this.activeCamera = this.app.root.findByName('Camera');
if(!this.activeCamera) return;
if(!this.activeCamera.followCamera) return;
//const targetPos = this.activeCamera.getPosition();
const targetPos = this.activeCamera.followCamera.followTarget.getPosition();
material.setParameter('curveCenterPos', [targetPos.x, targetPos.y, targetPos.z]);
};