port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

1514
underwater4k/4klang.asm Normal file

File diff suppressed because it is too large Load Diff

22
underwater4k/4klang.h Normal file
View File

@@ -0,0 +1,22 @@
// some useful song defines for 4klang
#define SAMPLE_RATE 44100
#define BPM 137.126862
#define MAX_INSTRUMENTS 9
#define MAX_PATTERNS 132
#define PATTERN_SIZE_SHIFT 3
#define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT)
#define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE)
#define SAMPLES_PER_TICK 4824
#define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS)
#define POLYPHONY 1
#define FLOAT_32BIT
#define SAMPLE_TYPE float
#define WINDOWS_OBJECT
// declaration of the external synth render function, you'll always need that
extern "C" void __stdcall _4klang_render(void*);
// declaration of the external envelope buffer. access only if you're song was exported with that option
extern "C" float _4klang_envelope_buffer;
// declaration of the external note buffer. access only if you're song was exported with that option
extern "C" int _4klang_note_buffer;

850
underwater4k/4klang.inc Normal file
View File

@@ -0,0 +1,850 @@
%macro export_func 1
global _%1
_%1:
%endmacro
%define USE_SECTIONS
%define SAMPLE_RATE 44100
%define MAX_INSTRUMENTS 9
%define MAX_VOICES 1
%define HLD 1
%define BPM 137.126862
%define MAX_PATTERNS 132
%define PATTERN_SIZE_SHIFT 3
%define PATTERN_SIZE (1 << PATTERN_SIZE_SHIFT)
%define MAX_TICKS (MAX_PATTERNS*PATTERN_SIZE)
%define SAMPLES_PER_TICK 4824
%define DEF_LFO_NORMALIZE 0.0000518242
%define MAX_SAMPLES (SAMPLES_PER_TICK*MAX_TICKS)
;%define GO4K_USE_16BIT_OUTPUT
;%define GO4K_USE_GROOVE_PATTERN
%define GO4K_USE_ENVELOPE_RECORDINGS
;%define GO4K_USE_NOTE_RECORDINGS
%define GO4K_CLIP_OUTPUT
%define GO4K_USE_DST
%define GO4K_USE_DLL
%define GO4K_USE_PAN
%define GO4K_USE_GLOBAL_DLL
%define GO4K_USE_FSTG
%define GO4K_USE_ENV_CHECK
%define GO4K_USE_ENV_MOD_GM
%define GO4K_USE_VCO_CHECK
%define GO4K_USE_VCO_PHASE_OFFSET
%define GO4K_USE_VCO_SHAPE
%define GO4K_USE_VCO_GATE
%define GO4K_USE_VCO_MOD_TM
%define GO4K_USE_VCO_MOD_DM
%define GO4K_USE_VCO_MOD_CM
%define GO4K_USE_VCF_CHECK
%define GO4K_USE_VCF_MOD_FM
%define GO4K_USE_VCF_MOD_RM
%define GO4K_USE_VCF_HIGH
%define GO4K_USE_VCF_BAND
%define GO4K_USE_VCF_PEAK
%define GO4K_USE_DST_CHECK
%define GO4K_USE_DLL_CHORUS
%define GO4K_USE_DLL_CHORUS_CLAMP
%define GO4K_USE_DLL_DAMP
%define GO4K_USE_DLL_DC_FILTER
%define GO4K_USE_FSTG_CHECK
%define GO4K_USE_WAVESHAPER_CLIP
%define MAX_DELAY 65536
%define MAX_WORKSPACE_SLOTS 8
%define GO4K_BEGIN_CMDDEF(def_name)
%define GO4K_END_CMDDEF db 0
%define GO4K_BEGIN_PARAMDEF(def_name)
%define GO4K_END_PARAMDEF
GO4K_ENV_ID equ 1
%macro GO4K_ENV 5
db %1
db %2
db %3
db %4
db %5
%endmacro
%define ATTAC(val) val
%define DECAY(val) val
%define SUSTAIN(val) val
%define RELEASE(val) val
%define GAIN(val) val
struc go4kENV_val
.attac resd 1
.decay resd 1
.sustain resd 1
.release resd 1
.gain resd 1
.size
endstruc
struc go4kENV_wrk
.state resd 1
.level resd 1
.gm resd 1
.am resd 1
.dm resd 1
.sm resd 1
.rm resd 1
.size
endstruc
%define ENV_STATE_ATTAC 0
%define ENV_STATE_DECAY 1
%define ENV_STATE_SUSTAIN 2
%define ENV_STATE_RELEASE 3
%define ENV_STATE_OFF 4
GO4K_VCO_ID equ 2
%macro GO4K_VCO 8
db %1
db %2
%ifdef GO4K_USE_VCO_PHASE_OFFSET
db %3
%endif
%ifdef GO4K_USE_VCO_GATE
db %4
%endif
db %5
%ifdef GO4K_USE_VCO_SHAPE
db %6
%endif
db %7
db %8
%endmacro
%define TRANSPOSE(val) val
%define DETUNE(val) val
%define PHASE(val) val
%define GATES(val) val
%define COLOR(val) val
%define SHAPE(val) val
%define FLAGS(val) val
%define SINE 0x01
%define TRISAW 0x02
%define PULSE 0x04
%define NOISE 0x08
%define LFO 0x10
%define GATE 0x20
struc go4kVCO_val
.transpose resd 1
.detune resd 1
%ifdef GO4K_USE_VCO_PHASE_OFFSET
.phaseofs resd 1
%endif
%ifdef GO4K_USE_VCO_GATE
.gate resd 1
%endif
.color resd 1
%ifdef GO4K_USE_VCO_SHAPE
.shape resd 1
%endif
.gain resd 1
.flags resd 1
.size
endstruc
struc go4kVCO_wrk
.phase resd 1
.tm resd 1
.dm resd 1
.fm resd 1
.pm resd 1
.cm resd 1
.sm resd 1
.gm resd 1
.size
endstruc
GO4K_VCF_ID equ 3
%macro GO4K_VCF 3
db %1
db %2
db %3
%endmacro
%define LOWPASS 0x1
%define HIGHPASS 0x2
%define BANDPASS 0x4
%define BANDSTOP 0x3
%define ALLPASS 0x7
%define PEAK 0x8
%define FREQUENCY(val) val
%define RESONANCE(val) val
%define VCFTYPE(val) val
struc go4kVCF_val
.freq resd 1
.res resd 1
.type resd 1
.size
endstruc
struc go4kVCF_wrk
.low resd 1
.high resd 1
.band resd 1
.freq resd 1
.fm resd 1
.rm resd 1
.size
endstruc
GO4K_DST_ID equ 4
%macro GO4K_DST 2
db %1
%ifdef GO4K_USE_DST_SH
db %2
%endif
%endmacro
%define DRIVE(val) val
%define SNHFREQ(val) val
struc go4kDST_val
.drive resd 1
%ifdef GO4K_USE_DST_SH
.snhfreq resd 1
%endif
.size
endstruc
struc go4kDST_wrk
%ifdef GO4K_USE_DST_SH
.out resd 1
.snhphase resd 1
%endif
.dm resd 1
.sm resd 1
.size
endstruc
GO4K_DLL_ID equ 5
%macro GO4K_DLL 8
db %1
db %2
db %3
%ifdef GO4K_USE_DLL_DAMP
db %4
%endif
%ifdef GO4K_USE_DLL_CHORUS
db %5
db %6
%endif
db %7
db %8
%endmacro
%define PREGAIN(val) val
%define DRY(val) val
%define FEEDBACK(val) val
%define DEPTH(val) val
%define DAMP(val) val
%define DELAY(val) val
%define COUNT(val) val
struc go4kDLL_val
.pregain resd 1
.dry resd 1
.feedback resd 1
%ifdef GO4K_USE_DLL_DAMP
.damp resd 1
%endif
%ifdef GO4K_USE_DLL_CHORUS
.freq resd 1
.depth
%endif
.delay resd 1
.count resd 1
.size
endstruc
struc go4kDLL_wrk
.index resd 1
.store resd 1
.dcin resd 1
.dcout resd 1
%ifdef GO4K_USE_DLL_CHORUS
.phase resd 1
%endif
.buffer resd MAX_DELAY
.size
endstruc
struc go4kDLL_wrk2
.pm resd 1
.fm resd 1
.im resd 1
.dm resd 1
.sm resd 1
.am resd 1
.size
endstruc
GO4K_FOP_ID equ 6
%macro GO4K_FOP 1
db %1
%endmacro
%define OP(val) val
%define FOP_POP 0x1
%define FOP_ADDP 0x2
%define FOP_MULP 0x3
%define FOP_PUSH 0x4
%define FOP_XCH 0x5
%define FOP_ADD 0x6
%define FOP_MUL 0x7
%define FOP_ADDP2 0x8
%define FOP_LOADNOTE 0x9
struc go4kFOP_val
.flags resd 1
.size
endstruc
struc go4kFOP_wrk
.size
endstruc
GO4K_FST_ID equ 7
%macro GO4K_FST 2
db %1
db %2
%endmacro
%define AMOUNT(val) val
%define DEST(val) val
struc go4kFST_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFST_wrk
.size
endstruc
GO4K_PAN_ID equ 8
%macro GO4K_PAN 1
%ifdef GO4K_USE_PAN
db %1
%endif
%endmacro
%define PANNING(val) val
struc go4kPAN_val
%ifdef GO4K_USE_PAN
.panning resd 1
%endif
.size
endstruc
struc go4kPAN_wrk
.pm resd 1
.size
endstruc
GO4K_OUT_ID equ 9
%macro GO4K_OUT 2
db %1
%ifdef GO4K_USE_GLOBAL_DLL
db %2
%endif
%endmacro
%define AUXSEND(val) val
struc go4kOUT_val
.gain resd 1
%ifdef GO4K_USE_GLOBAL_DLL
.auxsend resd 1
%endif
.size
endstruc
struc go4kOUT_wrk
.am resd 1
.gm resd 1
.size
endstruc
GO4K_ACC_ID equ 10
%macro GO4K_ACC 1
db %1
%endmacro
%define OUTPUT 0
%define AUX 8
%define ACCTYPE(val) val
struc go4kACC_val
.acctype resd 1
.size
endstruc
struc go4kACC_wrk
.size
endstruc
%ifdef GO4K_USE_FLD
GO4K_FLD_ID equ 11
%macro GO4K_FLD 1
db
%endmacro
%define VALUE(val) val
struc go4kFLD_val
.value resd 1
.size
endstruc
struc go4kFLD_wrk
.vm resd 1
.size
endstruc
%endif
%ifdef GO4K_USE_FSTG
GO4K_FSTG_ID equ 12
%macro GO4K_FSTG 2
db %1
dd %2
%endmacro
struc go4kFSTG_val
.amount resd 1
.op1 resd 1
.size
endstruc
struc go4kFSTG_wrk
.size
endstruc
%endif
struc go4k_instrument
.release resd 1
.note resd 1
.workspace resd 256
.dlloutl resd 1
.dlloutr resd 1
.outl resd 1
.outr resd 1
.size
endstruc
struc go4k_synth
.instruments resb go4k_instrument.size * MAX_INSTRUMENTS * MAX_VOICES
.global resb go4k_instrument.size * MAX_VOICES
.size
endstruc
%ifdef USE_SECTIONS
section .g4kmuc1 data align=1
%else
section .data align=1
%endif
go4k_patterns
db 0, 0, 0, 0, 0, 0, 0, 0,
db 50, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db HLD, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 38, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 57, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 45, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 48, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 36, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 55, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 43, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 60, HLD, 0, 0, 60, HLD, 0, 0,
db 60, HLD, 0, 0, 0, 0, 0, 0,
db 0, 50, 62, 50, 0, 50, 62, 50,
db 0, 45, 57, 45, 0, 45, 57, 45,
db 0, 48, 60, 48, 0, 48, 60, 48,
db 0, 55, 67, 55, 0, 55, 67, 55,
db 0, 0, 0, 0, 62, HLD, HLD, HLD,
db HLD, HLD, HLD, HLD, 62, HLD, HLD, HLD,
db 62, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 60, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 0, 0, 0, 88, 89, HLD, 89, HLD,
db 0, 0, 0, 88, 84, HLD, 84, HLD,
db 0, 0, 0, 86, 88, HLD, 88, HLD,
db 0, 0, 0, 84, 81, HLD, 81, HLD,
db 0, 0, 0, 84, 79, HLD, 79, HLD,
db 0, 0, 0, 84, 86, HLD, 86, HLD,
db 0, 0, 0, 84, 83, HLD, 83, HLD,
db 0, 0, 0, 89, 91, HLD, 91, HLD,
db 0, 0, 0, 91, 89, HLD, 89, HLD,
db 86, HLD, 0, 0, 0, 0, 74, HLD,
db 81, HLD, 0, 0, 0, 0, 69, HLD,
db 84, HLD, 0, 0, 0, 0, 72, HLD,
db 79, HLD, 0, 0, 0, 0, 67, HLD,
db 93, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 98, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 0, 0, 0, 0, 0, 0, 0, 91,
db 93, HLD, 91, HLD, 93, HLD, 96, HLD,
db 0, 0, 0, 0, 0, 0, 96, HLD,
db 98, HLD, HLD, HLD, 96, HLD, 98, HLD,
db 100, HLD, HLD, HLD, HLD, HLD, HLD, HLD,
db 0, 0, 0, 0, 0, 0, 98, 0,
db 100, HLD, 98, HLD, 100, HLD, 103, HLD,
db HLD, 0, 0, 0, 0, 0, 0, 0,
go4k_patterns_end
%ifdef USE_SECTIONS
section .g4kmuc2 data align=1
%else
section .data
%endif
go4k_pattern_lists
Instrument0List db 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 3, 1, 3, 4, 5, 4, 5, 6, 7, 6, 7, 8, 9, 8, 9, 1, 2, 0, 0,
Instrument1List db 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 0,
Instrument2List db 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 12, 12, 0, 0,
Instrument3List db 0, 0, 0, 0, 0, 0, 0, 16, 2, 2, 2, 2, 2, 2, 2, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Instrument4List db 0, 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Instrument5List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 20, 21, 22, 23, 22, 23, 22, 24, 22, 24, 25, 26, 27, 28, 20, 21, 20, 21, 22, 23, 22, 23, 22, 24, 22, 24, 25, 26, 27, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 20, 21, 22, 23, 22, 23, 22, 24, 22, 24, 25, 26, 27, 28, 20, 21, 20, 21, 22, 23, 22, 23, 22, 24, 22, 24, 25, 26, 27, 28, 20, 21, 20, 21, 22, 23, 22, 23, 22, 24, 22, 24, 25, 26, 27, 28, 0, 0, 0, 0,
Instrument6List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 29, 0, 30, 0, 30, 0, 31, 0, 31, 0, 32, 0, 32, 0, 29, 0, 29, 0, 30, 0, 30, 0, 31, 0, 31, 0, 32, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 29, 0, 30, 0, 30, 0, 31, 0, 31, 0, 32, 0, 32, 0, 29, 0, 29, 0, 30, 0, 30, 0, 31, 0, 31, 0, 32, 0, 32, 0, 29, 0, 0, 0,
Instrument7List db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 34, 2, 35, 36, 2, 2, 37, 38, 39, 2, 40, 41, 34, 2, 0, 33, 34, 2, 35, 36, 2, 2, 37, 38, 39, 2, 40, 41, 34, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 34, 2, 35, 36, 2, 2, 37, 38, 39, 2, 40, 41, 34, 2, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Instrument8List db 19, 2, 2, 2, 2, 2, 2, 2, 19, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 19, 2, 2, 42,
go4k_pattern_lists_end
%ifdef USE_SECTIONS
section .g4kmuc3 data align=1
%else
section .data
%endif
go4k_synth_instructions
GO4K_BEGIN_CMDDEF(Instrument0)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_DST_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_DST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument1)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_FSTG_ID
db GO4K_FOP_ID
db GO4K_ENV_ID
db GO4K_DST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument2)
db GO4K_ENV_ID
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument3)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCF_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument4)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument5)
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_ENV_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument6)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_FST_ID
db GO4K_FST_ID
db GO4K_FOP_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_PAN_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument7)
db GO4K_ENV_ID
db GO4K_VCO_ID
db GO4K_VCO_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_FOP_ID
db GO4K_PAN_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_DLL_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Instrument8)
db GO4K_ENV_ID
db GO4K_FOP_ID
db GO4K_FOP_ID
db GO4K_FSTG_ID
db GO4K_FSTG_ID
db GO4K_FSTG_ID
db GO4K_FSTG_ID
db GO4K_FOP_ID
GO4K_END_CMDDEF
GO4K_BEGIN_CMDDEF(Global)
db GO4K_ACC_ID
db GO4K_VCF_ID
db GO4K_DLL_ID
db GO4K_FOP_ID
db GO4K_VCF_ID
db GO4K_DLL_ID
db GO4K_ACC_ID
db GO4K_FOP_ID
db GO4K_OUT_ID
GO4K_END_CMDDEF
go4k_synth_instructions_end
%ifdef USE_SECTIONS
section .g4kmuc4 data align=1
%else
section .data
%endif
go4k_synth_parameter_values
GO4K_BEGIN_PARAMDEF(Instrument0)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(64),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(66),PHASE(96),GATES(0),COLOR(112),SHAPE(32),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(0),GATES(85),COLOR(48),SHAPE(80),GAIN(128),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(56),PHASE(32),GATES(85),COLOR(40),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_VCO TRANSPOSE(64),DETUNE(72),PHASE(48),GATES(85),COLOR(48),SHAPE(32),GAIN(128),FLAGS(SINE)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_DST DRIVE(80), SNHFREQ(128)
GO4K_VCF FREQUENCY(96),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(96), SNHFREQ(128)
GO4K_FOP OP(FOP_PUSH)
GO4K_VCF FREQUENCY(64),RESONANCE(64),VCFTYPE(HIGHPASS)
GO4K_FOP OP(FOP_XCH)
GO4K_VCF FREQUENCY(64),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_DST DRIVE(96), SNHFREQ(128)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(128), AUXSEND(8)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument1)
GO4K_ENV ATTAC(0),DECAY(32),SUSTAIN(96),RELEASE(64),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(72),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_FSTG AMOUNT(128),DEST(8*go4k_instrument.size*MAX_VOICES+0*MAX_WORKSPACE_SLOTS*4+2*4+go4k_instrument.workspace)
GO4K_FOP OP(FOP_POP)
GO4K_ENV ATTAC(0),DECAY(72),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_DST DRIVE(32), SNHFREQ(128)
GO4K_FST AMOUNT(80),DEST(9*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(44),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(SINE)
GO4K_ENV ATTAC(0),DECAY(32),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(0),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_VCF FREQUENCY(64),RESONANCE(128),VCFTYPE(HIGHPASS)
GO4K_VCF FREQUENCY(96),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_FOP OP(FOP_MULP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(128), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument2)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(0),RELEASE(72),GAIN(128)
GO4K_ENV ATTAC(0),DECAY(72),SUSTAIN(0),RELEASE(80),GAIN(128)
GO4K_FST AMOUNT(96),DEST(18*MAX_WORKSPACE_SLOTS+4)
GO4K_FST AMOUNT(96),DEST(19*MAX_WORKSPACE_SLOTS+4)
GO4K_FOP OP(FOP_POP)
GO4K_FOP OP(FOP_PUSH)
GO4K_VCO TRANSPOSE(72),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(SINE|LFO)
GO4K_FOP OP(FOP_ADDP)
GO4K_FST AMOUNT(32),DEST(13*MAX_WORKSPACE_SLOTS+5)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(96),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(SINE|LFO)
GO4K_FST AMOUNT(80),DEST(15*MAX_WORKSPACE_SLOTS+2)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(76),DETUNE(64),PHASE(0),GATES(85),COLOR(128),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(76),DETUNE(64),PHASE(0),GATES(85),COLOR(0),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_VCF FREQUENCY(24),RESONANCE(96),VCFTYPE(LOWPASS)
GO4K_VCF FREQUENCY(24),RESONANCE(96),VCFTYPE(PEAK)
GO4K_FOP OP(FOP_MULP)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(32),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(128),DRY(0),FEEDBACK(0),DAMP(0),FREQUENCY(0),DEPTH(0),DELAY(17),COUNT(1)
GO4K_OUT GAIN(40), AUXSEND(8)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument3)
GO4K_ENV ATTAC(0),DECAY(80),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_FST AMOUNT(128),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_ENV ATTAC(0),DECAY(32),SUSTAIN(0),RELEASE(0),GAIN(128)
GO4K_FST AMOUNT(104),DEST(6*MAX_WORKSPACE_SLOTS+1)
GO4K_FST AMOUNT(72),DEST(7*MAX_WORKSPACE_SLOTS+1)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(52),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(32),GAIN(48),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(80),GAIN(48),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(16),GAIN(64),FLAGS(NOISE)
GO4K_VCF FREQUENCY(112),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(16),FLAGS(NOISE)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(24),RESONANCE(32),VCFTYPE(HIGHPASS)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(8), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument4)
GO4K_ENV ATTAC(0),DECAY(128),SUSTAIN(128),RELEASE(0),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(NOISE)
GO4K_FOP OP(FOP_MULP)
GO4K_VCF FREQUENCY(112),RESONANCE(128),VCFTYPE(HIGHPASS)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(17),COLOR(17),SHAPE(64),GAIN(128),FLAGS(GATE|LFO)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(64)
GO4K_OUT GAIN(8), AUXSEND(16)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument5)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(64),RELEASE(72),GAIN(128)
GO4K_FST AMOUNT(112),DEST(0*MAX_WORKSPACE_SLOTS+2)
GO4K_VCO TRANSPOSE(52),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(0),SHAPE(64),GAIN(128),FLAGS(TRISAW)
GO4K_FOP OP(FOP_ADDP)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(16),RELEASE(64),GAIN(128)
GO4K_FST AMOUNT(96),DEST(9*MAX_WORKSPACE_SLOTS+4)
GO4K_FST AMOUNT(96),DEST(10*MAX_WORKSPACE_SLOTS+4)
GO4K_FOP OP(FOP_POP)
GO4K_VCF FREQUENCY(16),RESONANCE(128),VCFTYPE(PEAK)
GO4K_VCF FREQUENCY(8),RESONANCE(128),VCFTYPE(LOWPASS)
GO4K_FOP OP(FOP_MULP)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(16),COUNT(1)
GO4K_PAN PANNING(64)
GO4K_DLL PREGAIN(128),DRY(0),FEEDBACK(0),DAMP(0),FREQUENCY(0),DEPTH(0),DELAY(18),COUNT(1)
GO4K_OUT GAIN(32), AUXSEND(8)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument6)
GO4K_ENV ATTAC(48),DECAY(80),SUSTAIN(64),RELEASE(64),GAIN(128)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(64),FLAGS(NOISE)
GO4K_VCO TRANSPOSE(16),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(TRISAW|LFO)
GO4K_FOP OP(FOP_ADDP)
GO4K_FST AMOUNT(40),DEST(9*MAX_WORKSPACE_SLOTS+4)
GO4K_FST AMOUNT(58),DEST(9*MAX_WORKSPACE_SLOTS+5)
GO4K_FOP OP(FOP_POP)
GO4K_VCO TRANSPOSE(88),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(SINE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(64),GATES(85),COLOR(64),SHAPE(64),GAIN(8),FLAGS(NOISE)
GO4K_VCF FREQUENCY(72),RESONANCE(24),VCFTYPE(BANDPASS)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_PUSH)
GO4K_VCF FREQUENCY(32),RESONANCE(128),VCFTYPE(BANDPASS)
GO4K_FOP OP(FOP_XCH)
GO4K_VCF FREQUENCY(96),RESONANCE(128),VCFTYPE(BANDPASS)
GO4K_FOP OP(FOP_ADDP)
GO4K_FOP OP(FOP_MULP)
GO4K_DLL PREGAIN(64),DRY(128),FEEDBACK(64),DAMP(64),FREQUENCY(0),DEPTH(0),DELAY(19),COUNT(1)
GO4K_PAN PANNING(48)
GO4K_OUT GAIN(64), AUXSEND(16)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument7)
GO4K_ENV ATTAC(0),DECAY(64),SUSTAIN(64),RELEASE(64),GAIN(128)
GO4K_VCO TRANSPOSE(52),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(PULSE)
GO4K_VCO TRANSPOSE(64),DETUNE(64),PHASE(0),GATES(85),COLOR(64),SHAPE(64),GAIN(128),FLAGS(SINE)
GO4K_FOP OP(FOP_ADDP)
GO4K_VCF FREQUENCY(48),RESONANCE(64),VCFTYPE(LOWPASS)
GO4K_FOP OP(FOP_MULP)
GO4K_PAN PANNING(48)
GO4K_DLL PREGAIN(128),DRY(64),FEEDBACK(64),DAMP(64),FREQUENCY(48),DEPTH(64),DELAY(18),COUNT(1)
GO4K_FOP OP(FOP_XCH)
GO4K_DLL PREGAIN(112),DRY(64),FEEDBACK(64),DAMP(64),FREQUENCY(46),DEPTH(64),DELAY(18),COUNT(1)
GO4K_OUT GAIN(32), AUXSEND(0)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Instrument8)
GO4K_ENV ATTAC(0),DECAY(128),SUSTAIN(0),RELEASE(0),GAIN(0)
GO4K_FOP OP(FOP_PUSH)
GO4K_FOP OP(FOP_ADDP)
GO4K_FSTG AMOUNT(16),DEST(0*go4k_instrument.size*MAX_VOICES+0*MAX_WORKSPACE_SLOTS*4+2*4+go4k_instrument.workspace)
GO4K_FSTG AMOUNT(0),DEST(2*go4k_instrument.size*MAX_VOICES+0*MAX_WORKSPACE_SLOTS*4+2*4+go4k_instrument.workspace)
GO4K_FSTG AMOUNT(16),DEST(4*go4k_instrument.size*MAX_VOICES+0*MAX_WORKSPACE_SLOTS*4+2*4+go4k_instrument.workspace)
GO4K_FSTG AMOUNT(48),DEST(7*go4k_instrument.size*MAX_VOICES+0*MAX_WORKSPACE_SLOTS*4+2*4+go4k_instrument.workspace)
GO4K_FOP OP(FOP_POP)
GO4K_END_PARAMDEF
GO4K_BEGIN_PARAMDEF(Global)
GO4K_ACC ACCTYPE(AUX)
GO4K_VCF FREQUENCY(4),RESONANCE(64),VCFTYPE(HIGHPASS)
GO4K_DLL PREGAIN(24),DRY(128),FEEDBACK(126),DAMP(96),FREQUENCY(0),DEPTH(0),DELAY(0),COUNT(8)
GO4K_FOP OP(FOP_XCH)
GO4K_VCF FREQUENCY(4),RESONANCE(64),VCFTYPE(HIGHPASS)
GO4K_DLL PREGAIN(24),DRY(128),FEEDBACK(126),DAMP(96),FREQUENCY(0),DEPTH(0),DELAY(8),COUNT(8)
GO4K_ACC ACCTYPE(OUTPUT)
GO4K_FOP OP(FOP_ADDP2)
GO4K_OUT GAIN(48), AUXSEND(0)
GO4K_END_PARAMDEF
go4k_synth_parameter_values_end
%ifdef USE_SECTIONS
section .g4kmuc5 data align=1
%else
section .data
%endif
%ifdef GO4K_USE_DLL
global _go4k_delay_times
_go4k_delay_times
dw 1116
dw 1188
dw 1276
dw 1356
dw 1422
dw 1492
dw 1556
dw 1618
dw 1140
dw 1212
dw 1300
dw 1380
dw 1446
dw 1516
dw 1580
dw 1642
dw 14472
dw 528
dw 544
dw 19296
%endif

