আপনার Android অ্যাপে AGSL ব্যবহার করা

এই পৃষ্ঠায় AGSL-এর প্রাথমিক বিষয় এবং আপনার Android অ্যাপে AGSL ব্যবহার করার বিভিন্ন উপায় কভার করা হয়েছে।

একটি সাধারণ AGSL শেডার

প্রতিটি আঁকা পিক্সেলের জন্য আপনার শেডার কোড কল করা হয় এবং পিক্সেলটি যে রঙে আঁকা উচিত তা রিটার্ন করে। একটি অত্যন্ত সহজ শেডার হল এমন একটি যা সর্বদা একটি রঙে ফিরে আসে; এই উদাহরণে লাল রঙ ব্যবহার করা হয়েছে। শেডারটি String-এর মধ্যে সংজ্ঞায়িত করা হয়েছে।

Kotlin

private const val COLOR_SHADER_SRC =
   """half4 main(float2 fragCoord) {
      return half4(1,0,0,1);
   }"""

জাভা

private static final String COLOR_SHADER_SRC =
   "half4 main(float2 fragCoord) {\n" +
      "return half4(1,0,0,1);\n" +
   "}";

পরবর্তী ধাপ হল আপনার শেডার স্ট্রিং দিয়ে শুরু করা একটি RuntimeShader অবজেক্ট তৈরি করা। এটি শেডার কম্পাইলও করে।

Kotlin

val fixedColorShader = RuntimeShader(COLOR_SHADER_SRC)

জাভা

RuntimeShader fixedColorShader = new RuntimeShader(COLOR_SHADER_SRC);

স্ট্যান্ডার্ড Android শেডার যেখানে ব্যবহার করা যায়, সেখানে আপনার RuntimeShader ব্যবহার করা যাবে। উদাহরণস্বরূপ, Canvas ব্যবহার করে কাস্টম View-এ আঁকার জন্য আপনি এটি ব্যবহার করতে পারেন।

Kotlin

val paint = Paint()
paint.shader = fixedColorShader
override fun onDrawForeground(canvas: Canvas?) {
   canvas?.let {
      canvas.drawPaint(paint) // fill the Canvas with the shader
   }
}

জাভা

Paint paint = new Paint();
paint.setShader(fixedColorShader);
public void onDrawForeground(@Nullable Canvas canvas) {
   if (canvas != null) {
      canvas.drawPaint(paint); // fill the Canvas with the shader
   }
}

এটি একটি লাল View আঁকে। আপনি uniform ব্যবহার করে শেডারে কালার প্যারামিটার পাস করতে পারেন। প্রথমে, শেডারে uniform রঙ যোগ করুন:

Kotlin

private const val COLOR_SHADER_SRC =
"""layout(color) uniform half4 iColor;
   half4 main(float2 fragCoord) {
      return iColor;
   }"""

জাভা

private static final String COLOR_SHADER_SRC =
   "layout(color) uniform half4 iColor;\n"+
      "half4 main(float2 fragCoord) {\n" +
      "return iColor;\n" +
   "}";

তারপর, AGSL শেডারে কাঙ্খিত রঙ পাস করতে আপনার কাস্টম View থেকে setColorUniform কল করুন।

Kotlin

fixedColorShader.setColorUniform("iColor", Color.GREEN )

জাভা

fixedColorShader.setColorUniform("iColor", Color.GREEN );

এখন, আপনি একটি সবুজ View পাবেন; View-এর রঙ শেডারে এম্বেড করার পরিবর্তে আপনার কাস্টম View-এর কোড থেকে প্যারামিটার ব্যবহার করে নিয়ন্ত্রণ করা হয়।

পরিবর্তে আপনি রঙের সমাহার এফেক্ট তৈরি করতে পারেন। ইনপুট হিসেবে View রেজোলিউশন গ্রহণ করতে আপনাকে প্রথমে শেডার পরিবর্তন করতে হবে:

Kotlin

