playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF
https://playcanvas.com
MIT License
9.54k stars 1.33k forks source link

Shadow map bug #6874

Open AlexAPPi opened 1 month ago

AlexAPPi commented 1 month ago

In continuation of the solution to the problem: https://forum.playcanvas.com/t/shadow-calculation-coordinates-buffered/36196/4

I made a demo project demonstrating the problem: https://playcanvas.com/editor/scene/2046017

image

    _updateMaterialDefaultCoord() {

        if (this._material) {

            // Set default parameters which must be re-erased after pc.MeshInstance
            const defaultCoordOffset = this[defaultCoordOffsetAttrName];

            this._material.setParameter(coordXOffsetUniformName, defaultCoordOffset.x);
            this._material.setParameter(coordZOffsetUniformName, defaultCoordOffset.y);
        }
    }
    _initMaterial() {

        this._material = new pc.StandardMaterial();
        this._material.name = "Grid Material";
        this._material.chunks['transformVS'] = transformVS;

        this._updateMaterialDefaultCoord();
        this._updateMaterialCoordFactor();

        this._material.update();
    }

    _createPatch(graphicsDevice, x, z) {

        const patchMesh = new pc.Mesh.fromGeometry(graphicsDevice, new pc.BoxGeometry());
        const patchMeshInstance = new pc.MeshInstance(patchMesh, this._material);

        // Update shader uniforms
        // BUG: This doesn't work for shadow maps.
        patchMeshInstance.setParameter(coordXOffsetUniformName, x);
        patchMeshInstance.setParameter(coordZOffsetUniformName, z);

        return patchMeshInstance;
    }
     const transformVS = /** glsl */ `

    uniform float ${coordXOffsetUniformName};
    uniform float ${coordZOffsetUniformName};
    uniform float ${coordFactorOffsetUniformName};

    mat4 getModelMatrix() {
        return matrix_model;
    }

    vec4 getPosition() {

        dModelMatrix  = getModelMatrix();

        // append offset to local pos
        vec3 localPosOffset = vec3(${coordXOffsetUniformName} * ${coordFactorOffsetUniformName}, 0.0, ${coordZOffsetUniformName} * ${coordFactorOffsetUniformName});
        vec3 localPos = vertex_position + localPosOffset;
        vec4 posW = dModelMatrix * vec4(localPos, 1.0);
        vec4 screenPos = matrix_viewProjection * posW;

        dPositionW = posW.xyz;

        return screenPos;
    }

    vec3 getWorldPosition() {
        return dPositionW;
    }
`;
mvaligursky commented 3 weeks ago

To investigate this, please capture the frame with the SpectorJS, check the individual draw calls - make sure the uniforms values for draw calls are what you'd expect, and check the shader to see what happens with those. Considering you have shadow rendering issues with those, focus on looking at those draw calls.

AlexAPPi commented 1 day ago

To investigate this, please capture the frame with the SpectorJS, check the individual draw calls - make sure the uniforms values for draw calls are what you'd expect, and check the shader to see what happens with those. Considering you have shadow rendering issues with those, focus on looking at those draw calls.

When building a shadow map, updated parameter values ​​are not updated in the uniform.

image image image

mvaligursky commented 1 day ago

It's possible I fixed it here: https://github.com/playcanvas/engine/pull/6898/files#diff-b626bc502815d9db1afa6dd7c8573d4f59943982f3a723b426edbfaf1555f8b4

try passing 0xFFFFFFFF as a third parameter to MeshInstance.setParameter. As the original default value stands, it'd only use that value for the forward pass.

AlexAPPi commented 10 hours ago

Возможно, я исправил это здесь: https://github.com/playcanvas/engine/pull/6898/files#diff-b626bc502815d9db1afa6dd7c8573d4f59943982f3a723b426edbfaf1555f8b4

передать 0xFFFFFFFF в качестве третьего параметра в MeshInstance.setParameter. Исходное значение по умолчанию будет использоваться только для прямого прохода.

image

Great! It works!