2014-09-30 24 views
7

Coğrafi eşlemeli bir arazi oluşturuyorum. Şimdiye kadar gayet iyi çalışıyor. Kameranın yakınındaki arazi eğimi çok yüksektir ve geometri daha da uzaklaştıkça azalır. Arazinin geometrisi esas olarak kamerayı takip eder ve köşe noktalarının konumuna bağlı olarak bir yükseklik haritası oluşturur. Geometri mozaikleme çok yüksek olduğu için, örneklendiğinde dokudaki her pikseli zaman zaman görebilirsiniz. Açık piksel vuruşları yaratır. Bu sayede heightmap'in örneklemesini yumuşatabilirim. Ancak, bazı bilinear örnekleme kodlarıyla ilgili garip bir problemim var gibi görünüyor. Her tepe noktasının bir yükseklik haritasına göre yer değiştirmesiyle arazi oluşturuyorum.GLSL Vertex shader doğrusal olmayan örnekleme heightmap

üretir
vec2 worldToMapSpace(vec2 worldPosition) { 
    return (worldPosition/worldScale + 0.5); 
} 

float getHeight(vec3 worldPosition) 
{ 
     #ifdef USE_HEIGHTFIELD 
     vec2 heightUv = worldToMapSpace(worldPosition.xz); 
     vec2 tHeightSize = vec2(HEIGHTFIELD_SIZE_WIDTH, HEIGHTFIELD_SIZE_HEIGHT); //both 512 
     vec2 texel = vec2(1.0/tHeightSize); 
     //float coarseHeight = texture2DBilinear(heightfield, heightUv, texel, tHeightSize).r; 
     float coarseHeight = texture2D(heightfield, vUv).r; 
     return altitude * coarseHeight + heightOffset; 
    #else 
     return 0.0; 
    #endif 
} 

bu (her pikseli nasıl görebilirim dikkat edin):

İşte enter image description here

bir tel kafes olan belirli bir UV bir tepe yüksekliğini almak için kullanabilirim koordinat:

enter image description here

Ben arazi yumuşak örnekleme yapmak istedi. Bu yüzden standart texture2D işlevi yerine bazı doğrusal örneklemeyi kullanabileceğimi düşündüm. Bu yüzden burada iki-doğrusal örnekleme fonksiyonudur:

texelSize 1/heightmap boyutu olarak hesaplanır
vec4 texture2DBilinear(sampler2D textureSampler, vec2 uv, vec2 texelSize, vec2 textureSize) 
{ 
    vec4 tl = texture2D(textureSampler, uv); 
    vec4 tr = texture2D(textureSampler, uv + vec2(texelSize.x, 0.0)); 
    vec4 bl = texture2D(textureSampler, uv + vec2(0.0, texelSize.y)); 
    vec4 br = texture2D(textureSampler, uv + vec2(texelSize.x, texelSize.y)); 
    vec2 f = fract(uv.xy * textureSize); // get the decimal part 
    vec4 tA = mix(tl, tr, f.x); 
    vec4 tB = mix(bl, br, f.x); 
    return mix(tA, tB, f.y); 
} 

:

vec2 texel = vec2(1.0/tHeightSize); 

