Skip to content

Instantly share code, notes, and snippets.

@nothings
nothings / kotaku_hzd.md
Last active January 23, 2024 15:24
Why Frustum Culling Matters, and Why It's Not Important

There is a nice GIF illustrating a technique called "frustum culling" in this Kotaku article: http://kotaku.com/horizon-zero-dawn-uses-all-sorts-of-clever-tricks-to-lo-1794385026

The interwebs being what they are, this has also led to some controversy.

Some people have interpreted the opening sentence "Every time you move the camera in Horizon Zero Dawn, the game is doing all sorts of under-the-hood calculations, loading and unloading chunks of world to ensure that it all runs properly," as being about the GIF; that's not what frustum culling does, but that's probably not what the article's author meant anyway.

Are there other single-file public-domain libraries out there?

Yes. Here are some:

  • jo_gif.cpp: tiny GIF writer (public domain)
  • gif.h: animated GIF writer (public domain)
  • tiny_jpeg.h: JPEG encoder (public domain)
  • lodepng: PNG encoder/decoder (zlib license)
  • nanoSVG: 1-file SVG parser; 1-file SVG rasterizer (zlib license)
  • tinyobjloader: wavefront OBJ file loader (BSD license)
// based on xxhash32
unsigned int hash(char *data, size_t len)
{
unsigned int hash;
if (len < 4) {
// load 3 bytes, overlapping if len < 3
static unsigned char offset1[4] = { 0,0,1,1 };
static unsigned char offset2[4] = { 0,0,0,2 };
unsigned int h = data[0] + (data[offset1[len]]<<8) + (data[offset2[len]]<<16);
h = xxprime1 + h*xxprime2;
@nothings
nothings / gist:ef38135f4aa4799e8f09069a44ded5a2
Created October 21, 2019 00:26
current stb_platform API structure
typedef struct {
float seconds_delta;
double seconds;
stbp_uint64 ns;
stbp_uint64 ns_delta;
stbp_uint64 ms;
stbp_uint64 ms_delta;
} stbp_time_info;
typedef struct {
#ifndef STBP_NUM_INPUT_HISTORY
#define STBP_NUM_INPUT_HISTORY 20 // 100ms at 5ms/sample
#endif
#ifndef STBP_MAX_CHARS_PER_FRAME
#define STBP_MAX_CHARS_PER_FRAME 50
#endif
typedef struct {
float seconds_delta;
double seconds;
// "Virtual" key codes... these are not the same as windows; as many as possible are
// mapped to the ASCII codes so you can ASCII index them, and they're repacked to
// fit from 0..127. There are no keycodes for mouse buttons or IME events.
enum
{
// no mouse button aliases yet (ever?)
STBVK_PAUSE = 0x07, // new?
STBVK_BACK = 0x08,
STBVK_TAB = 0x09, // "\t"
STBVK_LWIN = 0x0a,
// Old code which could only have one value for all threads:
static int stbi__vertically_flip_on_load = 0;
STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
{
stbi__vertically_flip_on_load = flag_true_if_should_flip;
}
// New code which allows per-thread values without breaking old behavior:

People who program in C
People who care about the C standard
People who have stakes in C compiler behavior, and sample opinions on UB (reflecting my bias):

#define STB_DEFINE
#include "stb.h"
char *header;
typedef struct
{
char *id;
char *html;
char *commentary;
instruction = cccccccc t xx r bb i aaa
8-bit registers A,B,C,T
8-bit program counter X
input I
output O
1-bit register F
; constant
C <- -128..127