purplekingdomgames / ultraviolet Goto Github PK
View Code? Open in Web Editor NEWScala 3 to GLSL transpiler library
License: MIT License
Scala 3 to GLSL transpiler library
License: MIT License
In this example we multiply two matricies together, then multiply a vec4 by that, and swizzle.
vec2 scaleCoordsWithOffset(vec2 texcoord, vec2 offset){
mat4 transform = translate2d(offset) * scale2d(FRAME_SIZE);
return (transform * vec4(texcoord, 1.0, 1.0)).xy;
}
Here is the standard transform:
mat4 transform =
translate2d(POSITION) *
rotate2d(-1.0 * ROTATION) *
scale2d(SIZE * SCALE) *
translate2d(-(REF / SIZE) + 0.5) *
scale2d(vec2(1.0, -1.0) * FLIP);
gl_Position = u_projection * u_baseTransform * transform * VERTEX;
Like bvec2
- there is a list somewhere.
All the shader tests currently (I think) are like this:
inline def fragment: Shader[Env, vec4] = ???
But it would be super handy to be able to do either of these, too, as it unlocks things like the ability to use inline if
(removing the need for the GLSL ifdef
pre-processor):
inline def fragment(maxCount: Int): Shader[Env, vec4] = ???
inline def fragment: Int => Shader[Env, vec4] = maxCount => ???
They currently allow for a simple values to be assigned like:
val x = if x < 10 then 5 else 15
But I have a suspicion that if the body was a Block
then you'd get undesirable output.
I'd like to be able to do this:
import ultraviolet.environments.indigo.fragment.*
This would provide all the standard things available to an indigo fragment shader.
GLSL has no notion of Product types*. In GLSL, this isn't a problem because it's procedural and you can just assign multiple outputs to variables, or using the function argument out
keyword.
However this makes things difficult for the functional programmer who'd like to be able to return more than one value from a function.
One solution might be to allow things like this:
def foo(): (Float, Float, Float) =
(1.0f, 2.0f, 3.0f)
val (x, y, z) = foo()
Which just becomes:
float x;
float y;
float z;
void foo(){
x=1.0;
y=2.0;
z=3.0;
}
It would need to error if the function does anything else.
*UPDATE: Initial assert isn't quite right, there are structs.
Some way to add the ultraviolet lib to a project and kick out shaders for different platform flavours (webgl2, indigo, shadertoy) and also so generate a run a simple indigo project that loads and uses your shader for shadertoy-like local shader dev.
Example:
mat4 translate2d(vec2 t){
return mat4(1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
t.x, t.y, 0, 1
);
}
With no stacktrace? Some are just information?
I decided to limit the API to xyzw
- mostly because of the insane number of extension methods being generated - but I think rgba
are valid swizzles, perhaps they should be supported?
Should be able to render this following (taken from the webgl2 fundamentals site):
#version 300 es
// fragment shaders don't have a default precision so we need
// to pick one. highp is a good default. It means "high precision"
precision highp float;
// we need to declare an output for the fragment shader
out vec4 outColor;
void main() {
// Just set the output to a constant reddish-purple
outColor = vec4(1, 0, 0.5, 1);
}
Currently Ultraviolet is pretty much a straight translation from GLSL-like-Scala to GLSL and this is useful, but we're only scratching the surface.
Rather than returning just a string at the end of the printing process, we could also be returning metadata about the shader and which values it requires to be set.
This would allow us to do things like reading a UBO definition, only available in WebGL 2.0, and rewriting it as a series of uniform
statements when exporting to WebGL 1.0. This wouldn't be a super efficient shader, but it would mean you only need to write your code once and stand a fair chance of it working everywhere.
WebGL 2 hello triangle in Tyrian
Indigo
Shadertoy
vertex
fragment
prepare
light
composite
I think they are being pre-rendered into a raw string literal at the moment...
Not a priority, but it would be great to be able to compose Shader
types to facilitate testing and code reuse.
For any casual readers: I suspect this isn't as simple as it sounds because of the way inline macros work.
This would allow people to keep writing GLSL in external files the old fashioned way.
Example from Indigo:
layout (location = 7) in float a_rotation;
Otherwise keeping the two projects in sync will be hellish.
Most shader programs conform to some sort of structure, sometimes ultraviolet can support that and the user just needs to know to do it. E.g. and Indigo fragment shader needs this entry point:
void fragment() {
COLOR = vec4(1.0);
}
and that's perfectly encode-able as:
Shader[Env] { env =>
def fragment: Unit =
env.COLOR = vec4(1.0f)
}
But ShaderToy requires the following, that we cannot express (this is the default project code) because we don't support in
/out
function arguments:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
// Normalized pixel coordinates (from 0 to 1)
vec2 uv = fragCoord/iResolution.xy;
// Time varying pixel color
vec3 col = 0.5 + 0.5*cos(iTime+uv.xyx+vec3(0,2,4));
// Output to screen
fragColor = vec4(col,1.0);
}
Going back to the Indigo example, another, more testable way to express that function might be this:
Shader[Env, vec4] { env =>
vec4(1.0f)
}
where we consider the fragment
function definition and COLOR
output to just be part of the standard template. This makes the ShaderToy example work too (I think).
All we'd need to do is provide some sort of template information to the toGLSL
call so that the output is rendered differently.
Probably missing some way to run with an environment.
So that we could in theory provide different renderers / interpreters in the future.
Example from the docs:
const float array[3] = float[3](2.5, 7.0, 1.5);
Update, that's a terrible example! array
is the variable name! ๐
const float foo[3] = float[3](2.5, 7.0, 1.5);
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.