Зеленый хромированный ключевой шейдер, использующий глубину

#unity3d #gpu #shader #fragment-shader

#unity3d #графический процессор #шейдер #фрагмент-шейдер

Вопрос:

Я написал шейдер, который преобразует значение камеры RGB в HSV, а затем применяет некоторую фильтрацию для зеленого хрома. Текущая проблема

  1. Если объект на переднем плане (проигрыватель) имеет зеленые пиксели, он будет вырезан.

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

    фрагмент (v2f i): SV_Target { fixed4 col = tex2D(_MainTex, i.uv);

                  if (_ShowBackground)
                 {
                     fixed4 col2 = tex2D(_TexReplacer, i.uv);
                     col = col2;
                 }
                 else if (!_ShowOriginal)
                 {
                     fixed4 col2 = tex2D(_TexReplacer, i.uv);
    
                     float maskY = 0.2989 * _GreenColor.r   0.5866 * _GreenColor.g   0.1145 * _GreenColor.b;
                     float maskCr = 0.7132 * (_GreenColor.r - maskY);
                     float maskCb = 0.5647 * (_GreenColor.b - maskY);
    
                     float Y = 0.2989 * col.r   0.5866 * col.g   0.1145 * col.b;
                     float Cr = 0.7132 * (col.r - Y);
                     float Cb = 0.5647 * (col.b - Y);
    
                     float alpha = smoothstep(_Sensitivity, _Sensitivity   _Smooth, distance(float2(Cr, Cb), float2(maskCr, maskCb)));
    
                     col = (alpha * col)   ((1 - alpha) * col2);
                 }
                 return col;
             }
      

Комментарии:

1. Обратите внимание, что вам следует избегать if else операторов в шейдере. Вы можете использовать step(...) для этой цели.

Ответ №1:

Unity UnityObjectToClipPos(float3 pos) позволяет преобразовать вершину в пространство клипа. Это означает 0 1 , что по всем осям ось z — это расстояние от камеры рендеринга (я полагаю, от ближней к дальней плоскости отсечения).

Вы можете использовать это расстояние, чтобы просто применять ввод только к вершинам, расположенным дальше заданного порога.

Если вы не хотите использовать нормализованные координаты, вы также можете преобразовать свою вершину в мировое пространство, используя mul(unity_ObjectToWorld, vertex.position) , а затем в пространство камеры, умножив положение в мире с миром камеры на локальную матрицу (которую вы должны передать в свой шейдер).

Чтобы получить доступ к текстуре глубины камеры в шейдере, вы можете использовать _CameraDepthTexture (см. Документацию https://docs.unity3d.com/Manual/SL-CameraDepthTexture.html переменные шейдера раздела). Вы можете попробовать его, как и любую другую текстуру, используя tex2D(_CameraDepthTexture, i.uv);

Комментарии:

1. У меня уже есть камера глубины, можете ли вы объяснить, как это связано с вашим ответом? Извините, я в замешательстве

2. Спасибо, можете ли вы показать мне псевдокод, например, если я могу получить пиксели глубины из функции в шейдере, которая мне ее дает, как я могу использовать фрагментарный шейдер для удаления пикселей с порогового расстояния?

3. Вы просто используете if(currentDepth <= threshold) return originalColor; else return modifiedColor;