I was playing with Shaders and Mandelbrot Fractals to reply to a question on the Steam forum. I came up with this and thought I would share it here as well.
Feel free to improve and use this any way you want and share here.
Find attached the project folder, including source and .exe.
or make a new project and copy and paste this code.
// Project: Another Pixel Shader turorial
// Created: 2015-01-05 by JammySoft
// Using a very slightly modified version of the GLSL Shader available at
// http://rosettacode.org/wiki/Mandelbrot_set#GLSL
// get the time
StartTime#=Timer()
// set window properties
SetWindowTitle( "Mandelbrot_set" )
SetWindowSize( 1024, 768, 1 )
SetVirtualResolution( 1024, 768 )
SetSyncRate(60,0) ` this is unlimited frames per second
once=1
zoom#=5.5
SetRawMousePosition( 512,0 )
newmousex=1024
newmousey=0
x#=0
y#=0
green#=0
incrament#=0.01
` load a shader
` as we are using a sprite to display the shader we can work with pixel shaders and ignore vertex shaders at the moment.
Shader = LoadSpriteShader( "Mandelbrot.ps" )
` create a full screen sprite to apply the shader
CreateImageColor( 1, 255,0, 0,255 ) `this just creates an image of 1 pixel and colours it.
Sprite=CreateSprite(1) `make a sprite and call it sprite
SetSpritePosition(Sprite,0,0)
`assign the shader to the sprite.
SetSpriteShader( Sprite, Shader )
SetSpriteSize(Sprite,1024,768) ` make the sprite full screen
SetShaderConstantByName( Shader,"iResolution",1024,768,0,0 ) ` tell the shader the screen resolution
SetShaderConstantByName( Shader,"zoom",zoom#,0,0,0 )
SetShaderConstantByName( Shader,"xmove",x#,0,0,0 )
SetShaderConstantByName( Shader,"ymove",y#,0,0,0 )
SetShaderConstantByName( Shader,"green",0,0,0,0 )
do
green#=green#+incrament#
if green#>1.0 then incrament#=-0.001
if green#<0.0 then incrament#=0.001
SetShaderConstantByName( Shader,"green",green#,0,0,0 )
if GetRawMouseLeftState() =1
if zoom#>0.5 then zoom#=zoom#-0.01
if zoom#>0.05 then zoom#=zoom#-0.001
if zoom#>0.005 then zoom#=zoom#-0.001
if zoom#>0.0005 then zoom#=zoom#-0.0001
if zoom#>0.00005 then zoom#=zoom#-0.00001
once=1
StartTime#=Timer()
Endif
if GetRawMouseRightState() =1
if zoom#<30 then zoom#=zoom#+0.01
once=1
StartTime#=Timer()
Endif
oldmousex=newmousex
newmousex=GetRawMouseX()
movementx#=(oldmousex-newmousex)
movementx#=movementx#/500
x#=x#+movementx#
SetShaderConstantByName( Shader,"xmove",x#,0,0,0 )
oldmousey=newmousey
newmousey=GetRawMouseY()
movementy#=(oldmousey-newmousey)
movementy#=movementy#/1000
y#=y#+movementy#
SetShaderConstantByName( Shader,"ymove",y#,0,0,0 )
`GetRawMouseY()
SetShaderConstantByName( Shader,"zoom",zoom#,0,0,0 )
if toggle=0
PrintC("Frames Per Second = ")
Print( ScreenFPS() )
PrintC("Time To Draw = ")
PrintC( TimeToDraw# )
Print(" Seconds")
Print("Use mouse to move about")
Print("mouse buttons to zoom in and out")
Print("space-bar to Toggle Info")
Print("ANY OTHER KEY TO EXIT")
endif
if GetRawKeyReleased(32) =1
if toggle=1 then toggle=0 else toggle=1
if toggle=0 then SetRawMouseVisible( 1 ) else SetRawMouseVisible( 0 )
endif
if once=1
EndTime#=Timer()
Once=once+1
TimeToDraw#=EndTime#-StartTime#
endIf
sync()
if GetRawLastKey()<>0 and GetRawLastKey()<>32 then exit
loop
end
To create the shader open Note pad and copy this code, Name it Mandelbrot.ps and place it in your media folder.
uniform vec3 iResolution; // viewport resolution (in pixels)
uniform float zoom; // shader zoom
uniform float xmove;
uniform float ymove;
uniform float green;
void main(void)
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
float scale = iResolution.y / iResolution.x;
uv=((uv -0.5)*zoom);
uv.y*=scale;
uv.y+=0.0+ymove;
uv.x-=0.5+xmove;
vec2 z = vec2(0.0, 0.0);
vec3 c = vec3(0.0, 0.0, 0.0);
float v;
for(int i=0;(i<170);i++)
{
if(((z.x*z.x+z.y*z.y) >= 4.0)) break;
z = vec2(z.x*z.x - z.y*z.y, 2.0*z.y*z.x) + uv;
if((z.x*z.x+z.y*z.y) >= 2.0)
{
c.b=float(i)/20.0;
c.r=sin((float(i)/5.0));
c.g=green;
}
}
gl_FragColor = vec4(c,5.0);
}
That's it. I quite liked the result but know it can be improved. Give it a shot and post your program here.