Textura proyectiva e iluminación diferida.


10

En mi pregunta anterior , pregunté si es posible realizar texturas proyectivas con iluminación diferida. Ahora (más de medio año después) tengo un problema con mi implementación de lo mismo. Estoy tratando de aplicar esta técnica en paso ligero. (Mi proyector no afecta al albedo). Tengo este proyector Ver una matriz de proyección:

Matrix projection = Matrix.CreateOrthographicOffCenter(-halfWidth * Scale, halfWidth * Scale, -halfHeight * Scale, halfHeight * Scale, 1, 100000);
Matrix view       = Matrix.CreateLookAt(Position, Target, Vector3.Up);

Donde halfWidthy halfHeightes la mitad del ancho y la altura de la textura, Positiones la posición targetdel proyector y es el objetivo del proyector. Esto parece estar bien. Estoy dibujando quad de pantalla completa con este sombreador:

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);
}

En la primera parte del sombreador de píxeles se recupera la posición del G-buffer (este código lo estoy usando en otros sombreadores sin ningún problema) y luego se transforma en el espacio de proyección de la vista del proyector. El problema es que la proyección no aparece. Aquí hay una imagen de mi situación:

imagen del problema

Las líneas verdes son el proyector renderizado. ¿Dónde está escondido mi error? Estoy usando XNA 4. Gracias por los consejos y perdón por mi inglés.

EDITAR:

El sombreador anterior funciona pero la proyección era demasiado pequeña. Cuando cambié la propiedad Escala a un valor grande (por ejemplo, 100), aparece la proyección. Pero cuando la cámara se mueve hacia la proyección, la proyección se expande, como se puede ver en este video de YouTube .

Respuestas:


5

En su sombreador, necesitará eliminarlo, position.xyz /= w;ya que esto es lo que está causando su problema de cambio de tamaño:

// Transform position from screen space to world space 
position = mul(position, InvViewProjection); 
position.xyz /= position.w;  <<-- Comment this out

Eso debería hacer el truco.


0

Si obtiene resultados que son demasiado pequeños y llega a ese tamaño, ¿podría ser porque el tronco todavía está en 1 a -1 espacio o 0 a 1 o similar? ¿Es ese tu origo en el que se basa el frustum?

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.