private const val COLOR_SHADER_SRC =
"""uniform float2 iResolution;
   half4 main(float2 fragCoord) {
      float2 scaled = fragCoord/iResolution.xy;
      return half4(scaled, 0, 1);
   }"""

জাভা

private static final String COLOR_SHADER_SRC =
   "uniform float2 iResolution;\n" +
      "half4 main(float2 fragCoord) {\n" +
      "float2 scaled = fragCoord/iResolution.xy;\n" +
      "return half4(scaled, 0, 1);\n" +
   "}";

গ্রেডিয়েন্ট আঁকা হচ্ছে

এই শেডার একটু অভিনব কিছু করে। প্রতিটি পিক্সেলের জন্য, এটি একটি float2 ভেক্টর তৈরি করে যাতে রেজোলিউশন দ্বারা বিভক্ত x এবং y কোঅর্ডিনেট থাকে, যা শূন্য এবং একের মধ্যে একটি মান তৈরি করবে। তারপর, এটি সেই স্কেল করা ভেক্টর ব্যবহার করে রিটার্ন রঙের লাল এবং সবুজ উপাদান তৈরি করে।

setFloatUniform কল করে আপনি View-এর রেজোলিউশন AGSL শেডার uniform-এ পাস করেন।

Kotlin

val paint = Paint()
paint.shader = fixedColorShader
override fun onDrawForeground(canvas: Canvas?) {
   canvas?.let {
      fixedColorShader.setFloatUniform("iResolution", width.toFloat(), height.toFloat())
      canvas.drawPaint(paint)
   }
}

জাভা

Paint paint = new Paint();
paint.setShader(fixedColorShader);
public void onDrawForeground(@Nullable Canvas canvas) {
   if (canvas != null) {
      fixedColorShader.setFloatUniform("iResolution", (float)getWidth(), (float()getHeight()));
      canvas.drawPaint(paint);
   }
}
লাল ও সবুজ গ্রেডিয়েন্ট
লাল ও সবুজ গ্রেডিয়েন্ট

শেডার অ্যানিমেট করা হচ্ছে

আপনি একই ধরনের টেকনিক ব্যবহার করে শেডার অ্যানিমেট করতে পারেন, এর জন্য আপনাকে iTime এবং iDuration ইউনিফর্ম রিসিভ করার জন্য এটি পরিবর্তন করতে হবে। শেডার এই ভ্যালু ব্যবহার করে রঙের জন্য একটি ত্রিভুজাকার তরঙ্গ তৈরি করবে, যার ফলে সেগুলি তাদের গ্রেডিয়েন্ট ভ্যালু জুড়ে চক্রাকারে ঘুরতে থাকবে।

Kotlin

private const val DURATION = 4000f
private const val COLOR_SHADER_SRC = """
   uniform float2 iResolution;
   uniform float iTime;
   uniform float iDuration;
   half4 main(in float2 fragCoord) {
      float2 scaled = abs(1.0-mod(fragCoord/iResolution.xy+iTime/(iDuration/2.0),2.0));
      return half4(scaled, 0, 1.0);
   }
"""

জাভা

private static final float DURATION = 4000f;
private static final String COLOR_SHADER_SRC =
   "uniform float2 iResolution;\n"+
   "uniform float iTime;\n"+
   "uniform float iDuration;\n"+
   "half4 main(in float2 fragCoord) {\n"+
      "float2 scaled = abs(1.0-mod(fragCoord/iResolution.xy+iTime/(iDuration/2.0),2.0));\n"+
      "return half4(scaled, 0, 1.0);\n"+
   "}";

কাস্টম ভিউ সোর্স কোড থেকে, একটি ValueAnimator iTime ইউনিফর্ম আপডেট করে।

Kotlin

// declare the ValueAnimator
private val shaderAnimator = ValueAnimator.ofFloat(0f, DURATION)

// use it to animate the time uniform
shaderAnimator.duration = DURATION.toLong()
shaderAnimator.repeatCount = ValueAnimator.INFINITE
shaderAnimator.repeatMode = ValueAnimator.RESTART
shaderAnimator.interpolator = LinearInterpolator()

