Что не так с моим нормальным отображением? C ++ Directx

Привет, ребята, я пытаюсь реализовать Normal Mapping в Directx, и я очень близок к его созданию, но я получаю эти странные черные цвета на некоторых объектах. Вот как это выглядит без отображения нормалей:

введите описание изображения здесь

И когда я применяю эффект Normal Mapping, это выглядит так:

введите описание изображения здесь

введите описание изображения здесь

Где я получаю черный цвет, например, на стене и какой-то части куба, что странно.

Мой файл Pixel Shader выглядит следующим образом:

 cbuffer PositionBuffer : register(b1)
{
float3 cameraPos;
float pad;
float3 lightPos;
float pad1;
};

cbuffer PhongBuffer : register(b2) {
float4 ambient;
float4 diffus;
float4 blank;
float shininess;
float3 padd;
};

Texture2D texDiffuse : register(t0);
Texture2D texNormal : register(t1);

SamplerState texSampler : register(s0);

struct PSIn
{
float4 Pos  : SV_Position;
float3 Normal : NORMAL;
float2 TexCoord : TEX;
float4 PosWorld : VIEWPOSITION;
float4 Tangent : TANGENT; //Added this
float4 Binormal : BINORMAL; //Added this
};

//-----------------------------------------------------------------------------------------
// Pixel Shader
//-----------------------------------------------------------------------------------------

float4 PS_main(PSIn input) : SV_Target
{

float3 N;
float3 L;
float3 R;
float3 V;
float3 I;

float3 textureColor;
float4 bumpMap;
float3 bumpNormal;

// Sample the texture pixel at this location.
textureColor = texDiffuse.Sample(texSampler, input.TexCoord).xyz;

// Sample the pixel in the bump map.
bumpMap = texNormal.Sample(texSampler, input.TexCoord);

// Expand the range of the normal value from (0, +1) to (-1, +1).
bumpMap = (bumpMap * 2.0f) - 1.0f;

// Calculate the normal from the data in the bump map.
bumpNormal = (bumpMap.x * input.Tangent) + (bumpMap.y * input.Binormal) + (bumpMap.z * input.Normal);

// Normalize the resulting bump normal.
//bumpNormal = Normalize(bumpNormal;L = lightPos - input.PosWorld;
//N = input.Normal;
N = bumpNormal;
V = cameraPos - input.PosWorld;
R = reflect(-L, N);

L = normalize(L);
N = normalize(N);
V = normalize(V);
R = normalize(R);I = ambient.xyz + (textureColor * max(dot(L,N), 0) + blank.xyz * max(pow(dot(R,V), shininess), 0)); //Phong Shader Formula

if(texNormal.Sample(texSampler, input.TexCoord).z <= 0) { //Prevent the objects that don't have bump map from being given the Normal Mapping effect
return texDiffuse.Sample(texSampler, input.TexCoord);
}

if(dot(L, N) < 0) {
return texDiffuse.Sample(texSampler, input.TexCoord);
}

return float4(I, 1);

}

И мой Vertex Shader выглядит так:

cbuffer MatrixBuffer : register(b0)
{
matrix ModelToWorldMatrix;
matrix WorldToViewMatrix;
matrix ProjectionMatrix;
};struct VSIn
{
float3 Pos : POSITION;
float3 Normal : NORMAL;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
float2 TexCoord : TEX;
};

struct PSIn
{
float4 Pos  : SV_Position;
float3 Normal : NORMAL;
float2 TexCoord : TEX;
float4 PosWorld : VIEWPOSITION;
float3 Tangent : TANGENT; //Added this
float3 Binormal : BINORMAL; //Added this
};

//-----------------------------------------------------------------------------------------
// Vertex Shader
//-----------------------------------------------------------------------------------------

