Autor Wątek: Cone Step Mapping nieprawidłowe wyniki  (Przeczytany 559 razy)

Offline Glasgow

  • Użytkownik

# Kwiecień 20, 2017, 23:15:56
Próbuję zaimplementować Cone Step Mapping - korzystam z przykładowego kodu ze strony:
http://lonesock.net/files/ConeStepMapDemo.zip

Wynik działania programu:

Jak widać tekstury są zniekształcone.

Normalne:


Tessellation Evaluation Shader:
out vec2 esLocalCoord;
out vec3 esNormal;
out vec3 esTangent;

out vec3 esVert;
out vec3 esTextureSpaceVert;
out vec3 esTextureSpaceLightPos;
out float lightDist;
out float esDepth;
// ...

// funkcja main - pomijam nieistotne obliczenia
// ...

vec2 worldPos2D = interpolate2D();

// Wyliczam normalną, tangent, bitangent mając daną mapę wysokości.
height = texture(heightMap, vec3(esGlobalCoord, esIndexMap)).r * terrainInfo.w;

esLocalCoord = esGlobalCoord * 30.0;

vec3 off = vec3(1.0, 1.0, 0.0);
float hLeft = GetHeight(worldPos2D - off.xz);
float hRight = GetHeight(worldPos2D + off.xz);
float hFar = GetHeight(worldPos2D + off.zy);
float hNear = GetHeight(worldPos2D - off.zy);

esNormal.x = hLeft - hRight;
esNormal.y = hNear - hFar;
esNormal.z = 2.0;

esNormal = normalize(esNormal);
esTangent = normalize(vec3(1.0, 0.0, (hRight - hLeft) / 2.0));

esVert = vec3(worldPos2D.x, worldPos2D.y, height);
gl_Position  = vpMatrix * vec4(esVert, 1.0);


vec3 bitangent = normalize(cross(esTangent, esNormal));
esTextureSpaceVert = vec3(
dot(esTangent, gl_Position.xyz),
dot(bitangent, gl_Position.xyz),
dot(esNormal, gl_Position.xyz)
);

esTextureSpaceLightPos = vec3(
dot(esTangent, -light.position.xyz),
dot(bitangent, -light.position.xyz),
dot(esNormal, -light.position.xyz)
);
lightDist = length(esTextureSpaceLightPos);
//...


Fragment Shader:

#version 420

layout(early_fragment_tests) in;

const uint NUM_TEXTURES = 256;

const float depth = 0.3f;
const int conesteps = 50;
const float texSize = 512.0;

in vec2 esLocalCoord;
in vec3 esNormal;
in vec3 esTangent;

in vec3 esVert;
in vec3 esTextureSpaceVert;
in vec3 esTextureSpaceLightPos;
in float lightDist;
in float esDepth;

uniform sampler2DArray textures;
uniform sampler2DArray coneStepMap;

uniform uint textureID;
uniform int[NUM_TEXTURES] coneStepMapID;

out vec3 fragColor;

void intersect_square_cone_step (inout vec3 dp, in vec3 ds, in uint textureID)
{
float iz = max(abs(ds.x),abs(ds.y));
const float w = 1.2;
vec4 t;
dp += 0.3 * ds;

t = texture(coneStepMap, vec3(dp.xy, textureID));

dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);

t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);


t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
t = texture(coneStepMap, vec3(dp.xy, textureID));
dp += ds * w * (t.r - dp.z) / (iz/(t.g*t.g) + 1.0);
     
return;
}

vec3 ConeStepMapping(vec2 texCoord, uint textureID)
{
float a = -depth / esTextureSpaceVert.z;
vec3 s = esTextureSpaceVert * a;
s.z = 1.0;

vec3 pt_eye = vec3(texCoord, 0.0);
intersect_square_cone_step (pt_eye, s, coneStepMapID[textureID]);

vec4 c = texture(textures, vec3(pt_eye.xy, textureID));

vec4 t = texture(coneStepMap, vec3(pt_eye.xy, textureID));
t = vec4 ((t.ba-0.5) * (-depth * texSize), 1.0, 0.0);
t=normalize(t);

   // adjust the hit-position
   // (only useful if the light is near relative
   // to the depth)
   //p -= v*d*a;
   
   // compute attenuation
float att = 0.001;
att = min (1.0, 1.0 / (lightDist * att));

vec3 l = att * normalize(esTextureSpaceLightPos);

return vec3(0.34, 0.34, 0.34)*c.xyz
    + vec3(0.34, 0.34, 0.34) * c.xyz * max(0.0,dot(l,t.xyz));
}

void main () {
vec3 diffuseMap;
if(coneStepMapID[textureID] != -1)
diffuseMap = ConeStepMapping(esLocalCoord, textureID);
else
{
// inne obliczenia
}


fragColor = diffuseMap;
// <-
}

To są shadery mapy wysokości (terenu).
Wiele danych jak np. oświetlenie zostały wpisane na sztywno żeby spr. czy działa prawidłowo.
Obracając kamerę góra-dół obraz obraca się w boki (nie jak kamera góra-dół).
Co jest źle robione?



Z tymi samymi parametrami (tylko inna powierzchnia na której renderuję teksturę) program przykładowy wygląda tak:


« Ostatnia zmiana: Kwiecień 20, 2017, 23:21:13 wysłana przez Glasgow »

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Glasgow

  • Użytkownik

# Kwiecień 21, 2017, 14:08:09
Kosztowało mnie to nockę ale wreszcie się udało - myślałem, że eye space to po prostu normalne pomnożone przez transpose(inverse(mat3(Model_Matrix))), gdzie Model_Matrix jest jednostkowy - bo to teren, zatem mogę to pominąć.
Należało uwzględnić jednak nie Model_Matrix, a ModelView_Matrix oraz zanegować bitangent (dlaczego? nadal nie wiem :P).

To tak dla osób, które spotkałyby się z podobnym problemem - macie rozwiązanie na tacy.