BIN
underwater4k/4klang.obj Normal file

Binary file not shown.

BIN
underwater4k/GlU32.Lib Normal file

Binary file not shown.

BIN
underwater4k/OpenGL32.Lib Normal file

Binary file not shown.

364
underwater4k/Shaders.cpp Normal file
View File

@@ -0,0 +1,364 @@
//#define DEBUG_COMPRESSED_SHADER
#ifdef _DEBUG
#include "Shaders.h"
PFNGLCREATESHADERPROC glCreateShader = NULL;
PFNGLSHADERSOURCEPROC glShaderSource = NULL;
PFNGLCOMPILESHADERPROC glCompileShader = NULL;
PFNGLGETSHADERIVPROC glGetShaderiv = NULL;
PFNGLGETPROGRAMIVPROC glGetProgramiv = NULL;
PFNGLCREATEPROGRAMPROC glCreateProgram = NULL;
PFNGLATTACHSHADERPROC glAttachShader = NULL;
PFNGLLINKPROGRAMPROC glLinkProgram = NULL;
PFNGLUSEPROGRAMPROC glUseProgram = NULL;
PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = NULL;
PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = NULL;
void useProgram(GLhandleARB ah_Program)
{
glUseProgram(ah_Program);
}
void initShaders()
{
glCreateShader = (PFNGLCREATESHADERPROC)myGetProcAddress("glCreateShader");
glShaderSource = (PFNGLSHADERSOURCEPROC)myGetProcAddress("glShaderSource");
glCompileShader = (PFNGLCOMPILESHADERPROC)myGetProcAddress("glCompileShader");
glGetShaderiv = (PFNGLGETSHADERIVPROC)myGetProcAddress("glGetShaderiv");
glGetProgramiv = (PFNGLGETPROGRAMIVPROC)myGetProcAddress("glGetProgramiv");
glCreateProgram = (PFNGLCREATEPROGRAMPROC)myGetProcAddress("glCreateProgram");
glAttachShader = (PFNGLATTACHSHADERPROC)myGetProcAddress("glAttachShader");
glLinkProgram = (PFNGLLINKPROGRAMPROC)myGetProcAddress("glLinkProgram");
glUseProgram = (PFNGLUSEPROGRAMPROC)myGetProcAddress("glUseProgram");
glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)myGetProcAddress("glGetShaderInfoLog");
glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)myGetProcAddress("glGetProgramInfoLog");
if (!(glCreateShader && glShaderSource && glCompileShader && glGetShaderiv && glGetProgramiv && glCreateProgram && glAttachShader && glLinkProgram && glUseProgram && glGetShaderInfoLog && glGetProgramInfoLog))
{
std::cerr << "Some shader functions are not available!" << std::endl;
}
}
#include <sstream>
#include <fstream>
std::string ReplaceString(const std::string &stringSearchString, const std::string &stringReplaceString, std::string stringStringToReplace)
{
std::string::size_type pos = stringStringToReplace.find(stringSearchString, 0);
int intLengthSearch = stringSearchString.length();
int intLengthReplacment = stringReplaceString.length();
while(std::string::npos != pos)
{
stringStringToReplace.replace(pos, intLengthSearch, stringReplaceString);
pos = stringStringToReplace.find(stringSearchString, pos + intLengthReplacment);
}
return stringStringToReplace;
}
std::string MakeFileName( const char* as_FileName, int ShaderID, bool bDebug )
{
std::stringstream ss;
ss << as_FileName << "_" << ShaderID;
if( bDebug )
{
ss << "_dbg";
}
return ss.str();
}
void CreateSubShader( const char* as_FileName, int ShaderID, bool bDebug )
{
char* ls_ShaderSource = textFileRead(as_FileName);
std::string strData= ls_ShaderSource;
std::string strNewData;
bool bRemove= false;
for( size_t i= 0; i < strData.size(); ++i )
{
bool bEndRemove= false;
if( strData[ i ] == '@' )
{
if( i + 2 >= strData.size() )
{
break;
}
i++;
if( strData[ i ] == '@' )
{
bRemove= false;
}
else if( strData[ i ] == 'D' )
{
bRemove= !bDebug;
}
else
{
int ID= (int)(strData[ i ] - '0');
bRemove= ID!=ShaderID;
}
i++;
}
if( !bRemove || strData[ i ] == 10 || strData[ i ] == 13)
{
strNewData+= strData[ i ];
}
}
std::string strFileOut= MakeFileName( as_FileName, ShaderID, bDebug );
std::ofstream ofs(strFileOut.c_str());
// some Renaming
/*strNewData= ReplaceString( "rayDir","q", strNewData);
strNewData= ReplaceString( "cRes","b", strNewData);
strNewData= ReplaceString( "cFac","a", strNewData);
strNewData= ReplaceString( "CurStep","d", strNewData);
strNewData= ReplaceString( "CurStep","d", strNewData);
strNewData= ReplaceString( "rotate","r", strNewData);
strNewData= ReplaceString( "repeatHex","sh", strNewData);
strNewData= ReplaceString( "repeat","s", strNewData);
strNewData= ReplaceString( "pi2","P", strNewData);
strNewData= ReplaceString( "sqrtOf075","Q", strNewData);
strNewData= ReplaceString( "EndlessBar","O", strNewData);
strNewData= ReplaceString( "CurTime","R", strNewData);
strNewData= ReplaceString( "CurScene","S", strNewData);
strNewData= ReplaceString( "torus","T", strNewData);
strNewData= ReplaceString( "noise3D","N", strNewData);
strNewData= ReplaceString( "smoothnoise","M", strNewData);*/
ofs << strNewData;
}
void CreateAllSubShader( const char* as_FileName )
{
for( int i= 0; i < MAX_SHADER_ID; ++i )
{
CreateSubShader( as_FileName, i, true );
CreateSubShader( as_FileName, i, false );
}
}
void PrintErrors()
{
GLenum lr_Error = GL_NO_ERROR;
int li_ErrorCount = 5;
do
{
lr_Error = glGetError();
if (lr_Error != GL_NO_ERROR)
{
li_ErrorCount--;
char* ls_ErrorString = (char*)gluErrorString(lr_Error);
if (ls_ErrorString != 0)
std::cout << "OPENGL :: ERROR " << ls_ErrorString << std::endl;
}
if (li_ErrorCount == 0)
{
std::cout << "OPENGL :: ERROR Too many errors!" << std::endl;
break;
}
} while (lr_Error != GL_NO_ERROR);
}
GLhandleARB createVertexShader(const char* as_FileName)
{
GLhandleARB lh_Shader = 0;
char* ls_ShaderSource = textFileRead(as_FileName);
if (ls_ShaderSource == NULL)
{
std::cerr << "Error reading file: " << as_FileName << std::endl;
return lh_Shader;
}
lh_Shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(lh_Shader, 1, (const char**)&ls_ShaderSource, NULL);
glCompileShader(lh_Shader);
free(ls_ShaderSource);
int li_Status = 0;
glGetShaderiv(lh_Shader, GL_COMPILE_STATUS, &li_Status);
if (li_Status == GL_FALSE)
{
std::cerr << "Error compiling vertex shader: " << as_FileName << std::endl;
printShaderInfoLog(lh_Shader);
}
return lh_Shader;
}
#ifdef DEBUG_COMPRESSED_SHADER
#include "shader_code.h"
#endif
GLhandleARB createFragmentShader(const char* as_FileName, int ShaderID, bool bDebug)
{
CreateAllSubShader( as_FileName );
GLhandleARB lh_Shader = 0;
char* ls_ShaderSource = textFileRead(MakeFileName(as_FileName, ShaderID, bDebug).c_str());
if (ls_ShaderSource == NULL)
{
std::cerr << "Error reading file: " << as_FileName << std::endl;
return lh_Shader;
}
lh_Shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(lh_Shader, 1, (const char**)&ls_ShaderSource, NULL);
#ifdef DEBUG_COMPRESSED_SHADER
glShaderSource(lh_Shader, 1, (const char**)&mark_fs, NULL);
#endif
glCompileShader(lh_Shader);
int li_Status = 0;
glGetShaderiv(lh_Shader, GL_COMPILE_STATUS, &li_Status);
if (li_Status == GL_FALSE)
{
std::cerr << "Error compiling fragment shader: " << as_FileName << std::endl;
printShaderInfoLog(lh_Shader);
}
free(ls_ShaderSource);
return lh_Shader;
}
GLhandleARB createProgram(GLhandleARB ah_VertexShader, GLhandleARB ah_FragmentShader)
{
GLhandleARB lh_Program = 0;
if (ah_VertexShader + ah_FragmentShader <= 1)
{
std::cerr << "Cannot create program." << std::endl;
return lh_Program;
}
lh_Program = glCreateProgram();
glAttachShader(lh_Program, ah_VertexShader);
glAttachShader(lh_Program, ah_FragmentShader);
glLinkProgram(lh_Program);
int li_Status = 0;
glGetProgramiv(lh_Program, GL_LINK_STATUS, &li_Status);
if (li_Status == GL_FALSE)
{
std::cerr << "Error linking shaders." << std::endl;
printProgramInfoLog(lh_Program);
}
return lh_Program;
}
char* textFileRead(const char* as_FileName)
{
FILE* lh_File;
char* ls_Content = NULL;
size_t li_Count = 0;
if (as_FileName != NULL)
{
fopen_s(&lh_File, as_FileName, "rt");
if (lh_File != NULL)
{
fseek(lh_File, 0, SEEK_END);
li_Count = ftell(lh_File);
rewind(lh_File);
if (li_Count > 0)
{
ls_Content = (char*) malloc(sizeof(char) * (li_Count + 1));
li_Count = fread(ls_Content, sizeof(char), li_Count, lh_File);
ls_Content[li_Count] = '\0';
}
fclose(lh_File);
}
}
return ls_Content;
}
void printShaderInfoLog(GLhandleARB ah_Shader)
{
int li_InfologLength = 0;
int li_CharsWritten = 0;
char* li_InfoLog;
glGetShaderiv(ah_Shader, GL_INFO_LOG_LENGTH, &li_InfologLength);
if (li_InfologLength > 0)
{
li_InfoLog = (char*) malloc(li_InfologLength);
glGetShaderInfoLog(ah_Shader, li_InfologLength, &li_CharsWritten, li_InfoLog);
std::cerr << li_InfoLog << std::endl;
free(li_InfoLog);
}
}
void printProgramInfoLog(GLhandleARB ah_Program)
{
int li_InfologLength = 0;
int li_CharsWritten = 0;
char* ls_InfoLog;
glGetProgramiv(ah_Program, GL_INFO_LOG_LENGTH, &li_InfologLength);
if (li_InfologLength > 0)
{
ls_InfoLog = (char *)malloc(li_InfologLength);
glGetProgramInfoLog(ah_Program, li_InfologLength, &li_CharsWritten, ls_InfoLog);
std::cerr << ls_InfoLog << std::endl;
free(ls_InfoLog);
}
}
bool printShaderStatistics()
{
if (GL_VERSION_2_1) std::cout << "Supports OpenGL 2.1. " << std::endl;
else if (GL_VERSION_2_0) std::cout << "Supports OpenGL 2.0. " << std::endl;
else if (GL_VERSION_1_5) std::cout << "Supports OpenGL 1.5. " << std::endl;
else if (GL_VERSION_1_4) std::cout << "Supports OpenGL 1.4. " << std::endl;
else if (GL_VERSION_1_3) std::cout << "Supports OpenGL 1.3. " << std::endl;
else if (GL_VERSION_1_2) std::cout << "Supports OpenGL 1.2. " << std::endl;
else if (GL_VERSION_1_1) std::cout << "Supports OpenGL 1.1. " << std::endl;
if (GL_ARB_shader_objects && GL_ARB_vertex_shader && GL_ARB_fragment_shader)
{
std::cout << "Status: Using GLSL " << glGetString(GL_SHADING_LANGUAGE_VERSION_ARB) << std::endl;
}
else
{
std::cerr << "No GLSL support!" << std::endl;
return false;
}
return true;
}
#endif

