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

এই পৃষ্ঠায় AGSL বেসিকগুলি এবং আপনার Android অ্যাপে AGSL ব্যবহার করার বিভিন্ন উপায় রয়েছে৷

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

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

কোটলিন

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 অবজেক্ট তৈরি করা। এটি শেডারকেও কম্পাইল করে।

কোটলিন

val fixedColorShader = RuntimeShader(COLOR_SHADER_SRC)

জাভা

RuntimeShader fixedColorShader = new RuntimeShader(COLOR_SHADER_SRC);

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

কোটলিন

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 যোগ করুন:

কোটলিন

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 কল করুন।

কোটলিন

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

জাভা

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

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

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

কোটলিন

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" +
   "}";

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

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

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

কোটলিন

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 ইউনিফর্ম পেতে এটি পরিবর্তন করে শেডারকে অ্যানিমেট করতে একটি অনুরূপ কৌশল ব্যবহার করতে পারেন। শেডার রংগুলির জন্য একটি ত্রিভুজাকার তরঙ্গ তৈরি করতে এই মানগুলি ব্যবহার করবে, যার ফলে তারা তাদের গ্রেডিয়েন্ট মান জুড়ে পিছনে ঘুরবে।

কোটলিন

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 ইউনিফর্ম আপডেট করে।

কোটলিন

// 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

কোটলিন

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 ঘূর্ণনের জন্য একটি ম্যাট্রিক্স আপডেট করতে পারেন।

কোটলিন

// 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 ঘূর্ণনের কেন্দ্র হয় পাঠ্যটি পর্দায় আঁকা হয়।

কোটলিন

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 রচনার সাথে 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 এ প্রয়োগ করতে পারেন। তারপর আপনি আপনার Canvas ড্র স্কোপের মধ্যে অঙ্কন কমান্ডের প্যারামিটার হিসাবে ShaderBrush ব্যবহার করুন।

// 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 ব্যবহার করা

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

কোটলিন

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

জাভা

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

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

uniform shader background;       // Root node of View tree to be altered
return mix(returnColor, background.eval(fragCoord), 0.5);
বোতামের উপর গ্রিড মিশ্রিত
AGSL গ্রিড মিশ্রিত বোতামের উপর

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