2017-10-01 2 views
1

: 나는 확산 조명을 구현하기 위해 노력하고 있어요,하지만 난 뭔가를 이해하고 있지 않다 ... 생각하고, 내가 제대로 계산하고 있다면 몰라 https://www.gamasutra.com/view/feature/131275/implementing_lighting_models_with_.php?page=2다이렉트 X 11 확산 조명 구현

.

큐브의 정점 정보는 다음

SimpleVertex vertices[] = 
     { 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 

      { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, -1.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 

      { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(-1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 

      { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(1.0f, 0.0f, 0.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 

      { DirectX::XMFLOAT3(-1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, -1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, -1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, -1.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 

      { DirectX::XMFLOAT3(-1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(1.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, -1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(0.0f, 1.0f) }, 
      { DirectX::XMFLOAT3(1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(0.0f, 0.0f) }, 
      { DirectX::XMFLOAT3(-1.0f, 1.0f, 1.0f), DirectX::XMFLOAT3(0.0f, 0.0f, 1.0f), DirectX::XMFLOAT2(1.0f, 0.0f) }, 
     }; 

버텍스 쉐이더는 :

cbuffer ConstantBuffer : register(b0) 
{ 
    matrix World; 
    matrix View; 
    matrix Projection; 
    float4 vMeshColor; 
}; 

struct VS_INPUT 
{ 
    float4 Position : POSITION; 
    float3 Normal : NORMAL; 
    float2 Texture : TEXCOORD0; 
}; 

struct PS_INPUT 
{ 
    float4 Position : SV_POSITION; 
    float3 Normal : TEXCOORD0; 
    float2 Texture : TEXCOORD1; 
}; 

PS_INPUT VS(VS_INPUT input) 
{ 
    PS_INPUT output = (PS_INPUT)0; 

    output.Position = mul(input.Position, World); 
    output.Position = mul(output.Position, View); 
    output.Position = mul(output.Position, Projection); 

    output.Normal = mul(input.Normal, World); 
    output.Normal = mul(output.Normal, View); 
    output.Normal = mul(output.Normal, Projection); 
    output.Normal = normalize(output.Normal); 

    output.Texture = input.Texture; 

    return output; 
} 

화소이다

PS_OUTPUT PS(PS_INPUT input) 
{ 
    PS_OUTPUT output; 
    float4 ambient = {0.1, 0.0, 0.0, 1.0}; 
    float4 lightColor = { 1.0f, 1.0f, 1.0f, 1.0f}; 

    float3 lightPosition = (1.0f, 1.0f, 0.0f); 
    float3 lightDirection = normalize(lightPosition - input.Position); 

    float1 diffuse = saturate(dot(lightDirection, input.Normal)) * lightColor; 

    output.color = diffuse; 

    //float4 solidColor = float4(1.0f, 1.0f, 0.0f, 1.0f); 
    //output.color = solidColor; 
    return output; 
} 

결과 (큐브 (50)의 회전시) enter image description here

,451,515,

CPP : https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11Tutorials/Tutorial06/Tutorial06.cpp

HLSL : 여기 https://github.com/walbourn/directx-sdk-samples/blob/master/Direct3D11Tutorials/Tutorial06/Tutorial06.fx

답변

1

없습니다 많은 정보에 갈 수 있지만, 보통은 정점 (점)에서 특정 방향으로 가리키는 방향 벡터 (방향)입니다. 확산 조명을 계산할 때 빛의 위치를 ​​얻고 꼭지점 (이 경우에는 큐브에서 가정합니다)의 위치를 ​​얻고 두 벡터 사이의 각이 무엇인지 찾습니다. 삼각형 모양으로 빛의 위치에서 큐브의 꼭지점까지 선을 그린 다음 빛에서 그 선과 법선 벡터 (직각을 가리키는 선 또는 직각 또는 직선) 사이의 각도를 계산합니다. 큐브 표면. 이 두 벡터 사이의 각도가 높을수록 어두워집니다. 왜냐하면 여러분은 "내적"을 취하기 때문입니다. 각도가 직각 일 때 내적은 0이되어 빛이 없음을 의미합니다. "정상적인"방향이 빛의 방향을 직접 가리킬 때 내적 값은 1이며, 이는 완전한 빛을 의미합니다. 이 내적 (기본적으로 광도)에 다른 색상을 곱하면 꼭지점 (또는 입방체)에 있던 원래 색상의 밝기가 조정됩니다. 그것은 당신이 보는 색깔을 조절합니다. 그게 뭔가 설명했다는 희망.

숫자를 변경할 때 나타나는 것을 보는 이유는 무엇입니까?

위치를 기준으로 법선을 변경하면 다른 것을 보는 이유에 대해 질문 할 때 법선 벡터는 거의 항상 단위 벡터 (길이 1)입니다. 조명 계산을 수행 할 때 두 벡터가 모두 정규화되면 (단위 벡터 또는 길이가 1 인 벡터 모두) 0과 1 사이의 원하는 값만 얻습니다. 그렇지 않으면 엄청나게 큰 또는 작은 음수를 얻을 수 있습니다. 조명 배율로 45와 같은 거대한 숫자를 사용하면 상황이 올바르지 않을 것입니다. 쉐이더의 색상은 값을 업데이트 enter image description here

0과 1 : OK, 이것을 설명하기 복잡해진다, 나는 이것을 보여주기 위해 그림을 그릴 수 있는지 모르겠어요. 이 코드에서 일어나는 일은 여러분이 큐브의 각 꼭지 점을 가져 가고 있고, 이것을 월드/뷰/프로젝션 행렬이라고 부르는 것에 곱하는 것입니다. 기본적으로 큐브의 꼭지점을 가져 와서 세계의 해당 위치로 이동 한 다음 카메라 위치의 역인 위치로 이동합니다.이 위치는 대개 원점 (0, 0, 0) 바로 앞에있는 것을 의미합니다. 카메라. 그러면 투영 행렬이이 점들을 화면으로 변환합니다. 기억해야 할 중요한 점은 버텍스 쉐이더에서 들어오는 버텍스를이 마법의 WVP 행렬로 곱하면 최종 결과는 버텍스가 카메라 앞에서 끝난 다음 화면에 투사된다는 것입니다.

이제 두 번째 부분이 발생합니다. 이것이 바로 조명 계산입니다. 월드 공간에서 또는 월드 엑스 뷰 변환이 완료된 후에 수행 할 수 있습니다. 이 경우 코드는 월드 공간에서 조명 계산을 수행합니다. 즉, 큐브의 정점이 로컬 공간에있는 모든 위치에서 월드 위치로 변환됩니다. 그것은 세계 어느 곳이든 가능할 수 있습니다 (150, 20, 60). 빛의 위치가이 공간에서 세계 어딘가에 있기 때문에 이것을 세계 위치로 변환해야합니다. 법선 벡터는 대개 단위 벡터 (길이가 1 인 벡터)입니다. (0, 0, 0)에서 시작하여 방향을 가리키는 법선 벡터를 그림으로 그린다.

법선 벡터에 세계 행렬을 곱하는 첫 번째 경우에는 잘못되었습니다. 이상적으로 일어날 일은 법선 벡터가 꼭지점 위치의 변환을 '따라야'하고 나서 변환 된 세계 위치에서 길이가 1 인 점을 지적하는 것입니다. 나는 그것을 더 잘 설명하기 위해 뭔가를 그릴 수 있었으면 좋겠다. 첫 번째 것은 틀리며, 두 번째로 세계 행렬에 의해 위치를 배가시키는 것은 잘못된 것입니다.

편집 : 튜토리얼 코드를 살펴 보았지만 정상적으로 작동합니다. 당신은 (1, 1, 0)의 밝은 점을 지정한 다음 당신의 쉐이더에서 그것을 사용합니다. 반면 튜토리얼에서 두 개의 밝은 점은 다음과 같습니다.

XMFLOAT4(-0.577f, 0.577f, -0.577f, 1.0f), 
XMFLOAT4(0.0f, 0.0f, -1.0f, 1.0f), 

두 번째 것은 단위 벡터이며, Z는 -1입니다. 첫 번째 것은 A 단위 제곱 + B 제곱 + C 제곱 = 길이이기 때문에 단위 벡터 (길이 1)입니다. 이것이 둘 다 단위 벡터이고 내적이 올바르게 나타나는 이유입니다. 다른 (1, 1, 0) 벡터는 단위 벡터가 아닙니다. 코드와 튜토리얼의 내용이 같지 않아서 차이가 있는지 확실하지 않습니다. 이러한 변경으로 인해 코드가 작동하지 않는지 확실하지 않습니다. 또한 Chuck의 라이트 코드는 큐브가 가운데에 있기 때문에 작동합니다. 다른 곳으로 이동하면 어디서나 조명 버그를 얻을 수 있습니다. 나는 그가 데모를 위해서 이것을 단지 그렇게했다고 생각합니다.

+0

질문이 업데이트되었습니다. – Mike5050

+0

예,하지만이 예제에서는 법선을 사용하는 이유는 무엇입니까? 법선을 사용하면 예기치 않은 결과 (업데이트 된 게시물 참조)가 나오지만 큐브의 실제 꼭지점 위치를 사용하면 게시 한 결과가 나타납니다. – Mike5050

+0

좋아, 나는 당신의 업데이트를 보지 못했습니다! 그러나 더 명확하게, 내 확산 조명은 다음과 같이 좋지 않습니다. https://www.gamasutra.com/features/20030418/ambient%2Bdiffuse.jpg - 일반을 사용하는 경우 ... – Mike5050

관련 문제