21
underwater4k/Shaders.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
#define MAX_SHADER_ID 4
#include <windows.h>
#include <iostream>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glext.h"
#define myGetProcAddress(name) wglGetProcAddress((LPCSTR)name)
void initShaders();
GLhandleARB createVertexShader(const char* as_FileName);
GLhandleARB createFragmentShader(const char* as_FileName, int ShaderID, bool bDebug);
GLhandleARB createProgram(GLhandleARB ah_VertexShader, GLhandleARB ah_FragmentShader);
void PrintErrors();
void useProgram(GLhandleARB ah_Program);
char* textFileRead(const char* as_FileName);
void printShaderInfoLog(GLhandleARB ah_Shader);
void printProgramInfoLog(GLhandleARB ah_Program);
bool printShaderStatistics();

View File

@@ -0,0 +1,15 @@
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86
call "build.cmd" 1.33 800 600 W
call "build.cmd" 1.88 960 510 W
call "build.cmd" 1.33 1024 768
call "build.cmd" 1.25 1280 1024
call "build.cmd" 1.77 1280 720
call "build.cmd" 1.6 1280 800
call "build.cmd" 1.33 1280 960
call "build.cmd" 1.55 1400 900
call "build.cmd" 1.33 1400 1050
call "build.cmd" 1.6 1680 1050
call "build.cmd" 1.77 1920 1080
call "build.cmd" 1.6 1920 1200
call "build.cmd" 1.33 800 600

9
underwater4k/build.cmd Normal file
View File

@@ -0,0 +1,9 @@
IF [%4]==[W] GOTO :windowed
:fullscreen
cl /c @switches.txt /DASPECT=%1 /DSCREENWIDTH=%2 /DSCREENHEIGHT=%3 main_release.cpp
crinkler @linkparams.txt /out:"final\custom\mirror_%2x%3.exe"
goto :end
:windowed
cl /c @switches.txt /DASPECT=%1 /DSCREENWIDTH=%2 /DSCREENHEIGHT=%3 /DWINDOWED main_release.cpp
crinkler @linkparams.txt /out:"final\custom\mirror_%2x%3_window.exe"
:end

BIN
underwater4k/crinkler.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1 @@
minify\shader_minifier.exe "fragment.glsl_0" -o fragment_small.h -v

1
underwater4k/files.txt Normal file
View File

@@ -0,0 +1 @@
main_release.cpp

557
underwater4k/fragment.glsl Normal file
View File

