Difference between revisions of "1K Intro"
Line 7: | Line 7: | ||
Graphics are usualy done using OpenGL / GLSL, but there are 1K intros out there that have used D3D/DX11 instead. | Graphics are usualy done using OpenGL / GLSL, but there are 1K intros out there that have used D3D/DX11 instead. | ||
+ | === Tools === | ||
+ | There are a couple of options for tools, but general these tools are often used | ||
+ | * Visual Studio / Vscode / GCC Compiler | ||
+ | * NASM Assembler | ||
+ | * Optional: Shader minifier | ||
+ | * Crinkler or other external packer for compression | ||
+ | === Minimal intro code === | ||
+ | Here is a step by step breakdown of what a minimal intro/framework should contain. | ||
+ | As a general rule of thumb: The less functions you need to use/import, the more space you have for your effect and data. | ||
− | === Setup (Windows) === | + | ==== Setup (Windows) ==== |
* <code>ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN)</code> - Initialise fullscreen view | * <code>ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN)</code> - Initialise fullscreen view | ||
* <code>hwnd = CreateWindow((LPCSTR)0xC018, 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0)</code> - Setting up a Maximised Window | * <code>hwnd = CreateWindow((LPCSTR)0xC018, 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0)</code> - Setting up a Maximised Window | ||
Line 16: | Line 25: | ||
* <code>ShowCursor(NULL)</code> - Hide mousecursor (usually required by compo rules) | * <code>ShowCursor(NULL)</code> - Hide mousecursor (usually required by compo rules) | ||
− | === Setup (OpenGL) === | + | ==== Setup (OpenGL) ==== |
* <code>glContext = wglCreateContext(hdc)</code> - Create OpenGL context | * <code>glContext = wglCreateContext(hdc)</code> - Create OpenGL context | ||
* <code>wglMakeCurrent(hdc, glContext)</code> - Set OpenGL Context | * <code>wglMakeCurrent(hdc, glContext)</code> - Set OpenGL Context | ||
Line 22: | Line 31: | ||
* <code>glUseProgram(shaderProgram)</code> - Set active shader | * <code>glUseProgram(shaderProgram)</code> - Set active shader | ||
− | === Update Loop === | + | ==== Update Loop ==== |
* <code>t = GetTickCount()</code> - Optional: Get Current ticks | * <code>t = GetTickCount()</code> - Optional: Get Current ticks | ||
* <code>glColor3us(t,0,0) / glColor3i(t,0,0)</code> - Parse time via gl_Color (saves importing uniform functions) | * <code>glColor3us(t,0,0) / glColor3i(t,0,0)</code> - Parse time via gl_Color (saves importing uniform functions) | ||
Line 30: | Line 39: | ||
* <code>GetAsyncKeyState(VK_ESCAPE)</code> - Checks for escape key (required by compo rules) | * <code>GetAsyncKeyState(VK_ESCAPE)</code> - Checks for escape key (required by compo rules) | ||
− | === Closedown === | + | ==== Closedown ==== |
* <code>ExitProcess(0)</code> - Close down application | * <code>ExitProcess(0)</code> - Close down application | ||
Revision as of 05:15, 12 April 2024
Contents
Introduction
This category is dedicated to 1K Intros for Windows 32.
Windows 1K Intros can be setup in C or Aseembler, or a combination of both, with only the few windows calls that are used being linked in. In general writing everything in assembler should give you a little more freedom in pushing/popping your function arguments but in the past quality intros have been written in both languages.
Graphics are usualy done using OpenGL / GLSL, but there are 1K intros out there that have used D3D/DX11 instead.
Tools
There are a couple of options for tools, but general these tools are often used
- Visual Studio / Vscode / GCC Compiler
- NASM Assembler
- Optional: Shader minifier
- Crinkler or other external packer for compression
Minimal intro code
Here is a step by step breakdown of what a minimal intro/framework should contain. As a general rule of thumb: The less functions you need to use/import, the more space you have for your effect and data.
Setup (Windows)
-
ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN)
- Initialise fullscreen view -
hwnd = CreateWindow((LPCSTR)0xC018, 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0)
- Setting up a Maximised Window -
hdc = GetDC(hwnd)
- Get DeviceContext handle -
ChoosePixelFormat(hdc, &pfd)
- Set pixelformat describer by pfd to DeviceContext handle -
ShowCursor(NULL)
- Hide mousecursor (usually required by compo rules)
Setup (OpenGL)
-
glContext = wglCreateContext(hdc)
- Create OpenGL context -
wglMakeCurrent(hdc, glContext)
- Set OpenGL Context -
shaderProgam = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &shader)
- Create and compile GLSL Shader -
glUseProgram(shaderProgram)
- Set active shader
Update Loop
-
t = GetTickCount()
- Optional: Get Current ticks -
glColor3us(t,0,0) / glColor3i(t,0,0)
- Parse time via gl_Color (saves importing uniform functions) -
glRects(-1,-1,1,1) / glRecti(-1,-1,1,1)
- Draw a single quad with current Shader -
SwapBuffers(hDC)
- Swap Buffers -
PeekMessageA(0, 0, 0, 0, PM_REMOVE)
- Optional: Unanswered messages might stack up, but in practice you should be fine in fullscreen -
GetAsyncKeyState(VK_ESCAPE)
- Checks for escape key (required by compo rules)
Closedown
-
ExitProcess(0)
- Close down application
Graphics / effect
So when it comes to writing your 1K shader/effect, there are a couple to tricks you can utilise to get a small shader footpring
- Make use of the benefits of (Legacy) Desktop GLSL by using integers for smaller notation
- Make use of the fixed resolution to convert gl_FragCoord to UV -1..1 (this will have your centerY slightly off-centered)
- Pass time via glColor (no uniforms used)
- Using global variables to save space
Minimal GLSL example code
float t=gl_Color.x*1e7;
void main(){
vec2 p=gl_FragCoord.xy/960-1;
gl_FragColor=vec4(sin(p.x+t),0,p.y,1);
}
Shader minifier
While a shader minifier can be helpful at times, it will not save you from writing sloppy code or unthoughtful approaches. For most 4k's people can get away with sub-par optimised code and let shader-minifier do the work for you, but for 1k this is just not enough.
Sound
- Win32 Single Note MIDI
- Win32 MIDI player
- Bytebeat softsynth
- Shader softsynth
Compression
Microsoft Cabinet decompression
These functions allow for MSZIP (deflate) and MSLZ content to be loaded from the binary as payload at the cost of a a few more win32 function imports. Well this might be a good solution for 512 byte intros, the tipping point for Crinkler compression at the moment lies at the 800-850 bytes mark give or take.
Crinkler
Crinkler is the most commonly used compression at the moment for many 1K and 4K intros.
It has a seperate settings for 1K intro, namely /TINYIMPORT
and /TINYHEADER
which will better match the 1K usecase.
Crinkler reports
When using the /REPORT:intro_report.html
feature, crinkler will generate a report and heatmap for your intro binary.
This is helpful to see how good your (shader)code compresses and where you can maybe gain a few more bytes.
Word about the resulting executable
Please note that when using crinkler in TINYHEADER mode, the resulting windows header will most likely trigger virus scanners / microsoft defender and mark it as suspicious content, which is a side-effect in recent years. Just exclude your work directory from this scan during development. Compo machines will run without these scanners too, but it is good practice to include a (slightly larger) safe version too in the final archive.