I ask here because I feel my GPU is slow and I got only one feedback in tips and tricks.
It would be nice if you run this OpenGL shader and tell me your frames per seconds and the GPU modell you are using.
The CPU usage is not measurable here so my GPU seams to be runs on it's limit.
With the current screenres setting I get round about 20 FPS.
Insside the web browser with WebGL (OpenGL ES) on shadertoy.com I get only 3-5 FPS (same shader code)
Is it a normal result or not ?
Thank you.
Joshy
Code: Select all
dim as string SCODE
SCODE &= !"// Mountains. By David Hoskins - 2013 \n"
SCODE &= !"// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. \n"
SCODE &= !"// https://www.shadertoy.com/view/4slGD4 \n"
SCODE &= !"// A ray-marched version of my terrain renderer which uses \n"
SCODE &= !"// streaming texture normals for speed:- \n"
SCODE &= !"// http://www.youtube.com/watch?v=qzkBnCBpQAM \n"
SCODE &= !"// It uses binary subdivision to accurately find the height map. \n"
SCODE &= !"// Lots of thanks to Iñigo and his noise functions"
SCODE &= !"// Video of my OpenGL version that \n"
SCODE &= !"// http://www.youtube.com/watch?v=qzkBnCBpQAM \n"
SCODE &= !"// Stereo version code thanks to Croqueteer :) \n"
SCODE &= !"//#define STEREO \n" ' <--- !!! change it if you have 3D glasses
SCODE &= !"float treeLine = 0.0; \n"
SCODE &= !"float treeCol = 0.0; \n"
SCODE &= !"vec3 sunLight = normalize( vec3( 0.4, 0.4, 0.48 ) ); \n"
SCODE &= !"vec3 sunColour = vec3(1.0, .9, .83); \n"
SCODE &= !"float specular = 0.0; \n"
SCODE &= !"vec3 cameraPos; \n"
SCODE &= !"float ambient; \n"
SCODE &= !"vec2 add = vec2(1.0, 0.0); \n"
SCODE &= !"#define MOD2 vec2(3.07965, 7.4235) \n"
SCODE &= !"#define MOD3 vec3(3.07965, 7.1235, 4.998784) \n"
SCODE &= !"// This peturbs the fractal positions for each iteration down... \n"
SCODE &= !"// Helps make nice twisted landscapes... \n"
SCODE &= !"const mat2 rotate2D = mat2(1.3623, 1.7531, -1.7131, 1.4623); \n"
SCODE &= !"float Hash12(vec2 p) { \n"
SCODE &= !" p = fract(p / MOD2); \n"
SCODE &= !" p += dot(p.xy, p.yx+19.19); \n"
SCODE &= !" return fract(p.x * p.y); \n"
SCODE &= !"} \n"
SCODE &= !"vec2 Hash22(vec2 p) { \n"
SCODE &= !" vec3 p3 = fract(vec3(p.xyx) / MOD3); \n"
SCODE &= !" p3 += dot(p3.zxy, p3.yxz+19.19); \n"
SCODE &= !" return fract(vec2(p3.x * p3.y, p3.z*p3.x)); \n"
SCODE &= !"} \n"
SCODE &= !"float Noise( in vec2 x) { \n"
SCODE &= !" vec2 p = floor(x); \n"
SCODE &= !" vec2 f = fract(x); \n"
SCODE &= !" f = f*f*(3.0-2.0*f); \n"
SCODE &= !" float res = mix(mix( Hash12(p ), Hash12(p + add.xy),f.x), \n"
SCODE &= !" mix( Hash12(p + add.yx), Hash12(p + add.xx),f.x), \n"
SCODE &= !" f.y); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !"vec2 Noise2(in vec2 x) { \n"
SCODE &= !" vec2 p = floor(x); \n"
SCODE &= !" vec2 f = fract(x); \n"
SCODE &= !" f = f*f*(3.0-2.0*f); \n"
SCODE &= !" float n = p.x + p.y * 57.0; \n"
SCODE &= !" vec2 res = mix(mix( Hash22(p ), Hash22(p + add.xy),f.x), \n"
SCODE &= !" mix( Hash22(p + add.yx), Hash22(p + add.xx),f.x), \n"
SCODE &= !" f.y); \n"
SCODE &= !" return res; \n"
SCODE &= !"} \n"
SCODE &= !"float Trees(vec2 p) { \n"
SCODE &= !" return Noise(p*13.0)*treeLine; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Low def version for ray-marching through the height field... \n"
SCODE &= !"// Thanks to IQ for all the noise stuff... \n"
SCODE &= !"float Terrain( in vec2 p) { \n"
SCODE &= !" vec2 pos = p*0.05; \n"
SCODE &= !" float w = (Noise(pos*.25)*0.75+.15); \n"
SCODE &= !" w = 66.0 * w * w; \n"
SCODE &= !" vec2 dxy = vec2(0.0, 0.0); \n"
SCODE &= !" float f = .0; \n"
SCODE &= !" for (int i = 0; i < 5; i++) \n"
SCODE &= !" { \n"
SCODE &= !" f += w * Noise(pos); \n"
SCODE &= !" w = -w * 0.4; //...Flip negative and positive for variation \n"
SCODE &= !" pos = rotate2D * pos; \n"
SCODE &= !" } \n"
SCODE &= !" float ff = Noise(pos*.002); \n"
SCODE &= !" f += pow(abs(ff), 5.0)*275.-5.0; \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Map to lower resolution for height field mapping for Scene function... \n"
SCODE &= !"float Map(in vec3 p) { \n"
SCODE &= !" float h = Terrain(p.xz); \n"
SCODE &= !" float ff = Noise(p.xz*.3) + Noise(p.xz*3.3)*.5; \n"
SCODE &= !" treeLine = smoothstep(ff, .0+ff*2.0, h) * smoothstep(1.0+ff*3.0, .4+ff, h) ; \n"
SCODE &= !" treeCol = Trees(p.xz); \n"
SCODE &= !" h += treeCol; \n"
SCODE &= !" return p.y - h; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// High def version only used for grabbing normal information. \n"
SCODE &= !"float Terrain2( in vec2 p){ \n"
SCODE &= !" // There's some real magic numbers in here! \n"
SCODE &= !" // The Noise calls add large mountain ranges for more variation over distances... \n"
SCODE &= !" vec2 pos = p*0.05; \n"
SCODE &= !" float w = (Noise(pos*.25)*0.75+.15); \n"
SCODE &= !" w = 66.0 * w * w; \n"
SCODE &= !" vec2 dxy = vec2(0.0, 0.0); \n"
SCODE &= !" float f = .0; \n"
SCODE &= !" for (int i = 0; i < 5; i++) { \n"
SCODE &= !" f += w * Noise(pos); \n"
SCODE &= !" w = - w * 0.4; //...Flip negative and positive for varition \n"
SCODE &= !" pos = rotate2D * pos; \n"
SCODE &= !" } \n"
SCODE &= !" float ff = Noise(pos*.002); \n"
SCODE &= !" f += pow(abs(ff), 5.0)*275.-5.0; \n"
SCODE &= !" treeCol = Trees(p); \n"
SCODE &= !" f += treeCol; \n"
SCODE &= !" if (treeCol > 0.0) return f; \n"
SCODE &= !" // That's the last of the low resolution, now go down further for the Normal data... \n"
SCODE &= !" for (int i = 0; i < 6; i++) { \n"
SCODE &= !" f += w * Noise(pos); \n"
SCODE &= !" w = - w * 0.4; \n"
SCODE &= !" pos = rotate2D * pos; \n"
SCODE &= !" } \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"float FractalNoise(in vec2 xy){ \n"
SCODE &= !" float w = .7; \n"
SCODE &= !" float f = 0.0; \n"
SCODE &= !" for (int i = 0; i < 4; i++) { \n"
SCODE &= !" f += Noise(xy) * w; \n"
SCODE &= !" w *= 0.5; \n"
SCODE &= !" xy *= 2.7; \n"
SCODE &= !" } \n"
SCODE &= !" return f; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Simply Perlin clouds that fade to the horizon... \n"
SCODE &= !"// 200 units above the ground... \n"
SCODE &= !"vec3 GetClouds(in vec3 sky, in vec3 rd) { \n"
SCODE &= !" if (rd.y < 0.01) return sky; \n"
SCODE &= !" float v = (200.0-cameraPos.y)/rd.y; \n"
SCODE &= !" rd.xz *= v; \n"
SCODE &= !" rd.xz += cameraPos.xz; \n"
SCODE &= !" rd.xz *= .010; \n"
SCODE &= !" float f = (FractalNoise(rd.xz) -.55) * 5.0; \n"
SCODE &= !" // Uses the ray's y component for horizon fade of fixed colour clouds... \n"
SCODE &= !" sky = mix(sky, vec3(.55, .55, .52), clamp(f*rd.y-.1, 0.0, 1.0)); \n"
SCODE &= !" return sky; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Grab all sky information for a given ray from camera \n"
SCODE &= !"vec3 GetSky(in vec3 rd){ \n"
SCODE &= !" float sunAmount = max( dot( rd, sunLight), 0.0 ); \n"
SCODE &= !" float v = pow(1.0-max(rd.y,0.0),5.)*.5; \n"
SCODE &= !" vec3 sky = vec3(v*sunColour.x*0.4+0.18, v*sunColour.y*0.4+0.22, v*sunColour.z*0.4+.4); \n"
SCODE &= !" // Wide glare effect... \n"
SCODE &= !" sky = sky + sunColour * pow(sunAmount, 6.5)*.32; \n"
SCODE &= !" // Actual sun... \n"
SCODE &= !" sky = sky+ sunColour * min(pow(sunAmount, 1150.0), .3)*.65; \n"
SCODE &= !" return sky; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Merge mountains into the sky background for correct disappearance... \n"
SCODE &= !"vec3 ApplyFog( in vec3 rgb, in float dis, in vec3 dir){ \n"
SCODE &= !" float fogAmount = exp(-dis* 0.00005); \n"
SCODE &= !" return mix(GetSky(dir), rgb, fogAmount ); \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Calculate sun light... \n"
SCODE &= !"void DoLighting(inout vec3 mat, in vec3 pos, in vec3 normal, in vec3 eyeDir, in float dis) { \n"
SCODE &= !" float h = dot(sunLight,normal); \n"
SCODE &= !" float c = max(h, 0.0)+ambient; \n"
SCODE &= !" mat = mat * sunColour * c ; \n"
SCODE &= !" // Specular... \n"
SCODE &= !" if (h > 0.0) { \n"
SCODE &= !" vec3 R = reflect(sunLight, normal); \n"
SCODE &= !" float specAmount = pow( max(dot(R, normalize(eyeDir)), 0.0), 3.0)*specular; \n"
SCODE &= !" mat = mix(mat, sunColour, specAmount); \n"
SCODE &= !" } \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"// Hack the height, position, and normal data to create the coloured landscape \n"
SCODE &= !"vec3 TerrainColour(vec3 pos, vec3 normal, float dis){ \n"
SCODE &= !" vec3 mat; \n"
SCODE &= !" specular = .0; \n"
SCODE &= !" ambient = .1; \n"
SCODE &= !" vec3 dir = normalize(pos-cameraPos); \n"
SCODE &= !" vec3 matPos = pos * 2.0; // I had change scale halfway though, this lazy multiply allow me to keep the graphic scales I had \n"
SCODE &= !" float disSqrd = dis * dis; // Squaring it gives better distance scales. \n"
SCODE &= !" float f = clamp(Noise(matPos.xz*.05), 0.0,1.0);//*10.8; \n"
SCODE &= !" f += Noise(matPos.xz*.1+normal.yz*1.08)*.85; \n"
SCODE &= !" f *= .55; \n"
SCODE &= !" vec3 m = mix(vec3(.63*f+.2, .7*f+.1, .7*f+.1), vec3(f*.43+.1, f*.3+.2, f*.35+.1), f*.65); \n"
SCODE &= !" mat = m*vec3(f*m.x+.36, f*m.y+.30, f*m.z+.28); \n"
SCODE &= !" // Should have used smoothstep to add colours, but left it using 'if' for sanity... \n"
SCODE &= !" if (normal.y < .5) { \n"
SCODE &= !" float v = normal.y; \n"
SCODE &= !" float c = (.5-normal.y) * 4.0; \n"
SCODE &= !" c = clamp(c*c, 0.1, 1.0); \n"
SCODE &= !" f = Noise(vec2(matPos.x*.09, matPos.z*.095+matPos.yy*0.15)); \n"
SCODE &= !" f += Noise(vec2(matPos.x*2.233, matPos.z*2.23))*0.5; \n"
SCODE &= !" mat = mix(mat, vec3(.4*f), c); \n"
SCODE &= !" specular+=.1; \n"
SCODE &= !" } \n"
SCODE &= !" // Grass. Use the normal to decide when to plonk grass down... \n"
SCODE &= !" if (matPos.y < 45.35 && normal.y > .65) { \n"
SCODE &= !" m = vec3(Noise(matPos.xz*.023)*.5+.15, Noise(matPos.xz*.03)*.6+.25, 0.0); \n"
SCODE &= !" m *= (normal.y- 0.65)*.6; \n"
SCODE &= !" mat = mix(mat, m, clamp((normal.y-.65)*1.3 * (45.35-matPos.y)*0.1, 0.0, 1.0)); \n"
SCODE &= !" } \n"
SCODE &= !" if (treeCol > 0.0) { \n"
SCODE &= !" mat = vec3(.02+Noise(matPos.xz*5.0)*.03, .05, .0); \n"
SCODE &= !" normal = normalize(normal+vec3(Noise(matPos.xz*33.0)*1.0-.5, .0, Noise(matPos.xz*33.0)*1.0-.5)); \n"
SCODE &= !" specular = .0; \n"
SCODE &= !" } \n"
SCODE &= !" // Snow topped mountains... \n"
SCODE &= !" if (matPos.y > 80.0 && normal.y > .42) { \n"
SCODE &= !" float snow = clamp((matPos.y - 80.0 - Noise(matPos.xz * .1)*28.0) * 0.035, 0.0, 1.0); \n"
SCODE &= !" mat = mix(mat, vec3(.7,.7,.8), snow); \n"
SCODE &= !" specular += snow; \n"
SCODE &= !" ambient+=snow *.3; \n"
SCODE &= !" } \n"
SCODE &= !" // Beach effect... \n"
SCODE &= !" if (matPos.y < 1.45) { \n"
SCODE &= !" if (normal.y > .4) { \n"
SCODE &= !" f = Noise(matPos.xz * .084)*1.5; \n"
SCODE &= !" f = clamp((1.45-f-matPos.y) * 1.34, 0.0, .67); \n"
SCODE &= !" float t = (normal.y-.4); \n"
SCODE &= !" t = (t*t); \n"
SCODE &= !" mat = mix(mat, vec3(.09+t, .07+t, .03+t), f); \n"
SCODE &= !" } \n"
SCODE &= !" // Cheap under water darkening...it's wet after all... \n"
SCODE &= !" if (matPos.y < 0.0) { \n"
SCODE &= !" mat *= .5; \n"
SCODE &= !" } \n"
SCODE &= !" } \n"
SCODE &= !" \n"
SCODE &= !" DoLighting(mat, pos, normal,dir, disSqrd); \n"
SCODE &= !" // Do the water... \n"
SCODE &= !" if (matPos.y < 0.0) { \n"
SCODE &= !" // Pull back along the ray direction to get water surface point at y = 0.0 ... \n"
SCODE &= !" float time = (iGlobalTime)*.03; \n"
SCODE &= !" vec3 watPos = matPos; \n"
SCODE &= !" watPos += -dir * (watPos.y/dir.y); \n"
SCODE &= !" // Make some dodgy waves... \n"
SCODE &= !" float tx = cos(watPos.x*.052) *4.5; \n"
SCODE &= !" float tz = sin(watPos.z*.072) *4.5; \n"
SCODE &= !" vec2 co = Noise2(vec2(watPos.x*4.7+1.3+tz, watPos.z*4.69+time*35.0-tx)); \n"
SCODE &= !" co += Noise2(vec2(watPos.z*8.6+time*13.0-tx, watPos.x*8.712+tz))*.4; \n"
SCODE &= !" vec3 nor = normalize(vec3(co.x, 20.0, co.y)); \n"
SCODE &= !" nor = normalize(reflect(dir, nor));//normalize((-2.0*(dot(dir, nor))*nor)+dir); \n"
SCODE &= !" // Mix it in at depth transparancy to give beach cues.. \n"
SCODE &= !" mat = mix(mat, GetClouds(GetSky(nor)*vec3(.5,.6,1.0), nor)*.7, clamp((watPos.y-matPos.y)*.35, .2, .9)); \n"
SCODE &= !" // Add some extra water glint... \n"
SCODE &= !" float sunAmount = max( dot(nor, sunLight), 0.0 ); \n"
SCODE &= !" mat = mat + sunColour * pow(sunAmount, 228.5)*.6; \n"
SCODE &= !" } \n"
SCODE &= !" mat = ApplyFog(mat, disSqrd, dir); \n"
SCODE &= !" return mat; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"float BinarySubdivision(in vec3 rO, in vec3 rD, vec2 t) { \n"
SCODE &= !" // Home in on the surface by dividing by two and split... \n"
SCODE &= !" float halfwayT; \n"
SCODE &= !" for (int n = 0; n < 4; n++) { \n"
SCODE &= !" halfwayT = (t.x + t.y) * .5; \n"
SCODE &= !" vec3 p = rO + halfwayT*rD; \n"
SCODE &= !" if (Map(p) < 0.5) { \n"
SCODE &= !" t.x = halfwayT; \n"
SCODE &= !" } else { \n"
SCODE &= !" t.y = halfwayT; \n"
SCODE &= !" } \n"
SCODE &= !" } \n"
SCODE &= !" return t.x; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"bool Scene(in vec3 rO, in vec3 rD, out float resT, in vec2 fragCoord) { \n"
SCODE &= !" float t = 1.2 + Hash12(fragCoord.xy); \n"
SCODE &= !" float oldT = 0.0; \n"
SCODE &= !" float delta = 0.0; \n"
SCODE &= !" bool fin = false; \n"
SCODE &= !" bool res = false; \n"
SCODE &= !" vec2 distances; \n"
SCODE &= !" for( int j=0; j<150; j++ ) {\n"
SCODE &= !" if (t>150.0) break; // !!! t>240,0 \n"
SCODE &= !" vec3 p = rO + t*rD; \n"
SCODE &= !" float h = Map(p); // ...Get this positions height mapping. \n"
SCODE &= !" // Are we inside, and close enough to fudge a hit?... \n"
SCODE &= !" if( h < 0.5) { \n"
SCODE &= !" fin = true; \n"
SCODE &= !" distances = vec2(t, oldT); \n"
SCODE &= !" break; \n"
SCODE &= !" } \n"
SCODE &= !" // Delta ray advance - a fudge between the height returned and the distance already travelled. \n"
SCODE &= !" // It's a really fiddly compromise between speed and accuracy \n"
SCODE &= !" // Too large a step and the tops of ridges get missed. \n"
SCODE &= !" delta = max(0.01, 0.3*h) + (t*0.0065); \n"
SCODE &= !" oldT = t; \n"
SCODE &= !" t += delta; \n"
SCODE &= !" } \n"
SCODE &= !" if (fin) resT = BinarySubdivision(rO, rD, distances); \n"
SCODE &= !" return fin; \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
SCODE &= !"vec3 CameraPath( float t ) \n"
SCODE &= !"{ \n"
SCODE &= !" float m = 1.0+(iMouse.x/iResolution.x)*300.0; \n"
SCODE &= !" t = (iGlobalTime*1.5+m+657.0)*.006 + t; \n"
SCODE &= !" vec2 p = 476.0*vec2( sin(3.5*t), cos(1.5*t) ); \n"
SCODE &= !" return vec3(335.0-p.x, 0.6, 308.0+p.y); \n"
SCODE &= !"} \n"
SCODE &= !"// Some would say, most of the magic is done in post! :D \n"
SCODE &= !"vec3 PostEffects(in vec3 rgb, in vec2 uv) { \n"
SCODE &= !" vec3 c = (1.0 - exp(-rgb * 6.0)) * 1.0024; \n"
SCODE &= !" return c; \n"
SCODE &= !"} \n"
SCODE &= !"void mainImage( out vec4 fragColor, in vec2 fragCoord) { \n"
SCODE &= !" vec2 xy = -1.0 + 2.0*fragCoord.xy / iResolution.xy; \n"
SCODE &= !" vec2 uv = xy * vec2(iResolution.x/iResolution.y,1.0); \n"
SCODE &= !" vec3 camTar; \n"
SCODE &= !" #ifdef STEREO \n"
SCODE &= !" float isCyan = mod(fragCoord.x + mod(fragCoord.y,2.0),2.0); \n"
SCODE &= !" #endif \n"
SCODE &= !" // Use several forward heights, of decreasing influence with distance from the camera. \n"
SCODE &= !" float h = 0.0; \n"
SCODE &= !" float f = 1.0; \n"
SCODE &= !" for (int i = 0; i < 7; i++) { \n"
SCODE &= !" h += Terrain(CameraPath((.6-f)*.008).xz) * f; \n"
SCODE &= !" f -= .1; \n"
SCODE &= !" } \n"
SCODE &= !" cameraPos.xz = CameraPath(0.0).xz; \n"
SCODE &= !" camTar.xz = CameraPath(.005).xz; \n"
SCODE &= !" camTar.y = cameraPos.y = max((h*.25)+3.5, 1.0); \n"
SCODE &= !" float roll = 0.15*sin(iGlobalTime*.2); \n"
SCODE &= !" vec3 cw = normalize(camTar-cameraPos); \n"
SCODE &= !" vec3 cp = vec3(sin(roll), cos(roll),0.0); \n"
SCODE &= !" vec3 cu = normalize(cross(cw,cp)); \n"
SCODE &= !" vec3 cv = normalize(cross(cu,cw)); \n"
SCODE &= !" vec3 rd = normalize( uv.x*cu + uv.y*cv + 1.5*cw ); \n"
SCODE &= !" #ifdef STEREO \n"
SCODE &= !" cameraPos += .45*cu*isCyan; // move camera to the right - the rd vector is still good \n"
SCODE &= !" #endif \n"
SCODE &= !" vec3 col; \n"
SCODE &= !" float distance; \n"
SCODE &= !" if(!Scene(cameraPos,rd, distance, fragCoord)) { \n"
SCODE &= !" // Missed scene, now just get the sky value... \n"
SCODE &= !" col = GetSky(rd); \n"
SCODE &= !" col = GetClouds(col, rd); \n"
SCODE &= !" } \n"
SCODE &= !" else \n"
SCODE &= !" { \n"
SCODE &= !" // Get world coordinate of landscape... \n"
SCODE &= !" vec3 pos = cameraPos + distance * rd; \n"
SCODE &= !" // Get normal from sampling the high definition height map \n"
SCODE &= !" // Use the distance to sample larger gaps to help stop aliasing... \n"
SCODE &= !" float p = min(.3, .0005+.00005 * distance*distance); \n"
SCODE &= !" vec3 nor = vec3(0.0, Terrain2(pos.xz ), 0.0); \n"
SCODE &= !" vec3 v2 = nor-vec3(p , Terrain2(pos.xz+vec2(p,0.0 )), 0.0); \n"
SCODE &= !" vec3 v3 = nor-vec3(0.0, Terrain2(pos.xz+vec2(0.0,-p)), -p); \n"
SCODE &= !" nor = cross(v2, v3); \n"
SCODE &= !" nor = normalize(nor); \n"
SCODE &= !" // Get the colour using all available data... \n"
SCODE &= !" col = TerrainColour(pos, nor, distance); \n"
SCODE &= !" } \n"
SCODE &= !" // PostEffects \n"
SCODE &= !" col = (1.0 - exp(-col * 6.0)) * 1.024; \n"
SCODE &= !" #ifdef STEREO \n"
SCODE &= !" col *= vec3( isCyan, 1.0-isCyan, 1.0-isCyan ); \n"
SCODE &= !" #endif \n"
SCODE &= !" fragColor=vec4(col,1.0); \n"
SCODE &= !"} \n"
SCODE &= !"//-------------------------------------------------------------------------- \n"
#include once "fbgfx.bi"
#include once "GL/gl.bi"
#include once "GL/glext.bi"
#ifndef NULL
#define NULL 0
#endif
type vec3
as GLfloat x,y,z
end type
sub ErrorExit(msg as string)
if screenptr() then screen 0
dim as integer w,h
screeninfo w,h : w*=0.75:h*=0.75
screenres w,h
print msg
print "press any key to quit ..."
beep : sleep : end 1
end sub
' define OpenGL proc's
#define glDefine(n) dim shared as PFN##n##PROC n
' texture
' glDefine(glActiveTexture)
' shader
glDefine(glCreateShader)
glDefine(glDeleteShader)
glDefine(glShaderSource)
glDefine(glCompileShader)
glDefine(glGetShaderiv)
glDefine(glGetShaderInfoLog)
' program
glDefine(glCreateProgram)
glDefine(glDeleteProgram)
glDefine(glAttachShader)
glDefine(glDetachShader)
glDefine(glLinkProgram)
glDefine(glGetProgramiv)
glDefine(glGetProgramInfoLog)
glDefine(glUseProgram)
' uniform
glDefine(glGetUniformLocation)
glDefine(glUniform1f)
glDefine(glUniform2f)
glDefine(glUniform3f)
glDefine(glUniform4f)
glDefine(glUniform1i)
#undef glDefine
sub glScreen(w as integer=640, h as integer=360, b as integer=32, d as integer=24, s as integer=0, f as integer=0)
if ScreenPtr() then screen 0
ScreenControl FB.SET_GL_STENCIL_BITS,s
ScreenControl FB.SET_GL_DEPTH_BITS ,d
if ScreenRes(w,h,b,,FB.GFX_OPENGL or iif(f<>0,FB.GFX_FULLSCREEN,0)) then
ErrorExit("screenres(" & w & "," & h &") failed !")
end if
Windowtitle "offline shadertoy.com"
flip
' get OpenGL proc's (abort if something goes wrong)
#define glProc(n) n = ScreenGLProc(#n) : if n = 0 then ErrorExit(#n)
' texture
' glProc(glActiveTexture)
' shader
glProc(glCreateShader)
glProc(glDeleteShader)
glProc(glShaderSource)
glProc(glCompileShader)
glProc(glGetShaderiv)
glProc(glGetShaderInfoLog)
' program
glProc(glCreateProgram)
glProc(glDeleteProgram)
glProc(glAttachShader)
glProc(glDetachShader)
glProc(glLinkProgram)
glProc(glGetProgramiv)
glProc(glGetProgramInfoLog)
glProc(glUseProgram)
' uniform
glProc(glGetUniformLocation)
glProc(glUniform1f)
glProc(glUniform2f)
glProc(glUniform3f)
glProc(glUniform4f)
glProc(glUniform1i)
#undef glProc
end sub
type ShaderToy
declare destructor
declare function CompileFile(Filename as string) as boolean
declare function CompileCode(Code as string) as boolean
as GLuint FragmentShader
as GLuint ProgramObject
as string Shaderlog
end type
destructor ShaderToy
if ProgramObject then
glUseprogram(0)
if FragmentShader then
glDetachShader(ProgramObject,FragmentShader)
glDeleteShader(FragmentShader)
end if
glDeleteProgram(ProgramObject)
end if
end destructor
function ShaderToy.CompileFile(filename as string) as boolean
dim as string code
var hFile = FreeFile()
if open(filename,for input, as #hFile) then
ShaderLog = "can't read shader: " & chr(34) & filename & chr(34) & " !"
return false
end if
while not eof(hFile)
dim as string aLine
line input #hFile,aLine
code &= aLine & !"\n"
wend
close #hFile
return CompileCode(code)
end function
function ShaderToy.CompileCode(UserCode as string) as boolean
dim as GLint logSize
dim as GLint status
dim as string FragmentProlog
FragmentProlog & =!"uniform float iGlobalTime; // shader playback time (in seconds)\n"
FragmentProlog & =!"uniform vec3 iResolution; // viewport resolution (in pixels)\n"
FragmentProlog & =!"uniform vec4 iMouse; // mouse pixel coords. xy: current (if MLB down), zw: click\n"
FragmentProlog & =!"uniform vec4 iDate; // (year, month, day, time in seconds)\n"
FragmentProlog & =!"uniform sampler2D iChannel0;\n"
FragmentProlog & =!"uniform sampler2D iChannel1;\n"
FragmentProlog & =!"uniform sampler2D iChannel2;\n"
FragmentProlog & =!"uniform sampler2D iChannel3;\n"
dim as string FragmentEpilog
FragmentEpilog &= !"void main() {\n"
FragmentEpilog &= !" vec4 color;\n"
FragmentEpilog &= !" // call user shader\n"
FragmentEpilog &= !" mainImage(color, gl_FragCoord.xy);\n"
FragmentEpilog &= !" color.w = 1.0;\n"
FragmentEpilog &= !" gl_FragColor = color;\n"
FragmentEpilog &= !"}\n"
dim as string FragmentCode = FragmentProlog & UserCode & FragmentEpilog
FragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
if FragmentShader=0 then
ShaderLog = "glCreateShader(GL_FRAGMENT_SHADER) failed !"
return false
end if
dim as GLchar ptr pCode=strptr(FragmentCode)
glShaderSource (FragmentShader, 1, @pCode, NULL)
glCompileShader(FragmentShader)
glGetShaderiv (FragmentShader, GL_COMPILE_STATUS, @status)
if status = GL_FALSE then
glGetShaderiv(FragmentShader, GL_INFO_LOG_LENGTH, @logSize)
ShaderLog = space(logSize)
glGetShaderInfoLog(FragmentShader, logSize, NULL, cptr(GLchar ptr,strptr(ShaderLog)) )
ShaderLog = !"glCompileShader(FragmentShader) failed !\n" & Shaderlog
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
ProgramObject = glCreateProgram()
if ProgramObject=0 then
ShaderLog = "glCreateProgram() failed !"
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
glAttachShader(ProgramObject,FragmentShader)
glLinkProgram (ProgramObject)
glGetProgramiv(ProgramObject, GL_LINK_STATUS, @status)
if (status = GL_FALSE) then
glGetProgramiv(ProgramObject, GL_INFO_LOG_LENGTH, @logSize)
ShaderLog = space(logSize)
glGetProgramInfoLog (ProgramObject, logSize, NULL, cptr(GLchar ptr,strptr(ShaderLog)) )
ShaderLog = !"glLinkProgram() failed !\n" & Shaderlog
glDeleteShader(FragmentShader) : FragmentShader = 0
return false
end if
return true
end function
'
' main
'
' init Screenres, create the OpenGL context and load some OpenGL procs.
dim as integer pixels=640
' wide screen 16:9
glScreen pixels,pixels/16*9
' get curent resolution
dim as integer scr_w,scr_h
screeninfo scr_w,scr_h
dim as vec3 v3
v3.x=scr_w ' width in pixle
v3.y=scr_h '`height in pixle
v3.z=v3.x/v3.y ' pixel ratio
dim as ShaderToy Shader
if Shader.CompileCode(SCODE)=false then
ErrorExit Shader.ShaderLog
end if
' enable shader
glUseProgram(Shader.ProgramObject)
' get uniforms locations in shader program
var iGlobalTime = glGetUniformLocation(Shader.ProgramObject,"iGlobalTime")
var iResolution = glGetUniformLocation(Shader.ProgramObject,"iResolution")
var iMouse = glGetUniformLocation(Shader.ProgramObject,"iMouse")
' set vec3 iResolution
glUniform3f(iResolution,v3.x,v3.y,v3.z)
dim as integer mx,my,mb,frames,fps
dim as double tStart = Timer()
dim as double tLast=tStart
while inkey=""
dim as double tNow=Timer()-tStart
' set uniform float iGlobalTime
glUniform1f(iGlobalTime,tNow)
if frames mod 3=0 then
' set vec4 iMouse
if getMouse(mx,my,,mb)=0 then
if mb then
glUniform4f(iResolution,mx,scr_h-my,1,1)
else
glUniform4f(iResolution,0,0,0,0)
end if
end if
end if
'glClear(GL_COLOR_BUFFER_BIT)
' draw a rectangle (2 triangles over the whole screen)
glRectf(-1,-1,1,1)
flip ' swap the buffers
frames+=1
' update fps
if frames mod 24=0 then
fps=24/(tNow-tLast)
windowtitle "fps: " & fps
tLast=tNow
end if
wend
' disable shader
glUseProgram(0)