พื้นผิว Projective และแสงรอการตัดบัญชี


10

ในคำถามก่อนหน้านี้ฉันถามว่าเป็นไปได้ไหมที่จะทำพื้นผิวแบบ Projective ด้วยแสงที่เลื่อนออกไป ตอนนี้ (มากกว่าครึ่งปีต่อมา) ฉันมีปัญหากับการใช้งานสิ่งเดียวกัน ฉันพยายามที่จะใช้เทคนิคนี้ในการส่งผ่านแสง (โปรเจ็กเตอร์ของฉันไม่มีผลต่ออัลเบโด้) ฉันมีโปรเจ็กเตอร์นี้ดูเมทริกซ์การฉาย:

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เป็นเป้าหมายของโปรเจ็กเตอร์ ดูเหมือนว่าจะโอเค ฉันกำลังวาดรูปสี่เหลี่ยมเต็มหน้าจอด้วย shader นี้:

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-buffer (รหัสนี้ฉันใช้ในเฉดสีอื่น ๆ โดยไม่มีปัญหาใด ๆ ) และจากนั้นจะถูกเปลี่ยนเป็นพื้นที่การฉายของโปรเจ็กเตอร์ ปัญหาคือเส้นโครงไม่ปรากฏขึ้น นี่คือภาพสถานการณ์ของฉัน:

ภาพของปัญหา

เส้นสีเขียวคือ frustum ของโปรเจ็กเตอร์ที่แสดงผล ความผิดพลาดของฉันถูกซ่อนอยู่ที่ไหน ฉันใช้ XNA 4 ขอบคุณสำหรับคำแนะนำและขอโทษสำหรับภาษาอังกฤษของฉัน

แก้ไข:

Shader ด้านบนทำงานได้ แต่การฉายมีขนาดเล็กเกินไป เมื่อฉันเปลี่ยนคุณสมบัติมาตราส่วนเป็นค่าขนาดใหญ่ (เช่น 100) การฉายจะปรากฏขึ้น แต่เมื่อกล้องเคลื่อนไปที่การฉายภาพการฉายก็ขยายตามที่เห็นในวิดีโอ YouTubeนี้

คำตอบ:


5

ใน shader ของคุณคุณจะต้องลบposition.xyz /= w;เนื่องจากนี่คือสิ่งที่ทำให้เกิดปัญหาการปรับขนาดของคุณ:

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

นั่นควรทำเคล็ดลับ


0

หากคุณได้ผลลัพธ์ที่เล็กเกินไปและได้ขนาดนั้นอาจเป็นเพราะ frustum ยังคงอยู่ในพื้นที่ 1 ถึง -1 หรือ 0 ถึง 1 หรือคล้ายกัน? นั่นคือโอริโกของคุณที่ frustum ตั้งอยู่หรือ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.