স্থগিত আলো সেটআপে দ্বৈত প্যারাবোলয়েড পয়েন্ট হালকা ছায়া


10

আমি এই টিউটোরিয়াল / স্যাম্পল কোডটি নিয়ে প্রায় খেলছি যা লাইট-প্রি-পাসের একটি সাধারণ বাস্তবায়ন দেখায়, যা এক ধরণের স্থলিত আলো সেটআপ।

আমি ডুয়াল-প্যারাবোলয়েড ছায়া মানচিত্র ব্যবহার করে পয়েন্ট হালকা ছায়া গোটা বাস্তবায়নের প্রক্রিয়ায় আছি। আমি ডিপিএম-এর এই বিবরণটি অনুসরণ করছি: http: // gamedeلاف.eu/en/tutorials/dual-paraboloid-sadow- mapping.htm

আমি ছায়ার মানচিত্র তৈরি করতে সক্ষম হয়েছি এবং এগুলি দেখতে বেশ সুন্দর দেখাচ্ছে।

আমি বিশ্বাস করি যে আমার বর্তমান সমস্যাটি আমার পিক্সেল শেডারটিতে রয়েছে যা পয়েন্ট লাইটগুলি রেন্ডার করার সময় ছায়া মানচিত্রে একটি গভীরতার মান দেখায়।

আমার পয়েন্ট লাইট শেডার কোডটি এখানে: http://olhovsky.com/shadow_mapping/PointLight.fx

আগ্রহের পিক্সেল শেডার ফাংশনটি PointLightMeshShadowPS

কেউ কি এই ফাংশনে সুস্পষ্ট ত্রুটি দেখতে পাচ্ছেন?

আশা করি এর আগেও কেউ এই সমস্যা মোকাবেলা করেছেন :)

এখানে চিত্র বর্ণনা লিখুন

এখানে চিত্র বর্ণনা লিখুন

আপনি উপরের চিত্রগুলিতে দেখতে পাচ্ছেন, পোস্টের ছায়াগুলি পোস্টগুলির অবস্থানগুলির সাথে মেলে না, তাই কিছুটা রূপান্তরটি কোথাও ভুল ...

পয়েন্ট লাইট যখন মাটির খুব কাছাকাছি থাকে (প্রায় মাটির স্পর্শ করে) তখন এটি দেখতে দেখতে এটিই মনে হয়।

এখানে চিত্র বর্ণনা লিখুন

বিন্দু আলো মাটির কাছাকাছি যাওয়ার সাথে সাথে, ছায়াগুলি একসাথে এসে দুটি ছায়াযুক্ত মানচিত্রের যেখানে মিলিত হয় সেই লাইনের সাথে স্পর্শ করে (এটি সেই বিমানের সাথে যেখানে দুটি ছায়া মানচিত্র ক্যাপচার করার জন্য লাইট ক্যামেরাটি উল্টানো হয়েছিল)।


সম্পাদনা:

আরো তথ্য:

এখানে চিত্র বর্ণনা লিখুন

আমি যখন বিন্দু আলোটিকে উত্স থেকে দূরে সরিয়ে নিয়ে যাই, সেখানে আলোর ক্যামেরার "ডান" ভেক্টরের সমান্তরাল একটি লাইন থাকে যা ছায়াকে ক্লিপ করে। উপরের চিত্রটি পয়েন্ট আলোকে বাম দিকে সরানোর ফলাফল দেখায়। আমি যদি পয়েন্ট লাইটটি ডানদিকে নিয়ে যাই তবে ডানদিকে একটি সমতুল্য ক্লিপিং লাইন আছে সুতরাং আমি মনে করি এটি ইঙ্গিত করে যে আমি পিক্সেল শেডারটিতে কিছু ভুলভাবে রূপান্তর করছি, যেমনটি আমি ভেবেছিলাম।


সম্পাদনা করুন: এই প্রশ্নটি আরও স্পষ্ট করতে কোডের কয়েকটি অংশ এখানে দেওয়া হল।

আমি বর্তমানে ছায়াযুক্ত স্পট লাইট আঁকতে কোডটি ব্যবহার করছি । এটি কাজ করে এবং আপনার প্রত্যাশা অনুযায়ী ছায়া ম্যাপিং ব্যবহার করে।

VertexShaderOutputMeshBased SpotLightMeshVS(VertexShaderInput input)
{
    VertexShaderOutputMeshBased output = (VertexShaderOutputMeshBased)0;    
    output.Position = mul(input.Position, WorldViewProjection);

    //we will compute our texture coords based on pixel position further
    output.TexCoordScreenSpace = output.Position;
    return output;
}

//////////////////////////////////////////////////////
// Pixel shader to compute spot lights with shadows
//////////////////////////////////////////////////////
float4 SpotLightMeshShadowPS(VertexShaderOutputMeshBased input) : COLOR0
{
    //as we are using a sphere mesh, we need to recompute each pixel position into texture space coords
    float2 screenPos = PostProjectionSpaceToScreenSpace(input.TexCoordScreenSpace) + GBufferPixelSize;
    //read the depth value
    float depthValue = tex2D(depthSampler, screenPos).r;

    //if depth value == 1, we can assume its a background value, so skip it
    //we need this only if we are using back-face culling on our light volumes. Otherwise, our z-buffer
    //will reject this pixel anyway

    //if depth value == 1, we can assume its a background value, so skip it
    clip(-depthValue + 0.9999f);

    // Reconstruct position from the depth value, the FOV, aspect and pixel position
    depthValue*=FarClip;

    //convert screenPos to [-1..1] range
    float3 pos = float3(TanAspect*(screenPos*2 - 1)*depthValue, -depthValue);

    //light direction from current pixel to current light
    float3 lDir = LightPosition - pos;

    //compute attenuation, 1 - saturate(d2/r2)
    float atten = ComputeAttenuation(lDir);

    // Convert normal back with the decoding function
    float4 normalMap = tex2D(normalSampler, screenPos);
    float3 normal = DecodeNormal(normalMap);

    lDir = normalize(lDir);

    // N dot L lighting term, attenuated
    float nl = saturate(dot(normal, lDir))*atten;

    //spot light cone
    half spotAtten = min(1,max(0,dot(lDir,LightDir) - SpotAngle)*SpotExponent);
    nl *= spotAtten;

    //reject pixels outside our radius or that are not facing the light
    clip(nl -0.00001f);

    //compute shadow attenuation

    float4 lightPosition = mul(mul(float4(pos,1),CameraTransform), MatLightViewProjSpot);

    // Find the position in the shadow map for this pixel
    float2 shadowTexCoord = 0.5 * lightPosition.xy / 
                            lightPosition.w + float2( 0.5, 0.5 );
    shadowTexCoord.y = 1.0f - shadowTexCoord.y;
    //offset by the texel size
    shadowTexCoord += ShadowMapPixelSize;

    // Calculate the current pixel depth
    // The bias is used to prevent floating point errors 
    float ourdepth = (lightPosition.z / lightPosition.w) - DepthBias;

    nl = ComputeShadowPCF7Linear(nl, shadowTexCoord, ourdepth);

    float4 finalColor;

    //As our position is relative to camera position, we dont need to use (ViewPosition - pos) here
    float3 camDir = normalize(pos);

    // Calculate specular term
    float3 h = normalize(reflect(lDir, normal));
    float spec = nl*pow(saturate(dot(camDir, h)), normalMap.b*50);
    finalColor = float4(LightColor * nl, spec); 

    //output light
    return finalColor * LightBufferScale;
}

এখন আমি এখানে পয়েন্ট লাইট কোডটি ব্যবহার করছি যা ছায়ার মানচিত্র ব্যবহার করার সময় হালকা জায়গায় রূপান্তর করার ক্ষেত্রে কিছু বাগ রয়েছে g

VertexShaderOutputMeshBased PointLightMeshVS(VertexShaderInput input)
{
    VertexShaderOutputMeshBased output = (VertexShaderOutputMeshBased)0;    
    output.Position = mul(input.Position, WorldViewProjection);

    //we will compute our texture coords based on pixel position further
    output.TexCoordScreenSpace = output.Position;
    return output;
}

