use tksdl;
use tkopengl;
float frot=0;
int numframesrendered=0;
int tex_id;
float aspect = 1.0;
int TEX_W = 512;
int TEX_H = 256;
int TEX_D = 32;
int slice_offset = 0;
float anim_c = 0;
float anim_o = 0;
float anim_o2 = 0;
float anim_o3 = 0;
Texture tex_font;
Texture tex_pal;
Texture tex_circle;
Texture tex_fog;
int pal_off = 0;
int stars_num = 2048;
FloatArray stars;
stars.alloc(4 * 3 * stars_num); stars.useAll();
FloatArray stars_uv;
stars_uv.alloc(4 * 2 * stars_num); stars_uv.useAll();
FloatArray stars_spd;
stars_spd.alloc(stars_num); stars_spd.useAll();
float stars_sz = 0.023;
float stars_spread = 4.0;
function InitStarfield() {
int i = 0;
int k = 0;
int l = 0;
loop(stars_num)
{
float x = rnd(stars_spread) - stars_spread*0.5;
float y = rnd(stars_spread) - stars_spread*0.5;
float z = - rnd(5.0);
stars_uv[l+0] = 0.0;
stars_uv[l+1] = 0.0;
l += 2;
stars[k+0] = x - stars_sz;
stars[k+1] = y - stars_sz;
stars[k+2] = z;
k += 3;
stars_uv[l+0] = 1.0;
stars_uv[l+1] = 0.0;
l += 2;
stars[k+0] = x + stars_sz;
stars[k+1] = y - stars_sz;
stars[k+2] = z;
k += 3;
stars_uv[l+0] = 1.0;
stars_uv[l+1] = 1.0;
l += 2;
stars[k+0] = x + stars_sz;
stars[k+1] = y + stars_sz;
stars[k+2] = z;
k += 3;
stars_uv[l+0] = 0.0;
stars_uv[l+1] = 1.0;
l += 2;
stars[k+0] = x - stars_sz;
stars[k+1] = y + stars_sz;
stars[k+2] = z;
k += 3;
stars_spd[i++] = 0.008 + rnd(0.02);
}
}
function RenderStarfield(float dt) {
// :P
glDisable(GL_TEXTURE_3D);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
tex_circle.bind();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
zglInitPerspective(float(TEX_W)/float(TEX_H), 40.0, 0.0001, 10.0);
glLoadIdentity();
zglVertexPointer(stars);
glEnableClientState(GL_VERTEX_ARRAY);
zglTexCoordPointer2f(stars_uv);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1,1,1,1.0);
// Setup second texture unit (used to fade out stars depending on distance)
// Note: Fog ignores alpha !
glActiveTexture(GL_TEXTURE1);
glClientActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_1D);
tex_fog.bind();
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
// Sample RGB, multiply by previous texunit result
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
// Sample ALPHA, multiply by previous texunit result
glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
glTexEnvi(GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
// Enable texcoord generation
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
zglTexGen4f(GL_S, GL_OBJECT_PLANE, 0, 0, -0.2, 0);
////glMultiTexCoord1f(GL_TEXTURE1, 0.38);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_GEN_S);
glDrawArrays(GL_QUADS, 0, stars_num);
glDisable(GL_TEXTURE_1D);
glActiveTexture(GL_TEXTURE0);
glClientActiveTexture(GL_TEXTURE0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
int i = 0;
int k = 0;
compile loop(stars_num)
{
float z = stars[k+2];
float zspd = stars_spd[i++] ;
z += zspd * dt;
if(z > 0)
{
float x = rnd(stars_spread) - stars_spread*0.5;
float y = rnd(stars_spread) - stars_spread*0.5;
z = -5.0;
stars[k+3*0+0] = x - stars_sz;
stars[k+3*0+1] = y - stars_sz;
stars[k+3*1+0] = x + stars_sz;
stars[k+3*1+1] = y - stars_sz;
stars[k+3*2+0] = x + stars_sz;
stars[k+3*2+1] = y + stars_sz;
stars[k+3*3+0] = x - stars_sz;
stars[k+3*3+1] = y + stars_sz;
}
stars[k+3*0+2] = z;
stars[k+3*1+2] = z;
stars[k+3*2+2] = z;
stars[k+3*3+2] = z;
k += 3 * 4;
}
}
int scroll_off = 0;
float scroll_csx = 64;
float scroll_csy = 64;
float scroll_csx_anim = 0;
float scroll_csy_anim = 0;
float scroll_csy_anim2 = 0;
float scroll_cnt = scroll_csx;
String scroll_text = " to scroll or not to scroll..... ahhh...to be young again...and also a ROB0T !11 scrolly wrapZzzz ";
float scroll_oa = 0;
function RenderScrollText(float dt) {
scroll_csx = 64;
scroll_csy = 128 + sin(scroll_csy_anim)*64;
scroll_csx_anim += 0.0323910234 * dt;
wrap scroll_csx_anim 0 2PI;
scroll_csy_anim += ( (0.6 + 0.4 * sin(scroll_csy_anim2))) * 0.1293131231249 * dt;
wrap scroll_csy_anim2 0 2PI;
scroll_csy_anim2 += 0.058239402341 * dt;
wrap scroll_csy_anim2 0 2PI;
float vw = TEX_W;
float vh = TEX_H;
zglInit2D(vw, vh);
glLoadIdentity();
tex_font.bind();
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
int txti = scroll_off;
float cx = -scroll_csx + scroll_cnt;
float basecy = (vh-scroll_csy) * 0.5;
float ustep = 8.0 / tex_font.sx;
float u2step = (8.0 / scroll_csx) * (1.0 / tex_font.sx);
float vstep = 12.0 / tex_font.sy;
float f8 = (0.6 + sin(anim_c)*0.4);
int c32 = tex_pal[pal_off];
int r = ((c32>>16)&255) * f8;
int g = ((c32>> 8)&255) * f8;
int b = ((c32 )&255) * f8;
zglColorARGB(argb(255, r, g, b));
pal_off = (pal_off + 1) % tex_pal.sx;
float iaspd = 0.01310394134 * 1.3;
float ia = scroll_oa + cx*iaspd;
glBegin(GL_QUADS);
compile loop( (vw/scroll_csx) +2)
{
char c = scroll_text.getc(txti);
if(c > ' ')
{
c -= 33;
float u = c * ustep;
int k = 0;
loop(int(scroll_csx))
{
float cy = basecy + sin(ia) * (vh-scroll_csy) * 0.5;
glTexCoord2f(u, 0);
glVertex2f(cx, cy);
glTexCoord2f(u+u2step, 0);
glVertex2f(cx+1, cy);
glTexCoord2f(u+u2step, vstep);
glVertex2f(cx+1, cy+scroll_csy);
glTexCoord2f(u, vstep);
glVertex2f(cx, cy+scroll_csy);
cx += 1;
u += u2step;
ia += iaspd;
k++;
}
}
else
{
ia += scroll_csx * iaspd;
cx += scroll_csx;
}
txti++;
if(txti >= (scroll_text.length-1))
{
txti = 0;
}
}
glEnd();
scroll_cnt -= 2* dt;
if(scroll_cnt <= 0)
{
scroll_cnt += scroll_csx;
scroll_off++;
if(scroll_off >= (scroll_text.length-1))
{
scroll_off = 0;
}
}
scroll_oa -= 0.032412891234 * dt;
wrap scroll_oa 0 2PI;
anim_c += 0.11076134 * dt;
wrap anim_c 0 2PI;
}
int GRID_W = 64;
int GRID_H = 64;
FloatArray plasma_r; plasma_r.alloc((GRID_W + 1) * (GRID_H + 1)); plasma_r.useAll();
function RenderPlasmaGrid(float dt) {
float iaspd = 0.0101020123;
float oa = anim_o;
float oa2 = anim_o2;
float oa3 = anim_o3;
float oaspd = 0.105103724239612389;
float oaspd2 = 0.1312102342341039612389;
float oaspd3 = 0.142312341351345134;
float y = 0;
float xstep = TEX_W / float(GRID_W);
float ystep = TEX_H / float(GRID_H);
float v = 1.0;
float ustep = 1.0 / GRID_W;
float vstep = -1.0 / GRID_H;
float roff = (slice_offset/(float(TEX_D)));
// Calc texture coords
int k = 0;
compile loop(GRID_H + 1)
{
float ia = (0.5 + 0.5 * sin(oa)) * 2PI;
float ia2 = (0.5 + 0.5 * sin(oa3)) * 2PI;
loop(GRID_W + 1)
{
float tz = roff - (float(TEX_D-2)/TEX_D) * (0.5 + 0.5 * sin(ia));
plasma_r[k++] = tz;
ia += iaspd * (0.7 + 0.3 * sin(ia2));
ia2 += 2.93123491345013;
}
oa += oaspd * (0.8 + 0.2 * sin(oa2));
oa2 += oaspd2;
oa3 += oaspd3;
}
// Now render
k = 0;
glBegin(GL_QUADS);
compile loop(GRID_H)
{
int ix = 0;
float u = 0;
float x = 0;
loop(GRID_W)
{
float tzul = plasma_r[k];
float tzur = plasma_r[k + 1];
float tzdl = plasma_r[k + (GRID_W + 1)];
float tzdr = plasma_r[k + 1 + (GRID_W + 1)];
glTexCoord3f(u, v, tzul);
glVertex3f(x, y, 0);
glTexCoord3f(u+ustep, v, tzur);
glVertex3f(x + xstep, y, 0);
glTexCoord3f(u+ustep, v+vstep, tzdr);
glVertex3f(x + xstep, y + ystep, 0);
glTexCoord3f(u, v+vstep, tzdl);
glVertex3f(x, y + ystep, 0);
u += ustep;
x += xstep;
ix++;
k++;
}
k++;
v += vstep;
y += ystep;
}
glEnd();
anim_o += 0.0103423 * dt;
wrap anim_o 0 2PI;
anim_o2 += 0.021231359003423 * dt;
wrap anim_o2 0 2PI;
anim_o3 += 0.019230890130941321231359003423 * dt;
wrap anim_o3 0 2PI;
}
function onDraw() {
glDrawBuffer(GL_BACK);
float dt = FPS.precision;
dt = 1.0;
glViewport(0, 0, TEX_W, TEX_H);
// Render new texture slice
glDisable(GL_DEPTH_TEST);
glDisable(GL_TEXTURE_3D);
glClearColor(0,0,0.0,1);
glClear(GL_COLOR_BUFFER_BIT);
if( !(++numframesrendered&127) )
trace "FPS.real="+FPS.real;
RenderStarfield(dt);
// Render texture slice
RenderScrollText(dt);
glViewport(0, 0, Viewport.width, Viewport.height);
// Copy texture slice
glBindTexture(GL_TEXTURE_3D, tex_id);
glCopyTexSubImage3D(GL_TEXTURE_3D, 0,
0, 0, slice_offset,
0, 0,
TEX_W, TEX_H
);
// Pass2: Render 3D texture
glClearColor(1,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
zglInit2D(TEX_W / aspect, TEX_H);
glLoadIdentity();
if(aspect != 1.0f)
{
glTranslatef( -(640-512)/2, 0, 0);
}
glEnable(GL_TEXTURE_3D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glDisable(GL_BLEND);
glColor3f(0.1, 0.9, 0.1);
glDisable(GL_CULL_FACE);
RenderPlasmaGrid(dt);
glDisable(GL_TEXTURE_3D);
// Next slice
slice_offset = (slice_offset + 1) & (TEX_D-1);
}
function onKeyboard(Key _k) {
switch(_k.pressed)
{
case VKEY_ESCAPE:
SDL.exitEventLoop();
break;
case VKEY_RETURN:
Viewport.toggleFullScreen();
if(Viewport.width == 640)
{
aspect = 1.3333;
}
else
{
aspect = 1.0;
}
break;
}
}
function onReopen() {
tex_id = zglGenTexture();
glBindTexture(GL_TEXTURE_3D, tex_id);
// Note: omitting the first glTexParameteri call will cause GL to simply skip rendering textured triangles. WTF.
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT);
zglTexImage3D(GL_TEXTURE_3D,
0,
GL_RGB8,
TEX_W, TEX_H, TEX_D,
0,
GL_RGB,
GL_UNSIGNED_BYTE,
null
);
tex_font.loadImage("font.png", 0,0,0);
tex_font.expand2n();
tex_font.flags = TEX_MODULATE | TEX_ALPHA;
tex_font.unload();
tex_pal.loadImage("pal.png", 0,0,0);
tex_pal.unload();
tex_circle.loadImage("circle.png", 0,0,0);
tex_circle.flags = TEX_MODULATE | TEX_ALPHA | TEX_AUTOMIPMAP | TEX_MINFILTERTRILINEAR | TEX_MAGFILTERLINEAR;
tex_circle.unload();
// Create 1D fog/alpha fade texture
tex_fog.alloc(256, 1, 4);
tex_fog.flags = TEX_1D | TEX_ALPHA;
int i = 0;
float a = 0;
loop(64)
{
tex_fog[i++] = argb(a,255,255,255);
a += 4;
}
a = 255;
loop(192)
{
tex_fog[i++] = argb(a,255,255,255);
a-= 255 / 192.0;
}
tex_fog.unload();
InitStarfield();
}
function main() {
Viewport.doubleBuffer = true;
Viewport.openWindow(512, 256);
Viewport.setScreenResolution(640, 480, 32);
zglLoadExtensions();
use callbacks;
onReopen();
FPS.tickInterval=1000.0/60;
FPS.limit=60;
Viewport.caption="to scroll or not to scroll..";
Viewport.swapInterval(1);
SDL.eventLoop();
}