Kotlin-based shader language

Edwin has been working on a Kotlin-based shader language. It is still in progress, including the syntax, but you can give it a try already :slight_smile:

Here you can find over 10 examples written with that new syntax: poc-shader-generation/orx-shader-generator/src/jvmDemo/kotlin at master · edwinRNDR/poc-shader-generation · GitHub

If you clone the repo you can run those demo programs and write your own.

It seems to include many math and noise functions.

When I get a moment to try it I’m going to start from the simplest example: set a flat color, then use a uniform to change it over time, then move on from there. I am quite used to GLSL and it might take a bit of time to get used to a new syntax, although better auto-completion and type-checking sound very appealing.

So… anyone dares to try? Who can use it to draw a circle? :slight_smile:

4 Likes

Now there’s a README with useful information at

1 Like

I started writing some simple examples (more advanced ones are in the repo):

Plain color

HelloWorld01-2023-06-14-19.05.34

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.shadergenerator.dsl.functions.symbol
import org.openrndr.extra.shadergenerator.dsl.shadestyle.fragmentTransform

fun main() {
    application {
        program {
            extend {
                drawer.clear(ColorRGBa.WHITE)
                drawer.shadeStyle = shadeStyle {
                    @Suppress("LocalVariableName")
                    fragmentTransform {
                        x_fill = ColorRGBa.PINK.toVector4().symbol
                    }
                }
                drawer.circle(drawer.bounds.center, 200.0)
            }
        }
    }
}

Simple texture

HelloWorld02-2023-06-14-19.02.02

import org.openrndr.application
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.shadergenerator.dsl.functions.symbol
import org.openrndr.extra.shadergenerator.dsl.shadestyle.fragmentTransform
import org.openrndr.math.*

fun main() {
    application {
        program {
            extend {
                drawer.clear(ColorRGBa.WHITE)
                drawer.shadeStyle = shadeStyle {
                    @Suppress("LocalVariableName")
                    fragmentTransform {
                        val va_texCoord0 by parameter<Vector2>()
                        val r by sin(va_texCoord0.x * 15.0) * 0.5 + 0.5
                        val g by sin(va_texCoord0.y * 5.0) * 0.5 + 0.5
                        val c by Vector4(r, g, 1.0.symbol, 1.0.symbol)
                        x_fill = c
                    }
                }
                drawer.circle(drawer.bounds.center, 200.0)
            }
        }
    }
}

Simple SDF ellipse

HelloWorld02-2023-06-14-19.20.07

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.shadergenerator.dsl.functions.symbol
import org.openrndr.extra.shadergenerator.dsl.shadestyle.fragmentTransform
import org.openrndr.math.Vector2
import org.openrndr.math.Vector4

fun main() {
    application {
        program {
            extend {
                drawer.stroke = null
                drawer.shadeStyle = shadeStyle {
                    @Suppress("LocalVariableName")
                    fragmentTransform {
                        val va_texCoord0 by parameter<Vector2>()
                        val distToCenter = Vector2(va_texCoord0.x - 0.5, va_texCoord0.y - 0.5).length
                        val circle = smoothstep(0.3.symbol, 0.4.symbol, distToCenter)
                        val color0 = ColorRGBa.WHITE.toVector4().symbol
                        val color1 by Vector4(1.0, 0.5, 0.2, 1.0).symbol
                        x_fill = color0 * circle + color1 * (1.0 - circle)
                    }
                }
                drawer.rectangle(drawer.bounds)
            }
        }
    }
}
1 Like

This looks really cool! I’ve always been kinda scared of shaders/GLSL since it’s an entirely different language and I miss the comfortable IDE help I get with Kotlin.

Very smart to use delegated properties (by) to integrate stuff you need into a Kotlin environment. I’ve played around with using delegated properties to create a nice API for parameters that you can control with keyboard, mouse, midi, etc, but I never got around to finishing it.

Question: Does this change compute shaders not being available on Mac?

EDIT: typo

Hi @torb :wave:

When you say vectors do you mean GLSL? :slight_smile:

I’m curious about your API with delegated properties… I need to experiment with those too.

Latest additions to the Kotlin-based shading language are related to compute shaders. Unfortunately not yet for Mac. I hope those cross-platform (Vulkan) approaches make it possible at some point.

1 Like

Hey! :slight_smile:

When you say vectors do you mean GLSL ? :slight_smile:

Yeah I meant to write shaders!

I’m curious about your API with delegated properties…

I should try to put them into a more tidy repo and share them. I suppose maybe they could fit into ORX or something?

I need to experiment with those too.

They can be fun to work with. I have to say that in general Kotlin is the most fun programming language I’ve ever touched, and it’s a good fit for OPENRNDR since that adds to the fun, which I think is very important for creative coding as it’s a hobby for many of us.

Latest additions to the Kotlin-based shading language are related to compute shaders. Unfortunately not yet for Mac. I hope those cross-platform (Vulkan) approaches make it possible at some point.

My impression is that Vulkan is so difficult that very few outside extremely hard core game developers actually like working with it directly. For example: openFrameworks haven’t adopted it either.

If we are to move to a new API my guess is that WebGPU is a better option. It should be noted that native (i.e. non-web) implementations of WebGPU exist, including a JVM-wrapper. This means that you have the same GPU API across several native platforms and the web. None of this is very mature though, so unsure if it’s ready for prime time.

I think something like ANGLE could be more interesting in short term. It re-implements OpenGL ES using Vulkan, Metal and DirectX backends. This means that we could just carry on as we already do yet retain support. I think maybe it could mean getting compute support for macOS too? I also think OpenGL ES is similar enough to WebGL that it’s a reasonable strategy for support web too (I suppose this is what OPENRNDR already does?).

Apologies if this reply is too off topic.

There are so may approaches! It feels like


I think at some point it will happen. I hope newer versions of LWJGL and Kotlin will make it easy to run OPENRNDR on all desktops, mobiles and browsers with similar features.

Meanwhile, I think it can take years to experiment with everything that’s already available in OPENRNDR :slight_smile:

2 Likes

Well, the thing with ANGLE is that it basically let you continue using OpenGL-API indefinitely. I think API stability over time is important and if you OPENRNDR went that route programs should just continue to work as-is.

3 posts were split to a new topic: Shadertoy to OPENRNDR shader converter

I took a few minutes to generate screenshots of most demos in the poc-shader-generation repo. Enjoy :slight_smile:

Signed Distance Fields

ComputeStyle



Other

1 Like

Update: the repo has moved and can now be found at GitHub - openrndr/orsl: A shader language in Kotlin DSL.