seascape-shader

command
v0.0.0-...-b0a6657 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2024 License: MIT Imports: 10 Imported by: 0

README

Shadertoy to Pixel shader conversion

This will show you an example how you can take an example from shadertoy.com and use it with the Pixel Shader support.

"Seascape" by Alexander Alekseev aka TDM - 2014 is a nice one. It's very impressive and doesn't use textures so that simplifies things for us. Let's try that one.

Looking at the seascape.glsl example you can see iResolution, iTime and iMouse in there.

These are commonly needed to be exposed because these things are coming from outside and needs to be updated. Any other variable you need to have changed/updated from code can be exposed like those.

Command line arguments

./seascape-shader -h   # will show you the command line options

./seascape-shader -filename ./shaders/seascape.glsl    # Seascape
./seascape-shader -filename ./shaders/planetfall.glsl  # Planet Fall demo

Exposing variables

How to expose variables like this?

Well, first we need to figure out what type of variables they are. Looking at the shader, you can see iResolution.x in there. This tells you that it's not a simple type. In this case it's a vec2*, a Vector containing 2 values, x and y. This makes sense since resolution is described by x and y. That is, width and height.

And thus, we create our variable in Go with like so:

uResolution := mgl32.Vec2{float32(win.Bounds().W()), float32(win.Bounds().H())}

That is, to be of the type mgl32.Vec2. Here we create it by taking the window's width and height.

iTime is just a float, and thus that is just created like so:

var uTime float32

For the iMouse, it's a mgl32.Vec4, a Vector containing 4 variables. We only use x and y for the mouse position here though.

var uMouse mgl32.Vec4

And finally, to make our variables available in the shader itself we use:

canvas.SetUniform(name string, value interface{})

We create a handy function to do this:

func EasyBindUniforms(c *opengl.Canvas, unifs ...interface{}) {
	if len(unifs)%2 != 0 {
		panic("needs to be divisable by 2")
	}
	for i := 0; i < len(unifs); i += 2 {

		c.SetUniform(unifs[i+0].(string), unifs[i+1])
	}
}

and we call that function like so:

	EasyBindUniforms(canvas,
		"uResolution", &uResolution,
		"uTime", &uTime,
		"uMouse", &uMouse,
	)

Updating shader source file

We also need to do some updates to the shader file itself to match these variables. First thing would be to add the variables we exposed in Go.

uniform vec2 uResolution;
uniform float uTime;
uniform vec4 uMouse;

Then we just rename the variables to match.

We also need to rename the main function itself, as the one used here is specific for use with shadertoy. For our shader, the entrypoint is main(). So we rename:

void mainImage( out vec4 fragColor, in vec2 fragCoord )

to

void main() {

Also, rename:

fragCoord

to

gl_FragCoord

because this is available globaly in the OpenGL space for the shader.

We also need to add:

out vec4 fragColor;

to expose that.

Lastly, we need to add:

#version 330 core

at the top to tell what version we require.

Using shader

To use the shader in our canvas we do:

canvas.SetFragmentShader(fragSource string)

where fragSource is the fragment shader, not a path fo a file.

Result converting shadertoy shader to use with Pixel

Here is a diff of the changes:

code changes

And that is it. Running the program we should see this:

seascape animation

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL