2017-12-10 93 views
9

पर UINT8 घटक प्रकार के साथ बनावट बनावट मेरे पास एक छवि है जिसे मैं प्रोग्रामेटिक रूप से उत्पन्न करता हूं और मैं इस छवि को एक गणना शेडर को बनावट के रूप में भेजना चाहता हूं। जिस तरह से मैं इस छवि को उत्पन्न करता हूं वह यह है कि मैं प्रत्येक आरजीबीए घटकों की गणना UInt8 मानों के रूप में करता हूं, और उन्हें UInt32 में जोड़ता हूं और इसे छवि के बफर में संग्रहीत करता हूं। मैं कोड का निम्न भाग के साथ ऐसा कर:धातु कंप्यूट शेडर

guard let cgContext = CGContext(data: nil, 
           width: width, 
           height: height, 
           bitsPerComponent: 8, 
           bytesPerRow: 0, 
           space: CGColorSpaceCreateDeviceRGB(), 
           bitmapInfo: RGBA32.bitmapInfo) else { 
            print("Unable to create CGContext") 
            return 
} 

guard let buffer = cgContext.data else { 
    print("Unable to create textures") 
    return 
} 
let pixelBuffer = buffer.bindMemory(to: RGBA32.self, capacity: width * height) 
let heightFloat = Float(height) 
let widthFloat = Float(width) 
for i in 0 ..< height { 
    let latitude = Float(i + 1)/heightFloat 
    for j in 0 ..< width { 
    let longitude = Float(j + 1)/widthFloat 
    let x = UInt8(((sin(longitude * Float.pi * 2) * cos(latitude * Float.pi) + 1)/2) * 255) 
    let y = UInt8(((sin(longitude * Float.pi * 2) * sin(latitude * Float.pi) + 1)/2) * 255) 
    let z = UInt8(((cos(latitude * Float.pi) + 1)/2) * 255) 
    let offset = width * i + j 
    pixelBuffer[offset] = RGBA32(red: x, green: y, blue: z, alpha: 255) 
    } 
} 

let coordinateConversionImage = cgContext.makeImage() 

जहां RGBA32 एक छोटे से struct कि स्थानांतरण और UInt32 मूल्य बनाने करता है। यह छवि ठीक हो गई है क्योंकि मैं इसे UIImage में परिवर्तित कर सकता हूं और इसे अपनी फोटो लाइब्रेरी में सहेज सकता हूं।

समस्या उत्पन्न होती है जब मैं इस छवि को एक गणना शेडर को बनावट के रूप में भेजने की कोशिश करता हूं। नीचे मेरी शेडर कोड है:

kernel void updateEnvironmentMap(texture2d<uint, access::read> currentFrameTexture [[texture(0)]], 
           texture2d<uint, access::read> coordinateConversionTexture [[texture(1)]], 
           texture2d<uint, access::write> environmentMap [[texture(2)]] 
           uint2 gid [[thread_position_in_grid]]) 
{ 
    const uint4 pixel = {255, 127, 63, 255}; 
    environmentMap.write(pixel, gid); 
} 

इस कोड के साथ समस्या यह है कि मेरी बनावट के प्रकार uint है, जो कि 32-बिट, और मैं 32-बिट पिक्सल उसी तरह मैं पर क्या उत्पन्न करना चाहते है सीपीयू, 4 8-बिट मानों को जोड़कर। हालांकि, मैं धातु पर ऐसा नहीं कर सकता क्योंकि byte प्रकार है कि मैं सिर्फ एक साथ जोड़ सकता हूं और uint32 बना सकता हूं। तो, मेरा सवाल यह है कि 2 डी बनावट को संभालने और मेटल कंप्यूट शेडर पर 32-बिट पिक्सेल सेट करने का सही तरीका क्या है?

बोनस प्रश्न: इसके अलावा, मैंने इनपुट बनावट प्रकार के रूप में texture2d<float, access::read> के साथ उदाहरण शेडर कोड देखे हैं। मुझे लगता है कि यह 0.0 और 1.0 के बीच एक मान का प्रतिनिधित्व करता है लेकिन 0 और 255 के बीच मूल्यों के साथ एक असाइन किए गए int पर इसका क्या लाभ है?

संपादित करें: स्पष्टीकरण के लिए, शेडर के आउटपुट बनावट, environmentMap, इनपुट बनावट के समान सटीक गुण (चौड़ाई, ऊंचाई, पिक्सेलफॉर्मैट, आदि) है। मुझे लगता है कि यह काउंटर अंतर्ज्ञानी है कि हम uint4 को एक पिक्सेल के रूप में सेट कर रहे हैं, जिसका अर्थ है कि यह 4 32-बिट मानों से बना है, जबकि प्रत्येक पिक्सेल 32-बिट होना चाहिए। इस वर्तमान कोड के साथ, {255, 127, 63, 255} का सटीक परिणाम {2550, 127, 63, 255} है, जिसका अर्थ यह है कि आउटपुट बनावट में लिखे जाने से पहले मानों को 0-255 के बीच क्लैंप किया जाता है। लेकिन यह बेहद प्रतिद्वंद्वी है।

