این صفحه اصول AGSL و روش های مختلف استفاده از 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
شما می تواند در هر جایی که یک سایه زن استاندارد اندروید می تواند استفاده شود. به عنوان مثال، میتوانید از آن برای کشیدن به یک View
سفارشی با استفاده از Canvas
استفاده کنید.
کاتلین
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" + "}";
سپس، setColorUniform
از View
سفارشی خود فراخوانی کنید تا رنگ مورد نظر را به سایه زن AGSL منتقل کنید.
کاتلین
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" + "}";
رسم گرادیان
این سایه زن چیزی کمی فانتزی انجام می دهد. برای هر پیکسل، یک بردار float2
ایجاد می کند که شامل مختصات x و y تقسیم بر وضوح است که مقداری بین صفر و یک ایجاد می کند. سپس از آن بردار مقیاس شده برای ساخت اجزای قرمز و سبز رنگ برگشتی استفاده می کند.
با فراخوانی setFloatUniform
، وضوح View
به یک uniform
AGSL منتقل میکنید.
کاتلین
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
داخلی بهروزرسانی کنید.
کاتلین
// 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();
استفاده از RuntimeShader با Jetpack Compose
اگر UI خود را با استفاده از Jetpack Compose رندر می کنید، استفاده از 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)
}
استفاده از RuntimeShader با RenderEffect
میتوانید از RenderEffect
برای اعمال RuntimeShader
به View
والد و همه نماهای فرزند استفاده کنید. این گرانتر از ترسیم View
سفارشی است. اما به شما این امکان را می دهد که به راحتی افکتی ایجاد کنید که آنچه را که در ابتدا با استفاده از createRuntimeShaderEffect
ترسیم شده است، در خود جای دهد.
کاتلین
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);
یک جلوه شبکه ای که روی یک دکمه ترکیب شده است، اما در زیر یک دکمه اکشن شناور (زیرا در یک سلسله مراتب View
متفاوت است).
محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند.
تاریخ آخرین بهروزرسانی 2024-11-13 بهوقت ساعت هماهنگ جهانی.