Dark Bit Factory & Gravity
GENERAL => Projects => Topic started by: taj on May 02, 2007
-
Hi all,
I wrote another 1k. I had some time on my hands and it turned out to be one of my very best. It uses PS2.0, OGL,C and is an EXE (thanks Benny for help here).
http://www.pouet.net/prod.php?which=30589
http://www.intro-inferno.com/production.php?id=3551
Heres is the source:
// Chris Thornborrow (auld/sek/taj/copabars/fra/mess4u etc.)
// If you use this code please credit...blahblah
// Example OGL + shaders in 1k
// Requires crinkler - magnificent tool
// VS2005 modifications by benny!weltenkonstrukteur.de from dbf
// Greets!
// NOTE: DX will beat this no problem at all due to OpenGL forced
// to import shader calls as variables..nontheless we dont need
// d3dxblahblah to be loaded on users machine.
#include <windows.h>
#include <GL/gl.h>
#include "glext.h"
// NOTE: in glsl it is legal to have a fragment shader without a vertex shader
// Infact ATi/AMD drivers allow this but unwisely forget to set up variables for
// the fragment shader - thus all GLSL programs must have a vertex shader :-(
// Thanks ATI/AMD
// This is prtty dirty...note we do not transform the rectangle but we do use
// glRotatef to pass in a value we can use to animate...avoids one more getProcAddress later
const GLchar *vsh="\
varying vec4 p;\
void main(){\
p=sin(gl_ModelViewMatrix[1]*9.0);\
gl_Position=gl_Vertex;\
}";
// an iterative function for colour
const GLchar *fsh="\
varying vec4 p;\
void main(){\
float r,t,j;\
vec4 v=gl_FragCoord/400.0-1.0;\
r=v.x*p.r;\
for(int j=0;j<7;j++){\
t=v.x+p.r*p.g;\
v.x=t*t-v.y*v.y+r;\
v.y=p.g*3.0*t*v.y+v.y;\
}\
gl_FragColor=vec4(mix(p,vec4(t),max(t,v.x)));\
}";
//p.g*3.0*t*v.y+i;\
typedef void (*GenFP)(void); // any function ptr type would do
static GenFP glFP[7];
const static char* glnames[]={
"glCreateShader", "glCreateProgram", "glShaderSource", "glCompileShader",
"glAttachShader", "glLinkProgram", "glUseProgram"
};
static void setShaders() {
int i;
// 19. April 2007: "(GenFP) cast" added by benny!weltenkonstrukteur.de
for (i=0; i<7; i++) glFP[i] = (GenFP)wglGetProcAddress(glnames[i]);
GLuint v = ((PFNGLCREATESHADERPROC)(glFP[0]))(GL_VERTEX_SHADER);
GLuint f = ((PFNGLCREATESHADERPROC)(glFP[0]))(GL_FRAGMENT_SHADER);
GLuint p = ((PFNGLCREATEPROGRAMPROC)glFP[1])();
((PFNGLSHADERSOURCEPROC)glFP[2]) (v, 1, &vsh, NULL);
((PFNGLCOMPILESHADERPROC)glFP[3])(v);
((PFNGLSHADERSOURCEPROC)glFP[2]) (f, 1, &fsh, NULL);
((PFNGLCOMPILESHADERPROC)glFP[3])(f);
((PFNGLATTACHSHADERPROC)glFP[4])(p,v);
((PFNGLATTACHSHADERPROC)glFP[4])(p,f);
((PFNGLLINKPROGRAMPROC)glFP[5])(p);
((PFNGLUSEPROGRAMPROC) glFP[6])(p);
}
// force them to set everything to zero by making them static
static PIXELFORMATDESCRIPTOR pfd;
static DEVMODE dmScreenSettings;
void WINAPI WinMainCRTStartup()
{
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = 1024;
dmScreenSettings.dmPelsHeight= 768;
// dmScreenSettings.dmBitsPerPel = 32;
// its risky to remove the flag and bits but probably safe on compo machine :-)
dmScreenSettings.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
// minimal windows setup code for opengl
pfd.cColorBits = pfd.cDepthBits = 32;
pfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
// "HDC hDC" changed 19. April 2007 by benny!weltenkonstrukteur.de
HDC hDC = GetDC( CreateWindow("edit", 0, WS_POPUP|WS_VISIBLE|WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0) );
SetPixelFormat ( hDC, ChoosePixelFormat ( hDC, &pfd) , &pfd );
wglMakeCurrent ( hDC, wglCreateContext(hDC) );
setShaders();
ShowCursor(FALSE);
//**********************
// NOW THE MAIN LOOP...
//**********************
// there is no depth test or clear screen...as we draw in order and cover
// the whole area of the screen.
do {
//dodgy, no oglLoadIdentity- might break...
// change the first number to alter speed of intro...smaller is slower
// this is the fast version
glRotatef(0.3f,1,1,1);
// draw a single flat rectangle on screen...
glRecti(-1,-1,1,1);
SwapBuffers(hDC);
} while ( !GetAsyncKeyState(VK_ESCAPE) );
}
Hope u like it.
Chris
-
Thats awesome man:)
Really nice colors and movement, the middle speed is the best one according to me.
-
I love it, Chris. It really rocks. Just awesome !!!
Karma for mentioning me :-) and for sharing code - you rule !!!
-
all three didnt work on my PC just started up then seconds later crashed :( sorry dont have any details for the error just got one of those send error report to microsoft messages
-
Guys: thanks very much for nice comments. I had a free dsay and nothing to do at all, so inspired by Benny, I tried one more which came out nicly, even I like it. Thanks Benny.
Rain_storm, can you tell me what hardware/OS you have? There is no DX and no import by ordinal so in theory it works (ie Im not doing anything too dirty).
Chris
-
It wouldent work for me either, which was a shame since from the screenie it looked cool :'( I expect thats because my graphics card dosent support shaders.
-
Mike_g,
and anyone else trying to run this without shaders : it wont work. Shaders are a step function, I cant write a software fallback path I'm afraid.
Chris
-
Windows XP SP2 (with directX 9)
celeron D (345) @ 3.3GHz
intel extreme grahics integrated into the motherboard
I think it is probably a shader issue its a real piety can those shaders be downloaded or are they a part of the graphics card hardware.
-
Pixel shaders are part of the graphics hardware, there have been (at least) 4 revisions - 1.0, 1.1, 2.0, 3.0 - the newer your hardware the better supported they are. 2.0 is where most demos are targetted, and that has only recently been added to embedded (chipset) graphics solutions, so that might explain why it doesn't work for you. Not much you can do except upgrade... If you have an AGP or PCI Express slot on your board you can get something quite cheaply...
Jim
-
nice
-
Unfortunately I can't run it myself because of the PS, however it is lovely to see another release from you Chris, Karma up for sharing the source code, and thank you for spending some of your free time to create something for other people to enjoy!
-
Unfortunately I can't run it myself because of the PS, however it is lovely to see another release from you Chris, Karma up for sharing the source code, and thank you for spending some of your free time to create something for other people to enjoy!
I have holiday right now and its one of those lazy "at home" holidays. Benny inspired me to push a 1k exe out so I took the old mandelflow code, reworked it and hey presto.
http://in4k.untergrund.net/index.php?title=About_Flow2
Some more details. I guess you cant leave the scene except maybe by throwing your PC out of the window, I guess you just become inactive. Thanks to everyone for support - this 1k doesnt mean I'm "back" it just means I had a free day.
Chris
-
Old habits die hard, I suppose
-
Nice!
Just wondering whether the graphics represent piano keys? Just looked as like they were the keys! lol.
-
CLANKY,
You think the same as me :-) I almost called it pianobrot. I'd like to say it was designed that way but in truth the shaders are so small that you search for an interesting effect in the 10-15 bytes you have or so left for colour. In writing my glsl 1ks I usually spend half a day just tweaking that one line of colour code!
The truth is doing GLSL shaders in 1k is a bit like having a small suitcase, filling it with everything you need, then discovering your shoes dont fit and no matter how hard you try, you cant close the case. DX is the better choice at 1k :-(. Assembler helps for sure too (~10% which is huge at 1k).
MIX(v1,v2,v3) is a cool glsl command, it smoothly blends one vector (colour) with another, and the blendfactor is the third value. This is how the white is belnded with the inner colours. This I used on its own in mandelflow
http://www.intro-inferno.com/production.php?id=2062
The trick with the piano effect was realising suddenly that if I use a discontinuous function as the blend factor (v3) I might get a double of effect of smooth blending then a break to some other look and feel. Hence the piano around the edges.
MIX(v1,v2,max(a,b)) <- max gives a discontinuous function
It was then a matter of putting every variable I had into that equation until something cool popped out (thats the squeezing your shoes in bit ;-)).
Hmmm I just noiticed the last line of code:
gl_FragColor=vec4(mix(p,vec4(t),max(t,v.x)));
Can be written
gl_FragColor=mix(p,vec4(t),max(t,v.x));
so maybe I could squeeze the shoes in too. I hate it when the "obvious" escapes you until *after* release.
Chris
-
Just one question:
Is this using dot product multiplication? Or am I wrong? lol
gl_FragColor = vec4(mix(p, vec4(t), max(t, v.x)))
gl_FragColor = mix(p, vec4(t), max(t, v.x))
Yea. Sometimes in yabasic. lol... I get the same way! But, not as the way you do. I just struggle to get the gfx looking good lol.
-
CLANKY,
mix(a,b,c) = a*c + b(1-c)
So not dot product, for which in GLSL would be
dot(a,b)
Chris
-
so i take it glsl`s vec4 function is quite expensive in terms of exe size taj?
-
Nino,
well all glsl "code" is really a string. Its not compiled until you run the program! In other words the part of your code that is the shader is the text of the code itself.
eg
const char *vsh="varying vec4 p;void main(){p=gl_ModelViewMatrix[3];gl_Position=gl_Vertex;}";
which looks just like a string declaration in C is a shader program.
At run time this is passed to a series of command something like:
declare this shader (string)
compile this shader
link this shader with other shaders
attach the compiled code to a program
run the program
Its almost the same thing as you taking a text file, compiling and linking it! Infcat most people not worried about size coding store their shaders in seperate text files which are read when the program runs.
This means that vec4() is around 6 bytes v-e-c-4-(-). Tiny. Of course it may compress (strings do). But then again, by not using it you could put s-i-n-(-) elsewhere and get a better effect for example. Or create an animation by multiplying one variable by another. Once you get shaders up and running they are incredibly small (or can be).
To illustrate look at this:
const GLchar *vsh="varying vec4 p;void main(){p=gl_ModelViewMatrix[3];gl_Position=gl_Vertex;}";
const GLchar *fsh="\
varying vec4 p;\
void main(){vec4 d,v;float t=0.0;d=gl_FragCoord/400.0-1.0;d.y+=sin(p.z*5.0);\
do{t+=0.01;v=fract(p+0.5+t*d);}while(t<8.0&&length(v.xyz-0.5)<0.6);\
gl_FragColor=(v-0.5)+t/2.0;}";
Given a rectangle covering the screen, and that shader, produces an animation like the on in the picture (some of us know as "lattice"). Of course I never finished the colours or lighting so you have to use some imagination, nontheless the code is tiny.
The part that goes:
do{t+=0.01;v=fract(p+0.5+t*d);}while(t<8.0&&length(v.xyz-0.5)<0.6);\
is actually doing this ray-marching in a grid of spheres. The eye position is animated, there is
a test for going too far and there is a test that if we leave the intersecting spheres, we hit a wall.
So, raycasting using ray marching a complex curved surface in 1 line of code.
Shaders are damn powerful and may even beat assembler for size!!!
Chris
-
great and cheers taj k+,
this is going to really help me take my first steps into shaders.
great screenshot btw
-
Oh, I wanna be retired too! :clap:
-
@Chris: I know that you like comparisons between C and ASM, so here is your 1k recoded to ASM, one with opengl32 IBO (984 bytes) and the second without IBO (994 bytes)
What you do in 40 bytes ? :||
-
@Chris: I know that you like comparisons between C and ASM, so here is your 1k recoded to ASM, one with opengl32 IBO (984 bytes) and the second without IBO (994 bytes)
What you do in 40 bytes ? :||
IN C or asm ;-)???
Seriously this is interesting because it begins to put bounds on asm v c in terms of %age. Well done man, have some Karma. Its clear that for size coders, asm has the size advantage for sure *once* the algorithm etc are worked out. My main complaint about asm is that most coders jump to it before optimising what they can otherwise and that somehow in the scene is "better".
Hmmm I'm drunk, whats FBO? Frame buffer object?
Chris
-
...My main complaint about asm is that most coders jump to it before optimising what they can otherwise and that somehow in the scene is "better".
Very true...
Hmmm I'm drunk, whats FBO? Frame buffer object?
Oh yeah, you're really drunk ;)
IBO - Import By Ordinal
-
Hmmm I'm drunk, whats FBO? Frame buffer object?
Oh yeah, you're really drunk ;)
IBO - Import By Ordinal
Hahaha, blind too.
-
Aaagh just realised, 40 bytes ... in a shader , my god thats a LOT!!!
Oh man I better learn asm :-(
Chris
(or send you my C programs and do joint releases :-)
-
...My main complaint about asm is that most coders jump to it before optimising what they can otherwise and that somehow in the scene is "better".
Who gives a fuck about the scene anyway? :) Half of the scene is rotten anyway, only friends are important.
-
...My main complaint about asm is that most coders jump to it before optimising what they can otherwise and that somehow in the scene is "better".
Who gives a fuck about the scene anyway? :) Half of the scene is rotten anyway, only friends are important.
But but but, what if your freinds are sceners ??? Does not compute!!!
-
Half the scene is rotten :) Half is nice. :cheers:
-
Aaagh just realised, 40 bytes ... in a shader , my god thats a LOT!!!
Oh man I better learn asm :-(
I found more two bytes (982) :P
(or send you my C programs and do joint releases :-)
If you have something to kick mentor butt, count with me!
-
You two would totally rule if you teamed up.