@@ -0,0 +1,557 @@
@0
const int shader= 0;
@@
@1
const int shader= 1;
@@
@2
const int shader= 2;
@@
@3
const int shader= 3;
@@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
@D
/////////////////////////////////////////////////////////////////////
//Debugzeug fuer Kamerasteuerung
{
ro.x= gl_ModelViewMatrix[0][0];
ro.y= gl_ModelViewMatrix[0][1];
ro.z= gl_ModelViewMatrix[0][2];
float a1= gl_ModelViewMatrix[1][1];
float c1,s1;vec3 q1= vec3((Z.xy - 0.5), 0.8);
c1 = cos(a1); s1 = sin(a1);
rd.y = c1 * q1.y - s1 * q1.z;
rd.x= q1.x;
rd.z = s1 * q1.y + c1 * q1.z;
a1= gl_ModelViewMatrix[1][0];
q1=rd;
c1 = cos(a1); s1 = sin(a1);
rd.x = c1 * q1.x + s1 * q1.z;
rd.z = -s1 * q1.x + c1 * q1.z;
}
//Ende Debugzeug fuer Kamerasteuerung
/////////////////////////////////////////////////////////////////////
@@
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 0;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 0;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
/////////////////////////////////////////////////////////////////////
//Debugzeug fuer Kamerasteuerung
{
ro.x= gl_ModelViewMatrix[0][0];
ro.y= gl_ModelViewMatrix[0][1];
ro.z= gl_ModelViewMatrix[0][2];
float a1= gl_ModelViewMatrix[1][1];
float c1,s1;vec3 q1= vec3((Z.xy - 0.5), 0.8);
c1 = cos(a1); s1 = sin(a1);
rd.y = c1 * q1.y - s1 * q1.z;
rd.x= q1.x;
rd.z = s1 * q1.y + c1 * q1.z;
a1= gl_ModelViewMatrix[1][0];
q1=rd;
c1 = cos(a1); s1 = sin(a1);
rd.x = c1 * q1.x + s1 * q1.z;
rd.z = -s1 * q1.x + c1 * q1.z;
}
//Ende Debugzeug fuer Kamerasteuerung
/////////////////////////////////////////////////////////////////////
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 1;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 1;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
/////////////////////////////////////////////////////////////////////
//Debugzeug fuer Kamerasteuerung
{
ro.x= gl_ModelViewMatrix[0][0];
ro.y= gl_ModelViewMatrix[0][1];
ro.z= gl_ModelViewMatrix[0][2];
float a1= gl_ModelViewMatrix[1][1];
float c1,s1;vec3 q1= vec3((Z.xy - 0.5), 0.8);
c1 = cos(a1); s1 = sin(a1);
rd.y = c1 * q1.y - s1 * q1.z;
rd.x= q1.x;
rd.z = s1 * q1.y + c1 * q1.z;
a1= gl_ModelViewMatrix[1][0];
q1=rd;
c1 = cos(a1); s1 = sin(a1);
rd.x = c1 * q1.x + s1 * q1.z;
rd.z = -s1 * q1.x + c1 * q1.z;
}
//Ende Debugzeug fuer Kamerasteuerung
/////////////////////////////////////////////////////////////////////
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 2;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 2;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
/////////////////////////////////////////////////////////////////////
//Debugzeug fuer Kamerasteuerung
{
ro.x= gl_ModelViewMatrix[0][0];
ro.y= gl_ModelViewMatrix[0][1];
ro.z= gl_ModelViewMatrix[0][2];
float a1= gl_ModelViewMatrix[1][1];
float c1,s1;vec3 q1= vec3((Z.xy - 0.5), 0.8);
c1 = cos(a1); s1 = sin(a1);
rd.y = c1 * q1.y - s1 * q1.z;
rd.x= q1.x;
rd.z = s1 * q1.y + c1 * q1.z;
a1= gl_ModelViewMatrix[1][0];
q1=rd;
c1 = cos(a1); s1 = sin(a1);
rd.x = c1 * q1.x + s1 * q1.z;
rd.z = -s1 * q1.x + c1 * q1.z;
}
//Ende Debugzeug fuer Kamerasteuerung
/////////////////////////////////////////////////////////////////////
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 3;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,557 @@
const int shader= 3;
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
varying vec4 Y;
// Position of the fragment
varying vec2 Z;
uniform sampler2D V;
uniform sampler2D HEIGHT;
// Forward declarations
vec4 traceRay(vec3 ro, vec3 rd, int ignore);
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd);
// All data of our world
vec3 spherePos, lightDir, lightColor, waterColor, ro, rd, interlacing;
float sphereRadius, gf_DetailLevel, pi, eps, bigeps;
// Pseudo random number base generator (credits go to iq/rgba)
float rnd(vec2 x)
{
int n = int(x.x * 40 + x.y * 6400);
n = (n << 13) ^ n;
return 1 - float( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824;
}
// Generate cubic interpolated random values
float smoothrnd(vec2 x)
{
x = mod(x,1000.0);
vec2 a = fract(x);
x -= a;
vec2 u = a*a*(3.0-2.0*a);
return mix(
mix(rnd(x+vec2(0,0)),rnd(x+vec2(1,0)), u.x),
mix(rnd(x+vec2(0,1)),rnd(x+vec2(1,1)), u.x), u.y);
}
// Convert the cipher range from [-1,1] to [0,1]
float norm(float x)
{
return x * 0.5 + 0.5;
}
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
// Our heightmap calculation function, we could use some perlin noise here if it wouldn't be so performance killing
float height(vec2 x)
{
return texture2D(HEIGHT, x).x;
}
// Gets the terrain normal
vec3 getTerrainNormal(vec3 p)
{
return normalize(vec3(
height(p.xz - vec2(bigeps, 0)) - height(p.xz + vec2(bigeps, 0)),
2 * bigeps,
height(p.xz - vec2(0, bigeps)) - height(p.xz + vec2(0, bigeps))));
}
// Global diffuse lighting formula
vec3 diffuseLight(vec3 incolor, float shadow, vec3 normal)
{
return (0.3 + shadow * 0.7 * max(dot(normal, lightDir), 0.0)) * lightColor * incolor;
}
// Calculates the water "waves". To reduce the bumpiness, increment the y-axis
vec3 getWaterNormal(vec3 p)
{
return normalize(vec3(
texnoise(p.xz * 40 + Y.x*.5)*2-1,
8,
texnoise(p.xz * 80 - Y.x*.25)*2-1));
}
float caustic(vec3 p)
{
vec2 q = p.xz * (1 - p.y * .01);
float noiseX = texnoise(q * .125 * (.05*Y.x+vec2(2,3)));
float noiseY = texnoise(q * .125 * (.05*Y.x+vec2(4,5)));
q = mod(q * 10.0 + vec2(noiseX, noiseY) * 16.0, 1.0);
q -= step(0.5, q) * 2 * (q - 0.5);
q *= 2;
return max(pow(q.x, 4.0 + 4.0 * noiseX), pow(q.y, 4.0 + 4.0 * noiseX));
}
float caustics(vec3 p)
{
return caustic(p * 31) * caustic(p * 17);
}
// Our fake godray effect (bad if moving fast, but awesome any other time)
vec3 godrays(vec3 ro, vec3 rd, float maxt, vec3 color)
{
const int iterations = 16;
float dt = 0.001, t = 0;
float cs = 0.0;
for (int i = 0; i < iterations; ++i)
{
vec3 p = ro + rd * t;
vec2 q = p.xz * (1 - p.y * .4);
float shadow = 1.0-step(1,traceRay(p, lightDir, 2).w);
cs = max(cs, (1 + p.y * 8) * shadow * smoothstep(0.4, 0.7, texnoise(q * 64)) / (1+t*2));
t += dt;
}
return color + pow(cs, 4.0) * lightColor * .1;
}
// Calculate the terrain color for the given voxel
vec3 shadeTerrain(vec3 p, vec3 rd)
{
vec3 n = getTerrainNormal(p);
float vrn = voronoi(p.xz);
vec3 grassColor = vec3(0.8, 0.85, 0.4) * 1.5 * grass(p.xz);
vec3 dirtColor = vec3(0.65, 0.6, 0.4) * (.5+grass(p.xz));
vec3 stoneColor = vec3(0.5, 0.5, 0.4) * (.5+grass(p.xz));
float groundFactor = smoothstep(0.7, 0.8, n.y) * (1.0 - step(p.y, texnoise(p.xz*128)*0.01-0.003)); // shore
float dirtFactor = smoothstep(0.4, 0.6, texture2D(V, p.xz * 40).y);
vec3 ground = mix(mix(stoneColor, dirtColor, dirtFactor), grassColor, groundFactor);
vec3 rockColor = vec3(0.5, 0.5, 0.5) * (.75 + vrn) * (.75+.5*grass(p.xz * 8));
vec3 color = mix(ground, rockColor, smoothstep(0.0, 0.05,vrn));
float shadow = 1.0-step(1,traceRay(p + n * 0.005, lightDir, 2).w);
if (p.y <= 0)
color = max(0.0, 0.7 + 8 * p.y) * (color + lightColor * shadow * max(0, 1 + 32 * p.y) * caustics(p));
else
color *= 0.6+0.4*min(1.0, p.y * 999.0);
color = color * (.5+.5*vrn);
return diffuseLight(color, shadow, n);
}
// Create a blueish sky transition from navy blue to badass dark blue
vec3 shadeSky(vec3 ro, vec3 rd)
{
vec3 farColor = vec3(0.0, 0.0, 0.4);
return mix(waterColor, farColor, max(0, rd.y))
+ 0.25*lightColor * pow(max(0, dot(rd, lightDir)), 4)
+ lightColor * pow(max(0, dot(rd, lightDir)), 1000);
}
// Calculates the refraction and reflection of the water surface.
// Also mixes both values by the depth of the water and the fresnel term.
// Possible improvements: fix fake underwater reflection and refraction
vec3 shadeWaterRefl(vec3 p, vec3 newrd)
{
vec3 waterNormal = getWaterNormal(p);
// perform raytracing/raymarching for both reflection and refraction
// calc the water refraction, the refraction index (0.9) will decrease with the distance to allow a better over/under water transition
vec3 refrd = mix(newrd, refract(newrd, waterNormal, 0.9), step(0.0, ro.y));
vec4 refracted = traceRay(p, refrd, 2);//mix(0.9, 1.0, smoothstep(0.01, 0.0, length(p-ro)))), 2);
// calculate the depth factor (water entry point to terrain voxel) (black magic involved here!)
float depth = clamp(pow(1.03 * (1 - length(refracted.xyz - p)), 16.0), 0.0, 1.0);
float shadow = 0.9 + 0.1 * (1.0-step(1,traceRay(p + waterNormal * 0.005, lightDir, 2).w));
float fresnel = pow(clamp(abs(-rd.y), 0.0, 1.0),1.8);
// Finally stir the pot =)
return shadow * mix(
shadeSky(p, refrd), // Water color
mix(
shade(traceRay(p, reflect(newrd, waterNormal), 2), p, newrd), // Reflection color
shade(refracted, p, newrd), // Refraction color
fresnel), // fresnel term
pow(depth, 0.5)); // water color contribution
}
// Texture our "AMIGAAAAAAA!!" ball
vec3 shadeAttractor(vec3 p, vec3 rd)
{
vec3 n,color;
// get the sphere normal, first
n = normalize(p - spherePos);
// now calculate the texture coordinates
vec2 uv = 0.5 + 0.5 * vec2(atan(n.z, n.x), acos(n.y)) / pi;
// We'll animate our x-texture coordinate with the time, this gives the impression of a rotating ball
uv.x -= Y.x;
// This spell will convert any dull ball into an amiga ball, caution is advised.
color = mix(vec3(1), vec3(1, 0, 0), mod(step(fract(uv.x * 6), 0.5) + step(fract(uv.y * 6), 0.5), 2.0));
return diffuseLight(color, 1, n)
+ pow(max(dot(n, normalize(lightDir - rd)), 0.0), 33.0) * lightColor; // specular light spot
}
#define INTERVAL_ITERS 5
#define LINEAR_ACCURACY 0.5
// Raymarch the terrain function, returns the distance from the ray origin to the terrain voxel
// This function was originally adopted from an implementation by iq/rgba
float traceTerrain(vec3 ro, vec3 rd, float maxt)
{
float samplePosY, h, prevt, t;
vec3 samplePos;
// advance our sample position from our nearplane to our farplane
for (t = 0; t < maxt;)
{
// advance our ray
samplePos = ro + rd * t;
samplePosY = samplePos.y;
// get the height at the given sample 2d (!) position (we could enhance this by sampling a voxel and returning only the distance to the voxel)
h = height(samplePos.xz);
float dist = samplePosY - h;
if (dist < 0.0) break;
prevt = t;
if (dist > 0.0001)
t += max(dist * 1.4, 0.0001) * LINEAR_ACCURACY;
else
t += max(dist, 0.00001) * LINEAR_ACCURACY;
}
if (samplePosY <= h)
{
/// Interval mapping
float before = prevt;
vec3 beforePos = ro + rd * before;
float beforeH = height(beforePos.xz);
float after = t;
vec3 afterPos = ro + rd * after;
float afterH = height(afterPos.xz);
for (int i = 0; i < INTERVAL_ITERS; i++)
{
float interval = after - before;
float deltaL = beforeH - afterH;
float deltaR = rd.y * interval;
float curt = (beforeH * interval - deltaL * before) / (deltaR - deltaL);
if (curt <= before - 0.000001 || curt >= after + 0.000001) break;
samplePos = ro + rd * curt;
float h = height(samplePos.xz);
if (h <= samplePos.y)
{
beforeH = h;
before = curt;
t = curt;
}
else
{
afterH = h;
after = curt;
t = curt;
}
}
return t;
}
// we hit nothing
return 9.0;
}
// Ray vs. sphere intersection function
float traceAttractor(vec3 ro, vec3 rd)
{
vec3 dst = ro - spherePos;
float B,D;
B = dot(dst, rd);
if (B > 0)
return 9.0;
D = B*B - dot(dst, dst) + sphereRadius*sphereRadius;
if (D > 0)
{
return -B - sqrt(D);
}
return 9.0;
}
// Ray vs. plane intersection function
float traceWater(vec3 ro, vec3 rd)
{
float tPlane = -ro.y / rd.y;
return tPlane >= eps ? tPlane : 9.0;
}
// Raytracing entry point, returns voxel and object ID
// IDs:
// 0 = sky (not the armageddon, xTr1m!!)
// 1 = terrain
// 2 = water
// 3 = attractive amiga ball (you have never seen such a sexy amiga ball before, admit it!)
vec4 traceRay(vec3 ro, vec3 rd, int ignore)
{
float water, attractor, terrain, minDist;
// trace only the objects we need (only one could maximally be ignored)
water = ignore != 2 ? traceWater(ro, rd) : 9.0;
attractor = ignore != 3 ? traceAttractor(ro, rd) : 9.0;
terrain = ignore != 1 ? traceTerrain(ro, rd, min(0.5, 0.002+min(water, attractor))) : 9.0;
// auto detail level reducing (common dude, give the GPU some breathing room)
gf_DetailLevel /= 20;
// find the nearest distance
minDist = min(terrain, min(water, min(attractor, 9.0)));
// we hit nothing or the hitpoint is too far
if (minDist == 9)
return vec4(0);
// calculate the hit/voxel position
vec3 hitPos = ro + rd * minDist;
// check what we might have hit
if (minDist == terrain)
return vec4(hitPos, 1);
if (minDist == water)
return vec4(hitPos, 2);
if (minDist == attractor)
return vec4(hitPos, 3);
// Panic, worry, die to death! Probably we'll land on the moon (this should never happen)
//return vec4(0);
}
// Entrypoint for color calculation
vec3 shadeRefl(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for this very precise point in the space time continuum
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the distance value for the fog calculation
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
// in most cases we allow further raytracing here (not for the terrain, its not shiny enough)
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(shadeWaterRefl(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 3)
return mix(
// Our amiga ball is shiny so reflect the scene!
mix(shadeAttractor(hitPoint.xyz, rd), shade(traceRay(hitPoint.xyz, reflect(rd, normalize(hitPoint.xyz - spherePos)), 3), hitPoint.xyz, rd), 0.5)
, myFog, distance);
return shadeSky(newRo, rd);
}
// Get the color from the object we just hit (without further raytraces)
// this is necessary because no recursion is allowed in GLSL (damn you!)
vec3 shade(vec4 hitPoint, vec3 newRo, vec3 rd)
{
// determine the fog color for the very same point we discussed earlier
vec3 myFog = newRo.y < eps ? waterColor : shadeSky(ro, rd);
// generate the other distance value. Paid attention? If you don't know what value I'm talking about, rtfm or gtfo.
float distance = clamp(length(hitPoint.xyz - newRo) * (ro.y <= 0 ? 4 : 2), 0.0, 1.0);
// get the color of the hit object and mix it with the fog
if (hitPoint.w == 1)
return mix(shadeTerrain(hitPoint.xyz, rd), myFog, distance);
if (hitPoint.w == 2)
return mix(waterColor, myFog, distance);
if (hitPoint.w == 3)
return mix(shadeAttractor(hitPoint.xyz, rd), myFog, distance);
return myFog;
}
// Now we're just being copycats. We're not creative enough to define own entry points
// Sure, we could "#define MYENTRYPOINT main"! Or just void main(){MyEntryPoint();}
// None of that would help us win the compo, would it?
void main()
{
// Set the quality setting for the raymarcher, a higher value results in a longer processing time
// try to find a good balance between these two, low values wivoronoill result in a wobbling endresult
// low quality = 50.0 (visual results are ok at 640x480)
// mid quality = 100.0
// high quality = 200.0
gf_DetailLevel = 100;
// Give our saviour global variables some life!
pi = 3.1416;
interlacing = vec3(1.2, 0.9, 0.9);
eps = 0.0001;
bigeps = 0.01;
// Nifty random number generator gets initialized
float seed = 10;
// Determine the scene we're in
int scene = int(Y.x);
// Get the look direction for the current pixel (always look forwards)
rd = vec3((Z.xy - 0.5), 1);
float tex = texture2D(V, clamp(Z.xy, 0.0, 1.0), 1.0).x;
gl_FragColor = vec4(tex, tex, tex, 1);
return;
// Merry-go-round on a boat (yeah, this makes no sense. Go watch the intro and see for yourself)
if (scene > 22 && scene < 27)
{
seed = min(1.0, sin((Y.x-23)*pi*0.25)*12);
ro = vec3(0.12, 0.005, Y.x*0.08);
rd = vec3(gl_ModelViewMatrix * vec4(rd, 1));
rd.y += 0.1*cos(Y.x*4);
}
// Intermezzo: Dolphin like animation inside and outside the water, chasing that amiga ball!
else if (scene > 14 && scene < 23)
{
seed = min(1.0, sin((Y.x-15)*pi*0.125)*24);
rd += vec3(0,0.1*cos(Y.x*4), 0);
ro = vec3(0.08, 0.01*sin(Y.x*4)+0.002, Y.x*0.11);
}
// Intro and Outro: Show still scenes
else
{
// Get a random initial position for our camera
ro = vec3(0.1,0.004,0.0) + vec3(0.1,0.005,20)
*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)));
// Basing on the initial position, choose some "random" start and end points nearby
ro = mix(
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
ro+vec3(0.008)*vec3(rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++)), rnd(vec2(scene, seed++))),
// and move the camera!
Y.x-scene);
// We adjust the height of the camera to the terrain height
ro.y += height(ro.xz)+0.02;
// Deviate the camera position in the direction of the normal of the underlying terrain
ro += 0.02*getTerrainNormal(ro);
// Reusing a float variable here, this controls the scene fade in / fade out animation
seed = min(1.0, step(-28.0, -Y.x) * sin((Y.x-scene)*pi)*3);
}
/////////////////////////////////////////////////////////////////////
//Debugzeug fuer Kamerasteuerung
{
ro.x= gl_ModelViewMatrix[0][0];
ro.y= gl_ModelViewMatrix[0][1];
ro.z= gl_ModelViewMatrix[0][2];
float a1= gl_ModelViewMatrix[1][1];
float c1,s1;vec3 q1= vec3((Z.xy - 0.5), 0.8);
c1 = cos(a1); s1 = sin(a1);
rd.y = c1 * q1.y - s1 * q1.z;
rd.x= q1.x;
rd.z = s1 * q1.y + c1 * q1.z;
a1= gl_ModelViewMatrix[1][0];
q1=rd;
c1 = cos(a1); s1 = sin(a1);
rd.x = c1 * q1.x + s1 * q1.z;
rd.z = -s1 * q1.x + c1 * q1.z;
}
//Ende Debugzeug fuer Kamerasteuerung
/////////////////////////////////////////////////////////////////////
rd = normalize(rd);
// Now boot the amiga workbench (erm, no...)
// mantain a relative distance to the camera
if (scene > 22 && scene < 27)
spherePos = ro + 0.1 * vec3(gl_ModelViewMatrix * vec4(0, 0, 1, 1));
else
spherePos = ro + 0.02 * vec3(sin(Y.x), 0, 5+cos(Y.x));
spherePos.y += 0.01 + height(spherePos.xz); // mantain a relative height to the underlying terrain
sphereRadius = scene < 14 ? 0.0 : bigeps * 0.5 + bigeps * Y.z; // The amiga ball is bigger when the snare drum is hit!
spherePos += 2*sphereRadius * getTerrainNormal(spherePos); // deviate according to the underlying terrain's normal
// Make our world pretty and worthy to live in (you can cultivate algae and eat them, they're surely enough for survival)
lightDir = normalize(vec3(0.78, 0.12 + Y.x*.2, -0.18));
lightColor = vec3(2.4, 2.0, 1.0) + Y.x*.5;
waterColor = mix(vec3(0.4, 0.33, 0.4), vec3(0.4, 0.5, 0.6), Y.x);
// Our GPU feels good underwater, almost like a refreshing experience :) cool, eh?
if (ro.y <= 0)
{
// Less work to do...
gf_DetailLevel *= 0.75;
// ...and a cozy darker atmosphere
lightColor *= 0.8;
}
// Here we go, shoot'em rays and get the color of our fragment!
vec4 hit = traceRay(ro, rd, 0);
vec3 color = shadeRefl(hit, ro, rd);
// Underwater there are beams of light emanating from god (so called "god" rays...)
// ...this prooves that god is nothing less than a water surface.
if (ro.y <= 0)
color = godrays(ro, rd, length(hit.xyz-ro), color);
// Apply post processing and fade effects to the color, and finally return it.
gl_FragColor.xyz = color;
}

View File

