Dark Bit Factory & Gravity
PROGRAMMING => C / C++ /C# => Topic started by: taj on October 25, 2007
-
Hi guys,
Well Ive done a few 1k frameworks over time but they were all done without crinkler in mind. Given this is the defacto standard for 4k and now 1k - it was time to update. After days of trial and error, mainly error, I got this to work on my Ati, XP machines. No guarantees on anything else :-) yet. Its all very dodgy, laregly shouldnt work, but it does.
First windowing code. The code opens a full screen window, and sets up opengl. It runs a loop waiting for escape key and even includes the swapbuffers. It uses DEVMOVE setup to open at any resolution but this can be removed if you think you dont need it.
#include < windows.h >
#include < GL/gl.h >
static PIXELFORMATDESCRIPTOR pfd={
0, // Size Of This Pixel Format Descriptor... BAD coding, nothing new, saves 6 bytes
1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0
};
static DEVMODE dmScreenSettings={
"",0,0,sizeof(dmScreenSettings),0,DM_PELSWIDTH|DM_PELSHEIGHT,
0,0,0,0,0,0,0,0,0,0,0,0,0,"",0,0,1024,768,0,0,0,0,0,0,0,0,0,0
};
void WINAPI WinMainCRTStartup()
{
ChangeDisplaySettings (&dmScreenSettings,CDS_FULLSCREEN);
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) );
ShowCursor(FALSE);
do {
// insert breakpoint winning 1k here
SwapBuffers(hDC);
} while ( !GetAsyncKeyState(VK_ESCAPE) );
}
Next, shader code. Given two strings representing the vertex and pixel shaders, this routine is the smallest I could come up with under crinkler to create and bind the shader program.
static void setShaders(){
GLuint p,s;
p = ((PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram"))();
s = ((PFNGLCREATESHADERPROC)(wglGetProcAddress("glCreateShader")))(GL_VERTEX_SHADER);
((PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource")) (s, 1, &vsh, NULL);
((PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"))(s);
((PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader")) (p,s);
s = ((PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"))(GL_FRAGMENT_SHADER);
((PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource")) (s, 1, &fsh, NULL);
((PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"))(s);
((PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader")) (p,s);
((PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram"))(p);
((PFNGLUSEPROGRAMPROC) wglGetProcAddress("glUseProgram"))(p);
}
They are useful for 1k and 4k coders, though I think OpenGl at 1k is not really competitive anymore.
Chris
http://sizecoding.blogspot.com/
-
This will surely come in handy thanks for putting this together. I'm off to try to get this up and runnin
Edit: Looks like this is not gonna be easy lotsa "cannot convert from const char [n] to WCHAR" should I be replacing some 0's with ""
-
That's neat, need to do some tests ;D
Btw, do you have a little shader program example for me to test my asm version and compare with your C program (sizes) ?
-
Edit: Looks like this is not gonna be easy lotsa "cannot convert from const char [n] to WCHAR" should I be replacing some 0's with ""
OK as Jim said, thats a bit hopeful (the quotes) It works under VC Express but probably needs casting properly. Which version are you using rain? I'm sure this is easy to fix.
Chris
-
Visual Studio C++ 2005 Exress. I have been preatty much lost in the flood with C, so far I have only really managed to compile SDL based PE's but I find they are very big for what I need. This would be a great piece to strip apart as it gets a screen up and runnin in a few lines of code. Just getting past the compilation
-
"" is the correct initialiser, {0} might work too.
Edit: Looks like this is not gonna be easy lotsa "cannot convert from const char [n] to WCHAR" should I be replacing some 0's with ""
You need to turn off UNICODE
Project->Properties->Configuration Properties->General
and set Character Set to Use Multi-Byte Character Set.
Chris, I think it might be possible to save more bytes here
Place
#define WINVER 0x400
before you #include windows.h.
That would mean you could remove 8 0s off the end of the DEVMODE initialiser.
Basically that structure has grown in later versions of Windows, so various values of sizeof(dmScreenSettings) are valid. You're just telling it you're building for NT4 compatibility.
Jim
-
It was a great idea Jim but the compressor just sees all those lovely zeroes and handles them nicely, so though your suggestion works nicely, it doesn't save bytes :-(. Shame.
Chris
-
Bah, I didn't even shrink the source code ;D
Jim
-
Looking good. Thanks for sharing. WIll have a closer look on it later on !!!
-
Another idea...
How about
DEVMODE devmode;
...
{
//get the current display mode
devmode.dmSize = sizeof(devmode);
EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&devmode);
//modify any settings you like, if any
devmode.dmPelsWidth = 1024;
devmode.dmPelsWidth = 768;
//set the mode
ChangeDisplaySettings (&dmScreenSettings,CDS_FULLSCREEN);
}
or even
EnumDisplaySettings(NULL,0,&devmode);
that's likely to get you 800x600x32@60Hz on XP
Tried these and the return looks nonsense - plus I just had to add dmSize = in there the make it work at all. :(
Jim
-
Jim, basically thats how the framework looked before, I am switching to static declarations because its smaller than lines of code. Here is the code from before:
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = 1024;
dmScreenSettings.dmPelsHeight= 768;
dmScreenSettings.dmFields=DM_PELSWIDTH|DM_PELSHEIGHT;
ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN);
This is much bigger than the static version I've just published.
Chris
-
The idea was to not have a static declaration at all (takes up no space) and to make it a valid structure using EnumDisplayMode - on it's own, that would be smaller, but there's too much set up, as we both noticed :(
Jim
-
That's neat, need to do some tests ;D
Btw, do you have a little shader program example for me to test my asm version and compare with your C program (sizes) ?
Rbraz, I forgot this earlier.. I'll post something tonight.
Chris
-
Rbraz,
heres some example code for you. Its more or less the best I can do :-(. Size, crinkler flags etc in code...let me know what you get. It will be a good test of VC++ v hand coding.
For others, this is the smallest oldskool tunnel effect I can do in shaders. Its pretty small (the shader). IF ati drivers didnt break without a vertex shader I could do better. Oh well.
// Chris Thornborrow (auld)
// New crinkler optimised OpenGL 1k + shader framework.
// Sets screen size, loads vertex and fragment shader
// also exitProcess for some Nvidia and Vista machines
// Example shader included...
// /CRINKLER /COMPMODE:SLOW /HASHSIZE:200 /HASHTRIES:50 /ORDERTRIES:6000
// 915 bytes with VC++ Express
// Oldskool tunnel effect...but without real timer
#include <windows.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glext.h"
///////////////////////////////////////////////////////////////////
// WINDOWING
#define SCREENX 1024
#define SCREENY 768
static PIXELFORMATDESCRIPTOR pfd={
0, // Size Of This Pixel Format Descriptor... BAD coding, nothing new, saves 6 bytes
1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, 32, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0
};
static DEVMODE dmScreenSettings={
"",0,0,sizeof(dmScreenSettings),0,DM_PELSWIDTH|DM_PELSHEIGHT,
0,0,0,0,0,0,0,0,0,0,0,0,0,"",0,0,SCREENX,SCREENY,0,0,0,0,0,0,0,0,0,0
};
const char *vsh="varying vec4 v;void main(){v=ftransform();gl_Position=gl_Vertex;}";
const char *fsh="varying vec4 v;void main(){float t=length(v.xy);gl_FragColor=vec4(cos(4./t+v.z)*t);}";
void setShader() {
GLuint p,s;
p = ((PFNGLCREATEPROGRAMPROC)wglGetProcAddress("glCreateProgram"))();
s = ((PFNGLCREATESHADERPROC)(wglGetProcAddress("glCreateShader")))(GL_VERTEX_SHADER);
((PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource")) (s, 1, &vsh, NULL);
((PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"))(s);
((PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader")) (p,s);
s = ((PFNGLCREATESHADERPROC)wglGetProcAddress("glCreateShader"))(GL_FRAGMENT_SHADER);
((PFNGLSHADERSOURCEPROC)wglGetProcAddress("glShaderSource")) (s, 1, &fsh, NULL);
((PFNGLCOMPILESHADERPROC)wglGetProcAddress("glCompileShader"))(s);
((PFNGLATTACHSHADERPROC)wglGetProcAddress("glAttachShader")) (p,s);
((PFNGLLINKPROGRAMPROC)wglGetProcAddress("glLinkProgram"))(p);
((PFNGLUSEPROGRAMPROC) wglGetProcAddress("glUseProgram"))(p);
}
void WINAPI WinMainCRTStartup()
{
ChangeDisplaySettings (&dmScreenSettings,CDS_FULLSCREEN);
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) );
ShowCursor(FALSE);
setShader();
do {
glTranslatef(0,0,0.5f);
glRects(-1,-1,1,1);
SwapBuffers(hDC);
} while ( !GetAsyncKeyState(VK_ESCAPE) );
ExitProcess(0);
}
-
Ok, I got it down to 895 bytes, using your crinkler parameters.
I didn't have tried your new way to initialize shaders (setShader()), I will try it later to see how much bytes I can get.
Anyway, sometimes 20 bytes can be helpful :)
-
Yeah I agree rbraz - 20 bytes in shaders is actually quite a lot of help. Given you havent tried the new shader code too...thats probably another 20. So I'd guess 40 in all. Thats a lot at of advantage at 1k.
Now we have to wait for mentor to release his new 1k compressor ...
Chris
-
Yes, you are right, I've recoded it using your new shader setup and now it compress to 877 bytes.
This is annoying because the other code have less lines and looks "smart" but it is not what crinkler likes :)
-
Rbraz,
FYI iq of rgba gave me a D3D version of a 1k framework which with minimal shader comes in at 835 bytes. So its something like (for shaders using Crinkler):
OGL in C : 900
OGL in asm : 870
D3D in C: 830
D3D in asm: ??? 800???
D3D doesnt need the vertex shader and doesnt need to import shader commands but is a little heavier to initialise than OGL. Getting values into the shader is also easier with D3D.
Time to learn HLSL I guess: its a bigger advantage than learning asm!
Chris
-
Dunno if this is relevant to pixel shaders and all the malarkey, but have any of you looked at t-time by Peci^Scoopex (http://www.pouet.net/prod.php?which=19455) ? it displays a teapot OpenGL primitive in 256b.
-
Dunno if this is relevant to pixel shaders and all the malarkey, but have any of you looked at t-time by Peci^Scoopex (http://www.pouet.net/prod.php?which=19455) ? it displays a teapot OpenGL primitive in 256b.
P01, yes this is a great trick. I looked into this quite hard. Unfortunately its a real trick and unstable (see all the "it doesnt work here" comments). Also reading his seminar notes, it seems that it is limited in use...though to be honest I cant figure out why.
Chris
-
Update:
I've been working on a 1k recently. To cut a long story short, I managed to get the OGL framework down in size by repeatedly :whack: myself. The framework does the following:
* Opens a window full screen, any size
* Draws a rectangle to cover the screen
* Creates and tuns a minimal shader
* PASSES a TIMER into the shader
* Handles ESC
In all, using my crinkler and VC++ settings , it clocks in at 821 bytes which levels the playing field between OGL and D3D a bit more (considerably infact). If you want the framework send me a PM.
Taj
-
In all, using my crinkler and VC++ settings , it clocks in at 821 bytes which levels the playing field between OGL and D3D a bit more (considerably infact). If you want the framework send me a PM.
Im happy for you big guy. Bet that took a whole lotta head scratchin to do
-
In all, using my crinkler and VC++ settings , it clocks in at 821 bytes which levels the playing field between OGL and D3D a bit more (considerably infact). If you want the framework send me a PM.
Im happy for you big guy. Bet that took a whole lotta head scratchin to do
Well I started work on this 1k in November of last year , so 3 months its taken on and off.
-
Update:
I've been working on a 1k recently. To cut a long story short, I managed to get the OGL framework down in size by repeatedly :whack: myself. The framework does the following:
* Opens a window full screen, any size
* Draws a rectangle to cover the screen
* Creates and tuns a minimal shader
* PASSES a TIMER into the shader
* Handles ESC
In all, using my crinkler and VC++ settings , it clocks in at 821 bytes which levels the playing field between OGL and D3D a bit more (considerably infact). If you want the framework send me a PM.
Taj
Great news. Congratulations, taj. Now the war of between OGL/D3D
is open again ;-)
-
If you want to see code , its linked off my blog (http://sizecoding.blogspot.com/). Get the code for chocolux and you'll see three new tricks:
1. glRecti passing in time ! This is the big one.
2. #pragmas to assist crinkler (6 bytes saved - your mileage may vary)
3. __forceinline for the shader setup (1 byte - your mileage may vary)
This framwework is even smaller than Iqs :-)
Taj
-
Wow, the timer using GetTickCount() + glRecti idea is just amazing!
-
Hi folks, and thanks for a nice forum. I am trying to compile taj`s code in Visual Studio .Net 2005, but get an "error LNK2001: unresolved external symbol _WinMain@16" File: MSVRCT.lib error message. What can cause this problem, do i need to update the SDK?
-
zplex,
no you dont need to. It sounds like you are trying to compile as a console application not a windows application. I'll upload a minimal framework (give me a bit of time) and I hope you can import into VS2006 (I'm using VS Express).
Good to see you here.
Taj
-
OK Zplex,
in the archive is a wholly contained VC project with my source for my latest 1k (chocolux). This is a good base which you may strip the shaders out of and replace with your own.
Download the archive and unpack
Then get crinkler from here:http://www.crinkler.net/ (http://www.crinkler.net/) (the license of crinkler means I cant include it)
Put crinkler in your project directory but rename it to link.exe
Double click project file (dont try to start a new project yourself)
--- up to here it all works with VC Express (checked)
VC 2006 .NET ... I hope it imports OK.
If not, we'll do it the hard way :-)
Taj
-
Thanks man, really fast response :) The only thing that was a little troublesome now was that it didnt recognize the glext.h file in the project. But i just made a copy of it and put it in my C:\Programfiles\Microsoft Visual Studio 8\VC\PlatformSDK\Include\GL folder.
Here is a screenshot of the Visual Studio version i use, never heard about the 2006 version though :/
(http://img329.imageshack.us/img329/1634/vs2005veryg1.th.gif) (http://img329.imageshack.us/my.php?image=vs2005veryg1.gif)
-
Think I got confused...never mind :-) glad it works. Have fun.
-
Thanks Taj!
Jim