PSIn VS_main(VSIn input)
{
PSIn output = (PSIn)0;

// Model->View transformation
matrix MV = mul(WorldToViewMatrix, ModelToWorldMatrix);

// Model->View->Projection (clip space) transformation
// SV_Position expects the output position to be in clip space
matrix MVP = mul(ProjectionMatrix, MV);

// Perform transformations and send to output
output.Pos = mul(MVP, float4(input.Pos, 1));
output.Normal = normalize( mul(ModelToWorldMatrix, float4(input.Normal,0)).xyz ); //Convert the Normal for the vertex to World Space
output.TexCoord = input.TexCoord;
output.PosWorld = mul(ModelToWorldMatrix, float4(input.Pos, 1)); //Convert to World Space
output.Tangent = normalize( mul(ModelToWorldMatrix, float4(input.Tangent,0)).xyz ); //Convert the Tangent for the vertex to World Space
output.Binormal = normalize( mul(ModelToWorldMatrix, float4(input.Binormal,0)).xyz ); //Convert the Binormal for the vertex to World Spacereturn output;
}

Этот метод используется для вычисления бинормали и тангенса для каждой вершины со стороны процессора (взято из руководства Rasterek Tutorial http://www.rastertek.com/dx11tut20.html):

    void OBJModel_t::CalculateModelVectors(std::vector<vertex_t> & vertices) {
int faceCount, i, index;
vertex_t vertex1, vertex2, vertex3;
vec3f tangent, binormal, normal;
int m_vertexCount = vertices.size();

// Calculate the number of faces in the model.
faceCount = m_vertexCount / 3;

// Initialize the index to the model data.
index = 0;

// Go through all the faces and calculate the the tangent, binormal, and normal vectors.
for (i = 0; i<faceCount; i++)
{
// Get the three vertices for this face from the model.
vertex1.Pos.x = vertices[index].Pos.x;
vertex1.Pos.y = vertices[index].Pos.y;
vertex1.Pos.z = vertices[index].Pos.z;
vertex1.TexCoord.x = vertices[index].TexCoord.x;
vertex1.TexCoord.y = vertices[index].TexCoord.y;
vertex1.Normal.x = vertices[index].Normal.x;
vertex1.Normal.y = vertices[index].Normal.y;
vertex1.Normal.z = vertices[index].Normal.z;
index++;

vertex2.Pos.x = vertices[index].Pos.x;
vertex2.Pos.y = vertices[index].Pos.y;
vertex2.Pos.z = vertices[index].Pos.z;
vertex2.TexCoord.x = vertices[index].TexCoord.x;
vertex2.TexCoord.y = vertices[index].TexCoord.y;
vertex2.Normal.x = vertices[index].Normal.x;
vertex2.Normal.y = vertices[index].Normal.y;
vertex2.Normal.z = vertices[index].Normal.z;
index++;

vertex3.Pos.x = vertices[index].Pos.x;
vertex3.Pos.y = vertices[index].Pos.y;
vertex3.Pos.z = vertices[index].Pos.z;
vertex3.TexCoord.x = vertices[index].TexCoord.x;
vertex3.TexCoord.y = vertices[index].TexCoord.y;
vertex3.Normal.x = vertices[index].Normal.x;
vertex3.Normal.y = vertices[index].Normal.y;
vertex3.Normal.z = vertices[index].Normal.z;
index++;

// Calculate the tangent and binormal of that face.
CalculateTangentBinormal(vertex1, vertex2, vertex3, tangent, binormal);

// Calculate the new normal using the tangent and binormal.
CalculateNormal(tangent, binormal, normal);

// Store the normal, tangent, and binormal for this face back in the model structure.
vertices[index - 1].Normal.x = normal.x;
vertices[index - 1].Normal.y = normal.y;
vertices[index - 1].Normal.z = normal.z;
vertices[index - 1].Tangent.x = tangent.x;
vertices[index - 1].Tangent.y = tangent.y;
vertices[index - 1].Tangent.z = tangent.z;
vertices[index - 1].Binormal.x = binormal.x;
vertices[index - 1].Binormal.y = binormal.y;
vertices[index - 1].Binormal.z = binormal.z;

vertices[index - 2].Normal.x = normal.x;
vertices[index - 2].Normal.y = normal.y;
vertices[index - 2].Normal.z = normal.z;
vertices[index - 2].Tangent.x = tangent.x;
vertices[index - 2].Tangent.y = tangent.y;
vertices[index - 2].Tangent.z = tangent.z;
vertices[index - 2].Binormal.x = binormal.x;
vertices[index - 2].Binormal.y = binormal.y;
vertices[index - 2].Binormal.z = binormal.z;

vertices[index - 3].Normal.x = normal.x;
vertices[index - 3].Normal.y = normal.y;
vertices[index - 3].Normal.z = normal.z;
vertices[index - 3].Tangent.x = tangent.x;
vertices[index - 3].Tangent.y = tangent.y;
vertices[index - 3].Tangent.z = tangent.z;
vertices[index - 3].Binormal.x = binormal.x;
vertices[index - 3].Binormal.y = binormal.y;
vertices[index - 3].Binormal.z = binormal.z;
}

return;
}

void OBJModel_t::CalculateTangentBinormal(vertex_t vertex1, vertex_t vertex2, vertex_t vertex3, vec3f& tangent, vec3f& binormal) {

float vector1[3], vector2[3];
float tuVector[2], tvVector[2];
float den;
float length;// Calculate the two vectors for this face.
vector1[0] = vertex2.Pos.x - vertex1.Pos.x;
vector1[1] = vertex2.Pos.y - vertex1.Pos.y;
vector1[2] = vertex2.Pos.z - vertex1.Pos.z;

vector2[0] = vertex3.Pos.x - vertex1.Pos.x;
vector2[1] = vertex3.Pos.y - vertex1.Pos.y;
vector2[2] = vertex3.Pos.z - vertex1.Pos.z;

// Calculate the tu and tv texture space vectors.
tuVector[0] = vertex2.TexCoord.x - vertex1.TexCoord.x;
tvVector[0] = vertex2.TexCoord.y - vertex1.TexCoord.y;

tuVector[1] = vertex3.TexCoord.x - vertex1.TexCoord.x;
tvVector[1] = vertex3.TexCoord.y - vertex1.TexCoord.y;

// Calculate the denominator of the tangent/binormal equation.
den = 1.0f / (tuVector[0] * tvVector[1] - tuVector[1] * tvVector[0]);

// Calculate the cross products and multiply by the coefficient to get the tangent and binormal.
tangent.x = (tvVector[1] * vector1[0] - tvVector[0] * vector2[0]) * den;
tangent.y = (tvVector[1] * vector1[1] - tvVector[0] * vector2[1]) * den;
tangent.z = (tvVector[1] * vector1[2] - tvVector[0] * vector2[2]) * den;

binormal.x = (tuVector[0] * vector2[0] - tuVector[1] * vector1[0]) * den;
binormal.y = (tuVector[0] * vector2[1] - tuVector[1] * vector1[1]) * den;
binormal.z = (tuVector[0] * vector2[2] - tuVector[1] * vector1[2]) * den;

// Calculate the length of this normal.
length = sqrt((tangent.x * tangent.x) + (tangent.y * tangent.y) + (tangent.z * tangent.z));

// Normalize the normal and then store it
tangent.x = tangent.x / length;
tangent.y = tangent.y / length;
tangent.z = tangent.z / length;

// Calculate the length of this normal.
length = sqrt((binormal.x * binormal.x) + (binormal.y * binormal.y) + (binormal.z * binormal.z));

// Normalize the normal and then store it
binormal.x = binormal.x / length;
binormal.y = binormal.y / length;
binormal.z = binormal.z / length;

return;
}

void OBJModel_t::CalculateNormal(vec3f tangent, vec3f binormal, vec3f& normal)
{
float length;// Calculate the cross product of the tangent and binormal which will give the normal vector.
normal.x = (tangent.y * binormal.z) - (tangent.z * binormal.y);
normal.y = (tangent.z * binormal.x) - (tangent.x * binormal.z);
normal.z = (tangent.x * binormal.y) - (tangent.y * binormal.x);// Calculate the length of the normal.
length = sqrt((normal.x * normal.x) + (normal.y * normal.y) + (normal.z * normal.z));

// Normalize the normal.
normal.x = normal.x / length;
normal.y = normal.y / length;
normal.z = normal.z / length;

return;
}

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector