SceneKit SCNTechnique в сочетании с ошибкой отложенных бросков затенения - PullRequest
0 голосов
/ 30 января 2019

Проблема

Я создал минимальный проект SceneKit со сценой, которая содержит сферу, плоскость и один направленный источник света.Направленный свет отбрасывает тени, и для shadowMode установлено значение deferred.Все работает как надо.Сцена освещена, и сфера отбрасывает тень на плоскость.

Когда я устанавливаю минимальное наложение цвета SCNTechnique и назначаю его для свойства SCNView technique, консоль заливается этимсообщение:

[SceneKit] Error: Pass DeferredShadow is not linked to the rendering graph and will be ignored check it's input/output

Тем не менее, техника работает и отображает наложение цвета и тень:

The rendered scene

Когда я фиксирую кадр в отладчике шейдеров, все выглядит нормально:

The rendering graph

В Навигаторе отладки также нет ничего очевидного:

The debug navigator

Вопрос

Есть ли что-то очевидное, что я упускаю?Визуально все работает, но я хотел бы знать, пропустил ли я важный шаг или нет, чтобы предотвратить возникновение этой ошибки.

PS Я знаю, что тот же результат может быть достигнут с модификатором шейдера, но я хочуиспользуйте SCNTechnique для создания эффектов постобработки.

Код

Вот краткий обзор важных битов.Если вы хотите запустить пример, вы можете клонировать репозиторий GitHub .

Вот как настраиваются SCNView и directional SCNLight:

view.allowsCameraControl = true
view.showsStatistics = true
view.backgroundColor = UIColor.black

let dirLight = SCNLight()
dirLight.type = .directional
dirLight.castsShadow = true
dirLight.shadowMode = .deferred
dirLight.shadowColor = UIColor.black.withAlphaComponent(0.75)

let dirLightNode = SCNNode()
dirLightNode.light = dirLight
dirLightNode.eulerAngles = SCNVector3(-Float.pi / 2, 0, 0)

Техника имеет два прохода.Один, который рисует наложение цвета на объекты, для которого categoryBitmask установлено значение 2, а другой другой проход, который рисует всю сцену к цели цветопередачи.Это файл .plist этой техники:

<dict>
    <key>passes</key>
    <dict>
        <key>pass_draw_overlay</key>
        <dict>
            <key>draw</key>
            <string>DRAW_SCENE</string>
            <key>program</key>
            <string></string>
            <key>metalVertexShader</key>
            <string>colour_overlay_vertex</string>
            <key>metalFragmentShader</key>
            <string>colour_overlay_fragment</string>
            <key>includeCategoryMask</key>
            <string>2</string>
            <key>inputs</key>
            <dict>
                <key>colorSampler</key>
                <string>COLOR</string>
            </dict>
            <key>outputs</key>
            <dict>
                <key>color</key>
                <string>OVERLAY</string>
            </dict>
        </dict>
        <key>pass_combine</key>
        <dict>
            <key>colorStates</key>
            <dict>
                <key>clear</key>
                <false/>
            </dict>
            <key>inputs</key>
            <dict>
                <key>colorSampler</key>
                <string>COLOR</string>
                <key>overlaySampler</key>
                <string>OVERLAY</string>
            </dict>
            <key>outputs</key>
            <dict>
                <key>color</key>
                <string>COLOR</string>
            </dict>
            <key>metalFragmentShader</key>
            <string>combine_fragment</string>
            <key>metalVertexShader</key>
            <string>combine_vertex</string>
            <key>program</key>
            <string></string>
            <key>draw</key>
            <string>DRAW_QUAD</string>
        </dict>
    </dict>
    <key>sequence</key>
    <array>
        <string>pass_draw_overlay</string>
        <string>pass_combine</string>
    </array>
    <key>targets</key>
    <dict>
        <key>OVERLAY</key>
        <dict>
            <key>type</key>
            <string>color</string>
        </dict>
    </dict>
</dict>

Используемые металлические шейдеры:

vertex VertexOut colour_overlay_vertex(VertexIn in [[stage_in]],
                                  constant CustomNode& scn_node [[buffer(0)]])
{
    VertexOut out;
    out.position = scn_node.modelViewProjectionTransform * float4(in.position.xyz, 1.0);
    return out;
};

fragment half4 colour_overlay_fragment(VertexOut in [[stage_in]],
                                  texture2d<float, access::sample> colorSampler [[texture(0)]])
{
    return half4(0.0, 1.0, 0.0, 1.0);
};

vertex VertexOut combine_vertex(VertexIn in [[stage_in]],
                                constant SCNSceneBuffer& scn_frame [[buffer(1)]])
{
    VertexOut out;
    out.position = in.position;
    out.uv = float2( (in.position.x + 1.0) * 0.5, 1.0 - (in.position.y + 1.0) * 0.5 );
    return out;
};

fragment half4 combine_fragment(VertexOut vert [[stage_in]],
                                texture2d<float, access::sample> colorSampler [[texture(0)]],
                                texture2d<float, access::sample> overlaySampler [[texture(1)]])
{
    float4 fragmentColor = colorSampler.sample(s, vert.uv);
    float4 overlayColor = overlaySampler.sample(s, vert.uv);

    if (overlayColor.g < 1.0 ) {
        return half4(fragmentColor);
    }

    return half4(overlayColor);
}
...