Dark Bit Factory & Gravity

PROGRAMMING => C / C++ /C# => Topic started by: taj on October 25, 2007

Title: Tiny, tiny OpenGL window and shader setup code
Post 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.

Code: [Select]
#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.

Code: [Select]
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/
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: rain_storm on October 25, 2007
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 ""
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Rbz on October 25, 2007
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) ?


Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 26, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: rain_storm on October 26, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Jim on October 26, 2007
"" is the correct initialiser, {0} might work too.
Quote
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
Code: [Select]
#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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 27, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Jim on October 27, 2007
Bah, I didn't even shrink the source code ;D

Jim
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: benny! on October 27, 2007
Looking good. Thanks for sharing. WIll have a closer look on it later on !!!
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Jim on October 27, 2007
Another idea...
How about
Code: [Select]
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
Code: [Select]
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 27, 2007
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:
Code: [Select]
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Jim on October 28, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 28, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 28, 2007
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.

Code: [Select]
// 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);
}
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Rbz on October 29, 2007
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  :)

Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on October 30, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Rbz on November 04, 2007
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 :)
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on November 04, 2007
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

Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: p01 on November 05, 2007
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.
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on November 05, 2007
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on February 24, 2008
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: rain_storm on February 24, 2008
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on February 24, 2008
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.
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: benny! on February 25, 2008
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 ;-)
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on February 29, 2008
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Rbz on March 01, 2008
Wow, the timer using GetTickCount() + glRecti idea is just amazing!
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: zplex on March 11, 2008
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?
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on March 11, 2008
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on March 11, 2008
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
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: zplex on March 11, 2008
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)
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: taj on March 11, 2008
Think I got confused...never mind :-) glad it works. Have fun.
Title: Re: Tiny, tiny OpenGL window and shader setup code
Post by: Jim on March 11, 2008
Thanks Taj!

Jim