Я работаю над 3D-проектом в DirectX11, и в настоящее время я использую различные огни, используя Программу 3D-игры Фрэнка Луны с помощью книги DirectX11 с моим существующим кодом.Как правильно создать прожектор в DirectX11?
В настоящее время я разрабатываю прожектор, который должен следовать за положением камеры и смотреть в том же направлении, однако положение, которое горит, странно перемещается. Когда положение изменяется, вектор направления света, по-видимому, отслеживается в направлении (+ x, + y, 0). Лучше всего объясняется картиной.
Он послушай, как они освещены должным образом, и если камера остается на месте, в центре внимания можно перемещать, как и следовало ожидать, и он отслеживает направление камеры.
На этом изображении, я переместил камеру ближе к ящикам, вдоль оси, и световое пятно нужно просто получить меньше на ближайшем поле, но он вместо того, чтобы отслеживать вверх.
Это код, где в центре внимания структура создается до быть передан в постоянном буфере, то есть все значения в структуры, в сторону от поплавка используется в качестве прокладки в конце:
cb.spotLight = SpotLight();
cb.spotLight.ambient = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
cb.spotLight.specular = XMFLOAT4(0.5, 0.5, 0.5, 10.0);
cb.spotLight.diffuse = XMFLOAT4(0.5, 0.5, 0.5, 1.0);
cb.spotLight.attenuation = XMFLOAT3(1, 1, 1);
cb.spotLight.range = 15;
XMVECTOR cameraP = XMLoadFloat3(&cameraPos);
XMVECTOR s = XMVectorReplicate(cb.spotLight.range);
XMVECTOR l = XMLoadFloat3(&camera.getForwards());
XMVECTOR lookat = XMVectorMultiplyAdd(s, l, cameraP);
XMStoreFloat3(&cb.spotLight.direction, XMVector3Normalize(lookat - XMVectorSet(cameraPos.x, cameraPos.y, cameraPos.z, 1.0f)));
cb.spotLight.position = cameraPos;
cb.spotLight.spot = 96;
Вот функция используется для расчета окружающей среды, диффузные и зеркальные значений в центре внимания в шейдере:
void calculateSpotLight(Material mat, SpotLight light, float3 position, float3 normal, float3 toEye,
out float4 ambient, out float4 diffuse, out float4 specular)
{
ambient = float4(0, 0, 0, 0);
specular = float4(0, 0, 0, 0);
diffuse = float4(0, 0, 0, 0);
float3 lightV = light.position - position;
float distance = length(lightV);
if (distance > light.range)
{
return;
}
lightV /= distance;
ambient = mat.ambient * light.ambient;
float diffuseFact = dot(lightV, normal);
[flatten]
if (diffuseFact > 0.0f)
{
float3 vect = reflect(-lightV, normal);
float specularFact = pow(max(dot(vect, toEye), 0.0f), mat.specular.w);
diffuse = diffuseFact * mat.diffuse * light.diffuse;
specular = specularFact * mat.specular * light.specular;
}
float spot = pow(max(dot(-lightV, float3(-light.direction.x, -light.direction.y, light.direction.z)), 0.0f), light.spot);
float attenuation = spot/dot(light.attenuation, float3(1.0f, distance, distance*distance));
ambient *= spot;
diffuse *= attenuation;
specular *= attenuation;
}
и completenesses ради, вершину и соответствующей секция пиксельного шейдера.
VS_OUTPUT VS(float4 Pos : POSITION, float3 NormalL : NORMAL, float2 TexC : TEXCOORD)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = mul(Pos, World);
//Get normalised vector to camera position in world coordinates
output.PosW = normalize(eyePos - output.Pos.xyz);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
//Getting normalised surface normal
float3 normalW = mul(float4(NormalL, 0.0f), World).xyz;
normalW = normalize(normalW);
output.Norm = normalW;
output.TexC = TexC;
return output;
}
float4 PS(VS_OUTPUT input) : SV_Target
{
input.Norm = normalize(input.Norm);
Material newMat;
newMat.ambient = material.ambient;
newMat.diffuse = texCol;
newMat.specular = specCol;
float4 ambient = (0.0f, 0.0f, 0.0f, 0.0f);
float4 specular = (0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = (0.0f, 0.0f, 0.0f, 0.0f);
float4 amb, spec, diff;
calculateSpotLight(newMat, spotLight, input.PosW, input.Norm, input.PosW, amb, diff, spec);
ambient += amb;
specular += spec;
diffuse += diff;
//Other light types
float4 colour;
colour = ambient + specular + diffuse;
colour.a = material.diffuse.a;
return colour;
}
Где я ошибся?
@NicoSchertler К сожалению, знал, что я что-то забуду. Это прямо в нижней части раздела, как раз перед установкой 'float4 colour'. – Yann
Кажется, что существует несоответствие с вашим именем переменной. 'output.PosW' выглядит как позиция, но это направление к камере. Вы передаете это значение 'calculateSpotlight()' как параметр 'position', где он используется как позиция. Одна из двух частей должна быть изменена. Кроме того, когда вы вычисляете 'spot', вам не хватает минуса перед' light.direction.z'. Во всяком случае, там слишком много минусов ('reflect (-lightV, normal)', 'dot (-lightV, ...', '-light.direction'). –
Возможно, вы захотите взглянуть на [ FixedfuncEMUFX11] (https://github.com/walbourn/directx-sdk-samples), который имеет HLSLshaders, которые реализуют всю стандартную рендеринг с фиксированной функцией, включая точечные источники. –