Войти
ПрограммированиеФорумГрафика

SoftParticles: как вычислить - sceneZ c particleZ ?

#0
17:56, 5 дек. 2015

Пытаюсь сделать софтпартиклы по доке от NV (первый вариант) где на втором пассе юзается буффер глубины сцены,
а шейдер для партиклов сравнивает глубину партикла с восстановленной глубиной сцены.
На данный момент получилось следующее:


Видно не вооруженным глазом что при повороте камеры вокруг эмиттера - партиклы исчезают.
У меня какой-то косяк с вычислением "правильных глубин" - либо у сцены, либо у софтрартикла. Не могу понять что не так.

Самая суть шейдера:

#include "Uniforms.glsl"
#include "Samplers.glsl"
#include "Transform.glsl"
#include "ScreenPos.glsl"
#include "Fog.glsl"

varying vec2 vScreenPos;
varying vec2 vTexCoord;
varying vec4 vWorldPos;
varying vec3 vFarRay;
varying vec4 vPosProj;

#ifdef SP
    varying float vParticleViewProjZ;
#endif

void VS()
{
    mat4 modelMatrix = iModelMatrix;
    vec3 worldPos = GetWorldPos(modelMatrix);
    gl_Position = GetClipPos(worldPos);
    vPosProj = vec4(worldPos, 1.0) * cViewProj;
    vScreenPos = GetScreenPosPreDiv(gl_Position);
    vFarRay = GetFarRay(gl_Position);
    vTexCoord = GetTexCoord(iTexCoord);
    vWorldPos = vec4(worldPos, GetDepth(gl_Position));

    #ifdef VERTEXCOLOR
        vColor = iColor;
    #endif
    
    #ifdef SP
        vParticleViewProjZ = gl_Position.z;
        //vParticleViewProjZ = gl_Position.z / gl_Position.w; //NDC space [-1 1]
        //vParticleViewProjZ = GetDepth(gl_Position);
        //vParticleViewProjZ = gl_Position.w;
    #endif  
}

void PS()
{
...
            // VS :: vScreenPos = GetScreenPosPreDiv(gl_Position);
            float sceneZ = texture2D(sDepthBuffer, vScreenPos).r;   // read depthstencil texture(readabledepth)
            float restoredSceneZ = ReconstructDepth(sceneZ);        // to 0..1 range
            vec3 sceneWorldPos = vFarRay * restoredSceneZ;          // restore worldpos of backgroud sceneZ
            vec4 sceneViewPos = vec4(sceneWorldPos, 1.0) * cProj;   // restore viewproj of backgroud sceneZ
            
            
            float scale = 2.0; 
            // calc difference between sceneZ and particleZ 
            float diffZ = (sceneViewPos.z - vParticleViewProjZ) * scale;
            //float diffZ = (sceneViewPos.w - vWorldPos.z) * scale;  
            float input = clamp(diffZ, 0.0, 1.0);
            float contrastPower = 1.0;
            float output = 0.5 * pow(clamp(2*((input > 0.5) ? 1 - input : input), 0.0, 1.0), contrastPower);
            float weight = (input > 0.5) ? 1 - output : output; 
            
            diffColor.a *= weight;
            
            gl_FragColor = vec4(GetFog(diffColor.rgb, fogFactor), diffColor.a);
        #endif
    #endif
}


- Может кто делал свои софт партиклы, как вы восстанавливали глубину из текстуры и на какие матрицы умножали ?
- Вообще в каком пространстве должно идти сравнение (что-то мне подсказывает что в ViewProjection) ?
- Что нужно брать у текущего партикла в VS шейдере: vParticleViewProjZ = gl_Position.z; достаточно ?


 