@@ -0,0 +1,211 @@
/* File generated with Shader Minifier 1.1.1
* http://www.ctrl-alt-test.fr
*/
#ifndef FRAGMENT_SMALL_H_
# define FRAGMENT_SMALL_H_
# define V_Y "v"
# define V_Z "x"
char fragment_glsl_0[] = ""
"const int m=0;"
"varying vec4 v;"
"varying vec2 x;"
"vec3 r,i,z,f,s,y,w;"
"float e,c,a,n,p;"
"float t(vec2 v)"
"{"
"int i=int(v.x*40+v.y*6400);"
"i=i<<13^i;"
"return 1-float(i*(i*i*15731+789221)+1376312589&2147483647)/1073741824;"
"}"
"float d(vec2 v)"
"{"
"v=mod(v,1000.);"
"vec2 x=fract(v);"
"v-=x;"
"vec2 s=x*x*(3.-2.*x);"
"return mix(mix(t(v+vec2(0,0)),t(v+vec2(1,0)),s.x),mix(t(v+vec2(0,1)),t(v+vec2(1,1)),s.x),s.y);"
"}"
"float g(float x)"
"{"
"return x*.5+.5;"
"}"
"float d(float s,float z,float x)"
"{"
"float m=(g(sin(a*2*(s+z+v.x*x)))+g(sin(a*(z-s-v.x*x)))+g(sin(a*(z+v.x*x)))+g(sin(a*3*(s-v.x*x))))*.3;"
"return pow(m,2.);"
"}"
"vec3 h(vec3 x)"
"{"
"int v=int(mod(gl_FragCoord.x,3.));"
"if(v==0)"
"x*=w.xyz;"
"if(v==1)"
"x*=w.yzx;"
"if(v==2)"
"x*=w.zxy;"
"return x;"
"}"
"vec3 o(vec3 v)"
"{"
"vec2 m=x*2-1;"
"float y=m.x*(m.y+3);"
"return v+z*d(y+50*s.x,y+50*s.z,1.5)*g(m.y)*min(-s.y*30,.3);"
"}"
"float l(vec2 v)"
"{"
"return-.035+pow(d(v.x*10,v.y*10,0.)*2-1,2.)*.05-(v.x-.1)*.2;"
"}"
"vec3 u(vec3 v)"
"{"
"return normalize(vec3(l(v.xz-vec2(p,0))-l(v.xz+vec2(p,0)),2*p,l(v.xz-vec2(0,p))-l(v.xz+vec2(0,p))));"
"}"
"vec3 d(vec3 v,vec3 s)"
"{"
"return(.3+.7*max(dot(s,i),0.))*z*v;"
"}"
"vec3 M(vec3 v)"
"{"
"return normalize(vec3(d(v.x*160-cos(v.z*10)*12,v.z*140,4.),8,d(v.z*160-sin(v.x*10)*12,v.x*140,4.))*2-1);"
"}"
"vec3 M(vec3 v,vec3 x)"
"{"
"vec3 s=u(v),y=mix(vec3(.66,.55,.4)-.2*d(abs(v.xz*150))-.2*d(abs(v.yy+.002*d(abs(v.xz*150)))*3000),vec3(.1,.3,0)*(d(v.xz*7000.)*.4+.5),clamp(s.y*(d(v.x*111,v.z*111,0.)*.5-v.y*40),0.,1.));"
"if(v.y<=0)"
"y+=5*M(.8*v).x*min(.3,-v.y*8);"
"return d(y,s);"
"}"
"vec3 g(vec3 v,vec3 s)"
"{"
"return v.y<=-n*n?f:mix(vec3(-.5,-.25,0),vec3(2),1-(s.y*.5+.5));"
"}"
"vec3 h(vec3 s,vec3 x)"
"{"
"vec3 m,y;"
"m=normalize(s-r);"
"vec2 f=.5+.5*vec2(atan(m.z,m.x),acos(m.y))/a;"
"f.x-=v.x;"
"y=mix(vec3(1),vec3(1,0,0),mod(step(fract(f.x*6),.5)+step(fract(f.y*6),.5),2.));"
"return d(y,m)+pow(max(dot(m,normalize(i-x)),0.),33.)*z;"
"}"
"float M(vec3 v,vec3 x,float m)"
"{"
"float y,s,i,f;"
"y=0;"
"vec3 r=v;"
"for(float z=0;z<m;z+=y)"
"{"
"r+=x*y;"
"f=r.y;"
"float w=l(r.xz);"
"if(f<=w)"
"return z-y+y*(s-i)/(f-w+s-i);"
"s=w;"
"i=f;"
"y=.002+z/c;"
"}"
"return 9.;"
"}"
"float l(vec3 v,vec3 x)"
"{"
"vec3 s=v-r;"
"float i,y;"
"i=dot(s,x);"
"if(i>0)"
"return 9.;"
"y=i*i-dot(s,s)+e*e;"
"if(y>0)"
"return-i-sqrt(y);"
"return 9.;"
"}"
"float o(vec3 v,vec3 x)"
"{"
"float m=-v.y/x.y;"
"return m>=n?m:9.;"
"}"
"vec4 g(vec3 v,vec3 x,int m)"
"{"
"float s,i,y,f;"
"s=m!=2?o(v,x):9.;"
"i=m!=3?l(v,x):9.;"
"y=m!=1?M(v,x,min(.5,.002+min(s,i))):9.;"
"c/=20;"
"f=min(y,min(s,min(i,9.)));"
"if(f==9)"
"return vec4(0);"
"vec3 z=v+x*f;"
"if(f==y)"
"return vec4(z,1);"
"if(f==s)"
"return vec4(z,2);"
"if(f==i)"
"return vec4(z,3);"
"}"
"vec3 h(vec4 v,vec3 x,vec3 m)"
"{"
"vec3 y=x.y<n?f:g(s,m);"
"float i=clamp(length(v.xyz-x)*(s.y<=0?4:2),0.,1.);"
"if(v.w==1)"
"return mix(M(v.xyz,m),y,i);"
"if(v.w==2)"
"return mix(f,y,i);"
"if(v.w==3)"
"return mix(h(v.xyz,m),y,i);"
"return y;"
"}"
"vec3 t(vec3 v,vec3 m)"
"{"
"vec3 x=M(v);"
"vec4 i=g(v,refract(m,x,.9),2);"
"float z=clamp(pow(1.03*(1-length(i.xyz-v)),16.),0.,1.);"
"return mix(s.y<0?g(v,m):f,mix(h(g(v,reflect(m,x),2),v,m),h(i,v,m),clamp(-y.y+z,0.,1.)),i.w==3.?.5:pow(z,.5));"
"}"
"vec3 l(vec4 v,vec3 m,vec3 x)"
"{"
"vec3 y=m.y<n?f:g(s,x);"
"float i=clamp(length(v.xyz-m)*(s.y<=0?4:2),0.,1.);"
"if(v.w==1)"
"return mix(M(v.xyz,x),y,i);"
"if(v.w==2)"
"return mix(t(v.xyz,x),y,i);"
"if(v.w==3)"
"return mix(mix(h(v.xyz,x),h(g(v.xyz,reflect(x,normalize(v.xyz-r)),3),v.xyz,x),.5),y,i);"
"return g(m,x);"
"}"
"void main()"
"{"
"c=100;"
"a=3.1416;"
"w=vec3(1.2,.9,.9);"
"n=.0001;"
"p=.01;"
"float m=10;"
"int d=int(v.x);"
"y=vec3(x.xy-.5,1);"
"if(d>22&&d<27)"
"m=min(1.,sin((v.x-23)*a*.25)*12),s=vec3(.12,.005,v.x*.08),y=vec3(gl_ModelViewMatrix*vec4(y,1)),y.y+=.1*cos(v.x*4);"
"else"
" if(d>14&&d<23)"
"m=min(1.,sin((v.x-15)*a*.125)*24),y+=vec3(0,.1*cos(v.x*4),0),s=vec3(.08,.01*sin(v.x*4)+.002,v.x*.11);"
"else"
" s=vec3(.1,.004,0.)+vec3(.1,.005,20)*vec3(t(vec2(d,m++)),t(vec2(d,m++)),t(vec2(d,m++))),s=mix(s+vec3(.008)*vec3(t(vec2(d,m++)),t(vec2(d,m++)),t(vec2(d,m++))),s+vec3(.008)*vec3(t(vec2(d,m++)),t(vec2(d,m++)),t(vec2(d,m++))),v.x-d),s.y+=l(s.xz)+.02,s+=.02*u(s),m=min(1.,step(-28.,-v.x)*sin((v.x-d)*a)*3);"
"y=normalize(y);"
"if(d>22&&d<27)"
"r=s+.1*vec3(gl_ModelViewMatrix*vec4(0,0,1,1));"
"else"
" r=s+.02*vec3(sin(v.x),0,5+cos(v.x));"
"r.y+=.01+l(r.xz);"
"e=d<14?0.:p*.5+p*v.z;"
"r+=2*e*u(r);"
"i=vec3(.58,.58,-.58);"
"z=vec3(1.2);"
"f=vec3(.3,.33,.4);"
"if(s.y<=0)"
"c*=.75,z*=.8;"
"vec3 M=l(g(s,y,0),s,y);"
"if(s.y<=0)"
"M=o(M);"
"gl_FragColor.xyz=h(m*M);"
"}";
#endif // FRAGMENT_SMALL_H_

13146
underwater4k/glext.h Normal file

File diff suppressed because it is too large Load Diff

BIN
underwater4k/link.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,28 @@
/CRINKLER
/COMPMODE:SLOW
/ORDERTRIES:3000
/HASHTRIES:200
/UNSAFEIMPORT
/TRUNCATEFLOATS:24
/HASHSIZE:200
/REPORT:report.html
/RANGE:opengl32
/TRANSFORM:CALLS
/ENTRY:main
/SUBSYSTEM:WINDOWS
obj\bp4k_Compress_Slow\main_release.obj
4klang.obj
opengl32.lib
winmm.lib
kernel32.lib
user32.lib
gdi32.lib
winspool.lib
comdlg32.lib
advapi32.lib
shell32.lib
ole32.lib
oleaut32.lib
uuid.lib
odbc32.lib
odbccp32.lib

421
underwater4k/main.cpp Normal file
View File