float4 PointLightMeshShadowPS(VertexShaderOutputMeshBased input) : COLOR0
{
    // as we are using a sphere mesh, we need to recompute each pixel position 
    // into texture space coords
    float2 screenPos = 
        PostProjectionSpaceToScreenSpace(input.TexCoordScreenSpace) + GBufferPixelSize;

    // read the depth value
    float depthValue = tex2D(depthSampler, screenPos).r;

    // if depth value == 1, we can assume its a background value, so skip it
    // we need this only if we are using back-face culling on our light volumes. 
    // Otherwise, our z-buffer will reject this pixel anyway
    clip(-depthValue + 0.9999f);

    // Reconstruct position from the depth value, the FOV, aspect and pixel position
    depthValue *= FarClip;

    // convert screenPos to [-1..1] range
    float3 pos = float3(TanAspect*(screenPos*2 - 1)*depthValue, -depthValue);

    // light direction from current pixel to current light
    float3 lDir = LightPosition - pos;

    // compute attenuation, 1 - saturate(d2/r2)
    float atten = ComputeAttenuation(lDir);

    // Convert normal back with the decoding function
    float4 normalMap = tex2D(normalSampler, screenPos);
    float3 normal = DecodeNormal(normalMap);

    lDir = normalize(lDir);

    // N dot L lighting term, attenuated
    float nl = saturate(dot(normal, lDir))*atten;

    /* shadow stuff */

    float4 lightPosition = mul(mul(float4(pos,1),CameraTransform), LightViewProj);

    //float4 lightPosition = mul(float4(pos,1), LightViewProj);
    float posLength = length(lightPosition);
    lightPosition /= posLength;

    float ourdepth = (posLength - NearClip) / (FarClip - NearClip) - DepthBias;
    //float ourdepth = (lightPosition.z / lightPosition.w) - DepthBias;

    if(lightPosition.z > 0.0f)
    {
        float2 vTexFront;
        vTexFront.x =  (lightPosition.x /  (1.0f + lightPosition.z)) * 0.5f + 0.5f; 
        vTexFront.y =  1.0f - ((lightPosition.y /  (1.0f + lightPosition.z)) * 0.5f + 0.5f);    

        nl = ComputeShadow(FrontShadowMapSampler, nl, vTexFront, ourdepth);
    }
    else
    {
        // for the back the z has to be inverted        
        float2 vTexBack;
        vTexBack.x =  (lightPosition.x /  (1.0f - lightPosition.z)) * 0.5f + 0.5f; 
        vTexBack.y =  1.0f - ((lightPosition.y /  (1.0f - lightPosition.z)) * 0.5f + 0.5f); 

        nl = ComputeShadow(BackShadowMapSampler, nl, vTexBack, ourdepth);
    }

    /* shadow stuff */

    // reject pixels outside our radius or that are not facing the light
    clip(nl - 0.00001f);

    float4 finalColor;
    //As our position is relative to camera position, we dont need to use (ViewPosition - pos) here
    float3 camDir = normalize(pos);

    // Calculate specular term
    float3 h = normalize(reflect(lDir, normal));
    float spec = nl*pow(saturate(dot(camDir, h)), normalMap.b*100);
    finalColor = float4(LightColor * nl, spec);

    return finalColor * LightBufferScale;
}

এবং আপনি বলছেন ছায়ার মানচিত্রগুলি নিজেরাই কোনও সমস্যা করছে না / (আমি যদি বোঝাতে চাইছি আপনি যদি ছায়ার মানচিত্রগুলি টেক্সচারম্যাপে জ্বালান তবে তারা সঠিক দাগগুলি আরও গাen় করে দেবে?)
Ali1S232

আপনি কি 100% নিশ্চিত যে আলোক উত্সের অবস্থান থেকে ক্যামেরাটির রেন্ডারিং সঠিক?
রায় টি।

