Bu sayfada AGSL ile ilgili temel bilgiler ve Android uygulamanızda AGSL'yi kullanmanın farklı yolları ele alınmaktadır.
Basit bir AGSL gölgelendirici
Gölgelendirici kodunuz, çizilen her piksel için çağrılır ve pikselin boyanması gereken rengi döndürür. Son derece basit bir gölgelendirici, her zaman tek bir renk
döndürür. Bu örnekte kırmızı kullanılmaktadır. Gölgelendirici, bir String
içinde tanımlanır.
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" + "}";
Sonraki adım, gölgelendirici dizenizle başlatılan bir RuntimeShader
nesnesi oluşturmaktır. Bu işlem ayrıca gölgelendiriciyi de derler.
Kotlin
val fixedColorShader = RuntimeShader(COLOR_SHADER_SRC)
Java
RuntimeShader fixedColorShader = new RuntimeShader(COLOR_SHADER_SRC);
RuntimeShader
cihazınız standart bir Android gölgelendiricinin kullanılabileceği her yerde kullanılabilir. Örnek olarak, Canvas
kullanarak özel bir View
içine çizim yapmak üzere bunu kullanabilirsiniz.
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 } }
Bu, kırmızı bir View
çizer. Çizilecek gölgelendiriciye bir renk parametresi geçirmek için uniform
kullanabilirsiniz. İlk olarak, gölgelendiriciye uniform
rengini ekleyin:
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" + "}";
Ardından, istediğiniz rengi AGSL gölgelendiricisine geçirmek üzere özel View
cihazınızdan setColorUniform
çağrısı yapın.
Kotlin
fixedColorShader.setColorUniform("iColor", Color.GREEN )
Java
fixedColorShader.setColorUniform("iColor", Color.GREEN );
Şimdi yeşil bir View
elde edersiniz; View
rengi, gölgelendiriciye yerleştirmek yerine özel View
kodunuzdaki bir parametre kullanılarak kontrol edilir.
Bunun yerine bir renk gradyanı efekti oluşturabilirsiniz. Öncelikle giriş olarak View
çözünürlüğünü kabul etmek için gölgelendiriciyi değiştirmeniz gerekir:
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" + "}";
Gradyanı çizme
Bu gölgelendirici biraz gösterişli bir şey yapıyor. Her piksel için x ve y koordinatlarının çözünürlüğe bölünmesiyle elde edilen bir float2
vektörü oluşturur. Böylece, sıfır ile bir arasında bir değer oluşturulur. Daha sonra, dönüş renginin kırmızı ve yeşil bileşenlerini
oluşturmak için bu ölçeklendirilmiş vektörü kullanır.
View
çözünürlüğünü setFloatUniform
yöntemini çağırarak bir AGSL gölgelendiricisine uniform
iletirsiniz.
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); } }
Gölgelendiriciye animasyon ekleme
Gölgelendiriciyi iTime
ve iDuration
forma alacak şekilde değiştirerek benzer bir teknik kullanabilirsiniz. Gölgelendirici, renkler için üçgen bir dalga oluşturmak amacıyla bu değerleri kullanır. Böylece, renklerin gradyan değerleri arasında gidip gelirler.
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
, özel görünüm kaynak kodundaki iTime
tek tipliğini günceller.
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()); } });
Karmaşık nesneleri boyama
Arka planı doldurmak için gölgelendiriciyi çizmenize gerek yoktur; drawText
gibi Paint
nesnesini kabul eden her yerde kullanılabilir.
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);
Gölgeleme ve Tuval dönüşümleri
Gölgeli metninize döndürme gibi ek Canvas
dönüşümleri uygulayabilirsiniz. ValueAnimator
ürününde, yerleşik android.graphics.Camera
sınıfını kullanarak 3D rotasyonlar için bir matrisi güncelleyebilirsiniz.
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);
Metni köşe yerine merkez eksenden döndürmek istediğiniz için metin sınırlarını alın ve ardından metni çevirmek üzere matrisi değiştirmek için preTranslate
ve postTranslate
ile değiştirin. Böylece, metnin ekranda çizildiği konumu değiştirmeden, döndürmenin merkezi 0,0 olacaktır.
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 ile kullanma
Kullanıcı arayüzünüzü Jetpack Compose kullanarak oluşturuyorsanız RuntimeShader
kullanmak daha da kolaydır. Önceki gradyan gölgelendiriciyle başlayarak:
private const val COLOR_SHADER_SRC =
"""uniform float2 iResolution;
half4 main(float2 fragCoord) {
float2 scaled = fragCoord/iResolution.xy;
return half4(scaled, 0, 1);
}"""
Bu gölgelendiriciyi bir ShaderBrush
öğesine uygulayabilirsiniz. Daha sonra ShaderBrush
, Canvas
çizim kapsamınızdaki çizim komutlarına parametre olarak eklenir.
// 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 ile kullanma
RuntimeShader
öğesini üst View
ve tüm alt görünümlere uygulamak için RenderEffect
kullanabilirsiniz. Bu, özel bir View
çizmekten daha pahalıdır. ancak createRuntimeShaderEffect
kullanılarak başlangıçta çizilmiş olanları içeren bir efekti kolayca oluşturmanıza olanak tanır.
Kotlin
view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"))
Java
view.setRenderEffect(RenderEffect.createRuntimeShaderEffect(myShader, "background"));
İkinci parametre, RenderNode
öğesinin (Görünüm ve alt görünümleri) orijinal rengini elde etmek için bir koordinat parametresiyle (fragCoord'da iletilen gibi) eval
ile eval
oluşturarak her türlü efekti gerçekleştirebilmenizi sağlar.
uniform shader background; // Root node of View tree to be altered
return mix(returnColor, background.eval(fragCoord), 0.5);
Bir düğmenin üzerine karıştırılmış ancak kayan işlem düğmesinin altında (farklı bir View
hiyerarşisinde olduğu için) ızgara efekti.