#1
18:32, 5 дек. 2015
//--------------------------------------------------------------------------------------
// Pixel shader
//--------------------------------------------------------------------------------------
float4 PS_Particle( vertexOutput IN, float2 inScreenPos : VPOS ) : COLOR
{
  // screen uv
  float2 f2ScreenUV  = float2(  inScreenPos.x / g_ScreenSize.x + 0.5f / g_ScreenSize.x, 
                   inScreenPos.y / g_ScreenSize.y + 0.5f / g_ScreenSize.y );

  // depth for soft edges
  float fDepth    = IN.Depth.x / IN.Depth.y;
  // scene depth
  float fSceneDepth  = tex2D( SceneDepthSampler, f2ScreenUV ).r;
  
    float4 f4DepthViewSample = mul( float4( inScreenPos, fSceneDepth, 1 ), g_MatrixInvProj );
    float4 f4DepthViewParticle = mul( float4( inScreenPos, fDepth, 1 ), g_MatrixInvProj );
  
  float fDepthDiff = f4DepthViewSample.z/f4DepthViewSample.w - f4DepthViewParticle.z/f4DepthViewParticle.w;
            
  float fDepthFade = saturate( fDepthDiff / g_SoftData.x );
  // artefacts cleaning
  fDepthFade = fDepthDiff < -0.01f ? 1.0f : fDepthFade;

  // diffuse
  float4 TexColor = tex2D( DiffuseSampler, IN.TexCoord );
  
  if( IN.TexInterpolator >= 0.0f )
  {
    float4 TexColor2 = tex2D( DiffuseSampler, IN.TexCoord2 );

    TexColor = lerp( TexColor, TexColor2, IN.TexInterpolator );
  }

  // base color
  float4 Color = IN.Color * TexColor;
  // soft
  Color.a *= fDepthFade;

  // base color
//  float4 Color = float4( fDepth - fSceneDepth, 0.0f, 0.0f, 1.0f );

  return Color;
}

Я сравниваю в пространстве камеры, восстанавливаю дистанцию до камеры по матрице трансформации.

А что за среда разработки на видео?

#2
19:28, 5 дек. 2015

>float4 f4DepthViewParticle = mul( float4( inScreenPos, fDepth, 1 ), g_MatrixInvProj );
Интересно, а почему не брать в VS шейдре Z view позицию партикла(его же шейдер выполняется) и передавать через интерполятор?

Вот в этих двух значениях что передается IN.Depth.x / IN.Depth.y; ?

>А что за среда разработки на видео?
Редактор ухи - http://urho3d.github.io/

Спасибо за пример, буду пытаться через пространство камеры сравнивать.

#3
21:36, 5 дек. 2015

Вот так делается (глубина линейная)

out vec2      v_texCoord0;
out float      v_depth;
out  vec4      v_color;
uniform mat4    u_modelViewProjectionMatrix, u_modelViewMatrix;

layout(location = 0) in vec3 att_position;
layout(location = 4) in vec4 att_color4f;
layout(location = 5) in vec2 att_texCoordDiffuse;

void main (void) {
  v_texCoord0 = att_texCoordDiffuse;
  v_color = att_color4f;
  v_depth = -(u_modelViewMatrix * vec4(att_position, 1.0)).z;
  gl_Position = u_modelViewProjectionMatrix * vec4(att_position, 1.0);
}

in float    v_depth;
in vec4      v_color;
in vec2      v_texCoord0;

uniform sampler2D    u_map0;
uniform sampler2DRect  u_depthBufferMap;

uniform vec2      u_depthParms;
uniform vec2      u_mask;
uniform float      u_thickness;
uniform float      u_colorScale;



#include depth.inc

void main (void) {
  vec4 color = texture(u_map0, v_texCoord0);
  
  if(u_thickness > 0.0){
  // Z-feather
  float depth = DecodeDepth(texture2DRect(u_depthBufferMap, gl_FragCoord.xy).x, u_depthParms);
  float softness = clamp((depth - v_depth) / u_thickness, 0.0, 1.0);
  
  fragData = color * v_color * u_colorScale;
  fragData *= mix(vec4(1.0), vec4(softness), u_mask.xxxy);
  }
  else
  fragData = color * v_color;
}

#4
21:53, 5 дек. 2015

codingmonkey
> Вот в этих двух значениях что передается IN.Depth.x / IN.Depth.y; ?

  // world-space position
  OUT.Position  = mul( float4( f3Position, 1.0f ), f4x4Transform );
  // view-space position
  OUT.Position  = mul( OUT.Position, g_MatrixViewProj );
  // depth coordinate
    OUT.Depth.xy   = OUT.Position.zw;

Глубину подгоняем под [0;1] в VS. Почему сразу в VS не считаю, даже и не вспомню, может что от отладки осталось. Падения скорости тут не заметишь все равно.

ПрограммированиеФорумГрафика

Тема в архиве.