2013-08-15 15 views
7

Normal bir haritalama sorunum var. ASSIMP kütüphanesi ile yüklenen her modelde bir doku ve normal bir doku var. Her nesne üzerindeki teğet vektörleri ASSIMP kütüphanesinin yardımıyla hesaplıyorum, bu yüzden bunlar iyi olmalı. Nesneler normal haritalama ile mükemmel şekilde çalışır, ancak nesnelerden birini çevirmeye başladığımda (bu nedenle Model matrisi çevirilerle etkiler) ışıklandırma başarısız olur. Görüntünün üzerinde gördüğünüz gibi, (y eksenine çevrilmiş olan) zemin, dağınık ışığının çoğunu kaybediyor gibi görünüyor ve onun speküler ışığı yanlış yönde (ampul ve oyuncu pozisyonu arasında olmalıdır)Normal Haritalama ve çeviri aydınlatmamı bozuyor

Normal mapping gone wrong

O (çeviriler kaybolmuş olmalıdır rağmen) Normal matris ile bir ilgisi olabilir, shader kullanılan bir yanlış matris ile belki bir şeyler. Düşüncelerim tükeniyor ve bu konuyla ilgili biraz bilgi verebileceğinizi umuyordum.

Vertex Shader:

#version 330 

layout(location = 0) in vec3 position; 
layout(location = 1) in vec3 normal; 
layout(location = 2) in vec3 tangent; 
layout(location = 3) in vec3 color; 
layout(location = 4) in vec2 texCoord; 

// fragment pass through 
out vec3 Position; 
out vec3 Normal; 
out vec3 Tangent; 
out vec3 Color; 
out vec2 TexCoord; 

out vec3 TangentSurface2Light; 
out vec3 TangentSurface2View; 

uniform vec3 lightPos; 
uniform vec3 playerPos; 

// vertex transformation 
uniform mat4 model; 
uniform mat4 view; 
uniform mat4 projection; 

void main() 
{ 
    mat3 normalMatrix = mat3(transpose(inverse(model))); 
    Position = vec3(model * vec4(position, 1.0)); 
    Normal = normalMatrix * normal; 
    Tangent = tangent; 
    Color = color; 
    TexCoord = texCoord; 

    gl_Position = projection * view * model * vec4(position, 1.0); 

    // Calculate tangent matrix and calculate fragment bump mapping coord space. 
    vec3 light = lightPos; 
    vec3 n = normalize(normalMatrix * normal); 
    vec3 t = normalize(normalMatrix * tangent); 
    vec3 b = cross(n, t); 
    // create matrix for tangent (from vertex to tangent-space) 
    mat3 mat = mat3(t.x, b.x ,n.x, t.y, b.y ,n.y, t.z, b.z ,n.z); 
    vec3 vector = normalize(light - Position); 
    TangentSurface2Light = mat * vector; 
    vector = normalize(playerPos - Position); 
    TangentSurface2View = mat * vector; 
} 

Fragman Shader

#version 330 

in vec3 Position; 
in vec3 Normal; 
in vec3 Tangent; 
in vec3 Color; 
in vec2 TexCoord; 

in vec3 TangentSurface2Light; 
in vec3 TangentSurface2View; 

out vec4 outColor; 

uniform vec3 lightPos; 
uniform vec3 playerPos; 
uniform mat4 view; 
uniform sampler2D texture0; 
uniform sampler2D texture_normal; // normal 

uniform float repeatFactor = 1; 

void main() 
{ 
    vec4 texColor = texture(texture0, TexCoord * repeatFactor); 
    vec4 matColor = vec4(Color, 1.0); 
    vec3 light = vec3(vec4(lightPos, 1.0)); 
    float dist = length(light - Position); 
    // float att = 1.0/(1.0 + 0.01 * dist + 0.001 * dist * dist); 
    float att = 1.0; 
    // Ambient 
    vec4 ambient = vec4(0.2); 
    // Diffuse 
    // vec3 surface2light = normalize(light - Position); 
    vec3 surface2light = normalize(TangentSurface2Light); 
    // vec3 norm = normalize(Normal); 
    vec3 norm = normalize(texture(texture_normal, TexCoord * repeatFactor).xyz * 2.0 - 1.0); 
    float contribution = max(dot(norm, surface2light), 0.0); 
    vec4 diffuse = contribution * vec4(0.6); 
    // Specular 
    // vec3 surf2view = normalize(-Position); // Player is always at position 0 
    vec3 surf2view = normalize(TangentSurface2View); 
    vec3 reflection = reflect(-surface2light, norm); // reflection vector 
    float specContribution = pow(max(dot(surf2view, reflection), 0.0), 32); 
    vec4 specular = vec4(1.0) * specContribution; 

    outColor = (ambient + (diffuse * att)+ (specular * pow(att, 3))) * texColor; 
    // outColor = vec4(Color, 1.0) * texture(texture0, TexCoord); 
} 

DÜZENLEME

yerine dünya ve kamera uzay arasında pingponging dünya uzayda her şeyi (kolay hesaplamak için gölgelendirici kodunu Düzenlendi anlamak ve daha az hata eğilimli).

+0

** Sormak için yanlış yer. ** Muhtemelen * son derece şanslı olmadıkça, muhtemelen cevap alamazsınız. Http://gamedev.stackexchange.com adresinden veya http://www.gamedev.net adresinden sorun. –

+0

@TheOtherGuy: Öneriniz için teşekkürler.Orada da yayınlamaya çalışacağım, çünkü bu oyunla yakından alakalı. Muhtemelen daha fazla şansımız olacak :) –

+1

Pekala, iyi şanslar! –

cevap

4