animatedShader.setFloatUniform("iDuration", DURATION )
shaderAnimator.addUpdateListener { animation ->
    animatedShader.setFloatUniform("iTime", animation.animatedValue as Float )
}
shaderAnimator.start()

জাভা

// declare the ValueAnimator
private final ValueAnimator shaderAnimator = ValueAnimator.ofFloat(0f, DURATION);

// use it to animate the time uniform
shaderAnimator.setDuration((long)DURATION);
shaderAnimator.setRepeatCount(ValueAnimator.INFINITE);
shaderAnimator.setRepeatMode(ValueAnimator.RESTART);
shaderAnimator.setInterpolator(new LinearInterpolator());

animatedShader.setFloatUniform("iDuration", DURATION );
shaderAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
   public final void onAnimationUpdate(ValueAnimator animation) {
      animatedShader.setFloatUniform("iTime", (float)animation.getAnimatedValue());
   }
});
লাল ও সবুজ অ্যানিমেটেড গ্রেডিয়েন্ট
লাল ও সবুজ অ্যানিমেটেড গ্রেডিয়েন্ট

জটিল অবজেক্ট আঁকা

ব্যাকগ্রাউন্ড পূরণ করার জন্য আপনাকে শেডার আঁকতে হবে না; এটি এমন যেকোনও জায়গায় ব্যবহার করা যেতে পারে যেখানে Paint অবজেক্ট গ্রহণ করা হয়, যেমন drawText।

Kotlin

canvas.drawText(ANIMATED_TEXT, TEXT_MARGIN_DP, TEXT_MARGIN_DP + bounds.height(),
   paint)

জাভা

canvas.drawText(ANIMATED_TEXT, TEXT_MARGIN_DP, TEXT_MARGIN_DP + bounds.height(),
   paint);
লাল ও সবুজ অ্যানিমেটেড গ্রেডিয়েন্ট টেক্সট
লাল ও সবুজ অ্যানিমেটেড গ্রেডিয়েন্ট টেক্সট

শেডিং ও ক্যানভাস ট্রান্সফর্মেশন

আপনি শেড করা টেক্সটে অতিরিক্ত Canvas ট্রান্সফর্মেশন প্রয়োগ করতে পারেন, যেমন ঘোরানো। ValueAnimator-এ, আপনি বিল্ট-ইন android.graphics.Camera ক্লাস ব্যবহার করে 3D রোটেশনের জন্য ম্যাট্রিক্স আপডেট করতে পারবেন।

Kotlin

// in the ValueAnimator
camera.rotate(0.0f, animation.animatedValue as Float / DURATION * 360f, 0.0f)

জাভা

// in the ValueAnimator
camera.rotate(0.0f, (Float)animation.getAnimatedValue() / DURATION * 360f, 0.0f);

আপনি যেহেতু টেক্সটটি কোণের অক্ষের পরিবর্তে কেন্দ্র অক্ষ থেকে ঘোরাতে চান, তাই টেক্সটের বাউন্ড পান এবং তারপরে preTranslate ও postTranslate ব্যবহার করে ম্যাট্রিক্স পরিবর্তন করে টেক্সট অনুবাদ করুন যাতে স্ক্রিনে টেক্সটটি যে অবস্থানে আঁকা হয়েছে তা পরিবর্তন না করেই 0,0 হল ঘোরানোর কেন্দ্র।

Kotlin

linearColorPaint.getTextBounds(ANIMATED_TEXT, 0, ANIMATED_TEXT.length, bounds)
camera.getMatrix(rotationMatrix)
val centerX = (bounds.width().toFloat())/2
val centerY = (bounds.height().toFloat())/2
rotationMatrix.preTranslate(-centerX, -centerY)
rotationMatrix.postTranslate(centerX, centerY)
canvas.save()
canvas.concat(rotationMatrix)
canvas.drawText(ANIMATED_TEXT, 0f, 0f + bounds.height(), paint)
canvas.restore()