আলোর উত্সের অবস্থান থেকে ক্যামেরা রেন্ডারিংয়ে একটি প্রজেকশন ম্যাট্রিক্স থাকে না, কারণ প্যারাবোলয়েড ওয়ার্প পেতে প্রক্ষেপণটি ম্যানুয়ালি করা হয়। যদিও আমি কোডটি পরীক্ষা করব, ভাল ধারণা রায় টি।
ওলহোভস্কি

গেজেট: "মানে আপনি যদি ছায়ার মানচিত্রগুলি টেক্সচারম্যাপে জ্বালিয়ে দেন তবে তারা সঠিক দাগগুলি আরও গাen় করবে?" ছায়া মানচিত্র হালকা জায়গায় ছায়াগুলি সংরক্ষণ করে, আমি যদি মানচিত্রের দিকে তাকাই তবে নিশ্চিত হয়ে ওঠার সহজ উপায় নেই যে সেগুলি সঠিক কারণ আমি তাদের স্ক্রিনস্পেসে দেখি। একটি "টেক্সচারম্যাপ" কী - আপনার অর্থ একটি টেক্সচার? শ্যাডো মানচিত্রগুলি হয় অঙ্গবিন্যাস।
ওলোভস্কি

রায় টি .: চারদিকে আলো সরিয়ে নেওয়া ছায়ার মানচিত্রটি ক্লিপ হয়ে যায় তা প্রকাশ করে, তাই প্রকৃতপক্ষে ছায়াটি তৈরি করার সময় পরিবর্তিত হওয়ার ক্ষেত্রে সমস্যা আছে।
ওলহভস্কি

উত্তর:


2

পিক্সের সাহায্যে আপনি পিক্সেলকে বিচ্ছিন্নভাবে ডিবাগ করতে পারেন, সম্ভবত আপনি এইভাবে ত্রুটিটি খুঁজে পান। FOV বা একটি অভিক্ষেপ ত্রুটি হট ইঙ্গিত। নাকি আপনি ভুলে গেছেন বিশ্বের রূপান্তর ?!


আপনি এনভিডিয়া-এফএক্সকম্পোজার
Ali1S232

আমি মনে করি না যে এসেম্বলি কোডের মানগুলি পর্যবেক্ষণ করা এই মুহুর্তে আমাকে খুব সাহায্য করবে, কারণ রূপান্তরটি প্রথম স্থানে কীভাবে করা উচিত তা বুঝতে আমার সমস্যা হচ্ছে। সুতরাং 10 বা রেজিস্টারে যেখানে মান রয়েছে তাতে মানটি আসলেই সাহায্য করবে না।
ওলোভস্কি

"বা আপনি কি বিশ্ব রূপান্তর ভুলে গেছেন ?!" ছায়ার মানচিত্র তৈরি করার সময় আমি আসলে বিশ্বের রূপান্তরটি প্রয়োগ করতে ভুলে গেছি - দোহ! এটি এখন সমস্ত শ্যাডারগুলিকে যেমন রেখেছিল তেমন রেখে চলেছে।
ওলহোভস্কি

1

ওহে ওলোভস্কি, দুর্দান্ত চ্যালেঞ্জিং প্রশ্ন। আমি আপনার ব্যথা জানি, আমি আমার শেষ কাজটিতে ডেফার্ড শেডিং, ইনফার্ডেড লাইটিং এবং শেডো প্রয়োগ করেছি। এটি সত্যিই দুর্দান্ত মজাদার ছিল, তবে যখন এটি প্রত্যাশা অনুযায়ী কাজ করে নি তখন প্রচুর ব্যথাও হয়েছিল।

আমি মনে করি পিআইএক্সের সাথে পরামর্শটি আসলে একটি ভাল। শেডারের এসেম্বলারের নির্দেশাবলী আপনাকে গণ্ডগোল করতে হবে না, তবে আপনি ছায়া মানচিত্র এবং অন্যান্য লক্ষ্যগুলি রেন্ডার করতে পারেন, একটি পিক্সেল নির্বাচন করতে পারেন এবং এর পিক্সেল শেডারটি কল করতে পারেন এবং এটির মধ্য দিয়ে এবং এটির ভার্টেক্স-শেডারটিও দেখতে পারেন।

