Пытаюсь сделать софтпартиклы по доке от 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; достаточно ?
//-------------------------------------------------------------------------------------- // 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; }
Я сравниваю в пространстве камеры, восстанавливаю дистанцию до камеры по матрице трансформации.
А что за среда разработки на видео?
>float4 f4DepthViewParticle = mul( float4( inScreenPos, fDepth, 1 ), g_MatrixInvProj );
Интересно, а почему не брать в VS шейдре Z view позицию партикла(его же шейдер выполняется) и передавать через интерполятор?
Вот в этих двух значениях что передается IN.Depth.x / IN.Depth.y; ?
>А что за среда разработки на видео?
Редактор ухи - http://urho3d.github.io/
Спасибо за пример, буду пытаться через пространство камеры сравнивать.
Вот так делается (глубина линейная)
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;
}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 не считаю, даже и не вспомню, может что от отладки осталось. Падения скорости тут не заметишь все равно.
Тема в архиве.