تتناول هذه الصفحة أساسيات AGSL وطرقًا مختلفة لاستخدام AGSL في جهاز Android. التطبيق.
أداة تظليل AGSL بسيطة
يتم طلب رمز أداة التظليل لكل وحدة بكسل مرسومة، ويتم عرض لون البكسل.
به. أداة التظليل البسيطة للغاية هي التي يتم إرجاعها دائمًا
لون واحد؛ هذا المثال يستخدم اللون الأحمر. يتم تحديد أداة التظليل داخل String
.
Kotlin
private const val COLOR_SHADER_SRC = """half4 main(float2 fragCoord) { return half4(1,0,0,1); }"""
Java
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)
Java
RuntimeShader fixedColorShader = new RuntimeShader(COLOR_SHADER_SRC);
يمكن استخدام RuntimeShader
في أي مكان تتوفّر فيه أداة تظليل Android العادية. على سبيل المثال،
على سبيل المثال، يمكنك استخدامه للرسم إلى View
مخصّص باستخدام
Canvas
Kotlin
val paint = Paint() paint.shader = fixedColorShader override fun onDrawForeground(canvas: Canvas?) { canvas?.let { canvas.drawPaint(paint) // fill the Canvas with the shader } }
Java
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; }"""
Java
private static final String COLOR_SHADER_SRC = "layout(color) uniform half4 iColor;\n"+ "half4 main(float2 fragCoord) {\n" + "return iColor;\n" + "}";
بعد ذلك، يمكنك طلب setColorUniform
من View
المخصّص لتمرير اللون المطلوب.
باستخدام أداة تظليل AGSL.
Kotlin
fixedColorShader.setColorUniform("iColor", Color.GREEN )
Java
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); }"""
Java
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 مقسومًا على الدقة،
سوف يُنشئ قيمة بين صفر وواحد. ثم تستخدم هذا الخط المتجه المُعدَّل
لإنشاء المكونات الحمراء والخضراء للون الإرجاع.
يمكنك تمرير درجة دقة View
إلى أداة تظليل AGSL uniform
من خلال استدعاء
setFloatUniform
Kotlin
val paint = Paint() paint.shader = fixedColorShader override fun onDrawForeground(canvas: Canvas?) { canvas?.let { fixedColorShader.setFloatUniform("iResolution", width.toFloat(), height.toFloat()) canvas.drawPaint(paint) } }
Java
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); } """
Java
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()
Java
// 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)
Java
canvas.drawText(ANIMATED_TEXT, TEXT_MARGIN_DP, TEXT_MARGIN_DP + bounds.height(), paint);
تحويلات التظليل ولوحة الرسم
يمكنك تطبيق عمليات تحويل Canvas
إضافية على النص المظلّل، مثل
تدوير. في ValueAnimator
، يمكنك تعديل مصفوفة لعمليات التدوير الثلاثية الأبعاد.
باستخدام الميزات
android.graphics.Camera
.
Kotlin
// in the ValueAnimator camera.rotate(0.0f, animation.animatedValue as Float / DURATION * 360f, 0.0f)
Java
// 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()
Java
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();
استخدام RuntimeShader مع Jetpack Compose
يمكنك الآن استخدام RuntimeShader
بسهولة أكبر إذا كنت تعرض واجهة المستخدم باستخدام
Jetpack Compose بدءًا من نفس تظليل التدرج من
:before
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)
}
استخدام RuntimeShader مع RenderEffect
يمكنك استخدام
RenderEffect
لتطبيق
RuntimeShader
إلى أحد الوالدين View
و جميع المشاهدات من قِبل الأطفال. هذا الإجراء أكثر تكلفة من رسم View
مخصّص. لكن
يسمح لك بإنشاء تأثير يتضمن بسهولة ما قد يكون
مرسومة في الأصل باستخدام
createRuntimeShaderEffect
Kotlin
view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"))
Java
view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"));
المَعلمة الثانية هي اسم موحد أداة التظليل الذي يمكنك eval
باستخدامه
المعلمة الإحداثية (مثل المعلمة التي يتم تمريرها في fragCoord) للحصول على اللون الأصلي
من
RenderNode
(العرض وعنصره الفرعي
المستخدم)، مما يتيح لك تنفيذ جميع أنواع التأثيرات.
uniform shader background; // Root node of View tree to be altered
return mix(returnColor, background.eval(fragCoord), 0.5);
تأثير شبكة ممتلئ على زر، ولكن أسفل زر إجراء عائم
(بما أنّها في تدرّج View
هرمي مختلف).