@@ -0,0 +1,421 @@
#include <time.h>
#include <io.h>
#include <process.h>
#include "Shaders.h"
HWND hWnd;
static const int gi_ScreenWidth = 1280;
static const int gi_ScreenHeight = 720;
static const int textureSize = 2048;
static const char* gs_VertexShader = "vertex.glsl";
static const char* gs_ShaderFile = "fragment.glsl";
static const PIXELFORMATDESCRIPTOR pfd={
0, 1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 8
};
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,gi_ScreenWidth,gi_ScreenHeight
};
#define CHECK_DEBUG_OUTPUT(shader) \
{\
GLint success = 0;\
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);\
if (!success)\
{\
GLchar infoLog[16384];\
glGetShaderInfoLog(shader, 16384, NULL, infoLog);\
OutputDebugString(infoLog);\
}\
}
struct filemon_struct
{
unsigned int shaderProgram;
char* shaderFile;
HANDLE shaderCompileEvent;
__time64_t shaderChangedDate;
};
DWORD WINAPI filemon(void* args)
{
filemon_struct* data = (filemon_struct*)args;
while (true)
{
_finddata_t fdata;
long hfile = _findfirst(data->shaderFile, &fdata);
if (hfile != -1)
{
if (fdata.time_write != data->shaderChangedDate)
{
data->shaderChangedDate = fdata.time_write;
::SetEvent(data->shaderCompileEvent);
std::cout << "Shader loaded." << std::endl;
}
_findclose(hfile);
}
::Sleep(100);
}
return 0;
}
#include <cmath>
float g_DebugCamPos[ 3 ]= {0,0.0f,0.0f};
float g_DebugCamRot[ 2 ]= {0,0};
bool g_ShaderDebug= true;
int g_ShaderID= 0;
int g_SceneID= 0;
int g_MaxSceneID= 17;
float g_fSpeedFac= 1.0f;
bool g_bForceCompile= true;
void MoveCam( float& fCurTime, float& fDeltaTime )
{
if (GetActiveWindow() != hWnd)
return;
float fSpeed= 0.125f * fDeltaTime;
bool bShift= GetAsyncKeyState( VK_SHIFT ) || GetAsyncKeyState( VK_MBUTTON ) || GetAsyncKeyState( VK_RBUTTON );
bool bStrg= GetAsyncKeyState( VK_CONTROL ) != 0;
float a= g_DebugCamRot[ 0 ];
float b= g_DebugCamRot[ 1 ];
float g_Forward[ 3 ]= {sinf( a )*cosf(b),-sinf(b), cosf( a )*cosf(b)};
float g_Right[ 3 ]= {cosf( a ),0, -sinf( a )};
//if( bShift )
{
if( GetAsyncKeyState( VK_HOME ) )
{
g_DebugCamPos[ 0 ]= 0.0f;
g_DebugCamPos[ 1 ]= 2.0f;
g_DebugCamPos[ 2 ]= -5.0f;
g_DebugCamRot[ 0 ]= 0.0f;
g_DebugCamRot[ 1 ]= 0.0f;
}
if( GetAsyncKeyState( 'W' ) )
{
g_DebugCamPos[ 0 ]+= fSpeed * g_Forward[ 0 ];
g_DebugCamPos[ 1 ]+= fSpeed * g_Forward[ 1 ];
g_DebugCamPos[ 2 ]+= fSpeed * g_Forward[ 2 ];
}
if( GetAsyncKeyState( 'S' ) )
{
g_DebugCamPos[ 0 ]-= fSpeed * g_Forward[ 0 ];
g_DebugCamPos[ 1 ]-= fSpeed * g_Forward[ 1 ];
g_DebugCamPos[ 2 ]-= fSpeed * g_Forward[ 2 ];
}
if( GetAsyncKeyState( 'A' ) )
{
g_DebugCamPos[ 0 ]-= fSpeed * g_Right[ 0 ];
g_DebugCamPos[ 1 ]-= fSpeed * g_Right[ 1 ];
g_DebugCamPos[ 2 ]-= fSpeed * g_Right[ 2 ];
}
if( GetAsyncKeyState( 'D' ) )
{
g_DebugCamPos[ 0 ]+= fSpeed * g_Right[ 0 ];
g_DebugCamPos[ 1 ]+= fSpeed * g_Right[ 1 ];
g_DebugCamPos[ 2 ]+= fSpeed * g_Right[ 2 ];
}
if( GetAsyncKeyState( 'F' ) )
{
g_DebugCamPos[ 1 ]+= fSpeed;
}
if( GetAsyncKeyState( 'V' ) )
{
g_DebugCamPos[ 1 ]-= fSpeed;
}
//if( bStrg )
{
if( ( GetAsyncKeyState( VK_F1 ) & 1 ) != 0)
{
g_ShaderDebug= !g_ShaderDebug;
g_bForceCompile= true;
}
if( ( GetAsyncKeyState( VK_F2 ) & 1 ) != 0)
{
g_ShaderID= (g_ShaderID + MAX_SHADER_ID - 1 ) % MAX_SHADER_ID;
g_bForceCompile= true;
}
if( ( GetAsyncKeyState( VK_F3 ) & 1 )!= 0)
{
g_ShaderID= (g_ShaderID + MAX_SHADER_ID + 1 ) % MAX_SHADER_ID;
g_bForceCompile= true;
}
if( ( GetAsyncKeyState( VK_F4 ) & 1 )!= 0)
{
fCurTime= 0.0f;
}
if( ( GetAsyncKeyState( VK_F5 ) & 1 )!= 0)
{
g_fSpeedFac*= 2.0f;
if( g_fSpeedFac > 32.0f )
{
g_fSpeedFac= 32.0f;
}
}
if( ( GetAsyncKeyState( VK_F6 ) & 1 ) != 0)
{
g_fSpeedFac/= 2.0f;
if( g_fSpeedFac < 0.03125f )
{
g_fSpeedFac= 0.03125f;
}
}
if( ( GetAsyncKeyState( VK_F7 ) & 1 ) != 0)
{
g_SceneID= (g_SceneID + g_MaxSceneID - 1 ) % g_MaxSceneID;
}
if( ( GetAsyncKeyState( VK_F8 ) & 1 )!= 0)
{
g_SceneID= (g_SceneID + g_MaxSceneID + 1 ) % g_MaxSceneID;
}
}
}
static POINT OldCurPos;
POINT CurPos;
GetCursorPos( &CurPos );
if( bShift )
{
g_DebugCamRot[ 0 ]-= 0.003f * ( OldCurPos.x - CurPos.x );
g_DebugCamRot[ 1 ]-= 0.003f * ( OldCurPos.y - CurPos.y );
g_DebugCamRot[ 1 ]= max( g_DebugCamRot[ 1 ], -1.56f );
g_DebugCamRot[ 1 ]= min( g_DebugCamRot[ 1 ], 1.56f );
}
OldCurPos= CurPos;
}
LRESULT MessageCallback(HWND ar_Handle, UINT aw_Message, WPARAM aw_Param, LPARAM al_Param)
{
return DefWindowProc(ar_Handle, aw_Message, aw_Param, al_Param);
}
int gCurScene= 0;
int gCurSceneStart= 0;
int g_SceneLength[]=
{
16, 16, 16,
16, 16, 16,
16, 32, 16,
16, 16, 16,
0x80000000
};
int g_SceneShader[]=
{
0,0,0,
1,1,1,
2,2,2,
3,3,3,
};
float g_SceneFactor[]=
{
0, 0, 0,
0, 0, 1.0f,
0, 0, 1.0f,
0, 1.0f, 1.0f,
0,
};
void _cdecl main()
{
//ChangeDisplaySettings (&dmScreenSettings,CDS_FULLSCREEN);
//HDC hDC = GetDC(CreateWindow("edit", 0, WS_POPUP | WS_VISIBLE | WS_MAXIMIZE, 0, 0, 0, 0, 0, 0, 0, 0));
//HWND hWnd = CreateWindow("MDICLIENT", "Test", WS_OVERLAPPED | WS_VISIBLE | WS_SYSMENU, 0, 0, gi_ScreenWidth, gi_ScreenHeight, 0, 0, 0, 0);
WNDCLASSEX wndclass;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wndclass.lpfnWndProc = (WNDPROC)MessageCallback ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = NULL ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (DKGRAY_BRUSH) ;
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = "Window" ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx(&wndclass);
hWnd = CreateWindow(
"Window", /* Classname */
"Title", /* Title Text */
WS_EX_APPWINDOW, /* default window */
10, /* Windows decides the position */
30, /* where the window ends up on the screen */
gi_ScreenWidth, /* The programs width */
gi_ScreenHeight, /* and height in pixels */
NULL, /* The window is a child-window to desktop */
NULL, /* No menu */
GetModuleHandle(NULL), //GetModuleHandle(NULL), /* Program Instance handler */
NULL /* No Window Creation data */
);
HDC hDC = GetDC(hWnd);
SetPixelFormat(hDC, ChoosePixelFormat(hDC, &pfd), &pfd);
wglMakeCurrent(hDC, wglCreateContext(hDC));
initShaders();
filemon_struct fragmentShader = {0};
filemon_struct textureShader1 = {0};
filemon_struct textureShader2 = {0};
fragmentShader.shaderFile = "fragment.glsl";
fragmentShader.shaderCompileEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT("WriteEvent"));
textureShader1.shaderFile = "tex1.glsl";
textureShader1.shaderCompileEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT("WriteEvent"));
textureShader2.shaderFile = "tex2.glsl";
textureShader2.shaderCompileEvent = ::CreateEvent(NULL, FALSE, FALSE, TEXT("WriteEvent"));
SetThreadPriority((HANDLE)CreateThread(0, 0, &filemon, &fragmentShader, 0, 0), THREAD_PRIORITY_BELOW_NORMAL);
SetThreadPriority((HANDLE)CreateThread(0, 0, &filemon, &textureShader1, 0, 0), THREAD_PRIORITY_BELOW_NORMAL);
SetThreadPriority((HANDLE)CreateThread(0, 0, &filemon, &textureShader2, 0, 0), THREAD_PRIORITY_BELOW_NORMAL);
auto events = new HANDLE[2];
events[0] = fragmentShader.shaderCompileEvent;
events[1] = textureShader1.shaderCompileEvent;
events[2] = textureShader2.shaderCompileEvent;
ShowWindow (hWnd , SW_NORMAL );
::Sleep(100);
LARGE_INTEGER li_OldTime = { 0 };
unsigned int fbo1 = 0, fbo2 = 0;
int iStartTick= timeGetTime();
GLuint tex1, tex2;
glGenTextures(1, &tex1);
glGenTextures(1, &tex2);
glBindTexture(GL_TEXTURE_2D, tex1);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, textureSize, textureSize, 0, GL_RGBA, GL_FLOAT, 0);
glBindTexture(GL_TEXTURE_2D, tex2);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, textureSize, textureSize, 0, GL_RGBA, GL_FLOAT, 0);
((PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"))(1, &fbo1);
((PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"))(GL_FRAMEBUFFER, fbo1);
((PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"))(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
((PFNGLGENFRAMEBUFFERSPROC)wglGetProcAddress("glGenFramebuffers"))(1, &fbo2);
((PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"))(GL_FRAMEBUFFER, fbo2);
((PFNGLFRAMEBUFFERTEXTURE2DPROC)wglGetProcAddress("glFramebufferTexture2D"))(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
float lf_Time= 0.0f;
do
{
MSG msg;
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
return;
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if (::WaitForMultipleObjects(3, events, false, 0) == WAIT_OBJECT_0 || g_bForceCompile)
{
::Sleep(250);
fragmentShader.shaderProgram = createProgram(createVertexShader(gs_VertexShader), createFragmentShader(fragmentShader.shaderFile, g_ShaderID, g_ShaderDebug));
textureShader1.shaderProgram = createProgram(createVertexShader(gs_VertexShader), createFragmentShader(textureShader1.shaderFile, g_ShaderID, g_ShaderDebug));
textureShader2.shaderProgram = createProgram(createVertexShader(gs_VertexShader), createFragmentShader(textureShader2.shaderFile, g_ShaderID, g_ShaderDebug));
glViewport(0, 0, textureSize, textureSize);
((PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"))(GL_FRAMEBUFFER, fbo1);
((PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram"))(textureShader1.shaderProgram);
((PFNGLUNIFORM4FPROC)wglGetProcAddress("glUniform4f"))(0, textureSize, textureSize, lf_Time, 0);
glRects(-1, -1, 1, 1);
((PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"))(GL_FRAMEBUFFER, fbo2);
((PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram"))(textureShader2.shaderProgram);
((PFNGLUNIFORM4FPROC)wglGetProcAddress("glUniform4f"))(0, textureSize, textureSize, lf_Time, 0);
((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i"))(((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation"))(textureShader2.shaderProgram, "V"), 0);
((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture"))(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex1);
glRects(-1, -1, 1, 1);
((PFNGLBINDFRAMEBUFFERPROC)wglGetProcAddress("glBindFramebuffer"))(GL_FRAMEBUFFER, 0);
glViewport(0, 0, gi_ScreenWidth, gi_ScreenHeight);
PrintErrors();
g_bForceCompile= false;
}
int SceneEnd= g_SceneLength[ gCurScene ] * (44100 * 60 / 145);//samples per tick
LARGE_INTEGER li_CurrentTime, li_CurrentFrequency;
QueryPerformanceCounter(&li_CurrentTime);
QueryPerformanceFrequency(&li_CurrentFrequency);
float lf_DiffTime = (float)(li_CurrentTime.QuadPart - li_OldTime.QuadPart) / (float)li_CurrentFrequency.QuadPart;
char windowText[255];
sprintf_s(
windowText,
"Shader: %d Scene: %d FPS: %.2f, Render time: %.4fms",
g_ShaderID,
g_SceneID,
1.0f / lf_DiffTime,
lf_DiffTime );
::SetWindowTextA(hWnd, windowText);
li_OldTime = li_CurrentTime;
lf_Time+= lf_DiffTime / 8.0f / g_fSpeedFac;
if( lf_Time > 1.0f )
{
lf_Time= 0.0f;
}
float fBeat = lf_Time * 16.0f;
while( fBeat > 1.0f )
{
fBeat-= 1.0f;
}
if( fBeat < 0.0f)
{
fBeat = 0.0f;
}
fBeat = pow( 10.0f, 4.0f * -fBeat );
glColor3f((float)g_SceneID + lf_Time, fBeat, fBeat);
MoveCam(lf_Time, lf_DiffTime);
float fDebugData[ 16 ];
fDebugData[ 0 ]= g_DebugCamPos[ 0 ];
fDebugData[ 1 ]= g_DebugCamPos[ 1 ];
fDebugData[ 2 ]= g_DebugCamPos[ 2 ];
fDebugData[ 4 ]= g_DebugCamRot[ 0 ];
fDebugData[ 5 ]= g_DebugCamRot[ 1 ];
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((GLfloat*)&fDebugData);
((PFNGLUSEPROGRAMPROC)wglGetProcAddress("glUseProgram"))(fragmentShader.shaderProgram);
((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture"))(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex1);
((PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture"))(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex2);
((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i"))(((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation"))(fragmentShader.shaderProgram, "V"), 0);
((PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i"))(((PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress("glGetUniformLocation"))(fragmentShader.shaderProgram, "HEIGHT"), 1);
glRects(-1, -1, 1, 1);
SwapBuffers(hDC);
}
while ( !GetAsyncKeyState(VK_ESCAPE) );
ExitProcess(0);
}

View File

@@ -0,0 +1,451 @@
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include <mmreg.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "glext.h"
#include "small.h"
#include "4klang.h"
#pragma data_seg(".Shader0")
#include "fragment_small.h"
/*******************************************************/
/* config flags */
//#define DESKTOP_RESOLUTION
#define WINDOWED
#define CHANGERES_DELAY
#define CLEAR_SCREEN_WHILE_LOADING
#define SHADER_WARMUP
/* end config flags */
/*******************************************************/
#ifndef DESKTOP_RESOLUTION
#ifndef ASPECT
#define ASPECT 1.33
#endif
#ifndef SCREENWIDTH
#define SCREENWIDTH 800
#endif
#ifndef SCREENHEIGHT
#define SCREENHEIGHT 600
#endif
#else
// default aspect ratio for when using the desktop resolution
#ifndef ASPECT
#define ASPECT 1.77
#endif
#endif
#define USE_SOUND_THREAD
#define STR2(x) #x
#define STR(x) STR2(x)
#pragma data_seg(".vertexshader")
static char* vertexShader = "varying vec4 "V_Y";varying vec2 "V_Z";void main(){"V_Y"=gl_Color;"V_Z"=(gl_Vertex.xy*vec2("STR(ASPECT)",1))*.5+.5;gl_Position=gl_Vertex;}";
static char** vsh = &vertexShader;
static char* pixelShader = (char*)fragment_glsl_0;
static char** fsh = &pixelShader;
#pragma data_seg(".pfd")
static const PIXELFORMATDESCRIPTOR pfd={
0, 1, PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8
};
#ifndef DESKTOP_RESOLUTION
#pragma data_seg(".dms")
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,SCREENWIDTH,SCREENHEIGHT
};
#endif
#pragma bss_seg(".mainbss")
static SAMPLE_TYPE lpSoundBuffer[MAX_SAMPLES*2];
static HWAVEOUT hWaveOut;
static unsigned int shaders[5];
#pragma data_seg(".wavefmt")
WAVEFORMATEX WaveFMT =
{
#ifdef FLOAT_32BIT
WAVE_FORMAT_IEEE_FLOAT,
#else
WAVE_FORMAT_PCM,
#endif
2, // channels
SAMPLE_RATE, // samples per sec
SAMPLE_RATE*sizeof(SAMPLE_TYPE)*2, // bytes per sec
sizeof(SAMPLE_TYPE)*2, // block alignment;
sizeof(SAMPLE_TYPE)*8, // bits per sample
0 // extension not needed
};
#pragma data_seg(".wavehdr")
WAVEHDR WaveHDR =
{
(LPSTR)lpSoundBuffer,
MAX_SAMPLES*sizeof(SAMPLE_TYPE)*2,
0, 0, 0, 0, 0, 0
};
#pragma data_seg(".mmtime")
MMTIME MMTime =
{
TIME_SAMPLES,
0
};
#pragma data_seg(".maindata")
const float sceneLength = 64 * SAMPLES_PER_TICK;
const int shaderLength = 4 * 64 * SAMPLES_PER_TICK;
#pragma data_seg(".windowClass")
const char* edit = "edit";
#pragma data_seg(".glFunctions")
const char* glUseProgram = "glUseProgram";
const char* glCreateProgram = "glCreateProgram";
const char* glCreateShader = "glCreateShader";
const char* glShaderSource = "glShaderSource";
const char* glCompileShader = "glCompileShader";
const char* glAttachShader = "glAttachShader";
const char* glLinkProgram = "glLinkProgram";
#pragma code_seg(".initsnd")
__forceinline void InitSound()
{
_asm
{
#ifdef USE_SOUND_THREAD
push ESI
push ESI
push offset [lpSoundBuffer]
push dword ptr [_4klang_render]
push ESI
push ESI
call dword ptr [CreateThread]
#else
push offset [lpSoundBuffer]
push dword ptr [_4klang_render]
#endif
push ESI
push ESI
push ESI
push offset [WaveFMT]
push -0x1
push offset [hWaveOut]
call dword ptr [waveOutOpen]
push 0x20
push offset [WaveHDR]
push dword ptr [hWaveOut]
push 0x20
push offset [WaveHDR]
push dword ptr [hWaveOut]
call dword ptr [waveOutPrepareHeader]
call dword ptr [waveOutWrite]
}
}
#pragma code_seg(".envelope")
float get_Envelope(int instrument)
{
return (&_4klang_envelope_buffer)[(((MMTime.u.sample) >> 8) << 5) + POLYPHONY*instrument]; // the last number is the instrument
}
#pragma code_seg(".sample")
int get_Sample()
{
waveOutGetPosition(hWaveOut, &MMTime, sizeof(MMTIME));
return MMTime.u.sample;
}
#pragma code_seg(".compile")
unsigned int compileShader()
{
_asm
{
push glCreateProgram
call dword ptr [wglGetProcAddress]
call eax
mov ebx, eax
push ebx
push glLinkProgram
push GL_FRAGMENT_SHADER
push glCreateShader
push GL_VERTEX_SHADER
push glCreateShader
call dword ptr [wglGetProcAddress]
call eax
push eax
push ebx
push glAttachShader
push eax
push glCompileShader
push esi
push vsh
push 1
push eax
push glShaderSource
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
push eax
push ebx
push glAttachShader
push eax
push glCompileShader
push esi
push fsh
push 1
push eax
push glShaderSource
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
call dword ptr [wglGetProcAddress]
call eax
mov eax, ebx
}
}
// Aufbau der musik:
// Teil / Dauer in Szenen
// ----------------------
// Intro / 2
// A-Teil / 4
// B-Teil / 4
// A-Teil / 4
// Outro / 3 (wobei die letzte Szene für fade-out dienen soll)
#pragma code_seg(".main")
void _cdecl main()
{
register HDC hDC;
_asm
{
xor esi,esi
push esi //ShowCursor
push esi //CreateWindowExA
push esi
push esi
push esi
#ifdef DESKTOP_RESOLUTION
push esi
push esi
#else
#ifdef WINDOWED
push SCREENHEIGHT
push SCREENWIDTH
#else
push esi
push esi
#endif
#endif
push esi
push esi
#ifdef DESKTOP_RESOLUTION
push WS_POPUP | WS_VISIBLE | WS_MAXIMIZE
#else
#ifdef WINDOWED
push WS_POPUP | WS_VISIBLE
#else
push WS_POPUP | WS_VISIBLE | WS_MAXIMIZE
#endif
#endif
push esi
push edit
push esi
#ifndef WINDOWED
#ifndef DESKTOP_RESOLUTION
push 4 //ChangeDisplaySettings
push offset [dmScreenSettings]
call dword ptr [ChangeDisplaySettings]
#endif
#endif
call dword ptr [CreateWindowExA]
push eax
call dword ptr [GetDC]
mov hDC, eax
mov eax, offset [pfd]
push eax
push eax
push hDC
call dword ptr [ChoosePixelFormat]
push eax
push hDC
call dword ptr [SetPixelFormat]
push hDC
call dword ptr [wglCreateContext]
push eax
push hDC
call dword ptr [wglMakeCurrent]
mov ebx, offset [shaders]
mov edi, offset [fragment_glsl_0] + 12
call dword ptr[compileShader]
mov dword ptr[ebx], eax
inc dword ptr[edi]
add ebx, 4
call dword ptr[compileShader]
mov dword ptr[ebx], eax
inc dword ptr[edi]
add ebx, 4
call dword ptr[compileShader]
mov dword ptr[ebx], eax
inc dword ptr[edi]
add ebx, 4
call dword ptr[compileShader]
mov dword ptr[ebx], eax
inc dword ptr[edi]
add ebx, 4
mov dword ptr[ebx], eax
call dword ptr[ShowCursor]
#ifdef CHANGERES_DELAY
push 2048 // delay time in milliseconds
#endif
#ifdef CLEAR_SCREEN_WHILE_LOADING
push hDC
push 1 // glRects
push 1
push -1
push -1
push esi
push esi
push esi
call dword ptr[glColor3f]
call dword ptr[glRects]
call dword ptr[SwapBuffers]
#endif
#ifdef CHANGERES_DELAY
call dword ptr [Sleep]
#endif
}
#ifdef SHADER_WARMUP
_asm
{
push 1 // glRects
push 1
push -1
push -1
push dword ptr [shaders+12] // glUseProgram
push dword ptr [glUseProgram] // wglGetProcAddress
push 1 // glRects
push 1
push -1
push -1
push dword ptr [shaders+8] // glUseProgram
push dword ptr [glUseProgram] // wglGetProcAddress
push 1 // glRects
push 1
push -1
push -1
push dword ptr [shaders+4] // glUseProgram
push dword ptr [glUseProgram] // wglGetProcAddress
push 1 // glRects
push 1
push -1
push -1
push dword ptr [shaders+0] // glUseProgram
push dword ptr [glUseProgram] // wglGetProcAddress
call dword ptr [wglGetProcAddress]
call eax
call dword ptr[glRects]
call dword ptr [wglGetProcAddress]
call eax
call dword ptr[glRects]
call dword ptr [wglGetProcAddress]
call eax
call dword ptr[glRects]
call dword ptr [wglGetProcAddress]
call eax
call dword ptr[glRects]
}
#endif
_asm call dword ptr[InitSound]
while (true)
{
_asm
{
push PM_REMOVE // PeekMessageA
push esi
push esi
push esi
push esi
push hDC // SwapBuffers
push 1 // glRects
push 1
push -1
push -1
push esi //glColor3f
push esi
push esi
}
if (get_Sample() >= MAX_TICKS * SAMPLES_PER_TICK)
break;
_asm
{
mov dword ptr [esp],eax
cdq
div dword ptr [shaderLength]
mov ebx, eax
fild dword ptr [esp]
fdiv dword ptr [sceneLength]
fstp dword ptr [esp]
push 2
call dword ptr [get_Envelope]
fstp dword ptr [esp+4]
push 6
call dword ptr [get_Envelope]
fstp dword ptr [esp+8]
call dword ptr [glColor3f]
push dword ptr [ebx*4+shaders]
push dword ptr [glUseProgram]
call dword ptr [wglGetProcAddress]
call eax
call dword ptr[glRects]
call dword ptr[SwapBuffers]
call dword ptr[PeekMessageA]
}
if (GetAsyncKeyState(VK_ESCAPE))
break;
}
ExitProcess(0);
}

Binary file not shown.

191
underwater4k/release.h Normal file
View File

@@ -0,0 +1,191 @@
#pragma once
#pragma data_seg(".shaders")
static char* fsh =
"#define ve return\n" // Line 1
"#define ec float\n" // Line 1
"varying vec4 Y;" // Line 6
"varying vec2 Z;" // Line 9
"vec4 R(vec3 n,vec3 m,int k);" // Line 12
"vec3 T(vec4 j,vec3 l,vec3 m);" // Line 13
"vec3 f,b,a,h,e,d,X;" // Line 17
"ec g,W,c,V,U;ec A(vec2 j){" // Line 18
"int i=int(j.x*40+j.y*6400);" // Line 24
"i=(i<<13)^i;" // Line 25
"ve 1-ec((i*(i*i*15731+789221)+1376312589)&0x7fffffff)/1073741824;}ec B(vec2 k){" // Line 26
"k=mod(k,1000.);" // Line 33
"vec2 i=fract(k);" // Line 34
"k-=i;" // Line 35
"vec2 j=i*i*(3.-2.*i);" // Line 36
"ve mix(" // Line 37
"mix(A(k+vec2(0,0)),A(k+vec2(1,0)),j.x)," // Line 38
"mix(A(k+vec2(0,1)),A(k+vec2(1,1)),j.x),j.y);}ec C(ec i){" // Line 39
"ve i*.5+.5;}ec D(ec k,ec l,ec j){" // Line 46
"ec i=(" // Line 53
"C(sin(c*2*(k+l+Y.y*j)))+" // Line 54
"C(sin(c*(l-k-Y.y*j)))+" // Line 55
"C(sin(c*(l+Y.y*j)))+" // Line 56
"C(sin(c*3*(k-Y.y*j))))*.3;" // Line 57
"ve pow(i,2.);}vec3 E(vec3 j){" // Line 58
"int i=int(mod(gl_FragCoord.x,3.));" // Line 65
"if(i==0)j*=X.xyz;" // Line 66
"if(i==1)j*=X.yzx;" // Line 67
"if(i==2)j*=X.zxy;" // Line 68
"ve mix(j,vec3(C(B(Z*333+A(vec2(Y.y))*33333))),Y.x*.3+.03);}vec3 F(vec3 i){" // Line 69
"vec2 j=Z*2-1;" // Line 76
"ec k=j.x*(j.y+3);" // Line 77
"ve i+a*" // Line 78
"D(k+50*e.x,k+50*e.z,1.5)*" // Line 79
"(C(j.y))*min(-e.y*30,.3);}ec G(vec2 i){" // Line 80
"ve (-.035+pow((D(i.x*10,i.y*10,.0)*2-1),2.)*.05)" // Line 87
"-(i.x-.1)*.2;}vec3 H(vec3 i){" // Line 88
"ve normalize(vec3(" // Line 95
"G(i.xz-vec2(U,0))-G(i.xz+vec2(U,0))," // Line 96
"2*U," // Line 97
"G(i.xz-vec2(0,U))-G(i.xz+vec2(0,U))));}vec3 I(vec3 i,vec3 j){" // Line 98
"ve (.3+.7*max(dot(j,b),.0))*a*i;}vec3 J(vec3 i){" // Line 105
"ve normalize(vec3(" // Line 112
"D(i.x*160-cos(i.z*10)*12,i.z*140,4.)," // Line 113
"8," // Line 114
"D(i.z*160-sin(i.x*10)*12,i.x*140,4.))*2-1);}vec3 K(vec3 k,vec3 l){" // Line 115
"vec3 j=H(k);" // Line 122
"vec3 i=mix(" // Line 123
"vec3(.66,.55,.4)" // Line 125
"-.2*B(abs(k.xz*150))" // Line 128
"-.2*B(abs(k.yy+.002*B(abs(k.xz*150)))*3000)," // Line 131
"vec3(.1,.3,0)*(B(k.xz*7000.)*.4+.5)," // Line 134
"clamp(j.y*(D(k.x*111,k.z*111,.0)*.5-k.y*40),.0,1.));" // Line 137
"if(k.y<=0)" // Line 140
"i+=5*J(.8*k).x*min(.3,-k.y*8);" // Line 141
"ve I(i,j);}vec3 L(vec3 j,vec3 i){" // Line 144
"ve j.y<=-V*V?" // Line 151
"h:" // Line 152
"mix(vec3(-.5,-.25,0),vec3(2),1-(i.y*.5+.5));}vec3 M(vec3 k,vec3 j){" // Line 153
"vec3 m=J(k);" // Line 162
"vec4 l=R(k,refract(j,m,.9),2);" // Line 166
"ec i=clamp(pow(1.03*(1-length(l.xyz-k)),16.),.0,1.);" // Line 169
"ve mix(" // Line 172
"e.y<0?L(k,j):h," // Line 173
"mix(" // Line 174
"T(R(k,reflect(j,m),2),k,j)," // Line 175
"T(l,k,j)," // Line 176
"clamp(-d.y+i,.0,1.))," // Line 177
"l.w==3.?.5:pow(i,.5));}vec3 N(vec3 k,vec3 l){" // Line 178
"vec3 j,i;" // Line 186
"j=normalize(k-f);" // Line 189
"vec2 m=.5+.5*vec2(atan(j.z,j.x),acos(j.y))/c;" // Line 192
"m.x-=Y.y;" // Line 195
"i=mix(vec3(1),vec3(1,0,0),mod(step(fract(m.x*6),.5)+step(fract(m.y*6),.5),2.));" // Line 198
"ve I(i,j)" // Line 200
"+pow(max(dot(j,normalize(b-l)),.0),33.)*a;}ec O(vec3 n,vec3 m,ec l){" // Line 201
"ec i,j,k,p;" // Line 209
"i=0;" // Line 210
"vec3 o=n;" // Line 211
"for(ec q=0;q<l;q+=i)" // Line 214
"{" // Line 215
"o+=m*i;" // Line 217
"p=o.y;" // Line 218
"ec r=G(o.xz);" // Line 221
"if(p<=r)" // Line 223
"{" // Line 224
"ve q-i+i*(j-k)/(p-r+j-k);}" // Line 227
"j=r;" // Line 232
"k=p;" // Line 233
"i=.002+(q/W);}" // Line 237
"ve 9.;}ec P(vec3 m,vec3 l){" // Line 241
"vec3 k=m-f;" // Line 248
"ec i,j;" // Line 249
"i=dot(k,l);" // Line 250
"if(i>0)" // Line 251
"ve 9.;" // Line 252
"j=i*i-dot(k,k)+g*g;" // Line 253
"if(j>0)" // Line 254
"{" // Line 255
"ve -i-sqrt(j);}" // Line 256
"ve 9.;}ec Q(vec3 j,vec3 i){" // Line 258
"ec k=-j.y/i.y;" // Line 265
"ve k>=V?k:9.;}vec4 R(vec3 n,vec3 m,int k){" // Line 266
"ec p,i,o,l;" // Line 278
"p=k!=2?Q(n,m):9.;" // Line 281
"i=k!=3?P(n,m):9.;" // Line 282
"o=k!=1?O(n,m,min(.5,.002+min(p,i))):9.;" // Line 283
"W/=20;" // Line 286
"l=min(o,min(p,min(i,9.)));" // Line 289
"if(l==9)" // Line 292
"ve vec4(0);" // Line 293
"vec3 j=n+m*l;" // Line 296
"if(l==o)" // Line 299
"ve vec4(j,1);" // Line 300
"if(l==p)" // Line 301
"ve vec4(j,2);" // Line 302
"if(l==i)" // Line 303
"ve vec4(j,3);}vec3 S(vec4 j,vec3 l,vec3 m){" // Line 304
"vec3 k=l.y<V?h:L(e,m);" // Line 315
"ec i=clamp(length(j.xyz-l)*(e.y<=0?4:2),.0,1.);" // Line 318
"if(j.w==1)" // Line 322
"ve mix(K(j.xyz,m),k,i);" // Line 323
"if(j.w==2)" // Line 324
"ve mix(M(j.xyz,m),k,i);" // Line 325
"if(j.w==3)" // Line 326
"ve mix(" // Line 327
"mix(N(j.xyz,m),T(R(j.xyz,reflect(m,normalize(j.xyz-f)),3),j.xyz,m),.5)" // Line 329
",k,i);" // Line 330
"ve L(l,m);}vec3 T(vec4 j,vec3 l,vec3 m){" // Line 332
"vec3 k=l.y<V?h:L(e,m);" // Line 341
"ec i=clamp(length(j.xyz-l)*(e.y<=0?4:2),.0,1.);" // Line 344
"if(j.w==1)" // Line 347
"ve mix(K(j.xyz,m),k,i);" // Line 348
"if(j.w==2)" // Line 349
"ve mix(h,k,i);" // Line 350
"if(j.w==3)" // Line 351
"ve mix(N(j.xyz,m),k,i);" // Line 352
"ve k;}void main(){" // Line 354
"W=100;" // Line 368
"c=3.1416;" // Line 371
"X=vec3(1.2,.9,.9);" // Line 372
"V=.0001;" // Line 373
"U=.01;" // Line 374
"ec k=10;" // Line 377
"int j=int(Y.y);" // Line 380
"d=vec3((Z.xy-.5),1);" // Line 383
"if(j>22&&j<27)" // Line 386
"{" // Line 387
"k=min(1.,sin((Y.y-23)*c*.25)*12);" // Line 388
"e=vec3(.12,.005,Y.y*.08);" // Line 389
"d=vec3(gl_ModelViewMatrix*vec4(d,1));" // Line 390
"d.y+=.1*cos(Y.y*4);}" // Line 391
"else if(j>14&&j<23)" // Line 394
"{" // Line 395
"k=min(1.,sin((Y.y-15)*c*.125)*24);" // Line 396
"d+=vec3(0,.1*cos(Y.y*4),0);" // Line 397
"e=vec3(.08,.01*sin(Y.y*4)+.002,Y.y*.11);}" // Line 398
"else " // Line 402
"{" // Line 403
"e=vec3(.1,.004,.0)+vec3(.1,.005,20)" // Line 405
"*vec3(A(vec2(j,k++)),A(vec2(j,k++)),A(vec2(j,k++)));" // Line 406
"e=mix(" // Line 409
"e+vec3(.008)*vec3(A(vec2(j,k++)),A(vec2(j,k++)),A(vec2(j,k++)))," // Line 410
"e+vec3(.008)*vec3(A(vec2(j,k++)),A(vec2(j,k++)),A(vec2(j,k++)))," // Line 411
"Y.y-j);" // Line 413
"e.y+=G(e.xz)+.02;" // Line 416
"e+=.02*H(e);" // Line 419
"k=min(1.,step(-28.,-Y.y)*sin((Y.y-j)*c)*3);}" // Line 422
"d=normalize(d);" // Line 425
"if(j>22&&j<27)" // Line 429
"f=e+.1*vec3(gl_ModelViewMatrix*vec4(0,0,1,1));" // Line 430
"else " // Line 432
"f=e+.02*vec3(sin(Y.y),0,5+cos(Y.y));" // Line 433
"f.y+=.01+G(f.xz);" // Line 435
"g=j<14?.0:U*.5+U*Y.z;" // Line 436
"f+=2*g*H(f);" // Line 437
"b=vec3(.58,.58,-.58);" // Line 440
"a=vec3(1.2);" // Line 441
"h=vec3(.3,.33,.4);" // Line 442
"if(e.y<=0)" // Line 445
"{" // Line 446
"W*=.75;" // Line 448
"a*=.8;}" // Line 451
"vec3 i=S(R(e,d,0),e,d);" // Line 455
"if(e.y<=0)" // Line 459
"i=F(i);" // Line 460
"gl_FragColor.xyz=E(step(2.,Y.y)*k*i);}";

163
underwater4k/shader_code.h Normal file
View File

@@ -0,0 +1,163 @@
/* File generated with Shader Minifier 1.0.3
* http://www.ctrl-alt-test.fr
*/
#ifndef SHADER_CODE_H_
# define SHADER_CODE_H_
# define V_Y "v"
# define V_Z "m"
const char *mark_fs = ""
"varying vec4 v;"
"varying vec2 m;"
"vec3 f,z;"
"float x=6.28319;"
"vec2 n(vec2 f,float v)"
"{"
"return cos(v)*f+sin(v)*vec2(-f.y,f.x);"
"}"
"void i(inout vec3 v,float f)"
"{"
"float z=mod(atan(v.z,v.x),f)-f*.5;"
"v.xz=length(v.xz)*vec2(cos(z),sin(z));"
"}"
"float i(vec3 v,float f,float z)"
"{"
"return length(vec2(length(v.xz)-f,v.y))-z;"
"}"
"float s(vec3 v,float z)"
"{"
"return length(v)-z;"
"}"
"float i(vec3 v)"
"{"
"return v.y+.6;"
"}"
"float n(vec3 v)"
"{"
"return min(s(v+vec3(0,8.,0),8.5),i(v,2.3,.5));"
"}"
"float s(vec3 v)"
"{"
"float z=max(s(v,6.),v.y);"
"i(v,x/64.);"
"v.x=abs(v.x-5.)-2.;"
"float f=mix(length(v.yz),length(v.xyz),step(0.,v.x));"
"return min(z,f-.4);"
"}"
"float l(vec3 f)"
"{"
"return f.y-=4.,f.xz=n(f.xz,v.y*6.),i(f,x/12.),f.yz=n(f.yz,x/4.),min(i(f,2.,.15),s(f,1.5));"
"}"
"float h(vec3 v)"
"{"
"return min(min(min(i(v),n(v)),s(v)),l(v));"
"}"
"int g(vec3 v)"
"{"
"float z=1000.;"
"int f;"
"if(i(v)<z)"
"z=i(v),f=0;"
"if(n(v)<z)"
"z=n(v),f=1;"
"if(s(v)<z)"
"z=s(v),f=2;"
"if(l(v)<z)"
"z=l(v),f=3;"
"return f;"
"}"
"vec3 p(vec3 v)"
"{"
"vec3 z=vec3(.04,0.,0.),f;"
"f.x=h(v+z.xyy)-h(v-z.xyy);"
"f.y=h(v+z.yxy)-h(v-z.yxy);"
"f.z=h(v+z.yyx)-h(v-z.yyx);"
"return normalize(f);"
"}"
"float e(vec3 v)"
"{"
"float z=1.;"
"for(float f=.2;f<12.;f=f*1.1+.125)"
"z+=min(h(v+vec3(0.,1.,0.)*f),0.);"
"return clamp(z,.2,1.);"
"}"
"float e(vec3 v,vec3 f,float z,float i)"
"{"
"float x,y=sign(z);"
"for(x=y*.5+.5;i>0.;i--)"
"x-=(i*z-h(v+f*i*z*y))/exp2(i);"
"return x;"
"}"
"vec3 t(vec3 v)"
"{"
"float z=.3+.3*dot(v,vec3(0.,1.,0.));"
"i(v,x/16.);"
"v.x=abs(v.x-.2)-.08;"
"float f=mix(abs(v.z),length(v.xz),step(0.,v.x));"
"z+=pow(smoothstep(.1,0.,f),15.);"
"return vec3(z);"
"}"
"float c(vec3 v)"
"{"
"float z=abs(v.y-.9);"
"return.4+.3*(1-z);"
"}"
"void main()"
"{"
"int x=int(v.y);"
"float y=mod(v.y,1.);"
"z=vec3(m.xy-.5,1);"
"f=vec3(-30.-y*5.,3.,-16.+y*24.);"
"z.xz=n(z.xz,y*-2.5);"
"if(false)"
"{"
"f.x=gl_ModelViewMatrix[0][0];"
"f.y=gl_ModelViewMatrix[0][1];"
"f.z=gl_ModelViewMatrix[0][2];"
"float i=gl_ModelViewMatrix[1][1],s,r;"
"vec3 l=vec3(m.xy-.5,1);"
"s=cos(i);"
"r=sin(i);"
"z.y=s*l.y-r*l.z;"
"z.x=l.x;"
"z.z=r*l.y+s*l.z;"
"i=gl_ModelViewMatrix[1][0];"
"l=z;"
"s=cos(i);"
"r=sin(i);"
"z.x=s*l.x+r*l.z;"
"z.z=-r*l.x+s*l.z;"
"}"
"z=normalize(z);"
"vec3 i=vec3(0.,0.,0.);"
"float s=1.,l=0.,r=256.,a;"
"while(s>.1)"
"{"
"for(a=1.;l<r&&a>.05;l+=a)"
"a=h(f+z*l);"
"if(l<r)"
"{"
"f+=z*l;"
"vec3 o=p(f);"
"z=reflect(z,o);"
"l=.1;"
"vec3 d=vec3(.3,.2,.1);"
"float u=.125;"
"int M=g(f);"
"if(M==1)"
"d=vec3(.1,.1,.1),u=.8;"
"if(M==2)"
"d=vec3(.4,.3,.03),u=.2;"
"if(M==3)"
"d=vec3(.7,0.,0.),u=.2;"
"d*=c(o)*e(f)*e(f,o,.4,10.);"
"i+=s*d;"
"s*=u;"
"}"
"else"
" i+=s*t(z),s=0.;"
"}"
"gl_FragColor.xyz=i;"
"}";
#endif // SHADER_CODE_H_

127
underwater4k/small.h Normal file
View File

@@ -0,0 +1,127 @@
#pragma once
#pragma code_seg("sm0")
DWORD x_Ftol(float af_Value)
{
DWORD ldw_RetVal;
__asm fld af_Value
__asm fistp ldw_RetVal
return ldw_RetVal;
}
#pragma code_seg("sm1")
__forceinline float x_Frac(float af_Value)
{
return af_Value - x_Ftol(af_Value);
}
#pragma code_seg("sm2")
__forceinline float x_Abs(float af_Value)
{
__asm fld af_Value
__asm fabs
}
#pragma code_seg("sm3")
float x_Sin(float af_Value)
{
__asm fld af_Value
__asm fsin
}
#pragma code_seg("sm4")
float x_Sign(float af_Value)
{
if (af_Value != 0)
return af_Value / x_Abs(af_Value);
return 1.0f;
}
#pragma code_seg("sm5")
float x_Sqrt(float af_Value)
{
__asm fld af_Value
__asm fsqrt
}
#pragma code_seg("sm7")
__forceinline void x_MemCopy(void* av_Dest_, const void* av_Src_, size_t ai_Size)
{
__asm mov esi, av_Src_
__asm mov edi, av_Dest_
__asm mov ecx, ai_Size
__asm rep movsb
}
#pragma code_seg("sm8")
float x_Fmod(float x, float y)
{
__asm fld y
__asm fld x
__asm fprem
__asm fxch
__asm fstp x
}
#pragma data_seg("smA")
static unsigned long seed=0x12345678;
#pragma code_seg("sm9")
__forceinline void x_Randomize(unsigned long x)
{
seed = x;
}
#pragma code_seg("smB")
float x_Rand()
{
seed = seed * 0x76364873 + 1234567;
return (float)(seed & 0x7FFFFFFF) * (const float)(2.0f / (float)0x7FFFFFFF) - 1.0f;
}
#pragma code_seg("smS")
__forceinline size_t x_Strlen(const char* as_String)
{
size_t li_Length = 0;
while (*as_String++) ++li_Length;
return li_Length;
}
#pragma code_seg("smP")
float x_Pow(float x, float y){
float r;
__asm{
fld y
fld x
fyl2x
fld1
fld st(1)
fprem
f2xm1
faddp st(1),st
fscale
fxch st(1)
fstp st(0)
fstp r
}
return r;
}
extern "C"
{
int _fltused = 1;
}

23
underwater4k/switches.txt Normal file
View File

@@ -0,0 +1,23 @@
/O1
/Oi
/Os
/D "WIN32"
/D "NDEBUG"
/D "_WINDOWS"
/FD
/MT
/GS-
/GR-
/Fp".\obj\bp4k_Compress_Slow/cmath.pch"
/FAs
/Fa".\obj\bp4k_Compress_Slow/"
/Fo".\obj\bp4k_Compress_Slow/"
/Fd".\obj\bp4k_Compress_Slow/"
/FR".\obj\bp4k_Compress_Slow\\"
/W0
/nologo
/c
/Zi
/Gz
/TP
/errorReport:prompt

81
underwater4k/tex1.glsl Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

81
underwater4k/tex1.glsl_0 Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

81
underwater4k/tex1.glsl_1 Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

81
underwater4k/tex1.glsl_2 Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

81
underwater4k/tex1.glsl_3 Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return 1.0 - min1 * 10.0;//(min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.8)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

31
underwater4k/tex2.glsl Normal file
View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

31
underwater4k/tex2.glsl_0 Normal file
View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

31
underwater4k/tex2.glsl_1 Normal file
View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

31
underwater4k/tex2.glsl_2 Normal file
View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

31
underwater4k/tex2.glsl_3 Normal file
View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

View File

@@ -0,0 +1,31 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
uniform sampler2D V;
float voronoi(vec2 p)
{
return (0.01 + ((.25*texture2D(V, p * 128.0).x) + texture2D(V, p * 32.0).x)) * smoothstep(0.25, 0.35, texture2D(V, p * 11).y * texture2D(V, p * 13).y);
}
float texnoise(vec2 p)
{
return texture2D(V, p).y;
}
float grass(vec2 p)
{
return texnoise(p * 57) * texnoise(p * 13) * 2.0;
}
void main()
{
vec2 x = gl_FragCoord.xy / Z.xy;
float vrn = voronoi(x);
float r = -0.16 + texnoise(x) * 0.3 + mix(grass(x)*.5, vrn, smoothstep(0.0, 0.05,vrn)) * 0.002; // This line creates one entire continent and a big ocean!
gl_FragColor = vec4(r,r,r,1);
}

81
underwater4k/texture.glsl Normal file
View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,81 @@
// Parameters from our host
// x: #sceneid.#scenetime (float)
// y: undefined
// z: Snare drum intensity (amiga ball radius gain)
// w: undefined
uniform vec4 Z;
float rnd(vec2 p)
{
p.x += p.y * 57.;
return sin(cos(p.x) * p.x);
}
float scale;
vec2 hash( vec2 p )
{
p = mod(p, scale);
p = vec2( dot(p,vec2(127.1,311.7)),
dot(p,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(p)*43758.5453123);
}
float noise( in vec2 p, float s )
{
scale = s;
p *= s;
vec2 i = floor( p );
vec2 f = fract( p );
vec2 u = f*f*(3.0-2.0*f);
return mix( mix( dot( hash( i + vec2(0.0,0.0) ), f - vec2(0.0,0.0) ),
dot( hash( i + vec2(1.0,0.0) ), f - vec2(1.0,0.0) ), u.x),
mix( dot( hash( i + vec2(0.0,1.0) ), f - vec2(0.0,1.0) ),
dot( hash( i + vec2(1.0,1.0) ), f - vec2(1.0,1.0) ), u.x), u.y);
}
float voronoi(vec2 p)
{
p = mod(p, 1.0);
float min1 = 1, min2 = 1; float seed = 10; const int numPoints = 256;
for (int i = 0; i < numPoints; ++i)
{
vec2 pointPos = vec2(rnd(vec2(0, seed++)), rnd(vec2(1, seed++)))*.5+.5;
//pointPos += vec2(sin(Z.z+rnd(vec2(0, seed++))), cos(Z.z+rnd(vec2(1, seed++))))*0.1;
vec2 d = abs(p - pointPos);
vec2 s = step(0.5, d);
d = s+d*(-s*2+1);
float dist = length(d);
if (dist < min2)
{
if (dist < min1)
{
min2 = min1;
min1 = dist;
}
else
{
min2 = dist;
}
}
}
//return pow(1.0 - (min2 - min1), 32.0);
return (min2 - min1) * 8.0;
}
void main()
{
vec2 p = gl_FragCoord.xy / Z.xy;
float l = voronoi(p);
float f = 0.5;
float seed = 10.0;
for (float t = 2.0; t <= Z.x; t *= 2.0)
{
f += (0.5 / pow(t, 0.6)) * noise(p,t);
}
gl_FragColor = vec4(l,f,l,1);
}

View File

@@ -0,0 +1,26 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "underwater4k", "underwater4k.vcxproj", "{213903DE-E40A-4D23-9310-E520AC2B412E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Compress_Slow|Win32 = Compress_Slow|Win32
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{213903DE-E40A-4D23-9310-E520AC2B412E}.Compress_Slow|Win32.ActiveCfg = Compress_Slow|Win32
{213903DE-E40A-4D23-9310-E520AC2B412E}.Compress_Slow|Win32.Build.0 = Compress_Slow|Win32
{213903DE-E40A-4D23-9310-E520AC2B412E}.Debug|Win32.ActiveCfg = Debug|Win32
{213903DE-E40A-4D23-9310-E520AC2B412E}.Debug|Win32.Build.0 = Debug|Win32
{213903DE-E40A-4D23-9310-E520AC2B412E}.Release|Win32.ActiveCfg = Release|Win32
{213903DE-E40A-4D23-9310-E520AC2B412E}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(Performance) = preSolution
HasPerformanceSessions = true
EndGlobalSection
EndGlobal

Binary file not shown.

View File

@@ -0,0 +1,250 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Compress_Slow|Win32">
<Configuration>Compress_Slow</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{213903DE-E40A-4D23-9310-E520AC2B412E}</ProjectGuid>
<RootNamespace>bp4k</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>NotSet</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)obj\$(ProjectName)_$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)obj\$(ProjectName)_$(Configuration)\</IntDir>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</GenerateManifest>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">$(SolutionDir)bin\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">$(SolutionDir)obj\$(ProjectName)_$(Configuration)\</IntDir>
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">false</GenerateManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ExecutablePath>$(ProjectDir);$(ExecutablePath)</ExecutablePath>
<TargetName>$(ProjectName)_$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ExecutablePath>$(ProjectDir);$(ExecutablePath)</ExecutablePath>
<TargetName>$(ProjectName)_$(Configuration)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">
<TargetName>$(ProjectName)_$(Configuration)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
</ClCompile>
<Link>
<AdditionalDependencies>4klang.obj;Gdi32.lib;user32.lib;opengl32.lib;winmm.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<EntryPointSymbol>main</EntryPointSymbol>
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<PreBuildEvent>
<Command>rem minify\shader_minifier.exe "mark.fs_0" -o mark_0.h -v --no-renaming
rem minify\shader_minifier.exe "mark.fs_1" -o mark_1.h -v --no-renaming
rem minify\shader_minifier.exe "mark.fs_2" -o mark_2.h -v --no-renaming
rem minify\shader_minifier.exe "mark.fs_0" -o mark_small.h -v
</Command>
</PreBuildEvent>
<ClCompile>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
</ClCompile>
<Link>
<AdditionalDependencies>4klang.obj;Gdi32.lib;user32.lib;opengl32.lib;winmm.lib;libcmt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ManifestFile>
</ManifestFile>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<EntryPointSymbol>main</EntryPointSymbol>
<TargetMachine>MachineX86</TargetMachine>
<LinkErrorReporting>
</LinkErrorReporting>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">
<PreBuildEvent>
<Command>
</Command>
</PreBuildEvent>
<ClCompile>
<AdditionalOptions>/QIfist %(AdditionalOptions)</AdditionalOptions>
<Optimization>MinSpace</Optimization>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<WholeProgramOptimization>false</WholeProgramOptimization>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<FunctionLevelLinking>false</FunctionLevelLinking>
<FloatingPointModel>Fast</FloatingPointModel>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>TurnOffAllWarnings</WarningLevel>
<DebugInformationFormat>
</DebugInformationFormat>
<CallingConvention>StdCall</CallingConvention>
<StringPooling Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</StringPooling>
<StringPooling Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">true</StringPooling>
</ClCompile>
<Link>
<AdditionalOptions>/CRINKLER /COMPMODE:SLOW /ORDERTRIES:4000 /HASHTRIES:300 /UNSAFEIMPORT /TRUNCATEFLOATS:24 /HASHSIZE:200 /REPORT:report.html /RANGE:opengl32 /PROGRESSGUI /TRANSFORM:CALLS %(AdditionalOptions)</AdditionalOptions>
<AdditionalDependencies>4klang.obj;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<ManifestFile>
</ManifestFile>
<GenerateDebugInformation>false</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<LinkTimeCodeGeneration>
</LinkTimeCodeGeneration>
<EntryPointSymbol>main</EntryPointSymbol>
<TargetMachine>MachineX86</TargetMachine>
<LinkErrorReporting>
</LinkErrorReporting>
<SuppressStartupBanner Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</SuppressStartupBanner>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</ImageHasSafeExceptionHandlers>
<DataExecutionPrevention Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</DataExecutionPrevention>
<RandomizedBaseAddress Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</RandomizedBaseAddress>
<IgnoreAllDefaultLibraries Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">true</IgnoreAllDefaultLibraries>
</Link>
<ProjectReference>
<LinkLibraryDependencies Condition="'$(Configuration)|$(Platform)'=='Compress (Slow)|Win32'">false</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="main_release.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="Shaders.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="4klang.h" />
<ClInclude Include="fragment_small.h" />
<ClInclude Include="glext.h" />
<ClInclude Include="va_stdafx.h" />
<CustomBuild Include="release.h">
<Message Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">
</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">
</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">%(Outputs)</Outputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</Message>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalInputs)</AdditionalInputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(Outputs)</Outputs>
</CustomBuild>
<ClInclude Include="Shaders.h" />
<ClInclude Include="small.h" />
</ItemGroup>
<ItemGroup>
<CustomBuild Include="4klang.asm">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">yasm-1.2.0-win32.exe -f win32 -o 4klang.obj 4klang.asm</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">Compiling 4klang...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">4klang.obj</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">yasm-1.2.0-win32.exe -f win32 -o 4klang.obj 4klang.asm</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compiling 4klang...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4klang.obj</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">yasm-1.2.0-win32.exe -f win32 -o 4klang.obj 4klang.asm</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compiling 4klang...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4klang.obj</Outputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">4klang.inc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Compress_Slow|Win32'">4klang.inc</AdditionalInputs>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4klang.inc</AdditionalInputs>
</CustomBuild>
<None Include="4klang.inc" />
<None Include="tex1.glsl" />
<None Include="tex2.glsl">
<FileType>Document</FileType>
</None>
<None Include="fragment.glsl" />
<None Include="vertex.glsl" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<VSPerformanceSession Version="1.00">
<Options>
<Solution>underwater4k.sln</Solution>
<CollectionMethod>Sampling</CollectionMethod>
<AllocationMethod>None</AllocationMethod>
<AddReport>true</AddReport>
<ResourceBasedAnalysisSelected>true</ResourceBasedAnalysisSelected>
<UniqueReport>Timestamp</UniqueReport>
<SamplingMethod>Cycles</SamplingMethod>
<CycleCount>10000000</CycleCount>
<PageFaultCount>10</PageFaultCount>
<SysCallCount>10</SysCallCount>
<SamplingCounter Name="" ReloadValue="00000000000f4240" DisplayName="" />
<RelocateBinaries>false</RelocateBinaries>
<HardwareCounters EnableHWCounters="false" />
<EtwSettings />
<PdhSettings>
<PdhCountersEnabled>false</PdhCountersEnabled>
<PdhCountersRate>500</PdhCountersRate>
<PdhCounters>
<PdhCounter>\Memory\Pages/sec</PdhCounter>
<PdhCounter>\PhysicalDisk(_Total)\Avg. Disk Queue Length</PdhCounter>
<PdhCounter>\Processor(_Total)\% Processor Time</PdhCounter>
</PdhCounters>
</PdhSettings>
</Options>
<ExcludeSmallFuncs>true</ExcludeSmallFuncs>
<InteractionProfilingEnabled>false</InteractionProfilingEnabled>
<JScriptProfilingEnabled>false</JScriptProfilingEnabled>
<PreinstrumentEvent>
<InstrEventExclude>false</InstrEventExclude>
</PreinstrumentEvent>
<PostinstrumentEvent>
<InstrEventExclude>false</InstrEventExclude>
</PostinstrumentEvent>
<Binaries>
<ProjBinary>
<Path>bin\underwater4k_Debug.exe</Path>
<ArgumentTimestamp>01/01/0001 00:00:00</ArgumentTimestamp>
<Instrument>true</Instrument>
<Sample>true</Sample>
<ExternalWebsite>false</ExternalWebsite>
<InteractionProfilingEnabled>false</InteractionProfilingEnabled>
<IsLocalJavascript>false</IsLocalJavascript>
<IsWindowsStoreApp>false</IsWindowsStoreApp>
<IsWWA>false</IsWWA>
<LaunchProject>true</LaunchProject>
<OverrideProjectSettings>false</OverrideProjectSettings>
<LaunchMethod>Executable</LaunchMethod>
<ExecutablePath>bin\underwater4k_Debug.exe</ExecutablePath>
<StartupDirectory>.\</StartupDirectory>
<Arguments>
</Arguments>
<NetAppHost>IIS</NetAppHost>
<NetBrowser>InternetExplorer</NetBrowser>
<ExcludeSmallFuncs>true</ExcludeSmallFuncs>
<JScriptProfilingEnabled>false</JScriptProfilingEnabled>
<PreinstrumentEvent>
<InstrEventExclude>false</InstrEventExclude>
</PreinstrumentEvent>
<PostinstrumentEvent>
<InstrEventExclude>false</InstrEventExclude>
</PostinstrumentEvent>
<ProjRef>{213903DE-E40A-4D23-9310-E520AC2B412E}|underwater4k.vcxproj</ProjRef>
<ProjPath>underwater4k.vcxproj</ProjPath>
<ProjName>underwater4k</ProjName>
</ProjBinary>
</Binaries>
<Reports>
<Report>
<Path>underwater4k_Debug130816.vsp</Path>
</Report>
</Reports>
<Launches>
<ProjBinary>
<Path>:PB:{213903DE-E40A-4D23-9310-E520AC2B412E}|underwater4k.vcxproj</Path>
</ProjBinary>
</Launches>
</VSPerformanceSession>

Binary file not shown.

101
underwater4k/va_stdafx.h Normal file
View File

@@ -0,0 +1,101 @@
#define @0
#define @1
#define @2
#define @3
#define @@
#define uniform
#define varying
struct vec2
{
vec2(double t) {};
vec2(double x, double y) {};
double x;
double y;
vec2 operator + (vec2);
vec2 operator - (vec2);
vec2 operator * (vec2);
vec2 operator / (vec2);
vec2 operator + (double);
vec2 operator - (double);
vec2 operator * (double);
vec2 operator / (double);
friend vec2 operator +(double, vec2);
friend vec2 operator -(double, vec2);
friend vec2 operator *(double, vec2);
friend vec2 operator /(double, vec2);
void operator += (double);
void operator -= (double);
void operator *= (double);
void operator /= (double);
void operator += (vec2);
void operator -= (vec2);
void operator *= (vec2);
void operator /= (vec2);
};
struct vec3
{
vec3(double t) {};
vec3(double x, double y, double z) {};
double x;
double y;
double z;
vec3 operator + (vec3);
vec3 operator - (vec3);
vec3 operator * (vec3);
vec3 operator / (vec3);
vec3 operator + (double);
vec3 operator - (double);
vec3 operator * (double);
vec3 operator / (double);
friend vec3 operator +(double, vec3);
friend vec3 operator -(double, vec3);
friend vec3 operator *(double, vec3);
friend vec3 operator /(double, vec3);
void operator += (double);
void operator -= (double);
void operator *= (double);
void operator /= (double);
void operator += (vec3);
void operator -= (vec3);
void operator *= (vec3);
void operator /= (vec3);
};
struct vec4
{
vec4(double t) {};
vec4(double x, double y, double z, double w) {};
double x;
double y;
double z;
double w;
vec4 operator + (vec4);
vec4 operator - (vec4);
vec4 operator * (vec4);
vec4 operator / (vec4);
vec4 operator + (double);
vec4 operator - (double);
vec4 operator * (double);
vec4 operator / (double);
friend vec4 operator +(double, vec4);
friend vec4 operator -(double, vec4);
friend vec4 operator *(double, vec4);
friend vec4 operator /(double, vec4);
void operator += (double);
void operator -= (double);
void operator *= (double);
void operator /= (double);
void operator += (vec4);
void operator -= (vec4);
void operator *= (vec4);
void operator /= (vec4);
};
typedef double sampler2D;
vec4 texture2D(sampler2D t, vec2 uv);
template <typename T> T mix(T a, T b, double c);
template <typename T> T mod(T a, double b);
template <typename T> T fract(T a);
template <typename T> T step(double b, T a);
template <typename T> T smoothstep(double a, double b, T a);

9
underwater4k/vertex.glsl Normal file
View File

@@ -0,0 +1,9 @@
varying vec4 Y;
varying vec2 Z;
void main()
{
Y = gl_Color;
Z = (gl_Vertex.xy*vec2(1.7777,1.0))*0.5+0.5;
gl_Position = gl_Vertex;
}

Binary file not shown.