জাভা

linearColorPaint.getTextBounds(ANIMATED_TEXT, 0, ANIMATED_TEXT.length(), bounds);
camera.getMatrix(rotationMatrix);
float centerX = (float)bounds.width()/2.0f;
float centerY = (float)bounds.height()/2.0f;
rotationMatrix.preTranslate(-centerX, -centerY);
rotationMatrix.postTranslate(centerX, centerY);
canvas.save();
canvas.concat(rotationMatrix);
canvas.drawText(ANIMATED_TEXT, 0f, 0f + bounds.height(), paint);
canvas.restore();
লাল ও সবুজ রঙের রোটেটিং অ্যানিমেটেড গ্রেডিয়েন্ট টেক্সট
লাল ও সবুজ রঙের রোটেট করা অ্যানিমেটেড গ্রেডিয়েন্ট টেক্সট

Jetpack Compose-এর সাথে RuntimeShader ব্যবহার করা

Jetpack Compose ব্যবহার করে আপনার UI রেন্ডার করলে, RuntimeShader ব্যবহার করা আরও সহজ হয়। আগের মতো একই গ্রেডিয়েন্ট শেডার দিয়ে শুরু করা যাক:

private const val COLOR_SHADER_SRC =
    """uniform float2 iResolution;
   half4 main(float2 fragCoord) {
   float2 scaled = fragCoord/iResolution.xy;
   return half4(scaled, 0, 1);
}"""

আপনি সেই শেডারকে ShaderBrush-এ প্রয়োগ করতে পারবেন। আপনি তারপরে ShaderBrush-কে আপনার Canvas-এর ড্র স্কোপের মধ্যে ড্রয়িং কমান্ডের প্যারামিটার হিসেবে ব্যবহার করেন।

// created as top level constants
val colorShader = RuntimeShader(COLOR_SHADER_SRC)
val shaderBrush = ShaderBrush(colorShader)

Canvas(
   modifier = Modifier.fillMaxSize()
) {
   colorShader.setFloatUniform("iResolution",
   size.width, size.height)
   drawCircle(brush = shaderBrush)
}
AGSL কম্পোজ গ্রেডিয়েন্ট সার্কেল
লাল ও সবুজ গ্রেডিয়েন্ট বৃত্ত

RenderEffect-এর সাথে RuntimeShader ব্যবহার করা

আপনি RenderEffect ব্যবহার করে RuntimeShader প্যারেন্ট View এবং সব চাইল্ড ভিউতে প্রয়োগ করতে পারবেন। এটি কাস্টম View আঁকার চেয়ে বেশি ব্যয়বহুল। কিন্তু এটি আপনাকে সহজেই এমন একটি এফেক্ট তৈরি করতে দেয় যা createRuntimeShaderEffect ব্যবহার করে মূলত যা আঁকা হতো তা অন্তর্ভুক্ত করে।

Kotlin

view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"))

জাভা

view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"));

দ্বিতীয় প্যারামিটার হল শেডার ইউনিফর্মের নাম যা আপনি কোঅর্ডিনেট প্যারামিটারের (যেমন, fragCoord-এ পাস করা) সাথে eval করতে পারবেন যাতে RenderNode (ভিউ ও তার চাইল্ড ভিউ)-এর আসল রঙ পাওয়া যায়, এর ফলে আপনি সব ধরনের এফেক্ট পারফর্ম করতে পারবেন।

uniform shader background;       // Root node of View tree to be altered
return mix(returnColor, background.eval(fragCoord), 0.5);
বোতামের উপর গ্রিড ব্লেন্ড করা হয়েছে
AGSL গ্রিড ব্লেন্ডেড ওভার বোতাম

একটি বোতামের উপর গ্রিড এফেক্ট মিক্স করা হয়েছে, তবে ফ্লোটিং অ্যাকশন বোতামের নিচে (কারণ এটি একটি ভিন্ন View হায়ারার্কিতে রয়েছে)।