আমি অ্যান্ড্রয়েডে ক্যারেক্টার স্কিনিং কাজ করার চেষ্টা করছি।
ধারণাটি বেশ ভ্যানিলা: আমার স্কিনিং ম্যাট্রিক্স রয়েছে এবং প্রতিটি শীর্ষবিন্দু সহ আমি চারটি ম্যাট্রিক্স সূচক এবং চারটি সম্পর্কিত ওজন প্রেরণ করি। আমি তাদেরকে ভার্টেক্স শ্যাডারে সংযুক্ত করে প্রতিটি প্রান্তে এগুলি প্রয়োগ করি।
আমার গেমের আইওএস সংস্করণে আমি ভার্টেক্স শ্যাডারে এটি করছি (নরমালগুলিতে কিছু মনে করবেন না):
attribute vec4 in_pos;
attribute vec4 in_normal;
attribute vec2 in_texture_coords;
attribute vec4 in_bone_index;
attribute vec4 in_bone_weight;
varying vec2 fs_texture_coords;
uniform mat4 world_view_projection;
uniform mat4 bones[@bind_matrix_count];
void main()
{
// Skinning
vec4 transformed_pos =
((in_pos * bones[int(in_bone_index.x)]) * in_bone_weight.x) +
((in_pos * bones[int(in_bone_index.y)]) * in_bone_weight.y) +
((in_pos * bones[int(in_bone_index.z)]) * in_bone_weight.z) +
((in_pos * bones[int(in_bone_index.w)]) * in_bone_weight.w);
gl_Position = world_view_projection * transformed_pos;
fs_texture_coords = in_texture_coords;
}
এবং এটি বেশ ভাল কাজ করে। তবে অ্যান্ড্রয়েডে একই কোড সহ কিছু ডিভাইসে (উল্লেখযোগ্যভাবে Nexus 7 2013), আপনি uniform
অ ধ্রুবক সূচকগুলি দিয়ে অ্যাক্সেস করতে পারবেন না । অন্য পদগুলিতে, আপনি এটি করতে পারবেন না:
bones[int(in_bone_index.w)]
কারণ bones[some_non_constant]
সর্বদা হিসাবে মূল্যায়ন করা হয় bones[0]
, যা মোটেও মজাদার নয়। সবচেয়ে খারাপটি হ'ল শেডার সংকলক আনন্দের সাথে এটি সংকলন করে।
এই লোকটির মনে হয়েছিল ঠিক একই সমস্যা আছে have তিনি ম্যাট্রিকের পরিবর্তে ভেক্টর হিসাবে ইউনিফর্মটি অ্যাক্সেস করে সমাধান করেছেন। আমি একই কাজ করেছি, এবং বাস্তবে এটি কাজ করেছিল!
attribute vec4 in_pos;
attribute vec4 in_normal;
attribute vec2 in_texture_coords;
attribute vec4 in_bone_index;
attribute vec4 in_bone_weight;
varying vec2 fs_texture_coords;
uniform mat4 world_view_projection;
uniform vec4 bones[@bind_matrix_count * 4]; // four vec4's for each matrix
void main()
{
// Skinning
mat4 skin_0 = mat4(
bones[4 * int(in_bone_index.x) + 0],
bones[4 * int(in_bone_index.x) + 1],
bones[4 * int(in_bone_index.x) + 2],
bones[4 * int(in_bone_index.x) + 3]);
mat4 skin_1 = mat4(
bones[4 * int(in_bone_index.y) + 0],
bones[4 * int(in_bone_index.y) + 1],
bones[4 * int(in_bone_index.y) + 2],
bones[4 * int(in_bone_index.y) + 3]);
mat4 skin_2 = mat4(
bones[4 * int(in_bone_index.z) + 0],
bones[4 * int(in_bone_index.z) + 1],
bones[4 * int(in_bone_index.z) + 2],
bones[4 * int(in_bone_index.z) + 3]);
mat4 skin_3 = mat4(
bones[4 * int(in_bone_index.w) + 0],
bones[4 * int(in_bone_index.w) + 1],
bones[4 * int(in_bone_index.w) + 2],
bones[4 * int(in_bone_index.w) + 3]);
vec4 transformed_pos =
((in_pos * skin_0) * in_bone_weight.x) +
((in_pos * skin_1) * in_bone_weight.y) +
((in_pos * skin_2) * in_bone_weight.z) +
((in_pos * skin_3) * in_bone_weight.w);
gl_Position = world_view_projection * transformed_pos;
fs_texture_coords = in_texture_coords;
}
তবে আমি মনে করি এটি সুযোগ হিসাবে কাজ করেছে। uniform
গুলি এলোমেলোভাবে অ্যাক্সেস করার অর্থ নয়, তাই আমি আশঙ্কা করি যে এই "কৌশল" প্রতিটি ডিভাইসে কাজ করবে না।
এই লোকটি তার ম্যাট্রিকগুলি টেক্সচার হিসাবে পাস করছে, এটি একটি দুর্দান্ত ধারণা। আমি একটি 4x32 OES_texture_float টেক্সচার তৈরি করেছি, যেখানে প্রতিটি টেক্সেল একটি ম্যাট্রিক্স সারি এবং প্রতিটি টেক্সচার সারি একটি সম্পূর্ণ ম্যাট্রিক্স। আমি এটিতে এটি অ্যাক্সেস করি:
attribute vec4 in_pos;
attribute vec4 in_normal;
attribute vec2 in_texture_coords;
attribute vec4 in_bone_index;
attribute vec4 in_bone_weight;
varying vec2 fs_texture_coords;
uniform mat4 world_view_projection; // A texture!
uniform sampler2D bones;
void main()
{
// Skinning
mat4 bone0 = mat4(
texture2D(bones, vec2(0.00, in_bone_index.x / 32.0)),
texture2D(bones, vec2(0.25, in_bone_index.x / 32.0)),
texture2D(bones, vec2(0.50, in_bone_index.x / 32.0)),
texture2D(bones, vec2(0.75, in_bone_index.x / 32.0)));
mat4 bone1 = mat4(
texture2D(bones, vec2(0.00, in_bone_index.y / 32.0)),
texture2D(bones, vec2(0.25, in_bone_index.y / 32.0)),
texture2D(bones, vec2(0.50, in_bone_index.y / 32.0)),
texture2D(bones, vec2(0.75, in_bone_index.y / 32.0)));
mat4 bone2 = mat4(
texture2D(bones, vec2(0.00, in_bone_index.z / 32.0)),
texture2D(bones, vec2(0.25, in_bone_index.z / 32.0)),
texture2D(bones, vec2(0.50, in_bone_index.z / 32.0)),
texture2D(bones, vec2(0.75, in_bone_index.z / 32.0)));
mat4 bone3 = mat4(
texture2D(bones, vec2(0.00, in_bone_index.w / 32.0)),
texture2D(bones, vec2(0.25, in_bone_index.w / 32.0)),
texture2D(bones, vec2(0.50, in_bone_index.w / 32.0)),
texture2D(bones, vec2(0.75, in_bone_index.w / 32.0)));
vec4 transformed_pos =
((in_pos * bone0) * in_bone_weight.x) +
((in_pos * bone1) * in_bone_weight.y) +
((in_pos * bone2) * in_bone_weight.z) +
((in_pos * bone3) * in_bone_weight.w);
gl_Position = world_view_projection * transformed_pos;
fs_texture_coords = in_texture_coords;
}
প্রকৃতপক্ষে, এটি বেশ সুন্দর কাজ করেছে ... যতক্ষণ না আমি এটি আমার গ্যালাক্সি নোট 2 এ চেষ্টা করে দেখি এই বার সংকলকটি অভিযোগ করেছে যে আমি texture2D
ভার্টেক্স শেডারটিতে ব্যবহার করতে পারছি না !
সুতরাং আমি যা করছি তা যাচাই করা হচ্ছে জিপিইউ ভার্টেক্স শ্যাডারে টেক্সচার অ্যাক্সেসগুলি সমর্থন করে কিনা এবং যদি এটি OES_texture_float সমর্থন করে। যদি এটি হয়, আমি টেক্সচার পদ্ধতির ব্যবহার করছি। যদি এটি না হয় তবে আমি ভেক্টর পদ্ধতির ব্যবহার করছি।
যাইহোক, টেক্সচার পদ্ধতির সমস্ত প্ল্যাটফর্মগুলিতে পাওয়া যায় না এবং ভেক্টর পদ্ধতির সুযোগ অনুযায়ী কাজ করা হয়। আমি জানতে চাই যে আমার ত্বকের ম্যাট্রিক্সগুলি ভার্টেক্স শ্যাডারে পাস করার কোনও উপায় আছে কিনা, যা সমস্ত ডিভাইসে নির্ভরযোগ্যভাবে কাজ করে।
আমার অ্যান্ড্রয়েড ৪.১++ এর মতো ন্যূনতম যুক্তিসঙ্গত ওএস প্রয়োজনীয়তা থাকতে পারে তবে আমি এমন একটি সমাধান পেতে চাই যা সেই সমস্ত ডিভাইসে কাজ করে যা এই প্রয়োজনীয়তাগুলি পূরণ করে।