Piotr Prus
07/10/2023, 8:52 PMcolor_dodge
to blend this shader: https://www.shadertoy.com/view/MdjfRK
into transparent background version. I want the blaks to disappear, but do not loose the details of color noise.romainguy
07/10/2023, 9:05 PMromainguy
07/10/2023, 9:06 PMvec4(0.0)
instead (fully transparent)Timo Drick
07/11/2023, 8:24 AMTimo Drick
07/11/2023, 8:39 AMfloat grad = pow((r.y + r.y) * max(.0, uv.y) + .1, 4.0);
color = ramp(grad);
color /= (1.50 + max(vec3(0), color));
float alpha = 1.0-grad; // <-- you could use the grad value for alpha
return vec4(color * alpha, alpha); // <-- premultiply the color. It does not really make a big difference i think.
Timo Drick
07/11/2023, 8:39 AMPiotr Prus
07/11/2023, 9:30 AMTimo Drick
07/11/2023, 10:59 AMTimo Drick
07/11/2023, 11:03 AMfun Modifier.rainEffect() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) this.composed {
val shader = remember { RuntimeShader(SHADER_RAIN) }
val time by produceState(0f) {
while (true) {
withInfiniteAnimationFrameMillis {
value = it / 1000f
}
}
}
this.graphicsLayer {
// Pass the color to support color space automatically
shader.setFloatUniform("iResolution", density * 400, density * 400)
shader.setFloatUniform("iTime", time)
renderEffect = RenderEffect.createRuntimeShaderEffect(shader, "background")
.asComposeRenderEffect()
//renderEffect = RenderEffect.createBlurEffect(5f, 5f, Shader.TileMode.CLAMP).asComposeRenderEffect()
}
} else Modifier
In shader code you get the uniform shader background;
.
Than you do not need to use alpha color at all. And can do blending yourself.Timo Drick
07/11/2023, 11:05 AMTimo Drick
07/11/2023, 11:09 AMPiotr Prus
07/11/2023, 12:54 PMreturn vec4(color, 1.0);
and I have change that to:
return vec4(color, 0.0);
which returns transparent for all places where there is no noise function.Timo Drick
07/11/2023, 12:55 PMfloat alpha = 1.0-grad; // <-- you could use the grad value for alpha
return vec4(color * alpha, alpha); // <-- premultiply the color. It does not really make a big difference i think.
Piotr Prus
07/11/2023, 2:17 PMTimo Drick
07/11/2023, 9:51 PMTimo Drick
07/11/2023, 10:02 PMPiotr Prus
07/12/2023, 9:22 AMpackage com.piotrprus.flameshader
import android.graphics.RenderEffect
import android.graphics.RuntimeShader
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.withInfiniteAnimationFrameMillis
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asComposeRenderEffect
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import com.piotrprus.flameshader.ui.theme.FlameShaderTheme
const val GlowSource = """
uniform shader glowComposable;
uniform float2 iResolution; // viewport resolution (in pixels)
uniform float iTime; // shader playback time (in seconds)
float rand(vec2 n) {
return fract(sin(dot(n, vec2(12.9898,12.1414))) * 83758.5453);
}
float noise(vec2 n) {
const vec2 d = vec2(0.0, 1.0);
vec2 b = floor(n);
vec2 f = mix(vec2(0.0), vec2(1.0), fract(n));
return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
}
vec3 ramp(float t) {
return t <= .5 ? vec3( 1. - t * 1.4, .2, 1.05 ) / t : vec3( .3 * (1. - t) * 2., .2, 1.05 ) / t;
}
float fire(vec2 n) {
return noise(n) + noise(n * 2.1) * .6 + noise(n * 5.4) * .42;
}
vec4 main(vec2 fragCoord) {
float t = iTime;
vec2 uv = fragCoord / iResolution.y;
uv.x += uv.y < .5 ? 23.0 + t * .35 : -11.0 + t * .3;
uv.y = abs(uv.y - 0.5);
uv *= 2.5;
float q = fire(uv - t * .013) / 2.0;
vec2 r = vec2(fire(uv + q / 2.0 + t - uv.x - uv.y), fire(uv + q - t));
vec3 color = vec3(1.0 / (pow(vec3(0.5, 0.0, .1) + 1.61, vec3(4.0))));
float grad = pow((r.y + r.y) * max(.0, uv.y) + .1, 4.0);
color = ramp(grad);
color /= (1.50 + max(vec3(0), color));
float alpha = 1.0-grad; // <-- you could use the grad value for alpha
return vec4(color * alpha, alpha); // <-- premultiply the color. It does not really make a big difference i think.
// return vec4(color, 0.0);
}
"""
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FlameShaderTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MainScreen()
}
}
}
}
}
@Composable
fun MainScreen() {
Box(
modifier = Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Image(
painter = painterResource(id = R.drawable.vert_image),
contentDescription = null,
modifier = Modifier.fillMaxSize()
)
Box(modifier = Modifier.width(200.dp)) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(35.dp)
.flameEffect()
.background(Color.Black)
)
}
}
}
fun Modifier.flameEffect() =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) this.composed {
var size by remember { mutableStateOf(IntSize.Zero) }
val shader = remember { RuntimeShader(GlowSource) }
val time by produceState(0f) {
while (true) {
withInfiniteAnimationFrameMillis {
value = it / 1000f
}
}
}
this
.onPlaced { layoutCoordinates ->
size = layoutCoordinates.size
}
.graphicsLayer {
if (size != IntSize.Zero) {
// Pass the color to support color space automatically
shader.setFloatUniform(
"iResolution",
size.width.toFloat(),
size.height.toFloat()
)
shader.setFloatUniform("iTime", time)
clip = true
renderEffect = RenderEffect
.createRuntimeShaderEffect(shader, "glowComposable")
.asComposeRenderEffect()
}
}
} else Modifier
Piotr Prus
07/12/2023, 9:23 AMTimo Drick
07/12/2023, 9:28 AMPiotr Prus
07/12/2023, 9:43 AMTimo Drick
07/12/2023, 9:48 AM@RequiresApi(33)
fun Modifier.backgroundShader(shaderSrc: String): Modifier = this.drawWithCache {
val shader = RuntimeShader(shaderSrc)
val brush = ShaderBrush(shader)
onDrawBehind {
drawRect(brush, blendMode = BlendMode.Screen)
}
}
Timo Drick
07/12/2023, 9:49 AMTimo Drick
07/12/2023, 10:09 AMfun Modifier.flameEffect2() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) this.composed {
val shader = remember { RuntimeShader(GlowSource) }
val time by produceState(0f) {
while (true) {
withInfiniteAnimationFrameMillis {
value = it / 1000f
}
}
}
this.drawWithCache {
val brush = ShaderBrush(shader)
shader.setFloatUniform("iResolution", size.width, size.height)
shader.setFloatUniform("iTime", time)
onDrawBehind {
drawRect(brush)
}
}
} else this.background(Color.Black)
Timo Drick
07/12/2023, 10:09 AMTimo Drick
07/12/2023, 10:12 AMdrawRect(brush, blendMode = BlendMode.Screen)
Than you do not need to change the shader code. So you can always set the color to `return vec4(color, 1.0)`;Timo Drick
07/12/2023, 10:13 AMPiotr Prus
07/12/2023, 11:34 AMbrush
🙂 😂