उत्तर

8

आपके साथ परिचित होने की तुलना में खेलने में थोड़ा और जादू है, इसलिए मैं स्पष्ट करने की कोशिश करूंगा।

सबसे पहले, डिज़ाइन द्वारा, धातु में बनावट के भंडारण प्रारूप और आपके द्वारा पढ़ने/नमूने के दौरान प्राप्त होने वाले प्रकार के बीच एक ढीला कनेक्शन होता है। आपके पास .bgra8Unorm प्रारूप में एक बनावट हो सकती है, जब texture2d<float, access::sample> के रूप में बाध्य बनावट के माध्यम से नमूनाकरण किया जाता है तो आपको float4 आपको RGBA ऑर्डर में इसके घटकों के साथ float4 देगा। उन पैक किए गए बाइट्स से फ्लोट वेक्टर तक स्विफ्ट किए गए घटकों के साथ रूपांतरण धातु छायांकन भाषा विशिष्टता में निर्दिष्ट अनुसार अच्छी तरह से प्रलेखित रूपांतरण नियमों का पालन करता है।

यह भी मामला है कि जब एक बनावट को लिखते हैं जिसका भंडारण (उदाहरण के लिए) 8 बिट प्रति घटक है, तो मूल्य अंतर्निहित स्टोरेज प्रारूप में फिट होने के लिए क्लैंप किए जाएंगे। यह norm प्रकार का बना है या नहीं: यदि प्रारूप में norm है, तो मानों का अर्थ यह है कि उन्होंने 0 और 1 के बीच मान निर्दिष्ट किया है। अन्यथा, आपके द्वारा पढ़े गए मान सामान्य नहीं हैं।

एक उदाहरण: अगर एक बनावट .bgra8Unorm है और किसी दिए गए पिक्सेल बाइट [0, 64, 128, 255] को महत्व देता है, तो जब एक शेडर कि float घटकों का अनुरोध करता है में पढ़ा है, तो आपको [0.5, 0.25, 0, 1.0] मिल जाएगा जब आप इसे स्वाद लें। इसके विपरीत, यदि प्रारूप .rgba8Uint है, तो आपको [0, 64, 128, 255] मिल जाएगा।बनावट के भंडारण प्रारूप पर नमूनाकरण पर इसकी सामग्रियों का व्याख्या कैसे किया जाता है, इस पर एक प्रचलित प्रभाव पड़ता है।

मुझे लगता है कि आपके बनावट का पिक्सेल प्रारूप .rgba8Unorm जैसा कुछ है। अगर ऐसी बात है, तो आप प्राप्त कर सकते हैं इस तरह से अपनी गिरी लिख कर आप क्या चाहते हैं:

kernel void updateEnvironmentMap(texture2d<float, access::read> currentFrameTexture [[texture(0)]], 
           texture2d<float, access::read> coordinateConversionTexture [[texture(1)]], 
           texture2d<float, access::write> environmentMap [[texture(2)]] 
           uint2 gid [[thread_position_in_grid]]) 
{ 
    const float4 pixel(255, 127, 63, 255); 
    environmentMap.write(pixel * (1/255.0), gid); 
} 

इसके विपरीत, अगर आपके बनावट .rgba8Uint का एक ही प्रारूप है, आप एक ही प्रभाव इस तरह यह लिख कर दी जाएगी:

kernel void updateEnvironmentMap(texture2d<float, access::read> currentFrameTexture [[texture(0)]], 
           texture2d<float, access::read> coordinateConversionTexture [[texture(1)]], 
           texture2d<float, access::write> environmentMap [[texture(2)]] 
           uint2 gid [[thread_position_in_grid]]) 
{ 
    const float4 pixel(255, 127, 63, 255); 
    environmentMap.write(pixel, gid); 
} 

मैं समझता हूँ कि यह एक खिलौना उदाहरण है, लेकिन मुझे आशा है कि पूर्वगामी जानकारी के साथ आप पता लगा सकते हैं कि कैसे सही ढंग से स्टोर करने के लिए और नमूना मूल्यों को प्राप्त करने के लिए आप क्या चाहते हैं।

+0

धन्यवाद वॉरेन, इसने कई चीजों को मंजूरी दे दी। इसके अलावा, अगर कोई इस पर और जानकारी चाहता है, तो धातु छायांकन भाषा विशिष्टता के अध्याय 7.7 बनावट का पता लगाने और रूपांतरण नियम देखने के लिए जगह है। – halileohalilei

संबंधित मुद्दे