Tekstur proyektif dan pencahayaan yang ditangguhkan

10

Dalam pertanyaan saya sebelumnya , saya bertanya apakah mungkin melakukan textive proyektif dengan pencahayaan yang ditangguhkan. Sekarang (lebih dari setengah tahun kemudian) saya punya masalah dengan implementasi saya dari hal yang sama. Saya mencoba menerapkan teknik ini dalam light pass. (proyektor saya tidak mempengaruhi Albedo). Saya punya proyektor ini. Lihat matriks Proyeksi:

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

Di mana halfWidthdan mana halfHeightadalah setengah dari lebar dan tinggi tekstur, Positionadalah posisi Proyektor dan targetmerupakan target proyektor. Ini sepertinya ok. Saya menggambar quad layar penuh dengan shader ini:

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

Pada bagian pertama pixel shader dipulihkan posisi dari G-buffer (kode ini saya gunakan di shader lain tanpa masalah) dan kemudian diubah ke ruang proyeksi tampilan proyektor. Masalahnya adalah bahwa proyeksi tidak muncul. Ini gambar situasi saya:

gambar masalah

Garis hijau adalah frustrasi proyektor yang diberikan. Di mana kesalahan saya disembunyikan? Saya menggunakan XNA 4. Terima kasih atas sarannya dan maaf untuk bahasa Inggris saya.

EDIT:

Shader di atas berfungsi tetapi proyeksi terlalu kecil. Ketika saya mengubah properti Scale ke nilai besar (mis. 100), proyeksi muncul. Tetapi ketika kamera bergerak ke arah proyeksi, proyeksi mengembang, seperti yang dapat dilihat pada video YouTube ini .

Vodáček
sumber

Jawaban:

5

Di shader Anda, Anda harus menghapus position.xyz /= w;karena inilah yang menyebabkan masalah ukuran Anda:

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

Itu harus melakukan trik.

Neil Knight
sumber
0

Jika Anda mendapatkan hasil yang terlalu kecil dan mencapai ukuran itu mungkin karena frustum masih dalam 1 hingga -1 ruang atau 0 hingga 1 atau sejenisnya? Apakah itu origo Anda yang menjadi dasar frustum?

Mårten Möller
sumber