ve textureSize heightmap genişliği ve yüksekliği. ? Ben bu işlevi kullandığınızda, ancak bu sonuç almak:? Şimdi ben yanlış yapıyor Veya nasıl daha düzgün bir arazi örnekleme alabilirsiniz ne olabileceğini kötü :(Herhangi fikirleri görünüyor

float coarseHeight = texture2DBilinear(heightfield, heightUv, texel, tHeightSize).r; 

enter image description here

İşte DÜZENLEME

arazi bakıyor dikey görüntü var. Sen katmanları iyi çalışır görebilirsiniz. Uyarı ancak daha az nirengi sahip dış katmanları ve daha yüksek tessellasyona sahip olanlar her pikseli gösterirken daha pürüzsüz görünün. Doku örneklemesini düzeltmek için bir yol bulmaya çalışıyorum. enter image description here

+0

Neden ilk başta özel bir çift yönlü enterpolasyon kullanıyorsunuz? Her bir tepe noktasının yükseklik haritasında bir piksel varsa, 'pürüzsüz' hale getirmek için dokuda bir Gauss-Blur kullanmalısınız. Piksellerden daha fazla noktanız varsa, dahili doku enterpolasyonu işi yapar. – dari

+0

Merhaba dari, Soruyu açıklığa kavuşturmak zorundayım. Nedeni bir geoclipmapping tekniği kullanıyorum çünkü. Kameranın yakınındaki arazi çok yüksek bir mozaikleme. Tessellasyon çok yüksek olduğu için, piksellerden daha fazla üçgen var. Yani onun 1 ila 1 oranı değil. Örneğin, örneklemenin daha ince olması ya da piksel değerleri arasında enterpolasyona ihtiyacı vardır. – Mat

+0

Ve neden enterpolasyonda yapıyı kullanmıyorsunuz? https: //www.opengl.org/wiki/Sampler_Object # Sampling_parameters – dari

cevap

3

enter image description here

ı bulup catmulrom interpolasyon kullanan bir tekniği uygulamak başardı. Kod aşağıda.

// catmull works by specifying 4 control points p0, p1, p2, p3 and a weight. The function is used to calculate a point n between p1 and p2 based 
// on the weight. The weight is normalized, so if it's a value of 0 then the return value will be p1 and if its 1 it will return p2. 
float catmullRom(float p0, float p1, float p2, float p3, float weight) { 
    float weight2 = weight * weight; 
    return 0.5 * (
     p0 * weight * ((2.0 - weight) * weight - 1.0) + 
     p1 * (weight2 * (3.0 * weight - 5.0) + 2.0) + 
     p2 * weight * ((4.0 - 3.0 * weight) * weight + 1.0) + 
     p3 * (weight - 1.0) * weight2); 
} 

// Performs a horizontal catmulrom operation at a given V value. 
float textureCubicU(sampler2D samp, vec2 uv00, float texel, float offsetV, float frac) { 
    return catmullRom(
     texture2DLod(samp, uv00 + vec2(-texel, offsetV), 0.0).r, 
     texture2DLod(samp, uv00 + vec2(0.0, offsetV), 0.0).r, 
     texture2DLod(samp, uv00 + vec2(texel, offsetV), 0.0).r, 
     texture2DLod(samp, uv00 + vec2(texel * 2.0, offsetV), 0.0).r, 
    frac); 
} 

// Samples a texture using a bicubic sampling algorithm. This essentially queries neighbouring 
// pixels to get an average value. 
float textureBicubic(sampler2D samp, vec2 uv00, vec2 texel, vec2 frac) { 
    return catmullRom(
     textureCubicU(samp, uv00, texel.x, -texel.y, frac.x), 
     textureCubicU(samp, uv00, texel.x, 0.0, frac.x), 
     textureCubicU(samp, uv00, texel.x, texel.y, frac.x), 
     textureCubicU(samp, uv00, texel.x, texel.y * 2.0, frac.x), 
    frac.y); 
} 

    // Gets the UV coordinates based on the world X Z position 
    vec2 worldToMapSpace(vec2 worldPosition) { 
     return (worldPosition/worldScale + 0.5); 
    } 


// Gets the height at a location p (world space) 
float getHeight(vec3 worldPosition) 
{ 
    #ifdef USE_HEIGHTFIELD 

     vec2 heightUv = worldToMapSpace(worldPosition.xz); 
     vec2 tHeightSize = vec2(HEIGHTFIELD_WIDTH, HEIGHTFIELD_HEIGHT); 

     // If we increase the smoothness factor, the terrain becomes a lot smoother. 
     // This is because it has the effect of shrinking the texture size and increaing 
     // the texel size. Which means when we do sampling the samples are from farther away - making 
     // it smoother. However this means the terrain looks less like the original heightmap and so 
     // terrain picking goes a bit off. 
     float smoothness = 1.1; 
     tHeightSize /= smoothness; 

     // The size of each texel 
     vec2 texel = vec2(1.0/tHeightSize); 

     // Find the top-left texel we need to sample. 
     vec2 heightUv00 = (floor(heightUv * tHeightSize))/tHeightSize; 

     // Determine the fraction across the 4-texel quad we need to compute. 
     vec2 frac = vec2(heightUv - heightUv00) * tHeightSize; 

     float coarseHeight = textureBicubic(heightfield, heightUv00, texel, frac); 
     return altitude * coarseHeight + heightOffset; 
    #else 
     return 0.0; 
    #endif 
} 
+0

Bu kullanışlı! Teşekkürler. Sonucu (görüntü) paylaşır mısınız? – Nolesh