Matrislerle tuhaf işlemler yapıyorsunuz. VS'de ters görünüm dünyasında normal (model-alan) dönüşürsünüz. Bu hiç mantıklı değil. Dünya uzayında hesaplamaları yapmak daha kolay olabilir. Bazı örnek çalışma kodum var, ama biraz farklı adlandırma kullanıyor.

Vertex Shader: Burada projeksiyon (ekran) ile uzay için pozisyon dönüşümü

void main_vs(in A2V input, out V2P output) 
{ 
    output.position = mul(input.position, _worldViewProjection); 
    output.normal = input.normal; 
    output.binormal = input.binormal; 
    output.tangent = input.tangent; 
    output.positionWorld = mul(input.position, _world); 
    output.tex = input.tex; 
} 

, TBN model uzayda bırakılır, daha sonra kullanılacaktır. Ayrıca aydınlatma değerlendirmesi için dünya-uzay pozisyonu elde ediyoruz.

Pixel Shader: Burada

void main_ps(in V2P input, out float4 output : SV_Target) 
{ 
    float3x3 tbn = float3x3(input.tangent, -input.binormal, input.normal); 

    //extract & decode normal: 
    float3 texNormal = _normalTexture.Sample(_normalSampler, input.tex).xyz * 2 - 1; 

    //now transform TBN-space texNormal to world space: 
    float3 normal = mul(texNormal, tbn); 
    normal = normalize(mul(normal, _world)); 

    float3 lightDirection = -_lightPosition.xyz;//directional 
    float3 viewDirection = normalize(input.positionWorld - _camera); 
    float3 reflectedLight = reflect(lightDirection, normal); 

    float diffuseIntensity = dot(normal, lightDirection); 
    float specularIntensity = max(0, dot(reflectedLight, viewDirection)*1.3); 

    output = ((_ambient + diffuseIntensity * _diffuse) * _texture.Sample(_sampler, input.tex) 
     + pow(specularIntensity, 7) * float4(1,1,1,1)) * _lightColor; 
} 

Ben yönlü ışık kullanmak, sen öncelikle doku normal olması İşte

float3 lightDirection = normalize(input.positionWorld - _lightPosition.xyz);//omni 

böyle bir şey yapmak gerektiğini TBN-uzayda olduğunu. Daha sonra, model uzayına dönüştürmek için TBN matrisini uyguluyoruz. Sonra dünya uzay bunu dönüştürmeye Dünya matrisi uygulamak, zaten yukarıda ommitted vb

ışık pozisyonu, göz, diğer bazı gölgelendirici kodu var idi (DX11, ancak çevirmek kolaydır):

cbuffer ViewTranforms 
{ 
    row_major matrix _worldViewProjection; 
    row_major matrix _world; 
    float3 _camera; 
}; 

cbuffer BumpData 
{ 
    float4 _ambient; 
    float4 _diffuse; 
}; 

cbuffer Textures 
{ 
    texture2D _texture; 
    SamplerState _sampler; 

    texture2D _normalTexture; 
    SamplerState _normalSampler; 
}; 

cbuffer Light 
{ 
    float4 _lightPosition; 
    float4 _lightColor; 
}; 

//------------------------------------ 

struct A2V 
{ 
    float4 position : POSITION; 
    float3 normal : NORMAL; 
    float3 binormal : BINORMAL; 
    float3 tangent : TANGENT; 
    float2 tex : TEXCOORD; 
}; 

struct V2P 
{ 
    float4 position : SV_POSITION; 
    float3 normal : NORMAL; 
    float3 binormal : BINORMAL; 
    float3 tangent : TANGENT; 
    float3 positionWorld : NORMAL1; 
    float2 tex : TEXCOORD; 
}; 

Ayrıca, burada önceden hesaplanmış binormal kullanıyorum: kodunuzu bırakacaksınız, bunu hesaplar (çapraz (normal, teğet) yoluyla). Bu yardımcı olur umarım.

+0

Bazı gölgelendirici kodlarını gönderdiğiniz için teşekkürler, normal haritalama hesaplamalarındaki farklılıkları bulmama yardımcı olabilir. Ancak, vertex gölgelendiricide normal vektörlerinizde normalMatrix hesaplarını göremiyorum. AFAIK normal bir matris (translasyon bileşeni olmayan model (görünüm) matrisinin ters-ters matrisi) kullanmalı mıyım yoksa bir şeyleri mi özlüyorum? Şu anda normal matris için Model AND görünümü bileşenini kullanıyorum, ancak hala sadece model veya modelviewmatrix olması gerektiğinden emin değilim (modelviewmatrix çeviri yapılmadığında iyi sonuçlar sağlar, modelde bulunmuyor). –

+0

Yorumum çok uzun, bu yüzden onu böleceğim. Anlıyor musunuz, NEDEN M (V) matrisine ihtiyacınız var? Açıklamaya çalıştığım şey, farklı alanlarda (dünya, model, TBN, görünüm veya hatta ekran) hesaplamaları gerçekleştirebilmenizdir. Bunu yapmak için verilerinizi dönüştürmeniz gerekir, böylece tüm bileşenler (göz, ışık yönü, köşe noktası vb.) Aynı alanda veya çöplere geri dönecektir. – Celestis

+0

Örnek: Dünya uzayında ışık var ve bir köşe ve model alanında normal. Dağınık ışıklandırmayı hesaplamak için ne yaparsınız? Hem normal hem de vertex'i model matrisi ile çarpın - bu, modelden dünya uzayına normal ve vertex dönüşür. Sadece o zaman nokta yaparsın (hafif, normal). Ters dönüşüm onu ​​geriye doğru yapar. Işık modelini ters model matriksiyle çarparak, ışığı dünyadan model-mekana dönüştürebilirsiniz. Tüm değerleri hesaplamak için sadece farklı alan. – Celestis

İlgili konular