У своєму попередньому запитанні я запитав, чи можна робити проективну текстуру з відкладеним освітленням. Зараз (більш ніж через півроку) у мене проблема з моєю реалізацією того самого. Я намагаюся застосувати цю техніку при легкому проході. (мій проектор не впливає на альбедо). У мене є цей проектор Перегляд матриці проекції:
Matrix projection = Matrix.CreateOrthographicOffCenter(-halfWidth * Scale, halfWidth * Scale, -halfHeight * Scale, halfHeight * Scale, 1, 100000);
Matrix view = Matrix.CreateLookAt(Position, Target, Vector3.Up);
Де halfWidth
та halfHeight
є половиною ширини та висоти текстури Position
- це позиція target
проектора та мета проектора. Це здається нормальним. Я малюю повноекранний квадратик із цим шейдером:
float4x4 InvViewProjection;
texture2D DepthTexture;
texture2D NormalTexture;
texture2D ProjectorTexture;
float4x4 ProjectorViewProjection;
sampler2D depthSampler = sampler_state {
texture = <DepthTexture>;
minfilter = point;
magfilter = point;
mipfilter = point;
};
sampler2D normalSampler = sampler_state {
texture = <NormalTexture>;
minfilter = point;
magfilter = point;
mipfilter = point;
};
sampler2D projectorSampler = sampler_state {
texture = <ProjectorTexture>;
AddressU = Clamp;
AddressV = Clamp;
};
float viewportWidth;
float viewportHeight;
// Calculate the 2D screen position of a 3D position
float2 postProjToScreen(float4 position) {
float2 screenPos = position.xy / position.w;
return 0.5f * (float2(screenPos.x, -screenPos.y) + 1);
}
// Calculate the size of one half of a pixel, to convert
// between texels and pixels
float2 halfPixel() {
return 0.5f / float2(viewportWidth, viewportHeight);
}
struct VertexShaderInput {
float4 Position : POSITION0;
};
struct VertexShaderOutput {
float4 Position :POSITION0;
float4 PositionCopy : TEXCOORD1;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input) {
VertexShaderOutput output;
output.Position = input.Position;
output.PositionCopy=output.Position;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0 {
float2 texCoord =postProjToScreen(input.PositionCopy) + halfPixel();
// Extract the depth for this pixel from the depth map
float4 depth = tex2D(depthSampler, texCoord);
//return float4(depth.r,0,0,1);
// Recreate the position with the UV coordinates and depth value
float4 position;
position.x = texCoord.x * 2 - 1;
position.y = (1 - texCoord.y) * 2 - 1;
position.z = depth.r;
position.w = 1.0f;
// Transform position from screen space to world space
position = mul(position, InvViewProjection);
position.xyz /= position.w;
//compute projection
float3 projection=tex2D(projectorSampler,postProjToScreen(mul(position,ProjectorViewProjection)) + halfPixel());
return float4(projection,1);
}
У першій частині піксельних шейдерів відновлюється положення з G-буфера (цей код я використовую в інших шейдерах без будь-яких проблем), а потім перетворюється в простір проекції для перегляду проектора. Проблема в тому, що проекція не з’являється. Ось зображення моєї ситуації:
Зелені лінії - це фрустум проектованого проектора. Де прихована моя помилка? Я використовую XNA 4. Дякую за пораду і вибачте за мою англійську.
Редагувати:
Шейдер вище працює, але проекція була занадто маленькою. Коли я змінив властивість Scale на велике значення (наприклад, 100), з'явиться проекція. Але коли камера рухається до проекції, проекція розширюється, як це можна побачити на цьому відео YouTube .