এই জাতীয় পরিস্থিতিতে সাধারণ ডিবাগ কৌশলগুলি দৃশ্যের সরলীকরণ অন্তর্ভুক্ত।

আমার মনে যেটি আসে তা হ'ল: ক্যামেরাটি আলোক উত্সের মতো একই ফভি এবং অন্যান্য বৈশিষ্ট্যযুক্ত আলোর উত্সের মতো একই স্থানে রাখুন। এখন আপনি পিক্সেল-শেডারের মানগুলি সহজেই তুলনা করতে পারবেন। আপনার বর্তমান অবজেক্টের জন্য সাধারণ রেন্ডার-পাসের পিক্সেল-এক্সটি শ্যাডম্যাপে দেখার জন্য গণনা করা পিক্সেল-এক্সের সমান হওয়া উচিত, যতক্ষণ না এর রেজোলিউশন একই থাকে।

আর একটি হ'ল অর্থোগ্রাফিক প্রোজেকশনে স্যুইচ করা, সহজ, অনুমানযোগ্য এবং চেকযোগ্য কিছু রেন্ডার করুন। যত সহজ আপনি প্রতিটি গণনার পদক্ষেপ পরীক্ষা করতে পারেন।

এগুলি ছাড়াও, আপনি কীভাবে ম্যাট্রিক্স তৈরি করতে পারেন যা বর্তমান পিক্সেলের জন্য ছায়া-মানচিত্রে অবস্থান গণনা করে, এটি পর্দা-স্থান থেকে আলোক-স্পেসে রূপান্তর?


কেবল ছায়া মানচিত্রটি দেখলে একটি প্যারাব্লয়েড, এটি ডিবাগ করা আরও শক্ত করে তোলে এবং ছায়া-মানচিত্রে পিক্সেল অবস্থান এবং অবস্থানের তুলনা করতে লাইট পজিশনে ক্যামেরা স্থাপন করা ধারণাটি কোনও কাজ করবে না, :)
মাইক সেমদার

আপনি যদি আগ্রহী হন তবে আমাকে kris@olhovsky.com এ একটি ইমেল প্রেরণ করুন, এবং আমি আমার প্রকল্পের একটি অনুলিপি দিয়ে জবাব দেব। অন্যথায়: CameraTransformম্যাট্রিক্স আসলে দৃশ্যটি দেখছে এমন ক্যামেরার বিশ্ব ম্যাট্রিক্স। LightViewProjম্যাট্রিক্স আসলে আলোর বিশ্বের ম্যাট্রিক্স হিসাবে আলোর দৃশ্য ম্যাট্রিক্স মাত্র পরিচয় ম্যাট্রিক্স হয়।
ওলহভস্কি

আপনি কি এটি দিয়ে একটি সাধারণ সি ++ প্রকল্প তৈরি করতে পারেন? প্যারাব্লয়েড রূপান্তর জড়িত থাকতে হবে?
মাইক সেমদার

প্যারাবোলয়েড রূপান্তরটি আমি প্রশ্নের সাথে সংযুক্ত পিক্সেল শেডারে der আমার সি ++ দক্ষতাগুলি একটি দ্রুত সি ++ প্রকল্পের ড্রাম আপের মধ্যে সীমাবদ্ধ যা আমার মনে হয় পুরো বিলম্বিত রেন্ডারিং পাইপলাইনকে আবদ্ধ করে তোলে :) তবে, আপনি যদি সি ++ নিয়ে দক্ষ হন তবে আমার মনে হয় আমার সি # কোড পড়া খুব বেশি কঠিন হওয়া উচিত নয়। বিশেষত যেহেতু বেশিরভাগ উদ্বেগ সত্যই পিক্সেল শেডারে এবং সম্ভবত ম্যাট্রিকগুলি এটিতে চলে গেছে।
ওলোভস্কি

আমি জি_এমডিভিউ এবং জি_এমডিপি ওয়ার্ল্ডভিউতে উল্লেখ করছি। তারা কীভাবে গণনা করা যায় তা আপনি প্রদর্শন করতে পারেন।
মাইক সেমদার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.