Thanks Jim.
As a sorta bonus for folks, here is the complete code of the intro. The program works by drawing a quad on the screen, the shader does almost all the rest of the work. Rbraz , you might be interested to note that I do a translate and rotate in my application code but I found its nearly twenty bytes smaller (!!!) to code that as glMultMatrixf with a static array of floats for the matrix than standard glRotate and glTranslate
// Chris Thornborrow (auld)... lalala credit would be nice ... lalala
// Example OGL + shaders in 1k
// Requires crinkler
// VS2005 modifications by benny!weltenkonstrukteur.de
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glext.h"
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"
};
// Draws the labyrinth using a pair of shaders...
// Vertex shader does NOT transform incoming vertex but stores that in p instead for later use
// The fragment shader is a complicated. It essentially raycasts into a constantly changing
// equation, similar in concept to chladni :-). Its carfully tuned so we dont crash into it as we move
// and so we get a feeling of depth. The for loop could be smaller when written as a do .. while but then
// it wouldnt work on NVidia cards of 7xxx series or below.
// Fragment shader has 2 lines for setup, 1 line for raycasting and function testing, 1 line for colour.
const char *labvsh="varying vec4 p;void main(){p=ftransform();gl_Position=gl_Vertex;}";
const char *labfsh="\
varying vec4 p;\
void main(){\
vec3 V=vec3(0,3.5*sin(p.z),p.z);\
vec3 D=vec3(p.x,p.y,0.5)*0.08;\
for(int i=800;i>0;i--,V+=D)if(length(fract(abs(sin(V))))>1.5+0.5*sin(V.z)*sin(p.z*0.4))i=0;\
gl_FragColor=vec4(1,0.8,0.8,0)*dot(vec3(0.4),fract(V))-length(V-p.xyz)*0.1;\
}";
static void setShaders() {
// 19. April 2007: "(GenFP) cast" added by benny!weltenkonstrukteur.de
for (int 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, &labvsh, NULL);
((PFNGLSHADERSOURCEPROC)glFP[2]) (f, 1, &labfsh, NULL);
((PFNGLCOMPILESHADERPROC)glFP[3])(v);
((PFNGLCOMPILESHADERPROC)glFP[3])(f);
((PFNGLATTACHSHADERPROC)glFP[4])(p,v);
((PFNGLATTACHSHADERPROC)glFP[4])(p,f);
((PFNGLLINKPROGRAMPROC)glFP[5])(p);
((PFNGLUSEPROGRAMPROC) glFP[6])(p);
}
static PIXELFORMATDESCRIPTOR pfd;
static DEVMODE dmScreenSettings;
// This is an approximation to rotation by 1 degree round z axis
// because its an approximation, it deteriorates in time!!
// and a small translation (0.04) down the z axis
static const GLfloat m[16]={1,-0.01f,0,0,0.01f,1,0,0,0,0,1,0,0,0,0.04f,1};
void WINAPI WinMainCRTStartup()
{
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = 640;
dmScreenSettings.dmPelsHeight= 480;
//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
// risky but tested on 2xati cards and 1xnvidia8800
//pfd.cColorBits = 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 {
//move forward and rotate slightly each frame
//glMultMatrix is smaller (20 bytes) than glTranslatef and glRotatef!!
glMultMatrixf((const GLfloat*)&m);
glRecti(-1,-1,1,1);
SwapBuffers(hDC);
} while ( !GetAsyncKeyState(VK_ESCAPE) );
// necessary under vista it seems... :-( extra bytes required.
ExitProcess(0);
}
The cool thing is the intro works under XP/Vista, and all known Nvidia and ATi cards supporting PS3.0 (depsite all the quirks and bumps). Thats mostly thanks to help from DBF and some help from McZonk in Titan.
Chris