v4k initial commit
|
@ -0,0 +1,7 @@
|
||||||
|
.art*.zip
|
||||||
|
__pycache__
|
||||||
|
.vs
|
||||||
|
emsdk
|
||||||
|
demos/html5/*.data
|
||||||
|
demos/html5/*.js
|
||||||
|
demos/html5/*.html
|
211
MAKE.bat
|
@ -13,14 +13,14 @@ cd `dirname $0`
|
||||||
# tidy environment
|
# tidy environment
|
||||||
if [ "$1" = "tidy" ]; then
|
if [ "$1" = "tidy" ]; then
|
||||||
rm 0?-* 2> /dev/null
|
rm 0?-* 2> /dev/null
|
||||||
rm fwk.o 2> /dev/null
|
rm v4k.o 2> /dev/null
|
||||||
rm .art*.zip 2> /dev/null
|
rm .art*.zip 2> /dev/null
|
||||||
rm demos/lua/.art*.zip 2> /dev/null
|
rm engine/bind/.art*.zip 2> /dev/null
|
||||||
rm demos/html5/.art*.zip 2> /dev/null
|
rm demos/html5/.art*.zip 2> /dev/null
|
||||||
rm demos/lua/libfwk* 2> /dev/null
|
rm engine/bind/libv4k* 2> /dev/null
|
||||||
rm fwk_*.* 2> /dev/null
|
rm v4k_*.* 2> /dev/null
|
||||||
rm 3rd_*.* 2> /dev/null
|
rm 3rd_*.* 2> /dev/null
|
||||||
rm libfwk* 2> /dev/null
|
rm libv4k* 2> /dev/null
|
||||||
rm -rf *.dSYM 2> /dev/null
|
rm -rf *.dSYM 2> /dev/null
|
||||||
rm *.png 2> /dev/null
|
rm *.png 2> /dev/null
|
||||||
rm *.mp4 2> /dev/null
|
rm *.mp4 2> /dev/null
|
||||||
|
@ -38,6 +38,11 @@ if [ "$1" = "join" ]; then
|
||||||
sh tools/join.bat
|
sh tools/join.bat
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
if [ "$1" = "prep" ]; then
|
||||||
|
sh MAKE.bat join
|
||||||
|
sh MAKE.bat amalgamation
|
||||||
|
exit
|
||||||
|
fi
|
||||||
# cook
|
# cook
|
||||||
if [ "$1" = "cook" ]; then
|
if [ "$1" = "cook" ]; then
|
||||||
cc -o cook tools/cook.c -I.
|
cc -o cook tools/cook.c -I.
|
||||||
|
@ -62,6 +67,8 @@ while [ $# -ge 1 ]; do
|
||||||
echo sh MAKE.bat [gcc,clang,tcc] [dbg,dev,rel] [dll,static]
|
echo sh MAKE.bat [gcc,clang,tcc] [dbg,dev,rel] [dll,static]
|
||||||
echo sh MAKE.bat [tidy]
|
echo sh MAKE.bat [tidy]
|
||||||
echo sh MAKE.bat [split,join]
|
echo sh MAKE.bat [split,join]
|
||||||
|
echo sh MAKE.bat [amalgamation]
|
||||||
|
echo sh MAKE.bat [prep]
|
||||||
echo sh MAKE.bat [cook]
|
echo sh MAKE.bat [cook]
|
||||||
echo sh MAKE.bat [sln]
|
echo sh MAKE.bat [sln]
|
||||||
exit
|
exit
|
||||||
|
@ -147,19 +154,19 @@ if [ "$(uname)" != "Darwin" ]; then
|
||||||
chmod +x tools/xlsx2ini.linux
|
chmod +x tools/xlsx2ini.linux
|
||||||
chmod +x tools/premake5.linux
|
chmod +x tools/premake5.linux
|
||||||
chmod +x tools/ninja.linux
|
chmod +x tools/ninja.linux
|
||||||
chmod +x demos/lua/luajit.linux
|
chmod +x engine/bind/luajit.linux
|
||||||
|
|
||||||
echo build=$build, type=$dll, cc=$cc, args=$args
|
echo build=$build, type=$dll, cc=$cc, args=$args
|
||||||
|
|
||||||
# framework (as dynamic library)
|
# framework (as dynamic library)
|
||||||
if [ "$dll" = "dll" ]; then
|
if [ "$dll" = "dll" ]; then
|
||||||
echo libfwk.so && $cc -o libfwk.so engine/fwk.c -shared -fPIC -w -lX11 -lm -ldl -lpthread $flags $args
|
echo libv4k.so && $cc -o libv4k.so engine/v4k.c -shared -fPIC -w -lX11 -lm -ldl -lpthread $flags $args
|
||||||
cp libfwk.so demos/lua/
|
cp libv4k.so engine/bind/
|
||||||
export import="libfwk.so -Wl,-rpath,./"
|
export import="libv4k.so -Wl,-rpath,./"
|
||||||
else
|
else
|
||||||
# framework (static)
|
# framework (static)
|
||||||
echo fwk && $cc -c engine/fwk.c -w $flags $args
|
echo v4k && $cc -c engine/v4k.c -w $flags $args
|
||||||
export import=fwk.o
|
export import=v4k.o
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# editor
|
# editor
|
||||||
|
@ -202,19 +209,19 @@ if [ "$(uname)" = "Darwin" ]; then
|
||||||
chmod +x tools/xlsx2ini.osx
|
chmod +x tools/xlsx2ini.osx
|
||||||
chmod +x tools/premake5.osx
|
chmod +x tools/premake5.osx
|
||||||
chmod +x tools/ninja.osx
|
chmod +x tools/ninja.osx
|
||||||
chmod +x demos/lua/luajit.osx
|
chmod +x engine/bind/luajit.osx
|
||||||
|
|
||||||
echo build=$build, type=$dll, cc=$cc, args=$args
|
echo build=$build, type=$dll, cc=$cc, args=$args
|
||||||
|
|
||||||
# framework (as dynamic library)
|
# framework (as dynamic library)
|
||||||
if [ "$dll" = "dll" ]; then
|
if [ "$dll" = "dll" ]; then
|
||||||
echo libfwk && cc -ObjC -dynamiclib -o libfwk.dylib engine/fwk.c -framework cocoa -framework iokit -framework audiotoolbox -w $flags $args
|
echo libv4k && cc -ObjC -dynamiclib -o libv4k.dylib engine/v4k.c -framework cocoa -framework iokit -framework audiotoolbox -w $flags $args
|
||||||
cp libfwk.dylib demos/lua
|
cp libv4k.dylib engine/bind
|
||||||
export import=libfwk.dylib
|
export import=libv4k.dylib
|
||||||
else
|
else
|
||||||
# framework
|
# framework
|
||||||
echo fwk && cc -c -ObjC engine/fwk.c -w $flags $args
|
echo v4k && cc -c -ObjC engine/v4k.c -w $flags $args
|
||||||
export import=fwk.o
|
export import=v4k.o
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# editor
|
# editor
|
||||||
|
@ -253,13 +260,17 @@ if "%1"=="help" (
|
||||||
echo %0 [docs] ; generate tools/docs/docs.html file
|
echo %0 [docs] ; generate tools/docs/docs.html file
|
||||||
echo %0 [cook] ; cook .zipfiles with tools/cook.ini cookbook
|
echo %0 [cook] ; cook .zipfiles with tools/cook.ini cookbook
|
||||||
echo %0 [sync] ; sync repo to latest
|
echo %0 [sync] ; sync repo to latest
|
||||||
|
echo %0 [pull] ; pull changes from 'latest' upstream
|
||||||
|
echo %0 [git] ; prepare for commit
|
||||||
|
echo %0 [push] ; prepare for commit, stage changes and commit them
|
||||||
echo %0 [tidy] ; clean up temp files
|
echo %0 [tidy] ; clean up temp files
|
||||||
echo %0 [bindings] ; generate demos/lua bindings
|
echo %0 [bind] ; generate lua bindings
|
||||||
echo %0 [checkmem] ; check untracked allocators in FWK
|
echo %0 [checkmem] ; check untracked allocators in V4K
|
||||||
echo %0 [split^|join] ; engine/fwk* ^>split^> engine/split/* or engine/split/* ^>join^> engine/fwk*
|
echo %0 [split^|join] ; engine/v4k* ^>split^> engine/split/* or engine/split/* ^>join^> engine/v4k*
|
||||||
echo %0 [amalgamation] ; combine engine/fwk* into a single-header file
|
echo %0 [amalgamation] ; combine engine/v4k* into a single-header file
|
||||||
|
echo %0 [prep] ; combine split files into a single-header file, ready for use
|
||||||
echo %0 [sln] ; generate a xcode/gmake/ninja/visual studio solution
|
echo %0 [sln] ; generate a xcode/gmake/ninja/visual studio solution
|
||||||
echo %0 [cl^|tcc^|cc^|gcc^|clang^|clang-cl] [dbg^|dev^|rel] [static^|dll] [nofwk^|nodemos^|noeditor] [vis] [-- args]
|
echo %0 [cl^|tcc^|cc^|gcc^|clang^|clang-cl] [dbg^|dev^|rel] [static^|dll] [nov4k^|nodemos^|editor] [vis] [-- args]
|
||||||
echo cl \
|
echo cl \
|
||||||
echo tcc ^|
|
echo tcc ^|
|
||||||
echo cc ^| select compiler. must be accessible in PATH
|
echo cc ^| select compiler. must be accessible in PATH
|
||||||
|
@ -269,11 +280,11 @@ if "%1"=="help" (
|
||||||
echo dbg \ debug build: [x] ASAN [x] poison [x] asserts [x] profiler [x] symbols [ ] zero optimizations
|
echo dbg \ debug build: [x] ASAN [x] poison [x] asserts [x] profiler [x] symbols [ ] zero optimizations
|
||||||
echo dev ^| develop build: [ ] ASAN [x] poison [x] asserts [x] profiler [x] symbols [*] some optimizations (default^)
|
echo dev ^| develop build: [ ] ASAN [x] poison [x] asserts [x] profiler [x] symbols [*] some optimizations (default^)
|
||||||
echo rel / release build: [ ] ASAN [ ] poison [ ] asserts [ ] profiler [x] symbols (cl,clang-cl only^) [x] many optimizations
|
echo rel / release build: [ ] ASAN [ ] poison [ ] asserts [ ] profiler [x] symbols (cl,clang-cl only^) [x] many optimizations
|
||||||
echo static \ link fwk as static library
|
echo static \ link v4k as static library
|
||||||
echo dll / link fwk as dynamic library (dll^) (default^)
|
echo dll / link v4k as dynamic library (dll^) (default^)
|
||||||
echo nofwk \ do not compile framework
|
echo nov4k \ do not compile framework
|
||||||
echo nodemos ^| do not compile demos
|
echo nodemos ^| do not compile demos
|
||||||
echo noeditor / do not compile editor
|
echo editor / do compile editor
|
||||||
echo vis ^> visualize invokation cmdline.
|
echo vis ^> visualize invokation cmdline.
|
||||||
echo args ^> after `--` separator is found, pass all remaining arguments to compiler as-is
|
echo args ^> after `--` separator is found, pass all remaining arguments to compiler as-is
|
||||||
echo.
|
echo.
|
||||||
|
@ -290,18 +301,18 @@ if "%1"=="sync" (
|
||||||
rem cook asset files
|
rem cook asset files
|
||||||
if "%1"=="cook" (
|
if "%1"=="cook" (
|
||||||
rem generate cooker twice: use multi-threaded version if available (cl). then cook.
|
rem generate cooker twice: use multi-threaded version if available (cl). then cook.
|
||||||
rem call tools\tcc tools\cook.c -Iengine engine\fwk.c
|
rem call tools\tcc tools\cook.c -Iengine engine\v4k.c
|
||||||
rem cl tools\cook.c -Iengine engine\fwk.c
|
rem cl tools\cook.c -Iengine engine\v4k.c
|
||||||
rem cook
|
rem cook
|
||||||
tools\cook
|
tools\cook
|
||||||
|
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
rem generate bindings
|
rem generate bindings
|
||||||
if "%1"=="bindings" (
|
if "%1"=="bind" (
|
||||||
rem luajit
|
rem luajit
|
||||||
tools\luajit tools\luajit_make_bindings.lua > fwk.lua
|
tools\luajit tools\luajit_make_bindings.lua > v4k.lua
|
||||||
move /y fwk.lua demos\lua
|
move /y v4k.lua engine\bind
|
||||||
|
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
@ -318,45 +329,45 @@ if "%1"=="docs" (
|
||||||
set /p LAST_MODIFIED=<info.obj
|
set /p LAST_MODIFIED=<info.obj
|
||||||
|
|
||||||
rem ...and generate docs
|
rem ...and generate docs
|
||||||
cl tools\docs\docs.c engine\fwk.c -Iengine %2
|
cl tools\docs\docs.c engine\v4k.c -Iengine %2
|
||||||
docs engine\fwk.h --excluded=3rd_glad.h,fwk.h,fwk_compat.h, > fwk.html
|
docs engine\v4k.h --excluded=3rd_glad.h,v4k.h,v4k_compat.h, > v4k.html
|
||||||
move /y fwk.html engine\
|
move /y v4k.html engine\
|
||||||
|
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
rem generate single-header distribution
|
rem generate single-header distribution
|
||||||
if "%1"=="amalgamation" (
|
if "%1"=="amalgamation" (
|
||||||
echo // This file is intended to be consumed by a compiler. Do not read. > fwk.h
|
echo // This file is intended to be consumed by a compiler. Do not read. > v4k.h
|
||||||
echo // **Browse to any of the sources in engine/split/ folder instead** >> fwk.h
|
echo // **Browse to any of the sources in engine/split/ folder instead** >> v4k.h
|
||||||
echo // ---------------------------------------------------------------- >> fwk.h
|
echo // ---------------------------------------------------------------- >> v4k.h
|
||||||
echo // #define FWK_IMPLEMENTATION early in **one** C file to unroll the >> fwk.h
|
echo // #define V4K_IMPLEMENTATION early in **one** C file to unroll the >> v4k.h
|
||||||
echo // implementation. The symbol must be defined in a C (not C++^) file>> fwk.h
|
echo // implementation. The symbol must be defined in a C (not C++^) file>> v4k.h
|
||||||
echo // ---------------------------------------------------------------- >> fwk.h
|
echo // ---------------------------------------------------------------- >> v4k.h
|
||||||
echo #pragma once >> fwk.h
|
echo #pragma once >> v4k.h
|
||||||
type engine\split\3rd_font_md.h >> fwk.h
|
type engine\split\3rd_font_md.h >> v4k.h
|
||||||
type engine\split\3rd_glad.h >> fwk.h
|
type engine\split\3rd_glad.h >> v4k.h
|
||||||
type engine\fwk.h >> fwk.h
|
type engine\v4k.h >> v4k.h
|
||||||
echo #ifdef FWK_IMPLEMENTATION >> fwk.h
|
echo #ifdef V4K_IMPLEMENTATION >> v4k.h
|
||||||
echo #define FWK_3RD >> fwk.h
|
echo #define V4K_3RD >> v4k.h
|
||||||
type engine\fwk >> fwk.h
|
type engine\v4k >> v4k.h
|
||||||
type engine\fwk.c >> fwk.h
|
type engine\v4k.c >> v4k.h
|
||||||
echo #endif // FWK_IMPLEMENTATION >> fwk.h
|
echo #endif // V4K_IMPLEMENTATION >> v4k.h
|
||||||
move /y fwk.h engine\joint
|
move /y v4k.h engine\joint
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
rem generate prior files to a github release
|
rem generate prior files to a git release
|
||||||
if "%1"=="github" (
|
if "%1"=="git" (
|
||||||
rem call make.bat dll
|
rem call make.bat dll
|
||||||
call make.bat docs
|
call make.bat docs
|
||||||
call make.bat bindings
|
call make.bat bind
|
||||||
|
|
||||||
call make.bat amalgamation
|
call make.bat amalgamation
|
||||||
call make.bat split
|
call make.bat split
|
||||||
|
|
||||||
rem rd /q /s engine\split
|
rem rd /q /s engine\split
|
||||||
rem md engine\split
|
rem md engine\split
|
||||||
rem move /y fwk_*.? engine\split\
|
rem move /y v4k_*.? engine\split\
|
||||||
rem move /y 3rd_*.? engine\split\
|
rem move /y 3rd_*.? engine\split\
|
||||||
|
|
||||||
call make.bat tidy
|
call make.bat tidy
|
||||||
|
@ -364,6 +375,28 @@ rem move /y 3rd_*.? engine\split\
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if "%1"=="pull" (
|
||||||
|
git fetch v4k
|
||||||
|
git merge -Xrename-threshold=50 v4k/main
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1"=="push" (
|
||||||
|
call make.bat tidy
|
||||||
|
|
||||||
|
git status
|
||||||
|
git add .
|
||||||
|
git commit
|
||||||
|
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1"=="prep" (
|
||||||
|
call make.bat join
|
||||||
|
call make.bat amalgamation
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
rem shortcuts for split & join amalgamation scripts
|
rem shortcuts for split & join amalgamation scripts
|
||||||
if "%1"=="split" (
|
if "%1"=="split" (
|
||||||
call tools\split
|
call tools\split
|
||||||
|
@ -376,11 +409,19 @@ if "%1"=="join" (
|
||||||
|
|
||||||
rem check memory api calls
|
rem check memory api calls
|
||||||
if "%1"=="checkmem" (
|
if "%1"=="checkmem" (
|
||||||
findstr /RNC:"[^_xv]realloc[(]" engine\fwk.c engine\split\fwk*
|
findstr /RNC:"[^_xv]realloc[(]" engine\v4k.c engine\split\v4k*
|
||||||
findstr /RNC:"[^_xv]malloc[(]" engine\fwk.c engine\split\fwk*
|
findstr /RNC:"[^_xv]xrealloc[(]" engine\v4k.c engine\split\v4k*
|
||||||
findstr /RNC:"[^_xv]free[(]" engine\fwk.c engine\split\fwk*
|
findstr /RNC:"[^_xv]malloc[(]" engine\v4k.c engine\split\v4k*
|
||||||
findstr /RNC:"[^_xv]calloc[(]" engine\fwk.c engine\split\fwk*
|
findstr /RNC:"[^_xv]free[(]" engine\v4k.c engine\split\v4k*
|
||||||
findstr /RNC:"[^_xv]strdup[(]" engine\fwk.c engine\split\fwk*
|
findstr /RNC:"[^_xv]calloc[(]" engine\v4k.c engine\split\v4k*
|
||||||
|
findstr /RNC:"[^_xv]strdup[(]" engine\v4k.c engine\split\v4k*
|
||||||
|
exit /b
|
||||||
|
)
|
||||||
|
|
||||||
|
if "%1"=="html5" (
|
||||||
|
pushd demos\html5
|
||||||
|
call make.bat %2
|
||||||
|
popd
|
||||||
exit /b
|
exit /b
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -391,7 +432,7 @@ rem tidy environment
|
||||||
if "%1"=="tidy" (
|
if "%1"=="tidy" (
|
||||||
move /y ??-*.png demos > nul 2> nul
|
move /y ??-*.png demos > nul 2> nul
|
||||||
move /y ??-*.c demos > nul 2> nul
|
move /y ??-*.c demos > nul 2> nul
|
||||||
del demos\lua\fwk.dll > nul 2> nul
|
del engine\bind\v4k.dll > nul 2> nul
|
||||||
del .temp*.* > nul 2> nul
|
del .temp*.* > nul 2> nul
|
||||||
del *.zip > nul 2> nul
|
del *.zip > nul 2> nul
|
||||||
del *.mem > nul 2> nul
|
del *.mem > nul 2> nul
|
||||||
|
@ -408,7 +449,7 @@ if "%1"=="tidy" (
|
||||||
del *.def > nul 2> nul
|
del *.def > nul 2> nul
|
||||||
del *.dll > nul 2> nul
|
del *.dll > nul 2> nul
|
||||||
del 3rd_*.* > nul 2> nul
|
del 3rd_*.* > nul 2> nul
|
||||||
del fwk_*.* > nul 2> nul
|
del v4k_*.* > nul 2> nul
|
||||||
rem del ??-*.* > nul 2> nul
|
rem del ??-*.* > nul 2> nul
|
||||||
del temp_*.* > nul 2> nul
|
del temp_*.* > nul 2> nul
|
||||||
rd /q /s .vs > nul 2> nul
|
rd /q /s .vs > nul 2> nul
|
||||||
|
@ -426,9 +467,9 @@ set dll=dll
|
||||||
set build=dev
|
set build=dev
|
||||||
set args=-Iengine
|
set args=-Iengine
|
||||||
set other=
|
set other=
|
||||||
set fwk=yes
|
set v4k=yes
|
||||||
set demos=yes
|
set demos=yes
|
||||||
set editor=yes
|
set editor=no
|
||||||
set vis=no
|
set vis=no
|
||||||
set sln=no
|
set sln=no
|
||||||
set rc=0
|
set rc=0
|
||||||
|
@ -452,9 +493,10 @@ set rc=0
|
||||||
|
|
||||||
if "%1"=="vis" set "vis=yes" && goto loop
|
if "%1"=="vis" set "vis=yes" && goto loop
|
||||||
|
|
||||||
if "%1"=="nofwk" set "fwk=no" && goto loop
|
if "%1"=="nov4k" set "v4k=no" && goto loop
|
||||||
if "%1"=="nodemos" set "demos=no" && goto loop
|
if "%1"=="nodemos" set "demos=no" && goto loop
|
||||||
if "%1"=="noeditor" set "editor=no" && goto loop
|
if "%1"=="noeditor" set "editor=no" && goto loop
|
||||||
|
if "%1"=="editor" set "editor=yes" && goto loop
|
||||||
|
|
||||||
if "%1"=="tcc" set "cc=%1" && goto loop
|
if "%1"=="tcc" set "cc=%1" && goto loop
|
||||||
if "%1"=="cl" set "cc=%1" && goto loop
|
if "%1"=="cl" set "cc=%1" && goto loop
|
||||||
|
@ -530,10 +572,10 @@ if "!cc!"=="cl" (
|
||||||
|
|
||||||
if "!dll!"=="static" (
|
if "!dll!"=="static" (
|
||||||
set export=/c
|
set export=/c
|
||||||
set import=fwk.obj
|
set import=v4k.obj
|
||||||
) else (
|
) else (
|
||||||
set export=/DAPI=EXPORT /LD
|
set export=/DAPI=EXPORT /LD
|
||||||
set import=/DAPI=IMPORT fwk.lib
|
set import=/DAPI=IMPORT v4k.lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if "!build!"=="rel" (
|
if "!build!"=="rel" (
|
||||||
|
@ -554,15 +596,15 @@ if "!cc!"=="cl" (
|
||||||
|
|
||||||
if "!dll!"=="static" (
|
if "!dll!"=="static" (
|
||||||
set export=/c
|
set export=/c
|
||||||
set import=fwk.obj
|
set import=v4k.obj
|
||||||
) else (
|
) else (
|
||||||
set export=/DAPI=EXPORT /LD
|
set export=/DAPI=EXPORT /LD
|
||||||
set import=/DAPI=IMPORT fwk.lib
|
set import=/DAPI=IMPORT v4k.lib
|
||||||
)
|
)
|
||||||
|
|
||||||
set warnings_fwkc=-Wno-deprecated-declarations -Wno-tautological-constant-out-of-range-compare
|
set warnings_v4kc=-Wno-deprecated-declarations -Wno-tautological-constant-out-of-range-compare
|
||||||
set warnings_demos=-Wno-empty-body -Wno-format-security -Wno-pointer-sign
|
set warnings_demos=-Wno-empty-body -Wno-format-security -Wno-pointer-sign
|
||||||
set warnings=!warnings_fwkc! !warnings_demos!
|
set warnings=!warnings_v4kc! !warnings_demos!
|
||||||
|
|
||||||
if "!build!"=="rel" (
|
if "!build!"=="rel" (
|
||||||
set args=!warnings! /nologo /Zi /MT /openmp /DNDEBUG !args! /Os /Ox /O2 /Oy /GF /Gw /arch:AVX2
|
set args=!warnings! /nologo /Zi /MT /openmp /DNDEBUG !args! /Os /Ox /O2 /Oy /GF /Gw /arch:AVX2
|
||||||
|
@ -581,10 +623,10 @@ if "!cc!"=="cl" (
|
||||||
|
|
||||||
if "!dll!"=="static" (
|
if "!dll!"=="static" (
|
||||||
set export=-c
|
set export=-c
|
||||||
set import=fwk.o
|
set import=v4k.o
|
||||||
) else (
|
) else (
|
||||||
set export=-DAPI=EXPORT -shared
|
set export=-DAPI=EXPORT -shared
|
||||||
set import=-DAPI=IMPORT fwk.def
|
set import=-DAPI=IMPORT v4k.def
|
||||||
)
|
)
|
||||||
|
|
||||||
if "!build!"=="rel" (
|
if "!build!"=="rel" (
|
||||||
|
@ -606,10 +648,10 @@ if "!cc!"=="cl" (
|
||||||
|
|
||||||
if "!dll!"=="static" (
|
if "!dll!"=="static" (
|
||||||
set export=-c
|
set export=-c
|
||||||
set import=fwk.o !libs! -Wl,--allow-multiple-definition
|
set import=v4k.o !libs! -Wl,--allow-multiple-definition
|
||||||
) else (
|
) else (
|
||||||
set export=-DAPI=EXPORT -shared -o fwk.dll !libs! -Wl,--out-implib,fwk.a
|
set export=-DAPI=EXPORT -shared -o v4k.dll !libs! -Wl,--out-implib,v4k.a
|
||||||
set import=-DAPI=IMPORT fwk.a
|
set import=-DAPI=IMPORT v4k.a
|
||||||
)
|
)
|
||||||
|
|
||||||
set args=-Wno-implicit-function-declaration !args!
|
set args=-Wno-implicit-function-declaration !args!
|
||||||
|
@ -635,31 +677,34 @@ echo import=!import!, export=!export!
|
||||||
if "!cc!"=="tcc" set "cc=call tools\tcc"
|
if "!cc!"=="tcc" set "cc=call tools\tcc"
|
||||||
|
|
||||||
rem detect wether user-defined sources use single-header distro
|
rem detect wether user-defined sources use single-header distro
|
||||||
rem if so, remove API=IMPORT flags and also do not produce fwk.dll by default
|
rem if so, remove API=IMPORT flags and also do not produce v4k.dll by default
|
||||||
if not "!other!"=="" (
|
if not "!other!"=="" (
|
||||||
>nul find "FWK_IMPLEMENTATION" !other! && (
|
>nul find "V4K_IMPLEMENTATION" !other! && (
|
||||||
set import=
|
set import=
|
||||||
set fwk=no
|
set v4k=no
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
rem framework
|
rem framework
|
||||||
if "!fwk!"=="yes" (
|
if "!v4k!"=="yes" (
|
||||||
if "!vis!"=="yes" echo !cc! engine\fwk.c !export! !args! ^&^& if "!dll!"=="dll" copy /y fwk.dll demos\lua ^> nul
|
if "!vis!"=="yes" echo !cc! engine\v4k.c !export! !args! ^&^& if "!dll!"=="dll" copy /y v4k.dll engine\bind ^> nul
|
||||||
!echo! fwk && !cc! engine\fwk.c !export! !args! && if "!dll!"=="dll" copy /y fwk.dll demos\lua > nul || set rc=1
|
!echo! v4k && !cc! engine\v4k.c !export! !args! && if "!dll!"=="dll" copy /y v4k.dll engine\bind > nul || set rc=1
|
||||||
)
|
)
|
||||||
|
|
||||||
rem editor
|
rem editor
|
||||||
if "!editor!"=="yes" (
|
if "!editor!"=="yes" (
|
||||||
set edit=-DCOOK_ON_DEMAND -DUI_LESSER_SPACING -DUI_ICONS_SMALL
|
set edit=-DCOOK_ON_DEMAND -DUI_LESSER_SPACING -DUI_ICONS_SMALL
|
||||||
if "!vis!"=="yes" echo !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args!
|
if "!vis!"=="yes" echo !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args!
|
||||||
rem !echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1
|
!echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1
|
||||||
rem !echo! editor2 && !cc! !o! editor2.exe tools\editor\editor2.c !edit! !args! || set rc=1
|
!echo! editor2 && !cc! !o! editor2.exe tools\editor\editor2.c !edit! !args! || set rc=1
|
||||||
)
|
)
|
||||||
|
|
||||||
rem demos
|
rem demos
|
||||||
if "!demos!"=="yes" (
|
if "!demos!"=="yes" (
|
||||||
!echo! hello && !cc! !o! hello.exe hello.c !args! || set rc=1
|
!echo! hello && !cc! !o! hello.exe hello.c !args! || set rc=1
|
||||||
|
!echo! 99-syncdemo && !cc! !o! 99-syncdemo.exe demos\99-syncdemo.c !import! !args! || set rc=1
|
||||||
|
!echo! 99-shadertoy && !cc! !o! 99-shadertoy.exe demos\99-shadertoy.c !import! !args! || set rc=1
|
||||||
|
!echo! 99-material && !cc! !o! 99-material.exe demos\99-material.c !import! !args! || set rc=1
|
||||||
rem !echo! 00-ui && !cc! !o! 00-ui.exe demos\00-ui.c !import! !args! || set rc=1
|
rem !echo! 00-ui && !cc! !o! 00-ui.exe demos\00-ui.c !import! !args! || set rc=1
|
||||||
rem !echo! 01-sprite && !cc! !o! 01-sprite.exe demos\01-sprite.c !import! !args! || set rc=1
|
rem !echo! 01-sprite && !cc! !o! 01-sprite.exe demos\01-sprite.c !import! !args! || set rc=1
|
||||||
rem !echo! 02-ddraw && !cc! !o! 02-ddraw.exe demos\02-ddraw.c !import! !args! || set rc=1
|
rem !echo! 02-ddraw && !cc! !o! 02-ddraw.exe demos\02-ddraw.c !import! !args! || set rc=1
|
||||||
|
|
237
README.md
|
@ -1,19 +1,11 @@
|
||||||
<h1 align="center"><a href="https://bit.ly/-f-w-k-">F·W·K</a></h1>
|
<h1 align="center">V·4·K</h1>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
3D game framework in C.<br/>
|
3D game engine/framework in C, with Luajit and Python bindings.<br/>
|
||||||
</p>
|
|
||||||
|
|
||||||
<p align="center">
|
|
||||||
<img src="https://i.imgur.com/sInbRoA.gif"/><br/>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
- [x] ~~C++~~. C.
|
- [x] ~~Full featured~~, ~~Fast~~, ~~Modern C++~~. Small, Naive, Simple C.
|
||||||
- [x] ~~Fast~~. Naive.
|
- [x] ~~Rich build system~~, ~~Royaltie fee~~. Single file, Freely unlicensed.
|
||||||
- [x] ~~Modern~~. Simple.
|
|
||||||
- [x] ~~Full featured~~. Small.
|
|
||||||
- [x] ~~Rich build system~~. Single file.
|
|
||||||
- [x] ~~Royaltie fee~~. Free and unlicensed.
|
|
||||||
|
|
||||||
## Features ᕦ(ᐛ)ᕤ
|
## Features ᕦ(ᐛ)ᕤ
|
||||||
- [x] Pipeline: configurable and integrated [asset pipeline](tools/cook.ini).
|
- [x] Pipeline: configurable and integrated [asset pipeline](tools/cook.ini).
|
||||||
|
@ -38,7 +30,7 @@
|
||||||
- [x] Audio: WAV/FLAC, OGG/MP1/MP3, FUR, MOD/XM/S3M/IT, SFXR and MID+SF2/SF3.
|
- [x] Audio: WAV/FLAC, OGG/MP1/MP3, FUR, MOD/XM/S3M/IT, SFXR and MID+SF2/SF3.
|
||||||
- [x] Video: MP4, MPG, OGV, MKV, WMV and AVI. Also, MP4 recording with MPEG-1 fallback.
|
- [x] Video: MP4, MPG, OGV, MKV, WMV and AVI. Also, MP4 recording with MPEG-1 fallback.
|
||||||
- [x] Model: IQM/E, GLTF/2, GLB, FBX, OBJ, DAE, BLEND, MD3/5, MS3D, SMD, X, 3DS, BVH, DXF, LWO.
|
- [x] Model: IQM/E, GLTF/2, GLB, FBX, OBJ, DAE, BLEND, MD3/5, MS3D, SMD, X, 3DS, BVH, DXF, LWO.
|
||||||
- [x] Render: PBR (metallic-roughness) workflow. <!-- @todo: merge demo_pbr.c rendering code into fwk_render.c -->
|
- [x] Render: PBR (metallic-roughness) workflow. <!-- @todo: merge demo_pbr.c rendering code into v4k_render.c -->
|
||||||
- [x] Render: Cubemaps, panoramas and spherical harmonics. Rayleigh/Mie scattering.
|
- [x] Render: Cubemaps, panoramas and spherical harmonics. Rayleigh/Mie scattering.
|
||||||
- [x] Render: Post-effects (SSAO,FXAA1/3,CRT,Contrast,Grain,Outline,Vignette...).
|
- [x] Render: Post-effects (SSAO,FXAA1/3,CRT,Contrast,Grain,Outline,Vignette...).
|
||||||
- [x] Render: 3D Anims, skeletal anims, hardware skinning and instanced rendering.
|
- [x] Render: 3D Anims, skeletal anims, hardware skinning and instanced rendering.
|
||||||
|
@ -52,25 +44,36 @@
|
||||||
- [x] Scene handling.
|
- [x] Scene handling.
|
||||||
- [x] Profiler, stats and leaks finder.
|
- [x] Profiler, stats and leaks finder.
|
||||||
- [x] [Editor (wip)](https://user-images.githubusercontent.com/35402248/174457347-f787a6a2-aac8-404c-a5da-f44310c3d432.mp4).
|
- [x] [Editor (wip)](https://user-images.githubusercontent.com/35402248/174457347-f787a6a2-aac8-404c-a5da-f44310c3d432.mp4).
|
||||||
- [x] [Documentation (wip)](https://bit.ly/-f-w-k-).
|
- [x] [Documentation (wip)](https://bit.ly/v4k2023).
|
||||||
|
|
||||||
## Roadmap ᕕ(ᐛ)ᕗ (in order of arrival; ✱: partial support)
|
## Roadmap ᕕ(ᐛ)ᕗ (in order of arrival; ✱: partial support)
|
||||||
- [ ] AI pass: actors, waypoints, pathfinding, behavior trees (h/fsm,goap), and navmesh generation.
|
- [ ] AI pass: actors, waypoints, pathfinding, behavior trees (h/fsm,goap), and navmesh generation.
|
||||||
- [ ] Render pass: reverse-Z, automatic LODs, impostors, decals.
|
|
||||||
- [ ] Materials: (colors✱, textures✱, matcaps✱, videos✱, shadertoys✱). Shadertoys as post-fx✱. <!--materials as postfx, as they have an update() method -->
|
|
||||||
- [ ] Lighting: Hard/soft shadow mapping (VSM,CCSM). Baked lightmaps. Refl probes. Integrated PBR.
|
|
||||||
- [ ] Network/VM pass: Entity/component/systems and worlds. <!-- W/ECS, gameobj, serialization:load/save/merge, diff/patch ;; dead reckoning, interpolation, extrapolation, bandwidth budgets -->
|
- [ ] Network/VM pass: Entity/component/systems and worlds. <!-- W/ECS, gameobj, serialization:load/save/merge, diff/patch ;; dead reckoning, interpolation, extrapolation, bandwidth budgets -->
|
||||||
|
- [ ] Core pass: struct serialization.
|
||||||
- [ ] Message pipeline and replication. <!-- manual/replication channels, node sharding/clustering. -->
|
- [ ] Message pipeline and replication. <!-- manual/replication channels, node sharding/clustering. -->
|
||||||
- [ ] Digital signals, message buffering and event polling.
|
- [ ] Digital signals, message buffering and event polling.
|
||||||
- [ ] World streaming and level loading.
|
- [ ] World streaming and level loading.
|
||||||
- [ ] Scenegraphs and spatial partioning. BVH, PVS, occluders, frustum culling.
|
- [ ] Scenegraphs and spatial partioning. BVH, PVS, occluders, frustum culling.
|
||||||
- [ ] Server/client architecture. Hybrid P2P.
|
- [ ] Server/client architecture. Hybrid P2P.
|
||||||
- [ ] NAT traversal. Socketless API, message API and pub/sub wrappers (enet/websocket).
|
- [ ] NAT traversal. Socketless API, message API and pub/sub wrappers (enet/websocket).
|
||||||
|
- [ ] Editor pass = netbased + offline rendering + virtual input.
|
||||||
|
- [ ] Basic: Gizmos✱, scene tree, property editor✱, load/save✱, undo/redo✱, copy/paste, on/off (vis,tick,ddraw,log), vcs.
|
||||||
|
- [ ] Scenenode: node singleton display, node console, node labels, node outlines✱.<!-- node == gameobj ? -->
|
||||||
|
- [ ] Debug: toggles on/off (billboards✱, materials, un/lit, cast shadows, wireframe, skybox✱/mie✱, fog/atmosphere, collide✱, physics).
|
||||||
|
- [ ] Level: volumes, triggers, platforms, level streaming.
|
||||||
|
- [ ] Sub-editor: timeline and data tracks, node graphs. <!-- worthy: will be reused into materials, animgraphs and blueprints -->
|
||||||
|
- [ ] Sub-editor: Procedural content, brushes, noise and CSG.
|
||||||
|
- [ ] Sub-editor: blendshapes, additive anims, head/foot/hand IKs.
|
||||||
|
- [ ] Script pass: DLL✱ (module->plugin/sys), Lua✱, Luajit✱, Teal✱ and TypeScript.
|
||||||
|
- [ ] Render pass: reverse-Z, automatic LODs, impostors, decals.
|
||||||
|
- [ ] Materials: (colors✱, textures✱, matcaps✱, videos✱, shadertoys✱). Shadertoys as post-fx✱. <!--materials as postfx, as they have an update() method -->
|
||||||
|
- [ ] Lighting: Hard/soft shadow mapping (VSM,CCSM). Baked lightmaps. Refl probes. Integrated PBR.
|
||||||
- [ ] Tools pass
|
- [ ] Tools pass
|
||||||
- [ ] Extend shaders + bindings. Per-platform✱, per-type✱, per-asset options. GIF, PKM.
|
- [ ] Extend shaders + bindings. Per-platform✱, per-type✱, per-asset options. GIF, PKM.
|
||||||
- [ ] Extend atlas (sprite/lightmaps). Fit packing (sprites).
|
- [ ] Extend atlas (sprite/lightmaps). Fit packing (sprites).
|
||||||
- [ ] Extend bindings and messaging: parse C headers during cooking stage. <!-- msgs,docs,refl,meta,lua -- (*.c, *.h) as .proto/.pbc maybe, free reflection+automatic bindings -->
|
- [ ] Extend bindings and messaging: parse C headers during cooking stage. <!-- msgs,docs,refl,meta,lua -- (*.c, *.h) as .proto/.pbc maybe, free reflection+automatic bindings -->
|
||||||
- [ ] API pass
|
- [ ] API pass
|
||||||
|
- [ ] Extend math: quat2, bezier, catmull.
|
||||||
- [ ] Discuss API and freeze it.
|
- [ ] Discuss API and freeze it.
|
||||||
- [ ] Document everything.
|
- [ ] Document everything.
|
||||||
|
|
||||||
|
@ -79,7 +82,7 @@ Nice to have/extend (engine dependant):
|
||||||
- Animation pass: playlists, additive, blend/shapes, ik/bones, animgraph/controllers.
|
- Animation pass: playlists, additive, blend/shapes, ik/bones, animgraph/controllers.
|
||||||
// 6) anims, I (playlist: ~~forward/backwards/loop/rewind)~~, II (~~blend~~/shapes), III (ik/bone), IV (graph/controller)
|
// 6) anims, I (playlist: ~~forward/backwards/loop/rewind)~~, II (~~blend~~/shapes), III (ik/bone), IV (graph/controller)
|
||||||
// ~~blend anims~~, animtracks+animevents, additive anims,
|
// ~~blend anims~~, animtracks+animevents, additive anims,
|
||||||
// fwk_data: quantization: ~~half, quant, microfloat~~.
|
// v4k_data: quantization: ~~half, quant, microfloat~~.
|
||||||
// anim; ~~keyframes[] { frame+delay,frame+delay,... }, anim duration, anim flip,~~
|
// anim; ~~keyframes[] { frame+delay,frame+delay,... }, anim duration, anim flip,~~
|
||||||
// anim tracks / anim events
|
// anim tracks / anim events
|
||||||
- Audio pass: 3D audio, HRTF, FFT, filtering and sound occlusion.
|
- Audio pass: 3D audio, HRTF, FFT, filtering and sound occlusion.
|
||||||
|
@ -129,8 +132,8 @@ Engine types:
|
||||||
|
|
||||||
Nice to have:
|
Nice to have:
|
||||||
- [ ] fix leaks and todos
|
- [ ] fix leaks and todos
|
||||||
- [ ] fwk_app: cpu usage, orientation
|
- [ ] v4k_app: cpu usage, orientation
|
||||||
- [ ] fwk_input: mouse clip, mouse wrap,
|
- [ ] v4k_input: mouse clip, mouse wrap,
|
||||||
- [ ] zip0 seek-vfs optimization. zip_append_file is suboptimal, and requires tons of contiguous memory for giant files.
|
- [ ] zip0 seek-vfs optimization. zip_append_file is suboptimal, and requires tons of contiguous memory for giant files.
|
||||||
|
|
||||||
Almost done:
|
Almost done:
|
||||||
|
@ -172,37 +175,31 @@ Almost done:
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Hello FWK
|
## Hello V4K
|
||||||
```C
|
```C
|
||||||
#include "fwk.h" // Minimal C sample
|
#include "v4k.h" // Minimal C sample
|
||||||
int main() {
|
int main() {
|
||||||
window_create(75.0, 0); // 75% size, no extra flags
|
window_create(75.0, 0); // 75% size, no extra flags
|
||||||
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
while( window_swap() && !input(KEY_ESC) ) { // game loop
|
||||||
puts("hello FWK from C!");
|
puts("hello V4K from C!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```C
|
|
||||||
#include "fwk.h" // Minimal HTML5 sample
|
|
||||||
void render(void *arg) {
|
|
||||||
if( !input(KEY_ESC) ) puts("hello FWK from HTML5!");
|
|
||||||
}
|
|
||||||
int main() {
|
|
||||||
window_create(75.0, 0); // 75% size, no extra flags
|
|
||||||
window_loop(render, NULL); // game loop
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
local fwk = require("fwk") -- Minimal Lua sample
|
local v4k = require("v4k") -- Minimal Lua sample
|
||||||
fwk.window_create(75.0,0) -- 75% size, no extra flags
|
v4k.window_create(75.0,0) -- 75% size, no extra flags
|
||||||
while fwk.window_swap() and fwk.input(fwk.KEY_ESC) == 0 do -- game loop
|
while v4k.window_swap() and v4k.input(v4k.KEY_ESC) == 0 do -- game loop
|
||||||
print("hello FWK from Lua!")
|
print("hello V4K from Lua!")
|
||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
## Quickstart
|
## Quickstart
|
||||||
|
- Double-click `MAKE.bat` (Win) or `sh MAKE.bat` (Linux/OSX) to compile everything.
|
||||||
|
- `MAKE.bat sln` (Win) or `sh MAKE.bat sln` (Linux/OSX) to generate solutions/makefiles.
|
||||||
|
- `MAKE.bat help` (Win) or `sh MAKE.bat help` (Linux/OSX) for a bunch of options.
|
||||||
|
- `MAKE.bat hello.c` (Win) or `sh MAKE.bat hello.c` (Linux/OSX) to build a single executable.
|
||||||
|
- Alternatively,
|
||||||
```bat
|
```bat
|
||||||
echo win/vc && cl hello.c
|
echo win/vc && cl hello.c
|
||||||
echo win/clang-cl && clang-cl hello.c
|
echo win/clang-cl && clang-cl hello.c
|
||||||
|
@ -215,94 +212,108 @@ echo osx && cc -ObjC hello.c -framework cocoa -framework iokit -fr
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cook
|
## Cook
|
||||||
- Most asset types need to be cooked before being used in your application. Some other assets like `.png` do not.
|
- Assets need to be cooked before being consumed in your application. The [tools/](tools/) folder contains all the related binaries to perform any asset processing plus the [cookbook](tools/cook.ini) to do so.
|
||||||
- Cooked assets will be written into .zipfiles close to your executable, and mounted before entering game loop.
|
- Your game will cook all your assets as long as the [`tools/`](tools/) folder is next to your executable. Alternatively, cook them all just by invoking supplied [`tools/cook` standalone binary](tools/).
|
||||||
- Cooked .zipfiles and your executable are the only required assets when releasing your game.
|
- In both cases, assets will be cooked and packed into .zipfiles next to your executable, then mounted before entering game loop. These .zipfiles plus your executable are the only required files when releasing your game.
|
||||||
- Cook manually your assets by invoking supplied [`tools/cook` standalone binary](tools/).
|
|
||||||
- Cook automatically your assets by just playing your game: a runtime cook is already embedded into your binary.
|
|
||||||
- In order to achieve this, ensure the [`tools/` folder](tools/) is close to your executable.
|
|
||||||
- This folder contains all the related binaries to perform any asset conversion plus the [cookbook](tools/cook.ini) to do so.
|
|
||||||
|
|
||||||
## Extra tips
|
## Extra tips
|
||||||
- Any ico/png file named after the executable name will be automatically used as app icon.
|
- Any ico/png file named after the executable name will be automatically used as app icon.
|
||||||
- Similar to the ico/png case above, the cooked .zipfiles can be named after the main executable as well.
|
- Similar to the ico/png case above, the cooked .zipfiles can be named after the main executable as well.
|
||||||
- Dropped files into game window will be imported & saved into [`import/`](art/engine/import) folder.
|
- Dropped files into game window will be imported & saved into [`import/`](engine/art/import/) folder.
|
||||||
- Update the gamepad controller database by upgrading the [`gamecontrollerdb.txt`](art/engine/input) file.
|
- Update the gamepad controller database by upgrading the [`gamecontrollerdb.txt`](engine/art/input/) file.
|
||||||
- Depending on your IDE, you might need to browse to [`split/`](split/) sources when debugging FWK.
|
- Depending on your IDE, you might need to browse to [`engine/split/`](engine/split/) sources when debugging V4K.
|
||||||
- Cook assets on demand, as opposed to cook all existing assets on depot, by using `--cook-on-demand` flag.
|
- Cook assets on demand, as opposed to cook all existing assets on depot, by using `--cook-on-demand` flag.
|
||||||
- Linux/OSX users can optionally install wine and use the Windows tools instead (by using `--cook-wine` flag).
|
- Linux/OSX users can optionally install wine and use the Windows tools instead (by using `--cook-wine` flag).
|
||||||
- Disable automatic cooking by using `--cook-jobs=0` flag (not recommended).
|
- Disable automatic cooking by using `--cook-jobs=0` flag (not recommended).
|
||||||
- Generate a project solution by dropping `split/fwk.h, fwk.c and fwk` files into it.
|
- Generate a project solution by dropping `engine/v4k.h, v4k.c and v4k` files into it.
|
||||||
|
- Auto-generated Luajit and Python bindings can be found in the [`engine/bind/`](engine/bind/) folder.
|
||||||
|
<!-- - On windows + vc, you can use `make bindings` or `make docs` to generate everything prior to a release -->
|
||||||
<!-- - Note: Windows: Assimp.dll may need [this package installed](https://www.microsoft.com/en-us/download/confirmation.aspx?id=30679).-->
|
<!-- - Note: Windows: Assimp.dll may need [this package installed](https://www.microsoft.com/en-us/download/confirmation.aspx?id=30679).-->
|
||||||
|
|
||||||
## Credits (Artwork + demos)
|
## Credits
|
||||||
- [Nanofactory](https://sketchfab.com/3d-models/kgirls01-d2f946f58a8040ae993cda70c97b302c), for kgirls01 3D model (CC BY-NC-ND 4.0).
|
**Artwork**
|
||||||
- [RottingPixels](https://opengameart.org/content/2d-castle-platformer-tileset-16x16), for castle-tileset (CC0).
|
[Dean Evans, Raijin](https://youtu.be/RRvYkrrpMKo?t=147 "for the Map song (c)"),
|
||||||
- [wwwtyro](https://github.com/wwwtyro/glsl-atmosphere), for nicest rayleigh/mie scattering shader around (CC0).
|
[Nuulbee](https://sketchfab.com/3d-models/kgirls01-d2f946f58a8040ae993cda70c97b302c "for kgirls01 3D model (CC BY-NC-ND 4.0)"),
|
||||||
|
[Rotting Pixels](https://opengameart.org/content/2d-castle-platformer-tileset-16x16 "for castle-tileset (CC0)"),
|
||||||
|
[Tom Lewandowski](https://QuestStudios.com "for his MIDI recordings (c)"),
|
||||||
|
[Rye Terrell](https://github.com/wwwtyro/glsl-atmosphere "for nicest rayleigh/mie scattering shader around (CC0)"),
|
||||||
|
**Tools**
|
||||||
|
[Aaron Barany](https://github.com/akb825/Cuttlefish "for cuttlefish (APACHE2)"),
|
||||||
|
[Arseny Kapoulkine](https://github.com/zeux/pugixml/ "for pugixml (MIT)"),
|
||||||
|
[Assimp authors](https://github.com/assimp/assimp "for assimp (BSD3)"),
|
||||||
|
[Bernhard Schelling](https://github.com/schellingb/TinySoundFont "for tml.h (Zlib) and tsf.h (MIT)"),
|
||||||
|
[Christian Collins](http://www.schristiancollins.com "for GeneralUser GS soundfont (PD)"),
|
||||||
|
[FFMPEG authors](https://www.ffmpeg.org/ "for ffmpeg (LGPL21)"),
|
||||||
|
[Imagination](https://developer.imaginationtech.com/pvrtextool/ "for pvrtextoolcli (ITL)"),
|
||||||
|
[Krzysztof Gabis](https://github.com/kgabis/ape "for split.py/join.py (MIT)"),
|
||||||
|
[Lee Salzman](https://github.com/lsalzman/iqm/tree/5882b8c32fa622eba3861a621bb715d693573420/demo "for iqm.cpp (PD)"),
|
||||||
|
[Martín Lucas Golini](https://github.com/SpartanJ/eepp/commit/8552941da19380d7a629c4da80a976aec5d39e5c "for emscripten-fs.html (CC0)"),
|
||||||
|
[Mattias Gustavsson](https://github.com/mattiasgustavsson/libs "for mid.h (PD)"),
|
||||||
|
[Michael Schmoock](http://github.com/willsteel/lcpp "for lcpp (MIT)"),
|
||||||
|
[Morgan McGuire](https://casual-effects.com/markdeep/ "for markdeep (BSD2)"),
|
||||||
|
[Olivier Lapicque, Konstanty Bialkowski](https://github.com/Konstanty/libmodplug "for libmodplug (PD)"),
|
||||||
|
[Polyglot Team](https://docs.google.com/spreadsheets/d/17f0dQawb-s_Fd7DHgmVvJoEGDMH_yoSd8EYigrb0zmM/edit "for polyglot gamedev (CC0)"),
|
||||||
|
[Tildearrow](https://github.com/tildearrow/furnace/ "for Furnace (GPL2)"),
|
||||||
|
[Tomas Pettersson](http://www.drpetter.se/ "for sfxr (PD)"),
|
||||||
|
[Tor Andersson](https://github.com/ccxvii/asstools "for assiqe.c (BSD)"),
|
||||||
|
**Runtime**
|
||||||
|
[Andreas Mantler](https://github.com/ands "for their math library (PD)"),
|
||||||
|
[Barerose](https://github.com/barerose "for swrap (CC0) and math library (CC0)"),
|
||||||
|
[Camilla Löwy](https://github.com/elmindreda "for glfw3 (Zlib)"),
|
||||||
|
[Dave Rand](https://tools.ietf.org/html/rfc1978 "for ppp (PD)"),
|
||||||
|
[David Herberth](https://github.com/dav1dde/ "for glad generated code (PD)"),
|
||||||
|
[David Reid](https://github.com/mackron "for miniaudio (PD)"),
|
||||||
|
[Dominic Szablewski](https://github.com/phoboslab/pl_mpeg "for pl_mpeg (MIT)"),
|
||||||
|
[Dominik Madarász](https://github.com/zaklaus "for json5 parser (PD)"),
|
||||||
|
[Eduard Suica](https://github.com/eduardsui/tlse "for tlse (PD)"),
|
||||||
|
[Evan Wallace](https://github.com/evanw "for their math library (CC0)"),
|
||||||
|
[Gargaj+cce/Peisik](https://github.com/gargaj/foxotron "for Foxotron/PBR shaders (UNLICENSE)"),
|
||||||
|
[Guilherme Lampert](https://github.com/glampert "for their math library (PD)"),
|
||||||
|
[Guillaume Vareille](http://tinyfiledialogs.sourceforge.net "for tinyfiledialogs (ZLIB)"),
|
||||||
|
[Haruhiko Okumura](https://oku.edu.mie-u.ac.jp/~okumura/compression/ "for lzss (PD)"),
|
||||||
|
[Igor Pavlov](https://www.7-zip.org/ "for LZMA (PD)"),
|
||||||
|
[Ilya Muravyov](https://github.com/encode84 "for bcm, balz, crush, ulz, lz4x (PD)"),
|
||||||
|
[Jon Olick](https://www.jonolick.com/ "for jo_mp1 and jo_mpeg (PD)"),
|
||||||
|
[Joonas Pihlajamaa](https://github.com/jokkebk/JUnzip "for JUnzip library (PD)"),
|
||||||
|
[Juliette Focault](https://github.com/juliettef/IconFontCppHeaders/blob/main/IconsMaterialDesign.h "for the generated MD header (ZLIB)"),
|
||||||
|
[Kristoffer Grönlund](https://github.com/krig "for their math library (CC0)"),
|
||||||
|
[Lee Salzman](https://github.com/lsalzman/iqm/tree/5882b8c32fa622eba3861a621bb715d693573420/demo "for IQM spec & player (PD)"),
|
||||||
|
[Lee Salzman, V.Hrytsenko, D.Madarász](https://github.com/zpl-c/enet/ "for enet (MIT)"),
|
||||||
|
[Libtomcrypt](https://github.com/libtom/libtomcrypt "for libtomcrypt (Unlicense)"),
|
||||||
|
[Lua authors](https://www.lua.org/ "for Lua language (MIT)"),
|
||||||
|
[Mattias Gustavsson](https://github.com/mattiasgustavsson/libs "for thread.h and https.h (PD)"),
|
||||||
|
[Micha Mettke](https://github.com/vurtun "for their math library (PD)"),
|
||||||
|
[Micha Mettke, Chris Willcocks, Dmitry Hrabrov](https://github.com/vurtun/nuklear "for nuklear (PD)"),
|
||||||
|
[Michael Galetzka](https://github.com/Cultrarius/Swarmz "for swarmz (UNLICENSE)"),
|
||||||
|
[Mārtiņš Možeiko](https://gist.github.com/mmozeiko/68f0a8459ef2f98bcd879158011cc275 "for A* pathfinding (PD)"),
|
||||||
|
[Omar Cornut, vaiorabbit](https://github.com/ocornut/imgui/pull/3627 "for tables of unicode ranges (MIT-0)"),
|
||||||
|
[Rabia Alhaffar](https://github.com/Rabios/ice_libs "for ice_batt.h (PD)"),
|
||||||
|
[Rich Geldreich](https://github.com/richgel999/miniz "for miniz (PD)"),
|
||||||
|
[Ross Williams](http://ross.net/compression/lzrw3a.html "for lzrw3a (PD)"),
|
||||||
|
[Samuli Raivio](https://github.com/bqqbarbhg/bq_websocket "for bq_websocket (PD)"),
|
||||||
|
[Sean Barrett](https://github.com/nothings "for stb_image, stb_image_write, stb_sprintf, stb_truetype and stb_vorbis (PD)"),
|
||||||
|
[Sebastian Steinhauer](https://github.com/kieselsteini "for sts_mixer (PD)"),
|
||||||
|
[Stan Melax, Cloud Wu](https://web.archive.org/web/20031204035320/http://www.melax.com/polychop/gdmag.pdf "for polychop C algorithm (PD)"),
|
||||||
|
[Stefan Gustavson](https://github.com/stegu/perlin-noise "for simplex noise (PD)"),
|
||||||
|
[Sterling Orsten](https://github.com/sgorsten "for their math library (UNLICENSE)"),
|
||||||
|
[Tor Andersson](https://github.com/ccxvii/minilibs "for xml.c (PD)"),
|
||||||
|
[Vassvik](https://github.com/vassvik/mv_easy_font "for mv_easy_font (Unlicense)"),
|
||||||
|
[Wolfgang Draxinger](https://github.com/datenwolf "for their math library (WTFPL2)"),
|
||||||
|
|
||||||
## Credits (Tools)
|
<!--
|
||||||
- [Aaron Barany](https://github.com/akb825/Cuttlefish), for cuttlefish (APACHE2).
|
- [DavidLam](https://en.wikipedia.org/wiki/Tokamak_(software) "for tokamak physics engine (ZLIB)")
|
||||||
- [Arseny Kapoulkine](https://github.com/zeux/pugixml/), for pugixml (MIT).
|
- [FMS_Cat](https://gist.github.com/FMS-Cat/a1ccea3ce866c34706084e3526204f4f "for nicest VHS/VCR shader around (MIT)")
|
||||||
- [Assimp authors](https://github.com/assimp/assimp), for assimp (BSD3).
|
- [Goblin165cm](https://sketchfab.com/3d-models/halloween-little-witch-ccc023590bfb4789af9322864e42d1ab "for witch 3D model (CC BY 4.0)")
|
||||||
- [Bernhard Schelling](https://github.com/schellingb/TinySoundFont), for tml.h (Zlib) and tsf.h (MIT).
|
- [ID Software, David St-Louis](https://github.com/Daivuk/PureDOOM "for PureDOOM (Doom License)")
|
||||||
- [ffmpeg authors](https://www.ffmpeg.org/), for ffmpeg (LGPL21).
|
- [Miloslav Číž](https://codeberg.org/drummyfish/Anarch "for Anarch (CC0)")
|
||||||
- [Imagination](https://developer.imaginationtech.com/pvrtextool/), for pvrtextoolcli (ITL).
|
- [Quaternius](https://www.patreon.com/quaternius "for the lovely 3D robots (CC0)")
|
||||||
- [Krzysztof Gabis](https://github.com/kgabis/ape), for split.py/join.py (MIT).
|
- [Rxi](https://github.com/rxi/autobatch "for lovely sprites & cats demo (MIT)")
|
||||||
- [Lee Salzman](https://github.com/lsalzman/iqm/tree/5882b8c32fa622eba3861a621bb715d693573420/demo), for iqm.cpp (PD).
|
-->
|
||||||
- [Mattias Gustavsson](https://github.com/mattiasgustavsson/libs), for mid.h (PD).
|
|
||||||
- [Michael Schmoock](http://github.com/willsteel/lcpp), for lcpp (MIT).
|
|
||||||
- [Olivier Lapicque, Konstanty Bialkowski](https://github.com/Konstanty/libmodplug), for libmodplug (PD).
|
|
||||||
- [Polyglot Team](https://docs.google.com/spreadsheets/d/17f0dQawb-s_Fd7DHgmVvJoEGDMH_yoSd8EYigrb0zmM/edit), for polyglot gamedev (CC0).
|
|
||||||
- [Tildearrow](https://github.com/tildearrow/furnace/), for Furnace (GPL2).
|
|
||||||
- [Tomas Pettersson](http://www.drpetter.se/), for sfxr (PD).
|
|
||||||
- [Tor Andersson](https://github.com/ccxvii/asstools), for assiqe.c (BSD).
|
|
||||||
|
|
||||||
## Credits (Runtime)
|
|
||||||
- [Barerose](https://github.com/barerose), for swrap (CC0).
|
|
||||||
- [Camilla Löwy](https://github.com/elmindreda), for glfw3 (Zlib).
|
|
||||||
- [Dave Rand](https://tools.ietf.org/html/rfc1978) for ppp (PD).
|
|
||||||
- [David Herberth](https://github.com/dav1dde/), for glad generated code (PD).
|
|
||||||
- [David Reid](https://github.com/mackron), for miniaudio (PD).
|
|
||||||
- [Dominic Szablewski](https://github.com/phoboslab/pl_mpeg), for pl_mpeg (MIT).
|
|
||||||
- [Dominik Madarász](https://github.com/zaklaus), for json5 parser (PD).
|
|
||||||
- [Eduard Suica](https://github.com/eduardsui/tlse), for tlse (PD).
|
|
||||||
- [Gargaj+cce/Peisik](https://github.com/gargaj/foxotron), for Foxotron/PBR shaders (UNLICENSE).
|
|
||||||
- [Guillaume Vareille](http://tinyfiledialogs.sourceforge.net), for tinyfiledialogs (ZLIB).
|
|
||||||
- [Haruhiko Okumura](https://oku.edu.mie-u.ac.jp/~okumura/compression/) for lzss (PD).
|
|
||||||
- [Igor Pavlov](https://www.7-zip.org/) for LZMA (PD).
|
|
||||||
- [Ilya Muravyov](https://github.com/encode84) for bcm, balz, crush, ulz, lz4x (PD).
|
|
||||||
- [Jon Olick](https://www.jonolick.com/), for jo_mp1 and jo_mpeg (PD).
|
|
||||||
- [Joonas Pihlajamaa](https://github.com/jokkebk/JUnzip), for JUnzip library (PD).
|
|
||||||
- [Juliette Focault](https://github.com/juliettef/IconFontCppHeaders/blob/main/IconsMaterialDesign.h), for the generated MD header (ZLIB).
|
|
||||||
- [Lee Salzman](https://github.com/lsalzman/iqm/tree/5882b8c32fa622eba3861a621bb715d693573420/demo), for IQM spec & player (PD).
|
|
||||||
- [Lee Salzman, V.Hrytsenko, D.Madarász](https://github.com/zpl-c/enet/), for enet (MIT).
|
|
||||||
- [Libtomcrypt](https://github.com/libtom/libtomcrypt), for libtomcrypt (Unlicense).
|
|
||||||
- [Lua authors](https://www.lua.org/), for Lua language (MIT).
|
|
||||||
- [Mārtiņš Možeiko](https://gist.github.com/mmozeiko/68f0a8459ef2f98bcd879158011cc275), for A* pathfinding (PD).
|
|
||||||
- [Mattias Gustavsson](https://github.com/mattiasgustavsson/libs), for thread.h and https.h (PD).
|
|
||||||
- [Micha Mettke, Chris Willcocks, Dmitry Hrabrov](https://github.com/vurtun/nuklear), for nuklear (PD).
|
|
||||||
- [Michael Galetzka](https://github.com/Cultrarius/Swarmz), for swarmz (UNLICENSE).
|
|
||||||
- [Omar Cornut, vaiorabbit](https://github.com/ocornut/imgui/pull/3627), for tables of unicode ranges (MIT-0).
|
|
||||||
- [Rabia Alhaffar](https://github.com/Rabios/ice_libs), for ice_batt.h (PD).
|
|
||||||
- [Rich Geldreich](https://github.com/richgel999/miniz), for miniz (PD).
|
|
||||||
- [Ross Williams](http://ross.net/compression/lzrw3a.html) for lzrw3a (PD).
|
|
||||||
- [Samuli Raivio](https://github.com/bqqbarbhg/bq_websocket), for bq_websocket (PD).
|
|
||||||
- [Sean Barrett](https://github.com/nothings), for stb_image, stb_image_write, stb_sprintf, stb_truetype and stb_vorbis (PD).
|
|
||||||
- [Sebastian Steinhauer](https://github.com/kieselsteini), for sts_mixer (PD).
|
|
||||||
- [Stan Melax, Cloud Wu](https://web.archive.org/web/20031204035320/http://www.melax.com/polychop/gdmag.pdf), for polychop C algorithm (PD).
|
|
||||||
- [Stefan Gustavson](https://github.com/stegu/perlin-noise), for simplex noise (PD).
|
|
||||||
- [Tor Andersson](https://github.com/ccxvii/minilibs), for xml.c (PD).
|
|
||||||
- [Vassvik](https://github.com/vassvik/mv_easy_font), for mv_easy_font (Unlicense).
|
|
||||||
- Special thanks to [@ands](https://github.com/ands), [@barerose](https://github.com/barerose), [@datenwolf](https://github.com/datenwolf), [@evanw](https://github.com/evanw), [@glampert](https://github.com/glampert), [@krig](https://github.com/krig), [@sgorsten](https://github.com/sgorsten) and [@vurtun](https://github.com/vurtun) for their math libraries (PD,CC0,WTFPL2,CC0,PD,CC0,Unlicense,PD).
|
|
||||||
|
|
||||||
## Unlicense
|
## Unlicense
|
||||||
This software is released into the [public domain](https://unlicense.org/). Also dual-licensed as [0-BSD](https://opensource.org/licenses/0BSD) or [MIT (No Attribution)](https://github.com/aws/mit-0) for those countries where public domain is a concern (sigh). Any contribution to this repository is implicitly subjected to the same release conditions aforementioned.
|
This software is released into the [public domain](https://unlicense.org/). Also dual-licensed as [0-BSD](https://opensource.org/licenses/0BSD) or [MIT (No Attribution)](https://github.com/aws/mit-0) for those countries where public domain is a concern (sigh). Any contribution to this repository is implicitly subjected to the same release conditions aforementioned.
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
<p>
|
Still looking for alternatives? [amulet](https://github.com/ianmaclarty/amulet), [aroma](https://github.com/leafo/aroma/), [astera](https://github.com/tek256/astera), [blendelf](https://github.com/jesterKing/BlendELF), [bullordengine](https://github.com/MarilynDafa/Bulllord-Engine), [candle](https://github.com/EvilPudding/candle), [cave](https://github.com/kieselsteini/cave), [chickpea](https://github.com/ivansafrin/chickpea), [corange](https://github.com/orangeduck/Corange), [cute](https://github.com/RandyGaul/cute_framework), [dos-like](https://github.com/mattiasgustavsson/dos-like), [ejoy2d](https://github.com/ejoy/ejoy2d), [exengine](https://github.com/exezin/exengine), [gunslinger](https://github.com/MrFrenik/gunslinger), [hate](https://github.com/excessive/hate), [island](https://github.com/island-org/island), [juno](https://github.com/rxi/juno), [l](https://github.com/Lyatus/L), [lgf](https://github.com/Planimeter/lgf), [limbus](https://github.com/redien/limbus), [love](https://github.com/love2d/love/), [lovr](https://github.com/bjornbytes/lovr), [mini3d](https://github.com/mini3d/mini3d), [mintaro](https://github.com/mackron/mintaro), [mio](https://github.com/ccxvii/mio), [olive.c](https://github.com/tsoding/olive.c), [opensource](https://github.com/w23/OpenSource), [ouzel](https://github.com/elnormous/ouzel/), [pez](https://github.com/prideout/pez), [pixie](https://github.com/mattiasgustavsson/pixie), [punity](https://github.com/martincohen/Punity), [r96](https://github.com/badlogic/r96), [ricotech](https://github.com/dbechrd/RicoTech), [rizz](https://github.com/septag/rizz), [tigr](https://github.com/erkkah/tigr), [yourgamelib](https://github.com/duddel/yourgamelib)
|
||||||
<a href="https://github.com/r-lyeh/FWK/issues"><img alt="Issues" src="https://img.shields.io/github/issues-raw/r-lyeh/FWK.svg"/></a>
|
|
||||||
<a href="https://discord.gg/vu6Vt9d"><img alt="Discord" src="https://img.shields.io/discord/270565488365535232?color=5865F2&label=chat&logo=discord&logoColor=white"/></a><br/>
|
|
||||||
|
|
||||||
Still looking for alternatives?
|
<a href="https://github.com/r-lyeh/V4K/issues"><img alt="Issues" src="https://img.shields.io/github/issues-raw/r-lyeh/V4K.svg"/></a> <a href="https://discord.gg/vu6Vt9d"><img alt="Discord" src="https://img.shields.io/discord/270565488365535232?color=5865F2&label=chat&logo=discord&logoColor=white"/></a>
|
||||||
[amulet](https://github.com/ianmaclarty/amulet), [aroma](https://github.com/leafo/aroma/), [astera](https://github.com/tek256/astera), [blendelf](https://github.com/jesterKing/BlendELF), [bullordengine](https://github.com/MarilynDafa/Bulllord-Engine), [candle](https://github.com/EvilPudding/candle), [cave](https://github.com/kieselsteini/cave), [chickpea](https://github.com/ivansafrin/chickpea), [corange](https://github.com/orangeduck/Corange), [cute](https://github.com/RandyGaul/cute_framework), [dos-like](https://github.com/mattiasgustavsson/dos-like), [ejoy2d](https://github.com/ejoy/ejoy2d), [exengine](https://github.com/exezin/exengine), [gunslinger](https://github.com/MrFrenik/gunslinger), [hate](https://github.com/excessive/hate), [island](https://github.com/island-org/island), [juno](https://github.com/rxi/juno), [l](https://github.com/Lyatus/L), [lgf](https://github.com/Planimeter/lgf), [limbus](https://github.com/redien/limbus), [love](https://github.com/love2d/love/), [lovr](https://github.com/bjornbytes/lovr), [mini3d](https://github.com/mini3d/mini3d), [mintaro](https://github.com/mackron/mintaro), [mio](https://github.com/ccxvii/mio), [olive.c](https://github.com/tsoding/olive.c), [opensource](https://github.com/w23/OpenSource), [ouzel](https://github.com/elnormous/ouzel/), [pez](https://github.com/prideout/pez), [pixie](https://github.com/mattiasgustavsson/pixie), [punity](https://github.com/martincohen/Punity), [r96](https://github.com/badlogic/r96), [ricotech](https://github.com/dbechrd/RicoTech), [rizz](https://github.com/septag/rizz), [tigr](https://github.com/erkkah/tigr), [yourgamelib](https://github.com/duddel/yourgamelib)
|
|
||||||
</p>
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
https://www.tastyfish.cz/lrs/bytebeat.html
|
||||||
|
Outputting the variable i creates a periodical saw-shaped beat, multiplication/division decreases/increases the speed, addition/subtraction shifts the phase backward/forward.
|
||||||
|
Squaring (and other powers) create a wah-wah effect.
|
||||||
|
Crazier patterns can be achieved by using the variable in places of numerical constants, e.g. i << ((i / 512) % 8) (shifting by a value that depends on the variable).
|
||||||
|
Modulo (%) increases the frequency and decreases volume (limits the wave peak).
|
||||||
|
So called Sierpinski harmonies are often used melodic expressions of the form i*N & i >> M.
|
||||||
|
Bitwise and (&) can add distortion (create steps in the wave).
|
||||||
|
A macro structure of the song (silent/louds parts, verse/chorus, ...) can be achieved by combining multiple patterns with some low-frequency pattern, e.g. this alternates a slower and faster beat: int cond = (i & 0x8000) == 0;, cond * (i / 16) + !cond * (i / 32)
|
||||||
|
Extra variables can add more complexity (e.g. precompute some variable a which will subsequently be used multiple times in the final formula).
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
for (int t = 0;; ++t) {
|
||||||
|
putchar(
|
||||||
|
t|(t<<((t/920)%16))|(t/3*t&(t<<13)*t)|(t%16386?123:t&203?148:3)&(t/920)
|
||||||
|
// (t/8)>>(t>>9)*t/((t>>14&3)+4)
|
||||||
|
// ((1-(((t+10)>>((t>>9)&((t>>14))))&(t>>4&-2)))*2)*(((t>>10)^((t+((t>>6)&127))>>10))&1)*32+128
|
||||||
|
// t*((0xbadbea75>>((t>>12)&30)&3)*0.25*(0x5afe5>>((t>>16)&28)&3))
|
||||||
|
// ((t>>4)*(13&(0x8898a989>>(t>>11&30)))&255)+((((t>>9|(t>>2)|t>>8)*10+4*((t>>2)&t>>15|t>>8))&255)>>1)
|
||||||
|
// t*((t>>12|t>>8)&63&t>>4)
|
||||||
|
// ((0x47 >> ((t >> 9) % 32)) & (t >> (t % 32))) | (0x57 >> ((t >> 7) % 32)) | (0x06 >> ((t >> ((((t * 11) >> 14) & 0x0e) % 32)) % 32))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
// @todo: object_print(obj, "");
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// create the window
|
||||||
|
window_create( 0.75f, WINDOW_MSAA8 );
|
||||||
|
|
||||||
|
// create camera
|
||||||
|
camera_t cam = camera();
|
||||||
|
// load video, RGB texture, no audio
|
||||||
|
video_t *v = video( "bjork-all-is-full-of-love.mp4", VIDEO_RGB | VIDEO_NO_AUDIO ); video_seek(v, 30);
|
||||||
|
// load texture
|
||||||
|
texture_t t1 = texture("kgirl/g01_texture.png", TEXTURE_RGB);
|
||||||
|
texture_t t2 = texture("matcaps/material3", 0);
|
||||||
|
// load model
|
||||||
|
model_t m1 = model("suzanne.obj", MODEL_NO_ANIMATIONS);
|
||||||
|
model_t m2 = model("suzanne.obj", MODEL_NO_ANIMATIONS|MODEL_MATCAPS);
|
||||||
|
|
||||||
|
// spawn object1 (diffuse)
|
||||||
|
object_t* obj1 = scene_spawn();
|
||||||
|
object_model(obj1, m1);
|
||||||
|
object_diffuse(obj1, t1);
|
||||||
|
object_scale(obj1, vec3(3,3,3));
|
||||||
|
object_move(obj1, vec3(-10+5*0,0,-10));
|
||||||
|
object_pivot(obj1, vec3(0,90,0));
|
||||||
|
|
||||||
|
// spawn object2 (matcap)
|
||||||
|
object_t* obj2 = scene_spawn();
|
||||||
|
object_model(obj2, m2);
|
||||||
|
object_diffuse(obj2, t2);
|
||||||
|
object_scale(obj2, vec3(3,3,3));
|
||||||
|
object_move(obj2, vec3(-10+5*2,0,-10));
|
||||||
|
object_pivot(obj2, vec3(0,90,0));
|
||||||
|
|
||||||
|
// spawn object2 (video)
|
||||||
|
object_t* obj3 = scene_spawn();
|
||||||
|
object_model(obj3, m1);
|
||||||
|
object_diffuse(obj3, video_textures(v)[0]);
|
||||||
|
object_scale(obj3, vec3(3,3,3));
|
||||||
|
object_move(obj3, vec3(-10+5*1,0,-10));
|
||||||
|
object_pivot(obj3, vec3(0,90,0));
|
||||||
|
|
||||||
|
while(window_swap() && !input(KEY_ESC)) {
|
||||||
|
// draw environment
|
||||||
|
viewport_color( RGB3(22,22,32) );
|
||||||
|
ddraw_grid(0);
|
||||||
|
ddraw_flush();
|
||||||
|
|
||||||
|
// update video
|
||||||
|
video_decode( v );
|
||||||
|
|
||||||
|
// draw scene
|
||||||
|
scene_render(SCENE_FOREGROUND);
|
||||||
|
|
||||||
|
// fps camera
|
||||||
|
bool active = ui_active() || ui_hover() || gizmo_active() ? false : input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||||
|
if( active ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
|
vec2 mouselook = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * active);
|
||||||
|
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
|
camera_move(&cam, wasdec.x,wasdec.y,wasdec.z);
|
||||||
|
camera_fps(&cam, mouselook.x,mouselook.y);
|
||||||
|
window_cursor( !active );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
// core for remote procedure calls
|
||||||
|
// - rlyeh, public domain.
|
||||||
|
//
|
||||||
|
// format:
|
||||||
|
// - query: id method [args.....] ('subject' is alias for arg[0]; and 'object' can be any arg[1..])
|
||||||
|
// - answer: id error [values...]
|
||||||
|
//
|
||||||
|
// todo:
|
||||||
|
// - [ ] promote rpc_function to (int argc, void **args) ?
|
||||||
|
#define V4K_IMPLEMENTATION
|
||||||
|
#include "engine/joint/v4k.h"
|
||||||
|
|
||||||
|
#ifndef RPC_H
|
||||||
|
#define RPC_H
|
||||||
|
|
||||||
|
void rpc_insert(const char *signature, void * function );
|
||||||
|
|
||||||
|
char *rpc(const char *cmdline); // for debugging purposes
|
||||||
|
char* rpc_quick(unsigned query_number, const char* cmdline);
|
||||||
|
char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[]);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#define RPC_C
|
||||||
|
#ifdef RPC_C
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef void* (*rpc_function)();
|
||||||
|
|
||||||
|
typedef struct rpc_call {
|
||||||
|
char *method;
|
||||||
|
rpc_function function;
|
||||||
|
uint64_t function_hash;
|
||||||
|
} rpc_call;
|
||||||
|
|
||||||
|
#define RPC_SIGNATURE_i_iii UINT64_C(0x9830e90d3327e74b) // HASH_STR("int(int,int,int)")
|
||||||
|
#define RPC_SIGNATURE_i_ii UINT64_C(0xa7fcab437d38c750) // HASH_STR("int(int,int)")
|
||||||
|
#define RPC_SIGNATURE_s_s UINT64_C(0xc4db3d7818162463) // HASH_STR("char*(char*)")
|
||||||
|
#define RPC_SIGNATURE_s_v UINT64_C(0x8857a7c1cd20bd7b) // HASH_STR("char*(void)")
|
||||||
|
|
||||||
|
rpc_call rpc_new_call(const char *signature, rpc_function function) {
|
||||||
|
if( signature && function ) {
|
||||||
|
array(char*)tokens = strsplit(signature, "(,)"); array_pop(tokens);
|
||||||
|
if( array_count(tokens) >= 1 ) {
|
||||||
|
char *method = strrchr(tokens[0], ' ')+1;
|
||||||
|
char *rettype = va("%.*s", (int)(method - tokens[0] - 1), tokens[0]);
|
||||||
|
int num_args = array_count(tokens) - 1;
|
||||||
|
uint64_t hash = hash_str(va("%s(%s)", rettype, num_args ? strjoin(num_args, &tokens[1], ",") : "void" ));
|
||||||
|
method = va("%s%d", method, num_args );
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("%p %p %s %s(", function, (void*)hash, rettype, method); for(int i = 1, end = array_count(tokens); i < end; ++i) printf("%s%s", tokens[i], i == (end-1)? "":", "); puts(");");
|
||||||
|
#endif
|
||||||
|
return (rpc_call) { strdup(method), function, hash }; // LEAK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (rpc_call) {0};
|
||||||
|
}
|
||||||
|
|
||||||
|
static map(char*, rpc_call) rpc_calls = 0;
|
||||||
|
|
||||||
|
void rpc_insert(const char *signature, void *function ) {
|
||||||
|
rpc_call call = rpc_new_call(signature, function);
|
||||||
|
if( call.method ) {
|
||||||
|
if( !rpc_calls ) map_init(rpc_calls, less_str, hash_str);
|
||||||
|
if( map_find(rpc_calls, call.method)) {
|
||||||
|
map_erase(rpc_calls, call.method);
|
||||||
|
}
|
||||||
|
map_insert(rpc_calls, call.method, call);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *rpc_full(unsigned id, const char* method, unsigned num_args, char *args[]) {
|
||||||
|
#ifdef _DEBUG
|
||||||
|
printf("id:%x method:%s args:", id, method );
|
||||||
|
for( int i = 0; i < num_args; ++i ) printf("%s", args[i]); puts("");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
method = va("%s%d", method, num_args);
|
||||||
|
rpc_call *found = map_find(rpc_calls, (char*)method);
|
||||||
|
if( found ) {
|
||||||
|
switch(found->function_hash) {
|
||||||
|
default:
|
||||||
|
case RPC_SIGNATURE_i_iii: return va("%d \"%d %s\" %d", id, errno, strerror(errno), (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1]), atoi(args[2])) );
|
||||||
|
case RPC_SIGNATURE_i_ii: return va("%d \"%d %s\" %d", id, errno, strerror(errno), (int)(uintptr_t)found->function(atoi(args[0]), atoi(args[1])) );
|
||||||
|
case RPC_SIGNATURE_s_s: return va("%d \"%d %s\" %s", id, errno, strerror(errno), (char*)found->function(args[0]) );
|
||||||
|
case RPC_SIGNATURE_s_v: return va("%d \"%d %s\" %s", id, errno, strerror(errno), (char*)found->function() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return va("%d \"0\" ?", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
char* rpc_quick(unsigned query_number, const char* cmdline) {
|
||||||
|
array(char*) args = os_argparse(cmdline, false);
|
||||||
|
int num_args = array_count(args);
|
||||||
|
char *ret = num_args ? rpc_full(query_number, args[0], num_args - 1, &args[1]) : rpc_full(query_number, "", 0, NULL);
|
||||||
|
array_free(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *rpc(const char *cmdline) { // for debugging purposes
|
||||||
|
char *rc = rpc_quick(0, cmdline);
|
||||||
|
puts(rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int rpc_add2(int num1, int num2) {
|
||||||
|
return num1+num2;
|
||||||
|
}
|
||||||
|
int rpc_add3(int num1, int num2, int num3) {
|
||||||
|
return num1+num2+num3;
|
||||||
|
}
|
||||||
|
char *rpc_echo(char *text) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
rpc_insert("int add(int,int)", rpc_add2);
|
||||||
|
rpc_insert("int add(int,int,int)", rpc_add3);
|
||||||
|
rpc_insert("char* echo(char*)", rpc_echo);
|
||||||
|
rpc("add 1 2"); // -> 3
|
||||||
|
rpc("add 100 3 -3"); // -> 100
|
||||||
|
rpc("echo \"hello world\""); // -> hello world
|
||||||
|
}
|
||||||
|
#endif // RPC_C
|
|
@ -0,0 +1,43 @@
|
||||||
|
// shadertoy viewer
|
||||||
|
// - rlyeh, public domain
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
window_create(75, 0); // WINDOW_MSAA8);
|
||||||
|
window_title(__FILE__);
|
||||||
|
|
||||||
|
const char **list = file_list("demos/art/shadertoys/", "**.fs");
|
||||||
|
if(!list[0]) exit(-1);
|
||||||
|
array(char*) browser = 0;
|
||||||
|
while(*list) array_push(browser, STRDUP(file_name(*list++)));
|
||||||
|
int browser_count = array_count(browser);
|
||||||
|
|
||||||
|
shadertoy_t sh = {0};
|
||||||
|
|
||||||
|
while(window_swap() && !input(KEY_ESC)) {
|
||||||
|
// selector
|
||||||
|
int next = input_down(KEY_UP) || input_down(KEY_LEFT);
|
||||||
|
int prev = input_down(KEY_DOWN) || input_down(KEY_RIGHT);
|
||||||
|
static int selector = 0;
|
||||||
|
static int reload = 1;
|
||||||
|
if( next ) if( selector > 0 ) --selector, reload = 1;
|
||||||
|
if( prev ) if( selector < browser_count - 1 ) ++selector, reload = 1;
|
||||||
|
if( reload ) {
|
||||||
|
reload = 0;
|
||||||
|
window_title(va("V4K - %s", browser[selector]));
|
||||||
|
sh = shadertoy( browser[selector], 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw
|
||||||
|
shadertoy_render(&sh, window_delta());
|
||||||
|
|
||||||
|
// UI
|
||||||
|
if( ui_panel("Shadertoy", 0)) {
|
||||||
|
if( ui_list("In use", (const char**)browser, browser_count, &selector) ) {
|
||||||
|
reload = 1;
|
||||||
|
}
|
||||||
|
ui_panel_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
enum { MAX_NPCS = 5 };
|
||||||
|
struct player_t {
|
||||||
|
uint64_t seen_until;
|
||||||
|
float x,y,z,angle;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
struct npc_t {
|
||||||
|
float x,y,z;
|
||||||
|
uint32_t color;
|
||||||
|
};
|
||||||
|
struct world_t {
|
||||||
|
struct player_t player[MAX_CLIENTS];
|
||||||
|
struct npc_t npc[MAX_NPCS];
|
||||||
|
} world = {0};
|
||||||
|
|
||||||
|
void bind_netbuffers(int64_t self_id) {
|
||||||
|
uint32_t colors[] = { ORANGE,GREEN,RED,CYAN,PURPLE,YELLOW,GRAY,PINK,AQUA };
|
||||||
|
for (int64_t i=0; i<MAX_NPCS; ++i) {
|
||||||
|
// as an example, let only server to set initial pos
|
||||||
|
if (self_id==0) {
|
||||||
|
world.npc[i].x = i*3.f + 4.f;
|
||||||
|
}
|
||||||
|
world.npc[i].color = colors[i%(sizeof colors / sizeof colors[0])];
|
||||||
|
network_buffer(&world.npc[i], sizeof(struct npc_t), NETWORK_RECV, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int64_t i=0; i<MAX_CLIENTS; ++i) {
|
||||||
|
world.player[i].color = colors[i%(sizeof colors / sizeof colors[0])];
|
||||||
|
network_buffer(&world.player[i], sizeof(struct player_t), i!=self_id ? NETWORK_RECV : NETWORK_SEND, i /* each client owns exactly 1 buffer */);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// ifdef(win32, FreeConsole()); // tty_detach()
|
||||||
|
|
||||||
|
// network setup
|
||||||
|
network_create("127.0.0.1", 0, flag("--client") ? NETWORK_CONNECT : 0);
|
||||||
|
int64_t self_id = network_get(NETWORK_RANK);
|
||||||
|
bind_netbuffers(self_id);
|
||||||
|
|
||||||
|
// game setup
|
||||||
|
camera_t cam = camera();
|
||||||
|
window_create( 0.35f, WINDOW_MSAA8|WINDOW_SQUARE );
|
||||||
|
struct player_t *self = &world.player[self_id];
|
||||||
|
|
||||||
|
// game loop
|
||||||
|
while( window_swap() && !input(KEY_ESC) ) {
|
||||||
|
// network sync
|
||||||
|
char **event = network_sync(0); // timeout_ms:0
|
||||||
|
while(*event) printf( "network event: %s\n", *event++ );
|
||||||
|
|
||||||
|
self_id = network_get(NETWORK_RANK);
|
||||||
|
if (network_get(NETWORK_LIVE) == 0) {
|
||||||
|
network_create("127.0.0.1", 0, flag("--client") ? NETWORK_CONNECT|NETWORK_NOFAIL : 0);
|
||||||
|
self_id = network_get(NETWORK_RANK);
|
||||||
|
if (self_id != -1) {
|
||||||
|
bind_netbuffers(self_id);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// camera tracking
|
||||||
|
cam.position = vec3(self->x,100,self->z);
|
||||||
|
camera_lookat(&cam, vec3(self->x,0,self->z));
|
||||||
|
|
||||||
|
// input - move player
|
||||||
|
float iy = input(KEY_UP) - input(KEY_DOWN);
|
||||||
|
float ix = input(KEY_RIGHT) - input(KEY_LEFT);
|
||||||
|
if( iy || ix ) {
|
||||||
|
self->x += iy*window_delta()*15;
|
||||||
|
self->z += ix*window_delta()*15;
|
||||||
|
}
|
||||||
|
self->seen_until = date_epoch() + 4;
|
||||||
|
|
||||||
|
// npc - update npc movement on server-side
|
||||||
|
if (self_id == 0) {
|
||||||
|
for (int i = 0; i < MAX_NPCS; ++i) {
|
||||||
|
struct npc_t *n = &world.npc[i];
|
||||||
|
n->z = sinf(window_time())*4.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// background - draw grid
|
||||||
|
ddraw_grid(0);
|
||||||
|
|
||||||
|
// foreground - draw all players
|
||||||
|
for( int id = 0; id < MAX_CLIENTS; ++id ) {
|
||||||
|
struct player_t *p = &world.player[id];
|
||||||
|
if (p->seen_until < date_epoch()) continue; /* skip inactive players */
|
||||||
|
ddraw_color( p->color );
|
||||||
|
ddraw_capsule(vec3(p->x,0,p->z), vec3(p->x,2,p->z), 1);
|
||||||
|
ddraw_text(vec3(p->x,4,p->z), 0.01, stringf("player #%d", id));
|
||||||
|
}
|
||||||
|
for( int id = 0; id < MAX_NPCS; ++id ) {
|
||||||
|
struct npc_t *p = &world.npc[id];
|
||||||
|
ddraw_color( p->color );
|
||||||
|
ddraw_capsule(vec3(p->x,0,p->z), vec3(p->x,2,p->z), 1);
|
||||||
|
ddraw_text(vec3(p->x,4,p->z), 0.01, stringf("npc #%d", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
// stats
|
||||||
|
char title[64];
|
||||||
|
sprintf(title, "player #%lld", self_id);
|
||||||
|
window_title(title);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
SIERRA ON-LINE, INC.
|
||||||
|
3-D Animated Adventure Game Soundtrack Series
|
||||||
|
===============================================
|
||||||
|
LEISURE SUIT LARRY III: PASSIONATE PATTI-
|
||||||
|
IN PURSUIT OF THE PULSATING PECTORALS
|
||||||
|
|
||||||
|
|
||||||
|
"TAWNI AT THE BEACH"
|
||||||
|
Mike Dana
|
||||||
|
===============================================
|
||||||
|
Copyright (c)1989 Sierra On-Line, Inc.
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
GENERAL MIDI VERSION
|
||||||
|
|
||||||
|
System Requirements:
|
||||||
|
|
||||||
|
- MIDI Playback Software capable of reading Type 1 Standard
|
||||||
|
MIDI File format
|
||||||
|
- General MIDI sound device (Wave Table or better recommended)
|
||||||
|
|
||||||
|
|
||||||
|
This Standard MIDI File was recorded directly from Sierra's "Leisure Suit
|
||||||
|
Larry 3" adventure game. It has been converted from the MT-32 version for
|
||||||
|
playback on General MIDI sound cards. A Wave Table or better sound card is
|
||||||
|
highly recommended for optimal playback.
|
||||||
|
|
||||||
|
Recorded/converted for General MIDI by Tom Lewandowski.
|
||||||
|
Address questions or comments to:
|
||||||
|
|
||||||
|
QUEST STUDIOS
|
||||||
|
Tom Lewandowski
|
||||||
|
tom@queststudios.com
|
||||||
|
|
||||||
|
www.QuestStudios.com
|
||||||
|
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 55 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 39 KiB |
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 135 KiB |
|
@ -0,0 +1,40 @@
|
||||||
|
# Blender v2.64 (sub 0) OBJ File: ''
|
||||||
|
# www.blender.org
|
||||||
|
mtllib data/cube.mtl
|
||||||
|
o Cube
|
||||||
|
v 1.000000 -1.000000 -1.000000
|
||||||
|
v 1.000000 -1.000000 1.000000
|
||||||
|
v -1.000000 -1.000000 1.000000
|
||||||
|
v -1.000000 -1.000000 -1.000000
|
||||||
|
v 1.000000 1.000000 -0.999999
|
||||||
|
v 0.999999 1.000000 1.000001
|
||||||
|
v -1.000000 1.000000 1.000000
|
||||||
|
v -1.000000 1.000000 -1.000000
|
||||||
|
vt 0.666667 0.500000
|
||||||
|
vt 0.666667 1.000000
|
||||||
|
vt 0.333333 1.000000
|
||||||
|
vt 1.000000 0.500000
|
||||||
|
vt 1.000000 1.000000
|
||||||
|
vt 0.998981 0.000000
|
||||||
|
vt 0.666667 0.001019
|
||||||
|
vt 0.333333 0.500000
|
||||||
|
vt 0.333333 0.001020
|
||||||
|
vt 0.000000 1.000000
|
||||||
|
vt 0.333333 0.000000
|
||||||
|
vt 0.000000 0.500000
|
||||||
|
vt 0.665647 0.000000
|
||||||
|
vt 0.000000 0.001020
|
||||||
|
usemtl Material
|
||||||
|
s off
|
||||||
|
f 1/1 2/2 3/3
|
||||||
|
f 5/4 8/5 6/1
|
||||||
|
f 1/6 5/4 2/7
|
||||||
|
f 2/8 6/9 3/1
|
||||||
|
f 3/8 7/3 8/10
|
||||||
|
f 5/11 1/8 4/12
|
||||||
|
f 4/8 1/1 3/3
|
||||||
|
f 8/5 7/2 6/1
|
||||||
|
f 5/4 6/1 2/7
|
||||||
|
f 6/9 7/13 3/1
|
||||||
|
f 4/12 3/8 8/10
|
||||||
|
f 8/14 5/11 4/12
|
|
@ -0,0 +1,6 @@
|
||||||
|
Kristof Lovas
|
||||||
|
https://kristoflovas.gumroad.com/l/FWVNShaderBall
|
||||||
|
|
||||||
|
This is a much lower poly shader ball mesh than the regular ones available on the internet, its made from 10.000 triangles, and it uses face weighted normals, to achieve smooth shading. Its ideal for non tessellated material presentation, or to be used in a material showcasing scene, where a lot of them would appear on the screen at the same time.
|
||||||
|
|
||||||
|
To get the best shading, make sure you the vertex normals from the fbx, so the face weighted normals works!
|
|
@ -0,0 +1,5 @@
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
fragColor = vec4(uv,0.5+0.5*sin(iGlobalTime),1.0);
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
// Protean clouds by nimitz (twitter: @stormoid)
|
||||||
|
// https://www.shadertoy.com/view/3l23Rh
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||||
|
// Contact the author for other licensing options
|
||||||
|
|
||||||
|
/*
|
||||||
|
Technical details:
|
||||||
|
|
||||||
|
The main volume noise is generated from a deformed periodic grid, which can produce
|
||||||
|
a large range of noise-like patterns at very cheap evalutation cost. Allowing for multiple
|
||||||
|
fetches of volume gradient computation for improved lighting.
|
||||||
|
|
||||||
|
To further accelerate marching, since the volume is smooth, more than half the the density
|
||||||
|
information isn't used to rendering or shading but only as an underlying volume distance to
|
||||||
|
determine dynamic step size, by carefully selecting an equation (polynomial for speed) to
|
||||||
|
step as a function of overall density (not necessarialy rendered) the visual results can be
|
||||||
|
the same as a naive implementation with ~40% increase in rendering performance.
|
||||||
|
|
||||||
|
Since the dynamic marching step size is even less uniform due to steps not being rendered at all
|
||||||
|
the fog is evaluated as the difference of the fog integral at each rendered step.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
mat3 rot_x(float a){float sa = sin(a); float ca = cos(a); return mat3(1.,.0,.0, .0,ca,sa, .0,-sa,ca);}
|
||||||
|
mat3 rot_y(float a){float sa = sin(a); float ca = cos(a); return mat3(ca,.0,sa, .0,1.,.0, -sa,.0,ca);}
|
||||||
|
mat3 rot_z(float a){float sa = sin(a); float ca = cos(a); return mat3(ca,sa,.0, -sa,ca,.0, .0,.0,1.);}
|
||||||
|
mat2 rot(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);}
|
||||||
|
const float fov = 1.5;
|
||||||
|
|
||||||
|
const mat3 m3 = mat3(0.33338, 0.56034, -0.71817, -0.87887, 0.32651, -0.15323, 0.15162, 0.69596, 0.61339)*1.93;
|
||||||
|
float mag2(vec2 p){return dot(p,p);}
|
||||||
|
float mag2(vec3 p){return dot(p,p);}
|
||||||
|
|
||||||
|
float linstep(in float mn, in float mx, in float x){ return clamp((x - mn)/(mx - mn), 0., 1.); }
|
||||||
|
vec2 disp(float t){ return vec2(sin(t*0.22)*1., cos(t*0.175)*1.)*2.; }
|
||||||
|
float prm1 = 0.;
|
||||||
|
vec2 bsMo = vec2(0);
|
||||||
|
|
||||||
|
float colVar = 0.;
|
||||||
|
float shapeVar = 0.;
|
||||||
|
|
||||||
|
float mg2(vec2 p){return dot(p,p);}
|
||||||
|
|
||||||
|
vec2 map(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 p2 = p;
|
||||||
|
p2.xy -= disp(p.z).xy;
|
||||||
|
p.xy *= rot(sin(p.z+iTime)*0.15 + iTime*0.09);
|
||||||
|
float cl = mag2(p2.xy);
|
||||||
|
float d = 0.;
|
||||||
|
p *= .61;
|
||||||
|
float z = 1.;
|
||||||
|
float trk = 1.;
|
||||||
|
for(int i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
p += sin(p.zxy*0.75*trk + iTime*trk*.8)*(0.1 + prm1*0.2);
|
||||||
|
d -= abs(dot(cos(p), sin(p.yzx))*z);
|
||||||
|
z *= 0.57;
|
||||||
|
trk *= 1.4;
|
||||||
|
p = p*m3;
|
||||||
|
}
|
||||||
|
d = abs(d + prm1*3.)+ prm1*.3 - 2.5 + bsMo.y;
|
||||||
|
return vec2(d + cl*.2 + 0.25, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 render( in vec3 ro, in vec3 rd, float time )
|
||||||
|
{
|
||||||
|
vec4 rez = vec4(0);
|
||||||
|
const float ldst = 8.;
|
||||||
|
vec3 lpos = vec3(disp(time + ldst)*0.5, time + ldst);
|
||||||
|
float t = 1.5;
|
||||||
|
float fogT = 0.;
|
||||||
|
for(int i=0; i<130; i++)
|
||||||
|
{
|
||||||
|
if(rez.a > 0.99)break;
|
||||||
|
|
||||||
|
vec3 pos = ro + t*rd;
|
||||||
|
vec2 mpv = map(pos);
|
||||||
|
float den = clamp(mpv.x-0.3,0.,1.)*1.12;
|
||||||
|
float dn = clamp((mpv.x + 2.),0.,3.);
|
||||||
|
|
||||||
|
vec4 col = vec4(0);
|
||||||
|
if (mpv.x > 0.6)
|
||||||
|
{
|
||||||
|
|
||||||
|
col = vec4(sin(vec3(5.,0.4,0.2) + mpv.y*0.1 +sin(pos.z*0.4)*0.5 + 1.8)*0.5 + 0.5,0.08);
|
||||||
|
col *= den*den*den;
|
||||||
|
col.rgb *= linstep(4.,-2.5, mpv.x)*2.3;
|
||||||
|
float dif = clamp((den - map(pos+.8).x)/9., 0.001, 1. );
|
||||||
|
dif += clamp((den - map(pos+.35).x)/2.5, 0.001, 1. );
|
||||||
|
col.xyz *= den*(vec3(0.005,.045,.075) + 1.5*vec3(0.033,0.07,0.03)*dif);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fogC = exp(t*0.2 - 2.2);
|
||||||
|
col.rgba += vec4(0.06,0.11,0.11, 0.1)*clamp(fogC-fogT, 0., 1.);
|
||||||
|
fogT = fogC;
|
||||||
|
rez = rez + col*(1. - rez.a);
|
||||||
|
t += clamp(0.5 - dn*dn*.05, 0.09, 0.3);
|
||||||
|
}
|
||||||
|
return clamp(rez, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float getsat(vec3 c)
|
||||||
|
{
|
||||||
|
float mi = min(min(c.x, c.y), c.z);
|
||||||
|
float ma = max(max(c.x, c.y), c.z);
|
||||||
|
return (ma - mi)/(ma+ 1e-7);
|
||||||
|
}
|
||||||
|
|
||||||
|
//from my "Will it blend" shader (https://www.shadertoy.com/view/lsdGzN)
|
||||||
|
vec3 iLerp(in vec3 a, in vec3 b, in float x)
|
||||||
|
{
|
||||||
|
vec3 ic = mix(a, b, x) + vec3(1e-6,0.,0.);
|
||||||
|
float sd = abs(getsat(ic) - mix(getsat(a), getsat(b), x));
|
||||||
|
vec3 dir = normalize(vec3(2.*ic.x - ic.y - ic.z, 2.*ic.y - ic.x - ic.z, 2.*ic.z - ic.y - ic.x));
|
||||||
|
float lgt = dot(vec3(1.0), ic);
|
||||||
|
float ff = dot(dir, normalize(ic));
|
||||||
|
ic += 1.5*dir*sd*ff*lgt;
|
||||||
|
return clamp(ic,0.,1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
vec2 p = q - 0.5;
|
||||||
|
p.x *= iResolution.x/iResolution.y;
|
||||||
|
vec2 mous = iMouse.xy/iResolution.xy;
|
||||||
|
vec2 mo = mous - 0.5;
|
||||||
|
bsMo = mo;
|
||||||
|
mo = (mo==vec2(-0.5))?mo=vec2(0.12, 0.15):mo;
|
||||||
|
mo.x *= iResolution.x/iResolution.y;
|
||||||
|
mo*= 4.14;
|
||||||
|
mo.y = clamp(mo.y*0.6-.5,-4. ,.15 );
|
||||||
|
|
||||||
|
float time = iTime*3.;
|
||||||
|
vec3 ro = vec3(0,0,time);
|
||||||
|
|
||||||
|
|
||||||
|
ro += vec3(sin(iTime)*0.5,sin(iTime*1.)*0.,0);
|
||||||
|
|
||||||
|
float dspAmp = .85;
|
||||||
|
ro.xy += disp(ro.z)*dspAmp;
|
||||||
|
float tgtDst = 3.5;
|
||||||
|
|
||||||
|
|
||||||
|
vec3 target = normalize(ro - vec3(disp(time + tgtDst)*dspAmp, time + tgtDst));
|
||||||
|
ro.x -= bsMo.x*2.;
|
||||||
|
vec3 rightdir = normalize(cross(target, vec3(0,1,0)));
|
||||||
|
vec3 updir = normalize(cross(rightdir, target));
|
||||||
|
rightdir = normalize(cross(updir, target));
|
||||||
|
vec3 rd=normalize((p.x*rightdir + p.y*updir)*1. - target);
|
||||||
|
rd.xy *= rot(-disp(time + 3.5).x*0.2 + bsMo.x);
|
||||||
|
prm1 = smoothstep(-0.4, 0.4,sin(iTime*0.3));
|
||||||
|
vec4 scn = render(ro, rd, time);
|
||||||
|
|
||||||
|
vec3 col = scn.rgb;
|
||||||
|
col = iLerp(col.bgr, col.rgb, clamp(1.-prm1,0.05,1.));
|
||||||
|
|
||||||
|
col = pow(col, vec3(.55,0.65,0.6))*vec3(1.,.97,.9);
|
||||||
|
|
||||||
|
col *= pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.12)*0.7+0.3; //Vign
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,313 @@
|
||||||
|
//bio.jpg, hill.jpg, check.jpg
|
||||||
|
//Raymarch settings
|
||||||
|
|
||||||
|
#define MIN_DIST 0.001
|
||||||
|
#define MAX_DIST 32.0
|
||||||
|
#define MAX_STEPS 96
|
||||||
|
#define STEP_MULT 0.9
|
||||||
|
#define NORMAL_OFFS 0.01
|
||||||
|
#define FOCAL_LENGTH 0.8
|
||||||
|
|
||||||
|
//Scene settings
|
||||||
|
|
||||||
|
//#define SHOW_RAY_COST
|
||||||
|
|
||||||
|
//Colors
|
||||||
|
#define SKY_COLOR_1 vec3(0.60,0.00,0.00)
|
||||||
|
#define SKY_COLOR_2 vec3(1.00,0.50,0.00)
|
||||||
|
|
||||||
|
#define SUN_COLOR_1 vec3(1.00, 0.00, 0.00)
|
||||||
|
#define SUN_COLOR_2 vec3(1.00, 1.00, 0.00)
|
||||||
|
|
||||||
|
#define GRID_COLOR_1 vec3(0.00, 0.05, 0.20)
|
||||||
|
#define GRID_COLOR_2 vec3(1.00, 0.20, 0.60)
|
||||||
|
|
||||||
|
#define WATER_COLOR vec3(0.50, 1.00, 2.90)
|
||||||
|
|
||||||
|
//Parameters
|
||||||
|
#define GRID_SIZE 0.20
|
||||||
|
#define GRID_LINE_SIZE 1.25
|
||||||
|
|
||||||
|
#define WATER_LEVEL 0.20
|
||||||
|
#define WATER_FOG_SIZE 0.05
|
||||||
|
|
||||||
|
#define SUN_DIRECTION vec3( 0.10,-1.00,-0.03)
|
||||||
|
|
||||||
|
#define CLOUD_SCROLL vec2(0.002, 0.001)
|
||||||
|
#define CLOUD_BLUR 2.0
|
||||||
|
#define CLOUD_SCALE vec2(0.04, 0.10)
|
||||||
|
|
||||||
|
#define MOUNTAIN_SCALE 6.0
|
||||||
|
#define MOUNTAIN_SHIFT 5.3
|
||||||
|
|
||||||
|
//Color modes
|
||||||
|
//vec3(#,#,#) Number of bits per channel
|
||||||
|
|
||||||
|
//24 bit color
|
||||||
|
#define RGB888 vec3(8,8,8)
|
||||||
|
//16 bit color
|
||||||
|
#define RGB565 vec3(5,6,5)
|
||||||
|
#define RGB664 vec3(6,6,4)
|
||||||
|
//8 bit color
|
||||||
|
#define RGB332 vec3(3,3,2)
|
||||||
|
#define RGB242 vec3(2,4,2)
|
||||||
|
#define RGB222 vec3(2,2,2) //+2 unused
|
||||||
|
|
||||||
|
//#define DITHER_ENABLE
|
||||||
|
#define COLOR_MODE RGB242
|
||||||
|
|
||||||
|
//Object IDs
|
||||||
|
#define SKYDOME 0.
|
||||||
|
#define FLOOR 1.
|
||||||
|
#define RIVER 2.
|
||||||
|
|
||||||
|
float pi = atan(1.0) * 4.0;
|
||||||
|
float tau = atan(1.0) * 8.0;
|
||||||
|
|
||||||
|
vec3 dither(vec3 color, vec3 bits, vec2 pixel)
|
||||||
|
{
|
||||||
|
vec3 cmax = exp2(bits)-1.0;
|
||||||
|
|
||||||
|
vec3 dithfactor = mod(color, 1.0 / cmax) * cmax;
|
||||||
|
float dithlevel = texture(iChannel2,pixel / iChannelResolution[2].xy).r;
|
||||||
|
|
||||||
|
vec3 cl = floor(color * cmax)/cmax;
|
||||||
|
vec3 ch = ceil(color * cmax)/cmax;
|
||||||
|
|
||||||
|
return mix(cl, ch, step(dithlevel, dithfactor));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MarchResult
|
||||||
|
{
|
||||||
|
vec3 position;
|
||||||
|
vec3 normal;
|
||||||
|
float dist;
|
||||||
|
float steps;
|
||||||
|
float id;
|
||||||
|
};
|
||||||
|
|
||||||
|
//Returns a rotation matrix for the given angles around the X,Y,Z axes.
|
||||||
|
mat3 Rotate(vec3 angles)
|
||||||
|
{
|
||||||
|
vec3 c = cos(angles);
|
||||||
|
vec3 s = sin(angles);
|
||||||
|
|
||||||
|
mat3 rotX = mat3( 1.0, 0.0, 0.0, 0.0,c.x,s.x, 0.0,-s.x, c.x);
|
||||||
|
mat3 rotY = mat3( c.y, 0.0,-s.y, 0.0,1.0,0.0, s.y, 0.0, c.y);
|
||||||
|
mat3 rotZ = mat3( c.z, s.z, 0.0,-s.z,c.z,0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
return rotX * rotY * rotZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==== Distance field operators/functions by iq. ====
|
||||||
|
vec2 opU(vec2 d1, vec2 d2)
|
||||||
|
{
|
||||||
|
return (d1.x < d2.x) ? d1 : d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 opS(vec2 d1, vec2 d2)
|
||||||
|
{
|
||||||
|
return (-d1.x > d2.x) ? d1*vec2(-1,1) : d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 sdSphere(vec3 p, float s, float id)
|
||||||
|
{
|
||||||
|
return vec2(length(p) - s, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 sdPlane(vec3 p, vec4 n, float id)
|
||||||
|
{
|
||||||
|
// n must be normalized
|
||||||
|
return vec2(dot(p,n.xyz) + n.w, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 sdColumn(vec3 p, float r, float id)
|
||||||
|
{
|
||||||
|
return vec2(((abs(p.x)+abs(p.y))-r)/sqrt(2.0), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 dfRiver(vec3 p, float id)
|
||||||
|
{
|
||||||
|
float offs = sin(p.y)*0.15 + sin(p.y * 0.2);
|
||||||
|
|
||||||
|
return sdColumn(p.xzy + vec3(offs,0,0), 0.4, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Distance to the scene
|
||||||
|
vec2 Scene(vec3 p)
|
||||||
|
{
|
||||||
|
vec2 d = vec2(MAX_DIST, SKYDOME);
|
||||||
|
|
||||||
|
d = opU(sdPlane(p, vec4(0, 0,-1, 0), FLOOR), d);
|
||||||
|
|
||||||
|
d = opS(dfRiver(p, RIVER), d);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Surface normal at the current position
|
||||||
|
vec3 Normal(vec3 p)
|
||||||
|
{
|
||||||
|
vec3 off = vec3(NORMAL_OFFS, 0, 0);
|
||||||
|
return normalize
|
||||||
|
(
|
||||||
|
vec3
|
||||||
|
(
|
||||||
|
Scene(p + off.xyz).x - Scene(p - off.xyz).x,
|
||||||
|
Scene(p + off.zxy).x - Scene(p - off.zxy).x,
|
||||||
|
Scene(p + off.yzx).x - Scene(p - off.yzx).x
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Raymarch the scene with the given ray
|
||||||
|
MarchResult MarchRay(vec3 orig,vec3 dir)
|
||||||
|
{
|
||||||
|
float steps = 0.0;
|
||||||
|
float dist = 0.0;
|
||||||
|
float id = 0.0;
|
||||||
|
|
||||||
|
for(int i = 0;i < MAX_STEPS;i++)
|
||||||
|
{
|
||||||
|
vec2 object = Scene(orig + dir * dist);
|
||||||
|
|
||||||
|
//Add the sky dome and have it follow the camera.
|
||||||
|
object = opU(object, -sdSphere(dir * dist, MAX_DIST, SKYDOME));
|
||||||
|
|
||||||
|
dist += object.x * STEP_MULT;
|
||||||
|
|
||||||
|
id = object.y;
|
||||||
|
|
||||||
|
steps++;
|
||||||
|
|
||||||
|
if(abs(object.x) < MIN_DIST * dist)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MarchResult result;
|
||||||
|
|
||||||
|
result.position = orig + dir * dist;
|
||||||
|
result.normal = Normal(result.position);
|
||||||
|
result.dist = dist;
|
||||||
|
result.steps = steps;
|
||||||
|
result.id = id;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Scene texturing/shading
|
||||||
|
vec3 Shade(MarchResult hit, vec3 direction, vec3 camera)
|
||||||
|
{
|
||||||
|
vec3 color = vec3(0.0);
|
||||||
|
|
||||||
|
if(hit.id == FLOOR)
|
||||||
|
{
|
||||||
|
vec2 uv = abs(mod(hit.position.xy + GRID_SIZE/2.0, GRID_SIZE) - GRID_SIZE/2.0);
|
||||||
|
|
||||||
|
uv /= fwidth(hit.position.xy);
|
||||||
|
|
||||||
|
float riverEdge = dfRiver(hit.position, 0.0).x / fwidth(hit.position.xy).x;
|
||||||
|
|
||||||
|
float gln = min(min(uv.x, uv.y), riverEdge) / GRID_SIZE;
|
||||||
|
|
||||||
|
color = mix(GRID_COLOR_1, GRID_COLOR_2, 1.0 - smoothstep(0.0, GRID_LINE_SIZE / GRID_SIZE, gln));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hit.id == RIVER)
|
||||||
|
{
|
||||||
|
vec2 uv = vec2(hit.position.z, abs(mod(hit.position.y + GRID_SIZE/2.0, GRID_SIZE) - GRID_SIZE/2.0));
|
||||||
|
uv /= fwidth(hit.position.xy);
|
||||||
|
|
||||||
|
float gln = min(uv.x, uv.y) / GRID_SIZE;
|
||||||
|
|
||||||
|
color = mix(GRID_COLOR_1, GRID_COLOR_2, 1.0 - smoothstep(0.0, GRID_LINE_SIZE / GRID_SIZE, gln));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Distance fog
|
||||||
|
color *= 1.0 - smoothstep(0.0, MAX_DIST*0.9, hit.dist);
|
||||||
|
|
||||||
|
//Water
|
||||||
|
float waterMix = smoothstep(WATER_LEVEL - WATER_FOG_SIZE, WATER_LEVEL + WATER_FOG_SIZE, hit.position.z);
|
||||||
|
|
||||||
|
color = mix(color, WATER_COLOR, waterMix);
|
||||||
|
|
||||||
|
if(hit.id == SKYDOME)
|
||||||
|
{
|
||||||
|
//Sky gradient
|
||||||
|
//Causes weird position-colored artefacts around the horizon (AMD R9 270)
|
||||||
|
//color = mix(SKY_COLOR_1, SKY_COLOR_2, -hit.position.z/16.0);
|
||||||
|
color += mix(SKY_COLOR_1, SKY_COLOR_2, -hit.position.z/16.0);
|
||||||
|
|
||||||
|
//Sun
|
||||||
|
vec3 sunDir = normalize(SUN_DIRECTION);
|
||||||
|
|
||||||
|
float sun = smoothstep(0.950, 0.952, dot(direction, sunDir));
|
||||||
|
|
||||||
|
vec3 sunCol = mix(SUN_COLOR_1, SUN_COLOR_2, -hit.position.z/16.0);
|
||||||
|
|
||||||
|
color = mix(color, sunCol, sun);
|
||||||
|
|
||||||
|
//Clouds
|
||||||
|
vec2 cloudUV = CLOUD_SCALE * direction.xy / dot(direction, vec3(0, 0,-1));
|
||||||
|
cloudUV += CLOUD_SCROLL * iGlobalTime;
|
||||||
|
|
||||||
|
color *= smoothstep(0.5, 0.3, texture(iChannel1, cloudUV, CLOUD_BLUR).r) * 0.5 + 0.5;
|
||||||
|
|
||||||
|
//Mountains
|
||||||
|
float a = atan(hit.position.y, hit.position.x)/tau + 0.5;
|
||||||
|
a -= 3.28;
|
||||||
|
|
||||||
|
float mountains = MOUNTAIN_SCALE * texture(iChannel0, vec2(a, 0.1),-99.0).r - hit.position.z - MOUNTAIN_SHIFT;
|
||||||
|
|
||||||
|
color = mix(color, vec3(0.0), 1.0 - smoothstep(0.6, 0.7, mountains));
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 res = iResolution.xy / iResolution.y;
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.y;
|
||||||
|
|
||||||
|
//Camera stuff
|
||||||
|
vec3 angles = vec3(0);
|
||||||
|
|
||||||
|
//Auto mode
|
||||||
|
if(iMouse.xy == vec2(0,0))
|
||||||
|
{
|
||||||
|
angles.y = tau * (1.8 / 8.0);
|
||||||
|
angles.x = tau * (3.9 / 8.0) + sin(iGlobalTime * 0.1) * 0.3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
angles = vec3((iMouse.xy / iResolution.xy) * pi, 0);
|
||||||
|
angles.xy *= vec2(2.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
angles.y = clamp(angles.y, 0.0, 15.5 * tau / 64.0);
|
||||||
|
|
||||||
|
mat3 rotate = Rotate(angles.yzx);
|
||||||
|
|
||||||
|
vec3 orig = vec3(0, 0,-2) * rotate;
|
||||||
|
|
||||||
|
vec3 dir = normalize(vec3(uv - res / 2.0, FOCAL_LENGTH)) * rotate;
|
||||||
|
|
||||||
|
//Ray marching
|
||||||
|
MarchResult hit = MarchRay(orig, dir);
|
||||||
|
|
||||||
|
//Shading
|
||||||
|
vec3 color = Shade(hit, dir, orig);
|
||||||
|
|
||||||
|
#ifdef SHOW_RAY_COST
|
||||||
|
color = mix(vec3(0,1,0), vec3(1,0,0), hit.steps / float(MAX_STEPS));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DITHER_ENABLE
|
||||||
|
color = dither(color, COLOR_MODE, fragCoord);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fragColor = vec4(color, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,718 @@
|
||||||
|
#define line1 H_ e_ l_ l_ o_ _ BOLD S_ h_ a_ d_ e_ r_ t_ o_ y_ BOLD _ t_ h_ i_ s_ _ i_ s_ _ m_ y_
|
||||||
|
#define line2 BLUE p_ r_ o_ p_ o_ r_ t_ i_ o_ n_ a_ l_ BLUE _ f_ o_ n_ t_ _dot _ I_ _ h_ o_ p_ e_ _ y_ o_ u_
|
||||||
|
#define line3 GREEN l_ i_ k_ e_ GREEN _ i_ t_ _comma _ RED f_ e_ e_ l_ RED _ ITAL f_ r_ e_ e_ ITAL _ t_ o_ _ u_ s_ e_ _ i_ t_ _dot
|
||||||
|
#define line4 a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_
|
||||||
|
#define line5 A_ B_ C_ D_ E_ F_ G_ H_ I_ J_ K_ L_ M_ N_ O_ P_ Q_ R_ S_ T_ U_ V_ W_ X_ Y_ Z_
|
||||||
|
#define line6 _1 _2 _3 _4 _5 _6 _7 _8 _9 _0 _dot _comma _exclam _question _open1 _close1 _dotdot _dotcomma _equal _add _sub _mul _div _lt _gt _hash _and _or _und _open2 _close2 _open3 _close3
|
||||||
|
|
||||||
|
// line function, used in k, v, w, x, y, z, 1, 2, 4, 7 and ,
|
||||||
|
// rest is drawn using (stretched) circle(g)
|
||||||
|
|
||||||
|
// todo: distance fields of s,S, J { and }
|
||||||
|
// todo before we can show shaders :)
|
||||||
|
//
|
||||||
|
|
||||||
|
float line(vec2 p, vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 pa = p - a;
|
||||||
|
vec2 ba = b - a;
|
||||||
|
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||||
|
return length(pa - ba * h);
|
||||||
|
}
|
||||||
|
|
||||||
|
//These functions are re-used by multiple letters
|
||||||
|
float _u(vec2 uv, float w, float v) {
|
||||||
|
return length(vec2(
|
||||||
|
abs(length(vec2(uv.x,
|
||||||
|
max(0.0,-(.4-v)-uv.y) ))-w)
|
||||||
|
,max(0.,uv.y-.4)));
|
||||||
|
}
|
||||||
|
float _i(vec2 uv) {
|
||||||
|
return length(vec2(uv.x,max(0.,abs(uv.y)-.4)));
|
||||||
|
}
|
||||||
|
float _j(vec2 uv) {
|
||||||
|
uv.x+=.2;
|
||||||
|
uv.y+=.55;
|
||||||
|
float x = uv.x>0.&&uv.y<0.?
|
||||||
|
abs(length(uv)-.25)
|
||||||
|
:min(length(uv+vec2(0.,.25)),
|
||||||
|
length(vec2(uv.x-.25,max(0.,abs(uv.y-.475)-.475))));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float _l(vec2 uv) {
|
||||||
|
uv.y -= .2;
|
||||||
|
return length(vec2(uv.x,max(0.,abs(uv.y)-.6)));
|
||||||
|
}
|
||||||
|
float _o(vec2 uv) {
|
||||||
|
return abs(length(vec2(uv.x,max(0.,abs(uv.y)-.15)))-.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here is the alphabet
|
||||||
|
float aa(vec2 uv) {
|
||||||
|
uv = -uv;
|
||||||
|
float x = abs(length(vec2(max(0.,abs(uv.x)-.05),uv.y-.2))-.2);
|
||||||
|
x = min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y-.2)-.2))));
|
||||||
|
return min(x,(uv.x<0.?uv.y<0.:atan(uv.x,uv.y+0.15)>2.)?_o(uv):length(vec2(uv.x-.22734,uv.y+.254)));
|
||||||
|
}
|
||||||
|
float bb(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.x += .25;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float cc(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.y= abs(uv.y);
|
||||||
|
return uv.x<0.||atan(uv.x,uv.y-0.15)<1.14?x:
|
||||||
|
min(length(vec2(uv.x+.25,max(0.0,abs(uv.y)-.15))),//makes df right
|
||||||
|
length(uv+vec2(-.22734,-.254)));
|
||||||
|
}
|
||||||
|
float dd(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
return bb(uv);
|
||||||
|
}
|
||||||
|
float ee(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
return min(uv.x<0.||uv.y>.05||atan(uv.x,uv.y+0.15)>2.?x:length(vec2(uv.x-.22734,uv.y+.254)),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y-.05)));
|
||||||
|
}
|
||||||
|
float ff(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
uv.x += .05;
|
||||||
|
float x = _j(vec2(uv.x,-uv.y));
|
||||||
|
uv.y -= .4;
|
||||||
|
x = min(x,length(vec2(max(0.,abs(uv.x-.05)-.25),uv.y)));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float gg(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
return min(x,uv.x>0.||atan(uv.x,uv.y+.6)<-2.?
|
||||||
|
_u(uv,0.25,-0.2):
|
||||||
|
length(uv+vec2(.23,.7)));
|
||||||
|
}
|
||||||
|
float hh(vec2 uv) {
|
||||||
|
uv.y *= -1.;
|
||||||
|
float x = _u(uv,.25,.25);
|
||||||
|
uv.x += .25;
|
||||||
|
uv.y *= -1.;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float ii(vec2 uv) {
|
||||||
|
return min(_i(uv),length(vec2(uv.x,uv.y-.6)));
|
||||||
|
}
|
||||||
|
float jj(vec2 uv) {
|
||||||
|
uv.x+=.05;
|
||||||
|
return min(_j(uv),length(vec2(uv.x-.05,uv.y-.6)));
|
||||||
|
}
|
||||||
|
float kk(vec2 uv) {
|
||||||
|
float x = line(uv,vec2(-.25,-.1), vec2(0.25,0.4));
|
||||||
|
x = min(x,line(uv,vec2(-.15,.0), vec2(0.25,-0.4)));
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float ll(vec2 uv) {
|
||||||
|
return _l(uv);
|
||||||
|
}
|
||||||
|
float mm(vec2 uv) {
|
||||||
|
//uv.x *= 1.4;
|
||||||
|
uv.y *= -1.;
|
||||||
|
uv.x-=.175;
|
||||||
|
float x = _u(uv,.175,.175);
|
||||||
|
uv.x+=.35;
|
||||||
|
x = min(x,_u(uv,.175,.175));
|
||||||
|
uv.x+=.175;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float nn(vec2 uv) {
|
||||||
|
uv.y *= -1.;
|
||||||
|
float x = _u(uv,.25,.25);
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float oo(vec2 uv) {
|
||||||
|
return _o(uv);
|
||||||
|
}
|
||||||
|
float pp(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.x += .25;
|
||||||
|
uv.y += .4;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float qq(vec2 uv) {
|
||||||
|
uv.x = -uv.x;
|
||||||
|
return pp(uv);
|
||||||
|
}
|
||||||
|
float rr(vec2 uv) {
|
||||||
|
uv.x -= .05;
|
||||||
|
float x =atan(uv.x,uv.y-0.15)<1.14&&uv.y>0.?_o(uv):length(vec2(uv.x-.22734,uv.y-.254));
|
||||||
|
|
||||||
|
//)?_o(uv):length(vec2(uv.x-.22734,uv.y+.254))+.4);
|
||||||
|
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float ss(vec2 uv) {
|
||||||
|
if (uv.y <.225-uv.x*.5 && uv.x>0. || uv.y<-.225-uv.x*.5)
|
||||||
|
uv = -uv;
|
||||||
|
float a = abs(length(vec2(max(0.,abs(uv.x)-.05),uv.y-.2))-.2);
|
||||||
|
float b = length(vec2(uv.x-.231505,uv.y-.284));
|
||||||
|
float x = atan(uv.x-.05,uv.y-0.2)<1.14?a:b;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float tt(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
uv.y -= .4;
|
||||||
|
uv.x += .05;
|
||||||
|
float x = min(_j(uv),length(vec2(max(0.,abs(uv.x-.05)-.25),uv.y)));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float uu(vec2 uv) {
|
||||||
|
return _u(uv,.25,.25);
|
||||||
|
}
|
||||||
|
float vv(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return line(uv,vec2(0.25,0.4), vec2(0.,-0.4));
|
||||||
|
}
|
||||||
|
float ww(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return min(line(uv,vec2(0.3,0.4), vec2(.2,-0.4)),
|
||||||
|
line(uv,vec2(0.2,-0.4), vec2(0.,0.1)));
|
||||||
|
}
|
||||||
|
float xx(vec2 uv) {
|
||||||
|
uv=abs(uv);
|
||||||
|
return line(uv,vec2(0.,0.), vec2(.3,0.4));
|
||||||
|
}
|
||||||
|
float yy(vec2 uv) {
|
||||||
|
return min(line(uv,vec2(.0,-.2), vec2(-.3,0.4)),
|
||||||
|
line(uv,vec2(.3,.4), vec2(-.3,-0.8)));
|
||||||
|
}
|
||||||
|
float zz(vec2 uv) {
|
||||||
|
float l = line(uv,vec2(0.25,0.4), vec2(-0.25,-0.4));
|
||||||
|
uv.y=abs(uv.y);
|
||||||
|
float x = length(vec2(max(0.,abs(uv.x)-.25),uv.y-.4));
|
||||||
|
return min(x,l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capitals
|
||||||
|
float AA(vec2 uv) {
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(uv.x,
|
||||||
|
max(0.0,uv.y-.35) ))-0.25)
|
||||||
|
,min(0.,uv.y+.4)));
|
||||||
|
return min(x,length(vec2(max(0.,abs(uv.x)-.25),uv.y-.1) ));
|
||||||
|
}
|
||||||
|
|
||||||
|
float BB(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(max(0.0,uv.x),
|
||||||
|
uv.y-.25))-0.25)
|
||||||
|
,min(0.,uv.x+.25)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y)-.5)) ));
|
||||||
|
}
|
||||||
|
float CC(vec2 uv) {
|
||||||
|
float x = abs(length(vec2(uv.x,max(0.,abs(uv.y-.1)-.25)))-.25);
|
||||||
|
uv.y -= .1;
|
||||||
|
uv.y= abs(uv.y);
|
||||||
|
return uv.x<0.||atan(uv.x,uv.y-0.25)<1.14?x:
|
||||||
|
min(length(vec2(uv.x+.25,max(0.0,abs(uv.y)-.25))),//makes df right
|
||||||
|
length(uv+vec2(-.22734,-.354)));
|
||||||
|
}
|
||||||
|
float DD(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
//uv.y = abs(uv.y);
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(max(0.0,uv.x),
|
||||||
|
max(0.0,abs(uv.y)-.25)))-0.25)
|
||||||
|
,min(0.,uv.x+.25)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y)-.5)) ));
|
||||||
|
}
|
||||||
|
float EE(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
float x = min(length(vec2(max(0.,abs(uv.x)-.25),uv.y)),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y-.5)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float FF(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
float x = min(length(vec2(max(0.,abs(uv.x)-.25),uv.y)),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y-.5)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float GG(vec2 uv) {
|
||||||
|
float x = abs(length(vec2(uv.x,max(0.,abs(uv.y-.1)-.25)))-.25);
|
||||||
|
uv.y -= .1;
|
||||||
|
float a = atan(uv.x,max(0.,abs(uv.y)-0.25));
|
||||||
|
x = uv.x<0.||a<1.14 || a>3.?x:
|
||||||
|
min(length(vec2(uv.x+.25,max(0.0,abs(uv.y)-.25))),//makes df right
|
||||||
|
length(uv+vec2(-.22734,-.354)));
|
||||||
|
x = min(x,line(uv,vec2(.22734,-.1),vec2(.22734,-.354)));
|
||||||
|
return min(x,line(uv,vec2(.22734,-.1),vec2(.05,-.1)));
|
||||||
|
}
|
||||||
|
float HH(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
uv.x = abs(uv.x);
|
||||||
|
float x = length(vec2(max(0.,abs(uv.x)-.25),uv.y));
|
||||||
|
return min(x,length(vec2(uv.x-.25,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float II(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
float x = length(vec2(uv.x,max(0.,abs(uv.y)-.5)));
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
return min(x,length(vec2(max(0.,abs(uv.x)-.1),uv.y-.5)));
|
||||||
|
}
|
||||||
|
float JJ(vec2 uv) {
|
||||||
|
uv.x += .125;
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(uv.x,
|
||||||
|
min(0.0,uv.y+.15) ))-0.25)
|
||||||
|
,max(0.,max(-uv.x,uv.y-.6))));
|
||||||
|
return min(x,length(vec2(max(0.,abs(uv.x-.125)-.125),uv.y-.6)));
|
||||||
|
}
|
||||||
|
float KK(vec2 uv) {
|
||||||
|
float x = line(uv,vec2(-.25,-.1), vec2(0.25,0.6));
|
||||||
|
x = min(x,line(uv,vec2(-.1, .1), vec2(0.25,-0.4)));
|
||||||
|
// uv.x+=.25;
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y-.1)-.5))));
|
||||||
|
}
|
||||||
|
float LL(vec2 uv) {
|
||||||
|
uv.y -=.1;
|
||||||
|
float x = length(vec2(max(0.,abs(uv.x)-.2),uv.y+.5));
|
||||||
|
return min(x,length(vec2(uv.x+.2,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float MM(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
float x = min(length(vec2(uv.x-.35,max(0.,abs(uv.y)-.5))),
|
||||||
|
line(uv,vec2(-.35,.5),vec2(.0,-.1)));
|
||||||
|
x = min(x,line(uv,vec2(.0,-.1),vec2(.35,.5)));
|
||||||
|
return min(x,length(vec2(uv.x+.35,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float NN(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
float x = min(length(vec2(uv.x-.25,max(0.,abs(uv.y)-.5))),
|
||||||
|
line(uv,vec2(-.25,.5),vec2(.25,-.5)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y)-.5))));
|
||||||
|
}
|
||||||
|
float OO(vec2 uv) {
|
||||||
|
return abs(length(vec2(uv.x,max(0.,abs(uv.y-.1)-.25)))-.25);
|
||||||
|
}
|
||||||
|
float PP(vec2 uv) {
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(max(0.0,uv.x),
|
||||||
|
uv.y-.35))-0.25)
|
||||||
|
,min(0.,uv.x+.25)));
|
||||||
|
return min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y-.1)-.5)) ));
|
||||||
|
}
|
||||||
|
float QQ(vec2 uv) {
|
||||||
|
float x = abs(length(vec2(uv.x,max(0.,abs(uv.y-.1)-.25)))-.25);
|
||||||
|
uv.y += .3;
|
||||||
|
uv.x -= .2;
|
||||||
|
return min(x,length(vec2(abs(uv.x+uv.y),max(0.,abs(uv.x-uv.y)-.2)))/sqrt(2.));
|
||||||
|
}
|
||||||
|
float RR(vec2 uv) {
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(max(0.0,uv.x),
|
||||||
|
uv.y-.35))-0.25)
|
||||||
|
,min(0.,uv.x+.25)));
|
||||||
|
x = min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y-.1)-.5)) ));
|
||||||
|
return min(x,line(uv,vec2(0.0,0.1),vec2(0.25,-0.4)));
|
||||||
|
}
|
||||||
|
float SS(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
if (uv.y <.275-uv.x*.5 && uv.x>0. || uv.y<-.275-uv.x*.5)
|
||||||
|
uv = -uv;
|
||||||
|
float a = abs(length(vec2(max(0.,abs(uv.x)),uv.y-.25))-.25);
|
||||||
|
float b = length(vec2(uv.x-.236,uv.y-.332));
|
||||||
|
float x = atan(uv.x-.05,uv.y-0.25)<1.14?a:b;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float TT(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
float x = length(vec2(uv.x,max(0.,abs(uv.y)-.5)));
|
||||||
|
return min(x,length(vec2(max(0.,abs(uv.x)-.25),uv.y-.5)));
|
||||||
|
}
|
||||||
|
float UU(vec2 uv) {
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2(uv.x,
|
||||||
|
min(0.0,uv.y+.15) ))-0.25)
|
||||||
|
,max(0.,uv.y-.6)));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float VV(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return line(uv,vec2(0.25,0.6), vec2(0.,-0.4));
|
||||||
|
}
|
||||||
|
float WW(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return min(line(uv,vec2(0.3,0.6), vec2(.2,-0.4)),
|
||||||
|
line(uv,vec2(0.2,-0.4), vec2(0.,0.2)));
|
||||||
|
}
|
||||||
|
float XX(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv=abs(uv);
|
||||||
|
return line(uv,vec2(0.,0.), vec2(.3,0.5));
|
||||||
|
}
|
||||||
|
float YY(vec2 uv) {
|
||||||
|
return min(min(line(uv,vec2(.0, .1), vec2(-.3, 0.6)),
|
||||||
|
line(uv,vec2(.0, .1), vec2( .3, 0.6))),
|
||||||
|
length(vec2(uv.x,max(0.,abs(uv.y+.15)-.25))));
|
||||||
|
}
|
||||||
|
float ZZ(vec2 uv) {
|
||||||
|
float l = line(uv,vec2(0.25,0.6), vec2(-0.25,-0.4));
|
||||||
|
uv.y-=.1;
|
||||||
|
uv.y=abs(uv.y);
|
||||||
|
float x = length(vec2(max(0.,abs(uv.x)-.25),uv.y-.5));
|
||||||
|
return min(x,l);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Numbers
|
||||||
|
float _11(vec2 uv) {
|
||||||
|
return min(min(
|
||||||
|
line(uv,vec2(-0.2,0.45),vec2(0.,0.6)),
|
||||||
|
length(vec2(uv.x,max(0.,abs(uv.y-.1)-.5)))),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.2),uv.y+.4)));
|
||||||
|
|
||||||
|
}
|
||||||
|
float _22(vec2 uv) {
|
||||||
|
float x = min(line(uv,vec2(0.185,0.17),vec2(-.25,-.4)),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y+.4)));
|
||||||
|
uv.y-=.35;
|
||||||
|
uv.x += 0.025;
|
||||||
|
return min(x,abs(atan(uv.x,uv.y)-0.63)<1.64?abs(length(uv)-.275):
|
||||||
|
length(uv+vec2(.23,-.15)));
|
||||||
|
}
|
||||||
|
float _33(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
uv.y-=.25;
|
||||||
|
return atan(uv.x,uv.y)>-1.?abs(length(uv)-.25):
|
||||||
|
min(length(uv+vec2(.211,-.134)),length(uv+vec2(.0,.25)));
|
||||||
|
}
|
||||||
|
float _44(vec2 uv) {
|
||||||
|
float x = min(length(vec2(uv.x-.15,max(0.,abs(uv.y-.1)-.5))),
|
||||||
|
line(uv,vec2(0.15,0.6),vec2(-.25,-.1)));
|
||||||
|
return min(x,length(vec2(max(0.,abs(uv.x)-.25),uv.y+.1)));
|
||||||
|
}
|
||||||
|
float _55(vec2 uv) {
|
||||||
|
float b = min(length(vec2(max(0.,abs(uv.x)-.25),uv.y-.6)),
|
||||||
|
length(vec2(uv.x+.25,max(0.,abs(uv.y-.36)-.236))));
|
||||||
|
uv.y += 0.1;
|
||||||
|
uv.x += 0.05;
|
||||||
|
float c = abs(length(vec2(uv.x,max(0.,abs(uv.y)-.0)))-.3);
|
||||||
|
return min(b,abs(atan(uv.x,uv.y)+1.57)<.86 && uv.x<0.?
|
||||||
|
length(uv+vec2(.2,.224))
|
||||||
|
:c);
|
||||||
|
}
|
||||||
|
float _66(vec2 uv) {
|
||||||
|
uv.y-=.075;
|
||||||
|
uv = -uv;
|
||||||
|
float b = abs(length(vec2(uv.x,max(0.,abs(uv.y)-.275)))-.25);
|
||||||
|
uv.y-=.175;
|
||||||
|
float c = abs(length(vec2(uv.x,max(0.,abs(uv.y)-.05)))-.25);
|
||||||
|
return min(c,cos(atan(uv.x,uv.y+.45)+0.65)<0.||(uv.x>0.&& uv.y<0.)?b:
|
||||||
|
length(uv+vec2(0.2,0.6)));
|
||||||
|
}
|
||||||
|
float _77(vec2 uv) {
|
||||||
|
return min(length(vec2(max(0.,abs(uv.x)-.25),uv.y-.6)),
|
||||||
|
line(uv,vec2(-0.25,-0.39),vec2(0.25,0.6)));
|
||||||
|
}
|
||||||
|
float _88(vec2 uv) {
|
||||||
|
float l = length(vec2(max(0.,abs(uv.x)-.08),uv.y-.1+uv.x*.07));
|
||||||
|
uv.y-=.1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
uv.y-=.245;
|
||||||
|
return min(abs(length(uv)-.255),l);
|
||||||
|
}
|
||||||
|
float _99(vec2 uv) {
|
||||||
|
uv.y-=.125;
|
||||||
|
float b = abs(length(vec2(uv.x,max(0.,abs(uv.y)-.275)))-.25);
|
||||||
|
uv.y-=.175;
|
||||||
|
float c = abs(length(vec2(uv.x,max(0.,abs(uv.y)-.05)))-.25);
|
||||||
|
return min(c,cos(atan(uv.x,uv.y+.45)+0.65)<0.||(uv.x>0.&& uv.y<0.)?b:
|
||||||
|
length(uv+vec2(0.2,0.6)));
|
||||||
|
}
|
||||||
|
float _00(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
return abs(length(vec2(uv.x,max(0.,abs(uv.y)-.25)))-.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Symbols
|
||||||
|
float ddot(vec2 uv) {
|
||||||
|
uv.y+=.4;
|
||||||
|
return length(uv)*0.97;//-.03;
|
||||||
|
}
|
||||||
|
float comma(vec2 uv) {
|
||||||
|
return min(ddot(uv),line(uv,vec2(.031,-.405),vec2(-.029,-.52)));
|
||||||
|
}
|
||||||
|
float exclam(vec2 uv) {
|
||||||
|
return min(ddot(uv),length(vec2(uv.x,max(0.,abs(uv.y-.2)-.4)))-uv.y*.06);
|
||||||
|
}
|
||||||
|
float question(vec2 uv) {
|
||||||
|
float x = min(ddot(uv),length(vec2(uv.x,max(0.,abs(uv.y+.035)-.1125))));
|
||||||
|
uv.y-=.35;
|
||||||
|
uv.x += 0.025;
|
||||||
|
return min(x,abs(atan(uv.x,uv.y)-1.05)<2.?abs(length(uv)-.275):
|
||||||
|
length(uv+vec2(.225,-.16))-.0);
|
||||||
|
}
|
||||||
|
float open1(vec2 uv) {
|
||||||
|
uv.x-=.62;
|
||||||
|
return abs(atan(uv.x,uv.y)+1.57)<1.?
|
||||||
|
abs(length(uv)-.8)
|
||||||
|
:length(vec2(uv.x+.435,abs(uv.y)-.672));
|
||||||
|
}
|
||||||
|
float close1(vec2 uv) {
|
||||||
|
uv.x = -uv.x;
|
||||||
|
return open1(uv);
|
||||||
|
}
|
||||||
|
float dotdot(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
uv.y-=.25;
|
||||||
|
return length(uv);
|
||||||
|
}
|
||||||
|
float dotcomma(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
float x = line(uv,vec2(.0,-.28),vec2(-.029,-.32));
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
uv.y-=.25;
|
||||||
|
return min(length(uv),x);
|
||||||
|
}
|
||||||
|
float eequal(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
return length(vec2(max(0.,abs(uv.x)-.25),uv.y-.15));
|
||||||
|
}
|
||||||
|
float aadd(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
return min(length(vec2(max(0.,abs(uv.x)-.25),uv.y)),
|
||||||
|
length(vec2(uv.x,max(0.,abs(uv.y)-.25))));
|
||||||
|
}
|
||||||
|
float ssub(vec2 uv) {
|
||||||
|
return length(vec2(max(0.,abs(uv.x)-.25),uv.y-.1));
|
||||||
|
}
|
||||||
|
float mmul(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv = abs(uv);
|
||||||
|
return min(line(uv,vec2(0.866*.25,0.5*.25),vec2(0.))
|
||||||
|
,length(vec2(uv.x,max(0.,abs(uv.y)-.25))));
|
||||||
|
}
|
||||||
|
float ddiv(vec2 uv) {
|
||||||
|
return line(uv,vec2(-0.25,-0.4),vec2(0.25,0.6));
|
||||||
|
}
|
||||||
|
float lt(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
return line(uv,vec2(0.25,0.25),vec2(-0.25,0.));
|
||||||
|
}
|
||||||
|
float gt(vec2 uv) {
|
||||||
|
uv.x=-uv.x;
|
||||||
|
return lt(uv);
|
||||||
|
}
|
||||||
|
float hash(vec2 uv) {
|
||||||
|
uv.y-=.1;
|
||||||
|
uv.x -= uv.y*.1;
|
||||||
|
uv = abs(uv);
|
||||||
|
return min(length(vec2(uv.x-.125,max(0.,abs(uv.y)-.3))),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y-.125)));
|
||||||
|
}
|
||||||
|
float and(vec2 uv) {
|
||||||
|
uv.y-=.44;
|
||||||
|
uv.x+=.05;
|
||||||
|
float x = abs(atan(uv.x,uv.y))<2.356?abs(length(uv)-.15):1.0;
|
||||||
|
x = min(x,line(uv,vec2(-0.106,-0.106),vec2(0.4,-0.712)));
|
||||||
|
x = min(x,line(uv,vec2( 0.106,-0.106),vec2(-0.116,-0.397)));
|
||||||
|
uv.x-=.025;
|
||||||
|
uv.y+=.54;
|
||||||
|
x = min(x,abs(atan(uv.x,uv.y)-.785)>1.57?abs(length(uv)-.2):1.0);
|
||||||
|
return min(x,line(uv,vec2( 0.141,-0.141),vec2( 0.377,0.177)));
|
||||||
|
}
|
||||||
|
float or(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
return length(vec2(uv.x,max(0.,abs(uv.y)-.5)));
|
||||||
|
}
|
||||||
|
float und(vec2 uv) {
|
||||||
|
return length(vec2(max(0.,abs(uv.x)-.25),uv.y+.4));
|
||||||
|
}
|
||||||
|
float open2(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
return min(length(vec2(uv.x+.125,max(0.,abs(uv.y)-.5))),
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.125),uv.y-.5)));
|
||||||
|
}
|
||||||
|
float close2(vec2 uv) {
|
||||||
|
uv.x=-uv.x;
|
||||||
|
return open2(uv);
|
||||||
|
}
|
||||||
|
float open3(vec2 uv) {
|
||||||
|
uv.y -= .1;
|
||||||
|
uv.y = abs(uv.y);
|
||||||
|
float x = length(vec2(
|
||||||
|
abs(length(vec2((uv.x*sign(uv.y-.25)-.2),
|
||||||
|
max(0.0,abs(uv.y-.25)-.05) ))-0.2)
|
||||||
|
,max(0.,abs(uv.x)-.2)));
|
||||||
|
return x;
|
||||||
|
|
||||||
|
}
|
||||||
|
float close3(vec2 uv) {
|
||||||
|
uv.x=-uv.x;
|
||||||
|
return open3(uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 clc(vec2 uv, float cp, float w, float ital) {
|
||||||
|
return uv-vec2(cp-(w*.5)+uv.y*ital,0.);
|
||||||
|
}
|
||||||
|
bool hit(vec2 uv,inout float cp,float w, float px) {
|
||||||
|
return abs((cp+=w)-uv.x)<w+.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Render char if it's up
|
||||||
|
#define ch(l,w) if (hit(uv,cp,w,px)) { x=min(x,l(clc(uv,cp,w,ital))); us=cur;}
|
||||||
|
|
||||||
|
//Render char always (no effects anymore)
|
||||||
|
//#define ch(l,w) x = min(x,l(clc(uv,cp+=w,w,ital)));
|
||||||
|
|
||||||
|
//Make it a bit easier to type text
|
||||||
|
#define a_ ch(aa,0.7);
|
||||||
|
#define b_ ch(bb,0.7);
|
||||||
|
#define c_ ch(cc,0.7);
|
||||||
|
#define d_ ch(dd,0.7);
|
||||||
|
#define e_ ch(ee,0.7);
|
||||||
|
#define f_ ch(ff,0.6);
|
||||||
|
#define g_ ch(gg,0.7);
|
||||||
|
#define h_ ch(hh,0.7);
|
||||||
|
#define i_ ch(ii,0.3);
|
||||||
|
#define j_ ch(jj,0.3);
|
||||||
|
#define k_ ch(kk,0.7);
|
||||||
|
#define l_ ch(ll,0.3);
|
||||||
|
#define m_ ch(mm,0.9);
|
||||||
|
#define n_ ch(nn,0.7);
|
||||||
|
#define o_ ch(oo,0.7);
|
||||||
|
#define p_ ch(pp,0.7);
|
||||||
|
#define q_ ch(qq,0.7);
|
||||||
|
#define r_ ch(rr,0.7);
|
||||||
|
#define s_ ch(ss,0.7);
|
||||||
|
#define t_ ch(tt,0.7);
|
||||||
|
#define u_ ch(uu,0.7);
|
||||||
|
#define v_ ch(vv,0.7);
|
||||||
|
#define w_ ch(ww,0.9);
|
||||||
|
#define x_ ch(xx,0.8);
|
||||||
|
#define y_ ch(yy,0.8);
|
||||||
|
#define z_ ch(zz,0.7);
|
||||||
|
#define A_ ch(AA,0.7);
|
||||||
|
#define B_ ch(BB,0.7);
|
||||||
|
#define C_ ch(CC,0.7);
|
||||||
|
#define D_ ch(DD,0.7);
|
||||||
|
#define E_ ch(EE,0.7);
|
||||||
|
#define F_ ch(FF,0.7);
|
||||||
|
#define G_ ch(GG,0.7);
|
||||||
|
#define H_ ch(HH,0.7);
|
||||||
|
#define I_ ch(II,0.5);
|
||||||
|
#define J_ ch(JJ,0.5);
|
||||||
|
#define K_ ch(KK,0.7);
|
||||||
|
#define L_ ch(LL,0.5);
|
||||||
|
#define M_ ch(MM,0.9);
|
||||||
|
#define N_ ch(NN,0.7);
|
||||||
|
#define O_ ch(OO,0.7);
|
||||||
|
#define P_ ch(PP,0.7);
|
||||||
|
#define Q_ ch(QQ,0.7);
|
||||||
|
#define R_ ch(RR,0.7);
|
||||||
|
#define S_ ch(SS,0.7);
|
||||||
|
#define T_ ch(TT,0.7);
|
||||||
|
#define U_ ch(UU,0.7);
|
||||||
|
#define V_ ch(VV,0.7);
|
||||||
|
#define W_ ch(WW,0.9);
|
||||||
|
#define X_ ch(XX,0.8);
|
||||||
|
#define Y_ ch(YY,0.8);
|
||||||
|
#define Z_ ch(ZZ,0.7);
|
||||||
|
#define _1 ch(_11,0.7);
|
||||||
|
#define _2 ch(_22,0.7);
|
||||||
|
#define _3 ch(_33,0.7);
|
||||||
|
#define _4 ch(_44,0.7);
|
||||||
|
#define _5 ch(_55,0.7);
|
||||||
|
#define _6 ch(_66,0.7);
|
||||||
|
#define _7 ch(_77,0.7);
|
||||||
|
#define _8 ch(_88,0.7);
|
||||||
|
#define _9 ch(_99,0.7);
|
||||||
|
#define _0 ch(_00,0.7);
|
||||||
|
#define _dot ch(ddot,0.3);
|
||||||
|
#define _comma ch(comma,0.3);
|
||||||
|
#define _exclam ch(exclam,0.3);
|
||||||
|
#define _question ch(question,0.8);
|
||||||
|
#define _open1 ch(open1,0.7);
|
||||||
|
#define _close1 ch(close1,0.7);
|
||||||
|
#define _dotdot ch(dotdot,0.3);
|
||||||
|
#define _dotcomma ch(dotcomma,0.3);
|
||||||
|
#define _equal ch(eequal,0.7);
|
||||||
|
#define _add ch(aadd,0.7);
|
||||||
|
#define _sub ch(ssub,0.7);
|
||||||
|
#define _mul ch(mmul,0.7);
|
||||||
|
#define _div ch(ddiv,0.7);
|
||||||
|
#define _lt ch(lt,0.7);
|
||||||
|
#define _gt ch(gt,0.7);
|
||||||
|
#define _hash ch(hash,0.7);
|
||||||
|
#define _and ch(and,0.9);
|
||||||
|
#define _or ch(or,0.3);
|
||||||
|
#define _und ch(und,0.7);
|
||||||
|
#define _open2 ch(open2,0.6);
|
||||||
|
#define _close2 ch(close2,0.6);
|
||||||
|
#define _open3 ch(open3,0.7);
|
||||||
|
#define _close3 ch(close3,0.7);
|
||||||
|
|
||||||
|
//Space
|
||||||
|
#define _ cp+=.5;
|
||||||
|
|
||||||
|
//Markup
|
||||||
|
#define BOLD cur.w = 1.5-cur.w;
|
||||||
|
#define ITAL ital = 0.15-ital;
|
||||||
|
#define RED cur.r = 0.8-cur.r;
|
||||||
|
#define GREEN cur.g = 0.6-cur.g;
|
||||||
|
#define BLUE cur.b = 1.0-cur.b;
|
||||||
|
|
||||||
|
//Next line
|
||||||
|
#define crlf uv.y += 2.0; cp = 0.;
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
float ms = float(iMouse.w>0.);
|
||||||
|
float scale = 1.1-ms;// 2.0-cos(iGlobalTime*.1);
|
||||||
|
vec2 mouseOffs = ms*(iMouse.xy-.5*iResolution.xy)/scale;
|
||||||
|
vec2 uv = (fragCoord+mouseOffs-.5*iResolution.xy) / iResolution.x * 22.0 * scale;
|
||||||
|
|
||||||
|
//float ofs = floor(uv.x)+8.;
|
||||||
|
//uv.x = mod(uv.x,1.0)-.5;
|
||||||
|
|
||||||
|
float px = 22.0/iResolution.x*scale;
|
||||||
|
float x = 100.;
|
||||||
|
float cp = 0.;
|
||||||
|
vec4 cur = vec4(0.,0.,0.,0.5);
|
||||||
|
vec4 us = cur;
|
||||||
|
float ital = 0.0;
|
||||||
|
//uv+= .03*cos(uv*7.+iGlobalTime);
|
||||||
|
//uv.y += 2.;
|
||||||
|
uv.x += 10.1;
|
||||||
|
//uv.y -= 3.;
|
||||||
|
//uv.x += 5.;
|
||||||
|
|
||||||
|
int lnr = 2-int(floor(uv.y/2.));
|
||||||
|
uv.y = mod(uv.y,2.0)-1.0;
|
||||||
|
|
||||||
|
if (lnr==0) {line1}
|
||||||
|
if (lnr==1) {line2}
|
||||||
|
if (lnr==2) {line3}
|
||||||
|
if (lnr==3) {line4}
|
||||||
|
if (lnr==4) {line5}
|
||||||
|
if (lnr==5) {line6}
|
||||||
|
|
||||||
|
vec3 clr = vec3(0.0);
|
||||||
|
|
||||||
|
// Wobbly font
|
||||||
|
//float weight = 0.05+sin(length(-10.0+uv*3.9-10.0*sin(.09*iGlobalTime)))/50.;
|
||||||
|
|
||||||
|
float weight = 0.01+us.w*min(iGlobalTime*.02-.05,0.03);//+.03*length(sin(uv*6.+.3*iGlobalTime));//+0.02-0.06*cos(iGlobalTime*.4+1.);
|
||||||
|
if (ms>0.) {
|
||||||
|
fragColor = vec4(mix(us.rgb+0.5-0.5*smoothstep(0.,2.*px, abs(mod(x,.1)-.05)),vec3(1.0), sqrt(x)),1.0);
|
||||||
|
} else
|
||||||
|
fragColor = vec4(mix(us.rgb,vec3(1.0),smoothstep(weight-px,weight+px, x)),1.0);
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
// Smaller Number Printing - @P_Malin
|
||||||
|
// Creative Commons CC0 1.0 Universal (CC-0)
|
||||||
|
|
||||||
|
// Feel free to modify, distribute or use in commercial code, just don't hold me liable for anything bad that happens!
|
||||||
|
// If you use this code and want to give credit, that would be nice but you don't have to.
|
||||||
|
|
||||||
|
// I first made this number printing code in https://www.shadertoy.com/view/4sf3RN
|
||||||
|
// It started as a silly way of representing digits with rectangles.
|
||||||
|
// As people started actually using this in a number of places I thought I would try to condense the
|
||||||
|
// useful function a little so that it can be dropped into other shaders more easily,
|
||||||
|
// just snip between the perforations below.
|
||||||
|
// Also, the licence on the previous shader was a bit restrictive for utility code.
|
||||||
|
//
|
||||||
|
// Disclaimer: The values printed may not be accurate!
|
||||||
|
// Accuracy improvement for fractional values taken from TimoKinnunen https://www.shadertoy.com/view/lt3GRj
|
||||||
|
|
||||||
|
// ---- 8< ---- GLSL Number Printing - @P_Malin ---- 8< ----
|
||||||
|
// Creative Commons CC0 1.0 Universal (CC-0)
|
||||||
|
// https://www.shadertoy.com/view/4sBSWW
|
||||||
|
|
||||||
|
float DigitBin( const int x )
|
||||||
|
{
|
||||||
|
return x==0?480599.0:x==1?139810.0:x==2?476951.0:x==3?476999.0:x==4?350020.0:x==5?464711.0:x==6?464727.0:x==7?476228.0:x==8?481111.0:x==9?481095.0:0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PrintValue( vec2 vStringCoords, float fValue, float fMaxDigits, float fDecimalPlaces )
|
||||||
|
{
|
||||||
|
if ((vStringCoords.y < 0.0) || (vStringCoords.y >= 1.0)) return 0.0;
|
||||||
|
|
||||||
|
bool bNeg = ( fValue < 0.0 );
|
||||||
|
fValue = abs(fValue);
|
||||||
|
|
||||||
|
float fLog10Value = log2(abs(fValue)) / log2(10.0);
|
||||||
|
float fBiggestIndex = max(floor(fLog10Value), 0.0);
|
||||||
|
float fDigitIndex = fMaxDigits - floor(vStringCoords.x);
|
||||||
|
float fCharBin = 0.0;
|
||||||
|
if(fDigitIndex > (-fDecimalPlaces - 1.01)) {
|
||||||
|
if(fDigitIndex > fBiggestIndex) {
|
||||||
|
if((bNeg) && (fDigitIndex < (fBiggestIndex+1.5))) fCharBin = 1792.0;
|
||||||
|
} else {
|
||||||
|
if(fDigitIndex == -1.0) {
|
||||||
|
if(fDecimalPlaces > 0.0) fCharBin = 2.0;
|
||||||
|
} else {
|
||||||
|
float fReducedRangeValue = fValue;
|
||||||
|
if(fDigitIndex < 0.0) { fReducedRangeValue = fract( fValue ); fDigitIndex += 1.0; }
|
||||||
|
float fDigitValue = (abs(fReducedRangeValue / (pow(10.0, fDigitIndex))));
|
||||||
|
fCharBin = DigitBin(int(floor(mod(fDigitValue, 10.0))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return floor(mod((fCharBin / pow(2.0, floor(fract(vStringCoords.x) * 4.0) + (floor(vStringCoords.y * 5.0) * 4.0))), 2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 8< -------- 8< -------- 8< -------- 8< ----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Original interface
|
||||||
|
|
||||||
|
float PrintValue(const in vec2 fragCoord, const in vec2 vPixelCoords, const in vec2 vFontSize, const in float fValue, const in float fMaxDigits, const in float fDecimalPlaces)
|
||||||
|
{
|
||||||
|
vec2 vStringCharCoords = (fragCoord.xy - vPixelCoords) / vFontSize;
|
||||||
|
|
||||||
|
return PrintValue( vStringCharCoords, fValue, fMaxDigits, fDecimalPlaces );
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetCurve(float x)
|
||||||
|
{
|
||||||
|
return sin( x * 3.14159 * 4.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetCurveDeriv(float x)
|
||||||
|
{
|
||||||
|
return 3.14159 * 4.0 * cos( x * 3.14159 * 4.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec3 vColour = vec3(0.0);
|
||||||
|
|
||||||
|
// Multiples of 4x5 work best
|
||||||
|
vec2 vFontSize = vec2(8.0, 15.0);
|
||||||
|
|
||||||
|
// Draw Horizontal Line
|
||||||
|
if(abs(fragCoord.y - iResolution.y * 0.5) < 1.0)
|
||||||
|
{
|
||||||
|
vColour = vec3(0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw Sin Wave
|
||||||
|
// See the comment from iq or this page
|
||||||
|
// http://www.iquilezles.org/www/articles/distance/distance.htm
|
||||||
|
float fCurveX = fragCoord.x / iResolution.x;
|
||||||
|
float fSinY = (GetCurve(fCurveX) * 0.25 + 0.5) * iResolution.y;
|
||||||
|
float fSinYdX = (GetCurveDeriv(fCurveX) * 0.25) * iResolution.y / iResolution.x;
|
||||||
|
float fDistanceToCurve = abs(fSinY - fragCoord.y) / sqrt(1.0+fSinYdX*fSinYdX);
|
||||||
|
float fSetPixel = fDistanceToCurve - 1.0; // Add more thickness
|
||||||
|
vColour = mix(vec3(1.0, 0.0, 0.0), vColour, clamp(fSetPixel, 0.0, 1.0));
|
||||||
|
|
||||||
|
// Draw Sin Value
|
||||||
|
float fValue4 = GetCurve(iMouse.x / iResolution.x);
|
||||||
|
float fPixelYCoord = (fValue4 * 0.25 + 0.5) * iResolution.y;
|
||||||
|
|
||||||
|
// Plot Point on Sin Wave
|
||||||
|
float fDistToPointA = length( vec2(iMouse.x, fPixelYCoord) - fragCoord.xy) - 4.0;
|
||||||
|
vColour = mix(vColour, vec3(0.0, 0.0, 1.0), (1.0 - clamp(fDistToPointA, 0.0, 1.0)));
|
||||||
|
|
||||||
|
// Plot Mouse Pos
|
||||||
|
float fDistToPointB = length( vec2(iMouse.x, iMouse.y) - fragCoord.xy) - 4.0;
|
||||||
|
vColour = mix(vColour, vec3(0.0, 1.0, 0.0), (1.0 - clamp(fDistToPointB, 0.0, 1.0)));
|
||||||
|
|
||||||
|
// Print Sin Value
|
||||||
|
vec2 vPixelCoord4 = vec2(iMouse.x, fPixelYCoord) + vec2(4.0, 4.0);
|
||||||
|
float fDigits = 1.0;
|
||||||
|
float fDecimalPlaces = 2.0;
|
||||||
|
float fIsDigit4 = PrintValue( (fragCoord - vPixelCoord4) / vFontSize, fValue4, fDigits, fDecimalPlaces);
|
||||||
|
vColour = mix( vColour, vec3(0.0, 0.0, 1.0), fIsDigit4);
|
||||||
|
|
||||||
|
// Print Shader Time
|
||||||
|
vec2 vPixelCoord1 = vec2(96.0, 5.0);
|
||||||
|
float fValue1 = iTime;
|
||||||
|
fDigits = 6.0;
|
||||||
|
float fIsDigit1 = PrintValue( (fragCoord - vPixelCoord1) / vFontSize, fValue1, fDigits, fDecimalPlaces);
|
||||||
|
vColour = mix( vColour, vec3(0.0, 1.0, 1.0), fIsDigit1);
|
||||||
|
|
||||||
|
// Print Date
|
||||||
|
vColour = mix( vColour, vec3(1.0, 1.0, 0.0), PrintValue( (fragCoord - vec2(0.0, 5.0)) / vFontSize, iDate.x, 4.0, 0.0));
|
||||||
|
vColour = mix( vColour, vec3(1.0, 1.0, 0.0), PrintValue( (fragCoord - vec2(0.0 + 48.0, 5.0)) / vFontSize, iDate.y + 1.0, 2.0, 0.0));
|
||||||
|
vColour = mix( vColour, vec3(1.0, 1.0, 0.0), PrintValue( (fragCoord - vec2(0.0 + 72.0, 5.0)) / vFontSize, iDate.z, 2.0, 0.0));
|
||||||
|
|
||||||
|
// Draw Time
|
||||||
|
vColour = mix( vColour, vec3(1.0, 0.0, 1.0), PrintValue( (fragCoord - vec2(184.0, 5.0)) / vFontSize, mod(iDate.w / (60.0 * 60.0), 12.0), 2.0, 0.0));
|
||||||
|
vColour = mix( vColour, vec3(1.0, 0.0, 1.0), PrintValue( (fragCoord - vec2(184.0 + 24.0, 5.0)) / vFontSize, mod(iDate.w / 60.0, 60.0), 2.0, 0.0));
|
||||||
|
vColour = mix( vColour, vec3(1.0, 0.0, 1.0), PrintValue( (fragCoord - vec2(184.0 + 48.0, 5.0)) / vFontSize, mod(iDate.w, 60.0), 2.0, 0.0));
|
||||||
|
|
||||||
|
if(iMouse.x > 0.0)
|
||||||
|
{
|
||||||
|
// Print Mouse X
|
||||||
|
vec2 vPixelCoord2 = iMouse.xy + vec2(-52.0, 6.0);
|
||||||
|
float fValue2 = iMouse.x / iResolution.x;
|
||||||
|
fDigits = 1.0;
|
||||||
|
fDecimalPlaces = 3.0;
|
||||||
|
float fIsDigit2 = PrintValue( (fragCoord - vPixelCoord2) / vFontSize, fValue2, fDigits, fDecimalPlaces);
|
||||||
|
vColour = mix( vColour, vec3(0.0, 1.0, 0.0), fIsDigit2);
|
||||||
|
|
||||||
|
// Print Mouse Y
|
||||||
|
vec2 vPixelCoord3 = iMouse.xy + vec2(0.0, 6.0);
|
||||||
|
float fValue3 = iMouse.y / iResolution.y;
|
||||||
|
fDigits = 1.0;
|
||||||
|
float fIsDigit3 = PrintValue( (fragCoord - vPixelCoord3) / vFontSize, fValue3, fDigits, fDecimalPlaces);
|
||||||
|
vColour = mix( vColour, vec3(0.0, 1.0, 0.0), fIsDigit3);
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(vColour,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
// Created by anatole duprat - XT95/2015
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
//More details here http://www.aduprat.com/portfolio/?page=articles/hemisphericalSDFAO
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
vec3 raymarche( in vec3 ro, in vec3 rd, in vec2 nfplane );
|
||||||
|
vec3 normal( in vec3 p );
|
||||||
|
float box( in vec3 p, in vec3 data );
|
||||||
|
float map( in vec3 p );
|
||||||
|
|
||||||
|
mat3 lookat( in vec3 fw, in vec3 up );
|
||||||
|
mat3 rotate( in vec3 v, in float angle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Random number [0:1] without sine
|
||||||
|
#define HASHSCALE1 .1031
|
||||||
|
float hash(float p)
|
||||||
|
{
|
||||||
|
vec3 p3 = fract(vec3(p) * HASHSCALE1);
|
||||||
|
p3 += dot(p3, p3.yzx + 19.19);
|
||||||
|
return fract((p3.x + p3.y) * p3.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 randomSphereDir(vec2 rnd)
|
||||||
|
{
|
||||||
|
float s = rnd.x*PI*2.;
|
||||||
|
float t = rnd.y*2.-1.;
|
||||||
|
return vec3(sin(s), cos(s), t) / sqrt(1.0 + t * t);
|
||||||
|
}
|
||||||
|
vec3 randomHemisphereDir(vec3 dir, float i)
|
||||||
|
{
|
||||||
|
vec3 v = randomSphereDir( vec2(hash(i+1.), hash(i+2.)) );
|
||||||
|
return v * sign(dot(v, dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
float ambientOcclusion( in vec3 p, in vec3 n, in float maxDist, in float falloff )
|
||||||
|
{
|
||||||
|
const int nbIte = 32;
|
||||||
|
const float nbIteInv = 1./float(nbIte);
|
||||||
|
const float rad = 1.-1.*nbIteInv; //Hemispherical factor (self occlusion correction)
|
||||||
|
|
||||||
|
float ao = 0.0;
|
||||||
|
|
||||||
|
for( int i=0; i<nbIte; i++ )
|
||||||
|
{
|
||||||
|
float l = hash(float(i))*maxDist;
|
||||||
|
vec3 rd = normalize(n+randomHemisphereDir(n, l )*rad)*l; // mix direction with the normal
|
||||||
|
// for self occlusion problems!
|
||||||
|
|
||||||
|
ao += (l - max(map( p + rd ),0.)) / maxDist * falloff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clamp( 1.-ao*nbIteInv, 0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float classicAmbientOcclusion( in vec3 p, in vec3 n, in float maxDist, in float falloff )
|
||||||
|
{
|
||||||
|
float ao = 0.0;
|
||||||
|
const int nbIte = 6;
|
||||||
|
for( int i=0; i<nbIte; i++ )
|
||||||
|
{
|
||||||
|
float l = hash(float(i))*maxDist;
|
||||||
|
vec3 rd = n*l;
|
||||||
|
|
||||||
|
ao += (l - max(map( p + rd ),0.)) / maxDist * falloff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clamp( 1.-ao/float(nbIte), 0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Shading
|
||||||
|
vec3 shade( in vec3 p, in vec3 n, in vec3 org, in vec3 dir, vec2 v )
|
||||||
|
{
|
||||||
|
vec3 col = vec3(1.);
|
||||||
|
|
||||||
|
float a = ambientOcclusion(p,n, 4., 2.);
|
||||||
|
float b = classicAmbientOcclusion(p,n, 4., 1.2);
|
||||||
|
|
||||||
|
if( iMouse.z > .5 )
|
||||||
|
{
|
||||||
|
if( v.x-iMouse.x/iResolution.x >0. )
|
||||||
|
col *= a;
|
||||||
|
else
|
||||||
|
col *= b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( v.x > 0.5 )
|
||||||
|
col *= a;
|
||||||
|
else
|
||||||
|
col *= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Main
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
//screen coords
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
vec2 v = -1.0+2.0*q;
|
||||||
|
v.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
//camera ray
|
||||||
|
float ctime = (iGlobalTime)*.25;
|
||||||
|
vec3 ro = vec3( cos(ctime)*5.,10.+cos(ctime*.5)*3.,-13.+sin(ctime) );
|
||||||
|
vec3 rd = normalize( vec3(v.x, v.y, 1.5) );
|
||||||
|
rd = lookat( -ro + vec3(0., 5., 0.), vec3(0., 1., 0.) ) * rd;
|
||||||
|
|
||||||
|
//classic raymarching by distance field
|
||||||
|
vec3 p = raymarche(ro, rd, vec2(1., 30.) );
|
||||||
|
vec3 n = normal(p.xyz);
|
||||||
|
vec3 col = shade(p, n, ro, rd, q);
|
||||||
|
|
||||||
|
//Gamma correction
|
||||||
|
col = pow(col, vec3(1./2.2));
|
||||||
|
|
||||||
|
if( iMouse.z > .5 )
|
||||||
|
{
|
||||||
|
if( abs(q.x-iMouse.x/iResolution.x) < 1./iResolution.x )
|
||||||
|
col = vec3(0.);
|
||||||
|
}
|
||||||
|
else if( abs(q.x-.5) < 1./iResolution.x)
|
||||||
|
col = vec3(0.);
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1. );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float map( in vec3 p )
|
||||||
|
{
|
||||||
|
float d = -box(p-vec3(0.,10.,0.),vec3(10.));
|
||||||
|
d = min(d, box(rotate(vec3(0.,1.,0.), 1.)*(p-vec3(4.,5.,6.)), vec3(3.,5.,3.)) );
|
||||||
|
d = min(d, box(rotate(vec3(0.,1.,0.),-1.)*(p-vec3(-4.,2.,0.)), vec3(2.)) );
|
||||||
|
d = max(d, -p.z-9.);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 raymarche( in vec3 ro, in vec3 rd, in vec2 nfplane )
|
||||||
|
{
|
||||||
|
vec3 p = ro+rd*nfplane.x;
|
||||||
|
float t = 0.;
|
||||||
|
for(int i=0; i<64; i++)
|
||||||
|
{
|
||||||
|
float d = map(p);
|
||||||
|
t += d;
|
||||||
|
p += rd*d;
|
||||||
|
if( d < 0.001 || t > nfplane.y )
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
vec3 normal( in vec3 p )
|
||||||
|
{
|
||||||
|
vec3 eps = vec3(0.001, 0.0, 0.0);
|
||||||
|
return normalize( vec3(
|
||||||
|
map(p+eps.xyy)-map(p-eps.xyy),
|
||||||
|
map(p+eps.yxy)-map(p-eps.yxy),
|
||||||
|
map(p+eps.yyx)-map(p-eps.yyx)
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float box( in vec3 p, in vec3 data )
|
||||||
|
{
|
||||||
|
return max(max(abs(p.x)-data.x,abs(p.y)-data.y),abs(p.z)-data.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mat3 lookat( in vec3 fw, in vec3 up )
|
||||||
|
{
|
||||||
|
fw = normalize(fw);
|
||||||
|
vec3 rt = normalize( cross(fw, normalize(up)) );
|
||||||
|
return mat3( rt, cross(rt, fw), fw );
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 rotate( in vec3 v, in float angle)
|
||||||
|
{
|
||||||
|
float c = cos(angle);
|
||||||
|
float s = sin(angle);
|
||||||
|
|
||||||
|
return mat3(c + (1.0 - c) * v.x * v.x, (1.0 - c) * v.x * v.y - s * v.z, (1.0 - c) * v.x * v.z + s * v.y,
|
||||||
|
(1.0 - c) * v.x * v.y + s * v.z, c + (1.0 - c) * v.y * v.y, (1.0 - c) * v.y * v.z - s * v.x,
|
||||||
|
(1.0 - c) * v.x * v.z - s * v.y, (1.0 - c) * v.y * v.z + s * v.x, c + (1.0 - c) * v.z * v.z
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,436 @@
|
||||||
|
// Wolfenstein. Created by Reinder Nijhoff 2013
|
||||||
|
// @reindernijhoff
|
||||||
|
//
|
||||||
|
// https://www.shadertoy.com/view/4sfGWX
|
||||||
|
//
|
||||||
|
|
||||||
|
#define NUM_MATERIALS 3
|
||||||
|
#define NUM_OBJECTS 1
|
||||||
|
#define SECONDS_IN_ROOM 3.
|
||||||
|
#define ROOM_SIZE 10.
|
||||||
|
#define MAXSTEPS 17
|
||||||
|
#define MATERIAL_DOOR 200
|
||||||
|
#define MATERIAL_DOORWAY 201
|
||||||
|
|
||||||
|
#define COL(r,g,b) vec3(r/255.,g/255.,b/255.)
|
||||||
|
|
||||||
|
#define time (iGlobalTime+40.)
|
||||||
|
vec3 rdcenter;
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Math functions
|
||||||
|
|
||||||
|
float hash( const float n ) {
|
||||||
|
return fract(sin(n*14.1234512)*51231.545341231);
|
||||||
|
}
|
||||||
|
float hash( const vec2 x ) {
|
||||||
|
float n = dot( x, vec2(14.1432,1131.15532) );
|
||||||
|
return fract(sin(n)*51231.545341231);
|
||||||
|
}
|
||||||
|
float crossp( const vec2 a, const vec2 b ) { return a.x*b.y - a.y*b.x; }
|
||||||
|
vec3 rotate(vec3 r, float v){ return vec3(r.x*cos(v)+r.z*sin(v),r.y,r.z*cos(v)-r.x*sin(v));}
|
||||||
|
bool intersectSegment(const vec3 ro, const vec3 rd, const vec2 a, const vec2 b, out float dist, out float u) {
|
||||||
|
vec2 p = ro.xz; vec2 r = rd.xz;
|
||||||
|
vec2 q = a-p; vec2 s = b-a;
|
||||||
|
float rCrossS = crossp(r, s);
|
||||||
|
|
||||||
|
if( rCrossS == 0.){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dist = crossp(q, s) / rCrossS;
|
||||||
|
u = crossp(q, r) / rCrossS;
|
||||||
|
|
||||||
|
if(0. <= dist && 0. <= u && u <= 1.){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Material helper functions
|
||||||
|
|
||||||
|
float onCircle( const vec2 c, const vec2 centre, const float radius ) {
|
||||||
|
return clamp( 4.*(radius - distance(c,centre)), 0., 1. );
|
||||||
|
}
|
||||||
|
float onCircleLine( const vec2 c, const vec2 centre, const float radius ) {
|
||||||
|
return clamp( 1.-1.5*abs(radius - distance(c,centre)), 0., 1. );
|
||||||
|
}
|
||||||
|
float onLine( const float c, const float b ) {
|
||||||
|
return clamp( 1.-abs(b-c), 0., 1. );
|
||||||
|
}
|
||||||
|
float onBand( const float c, const float mi, const float ma ) {
|
||||||
|
return clamp( (ma-c+1.), 0., 1. )*clamp( (c-mi+1.), 0., 1. );
|
||||||
|
}
|
||||||
|
float onLineSegmentX( const vec2 c, const float b, const float mi, const float ma ) {
|
||||||
|
return onLine( c.x, b )*onBand( c.y, mi, ma );
|
||||||
|
}
|
||||||
|
float onLineSegmentY( const vec2 c, const float b, const float mi, const float ma ) {
|
||||||
|
return onLine( c.y, b )*onBand( c.x, mi, ma );
|
||||||
|
}
|
||||||
|
float onRect( const vec2 c, const vec2 lt, const vec2 rb ) {
|
||||||
|
return onBand( c.x, lt.x, rb.x )*onBand( c.y, lt.y, rb.y );
|
||||||
|
}
|
||||||
|
vec3 addBevel( const vec2 c, const vec2 lt, const vec2 rb, const float size, const float strength, const float lil, const float lit, const vec3 col ) {
|
||||||
|
float xl = clamp( (c.x-lt.x)/size, 0., 1. );
|
||||||
|
float xr = clamp( (rb.x-c.x)/size, 0., 1. );
|
||||||
|
float yt = clamp( (c.y-lt.y)/size, 0., 1. );
|
||||||
|
float yb = clamp( (rb.y-c.y)/size, 0., 1. );
|
||||||
|
|
||||||
|
return mix( col, col*clamp(1.0+strength*(lil*(xl-xr)+lit*(yb-yt)), 0., 2.), onRect( c, lt, rb ) );
|
||||||
|
}
|
||||||
|
vec3 addKnob( const vec2 c, const vec2 centre, const float radius, const float strength, const vec3 col ) {
|
||||||
|
vec2 lv = normalize( centre-c );
|
||||||
|
return mix( col, col*(1.0+strength*dot(lv,vec2(-0.7071,0.7071))), onCircle(c, centre, radius ) );
|
||||||
|
}
|
||||||
|
float stepeq( float a, float b ) {
|
||||||
|
return step( a, b )*step( b, a );
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Generate materials!
|
||||||
|
|
||||||
|
void getMaterialColor( const int material, in vec2 uv, const float decorationHash, out vec3 col ) {
|
||||||
|
vec3 fgcol;
|
||||||
|
|
||||||
|
uv = floor( mod(uv+64., vec2(64.)) );
|
||||||
|
vec2 uvs = uv / 64.;
|
||||||
|
|
||||||
|
// basecolor
|
||||||
|
vec3 basecol = vec3( mix(55./255.,84./255.,uvs.y ) );
|
||||||
|
float br = hash(uv);
|
||||||
|
col = basecol;
|
||||||
|
// grey bricks
|
||||||
|
if( material == 0 || material == 1 ) {
|
||||||
|
vec2 buv = vec2( mod(uv.x+1. + (floor((uv.y+1.) / 16.) * 16.), 32.) , mod( uv.y+1., 16.) );
|
||||||
|
float bbr = mix( 190./255., 91./255., (buv.y)/14. ) + 0.05*br;
|
||||||
|
if ( buv.x < 2. || buv.y < 2.) {
|
||||||
|
bbr = 72./255.;
|
||||||
|
}
|
||||||
|
col = vec3(bbr*0.95);
|
||||||
|
col = addBevel( buv, vec2(1.,1.), vec2( 31.5, 15.), 2., 0.35, 1., 1., col);
|
||||||
|
// blue wall
|
||||||
|
if( material == 1 ) {
|
||||||
|
col *= 1.3*COL(11.,50.,209.);
|
||||||
|
col = mix( col, COL(2.,15.,86.), onBand(uv.y,14.,49.));
|
||||||
|
col = mix( col, COL(9.,44.,185.)*(0.9+0.1*br), onBand(uv.y,16.,47.));
|
||||||
|
col = mix( col, COL(3.,25.,122.), onBand(uv.y,21.,42.));
|
||||||
|
col = addBevel( uv, vec2(-1.,16.), vec2( 65., 21.), 1., 0.35, 1., 1., col);
|
||||||
|
col = addBevel( uv, vec2(-1.,43.), vec2( 65., 48.), 1., 0.35, 1., 1., col);
|
||||||
|
|
||||||
|
col = mix( col, COL(2.,11.,74.), onRect(uv, vec2(22.,22.), vec2(42.,42.)));
|
||||||
|
col = mix( col, COL(9.,44.,185.)*(0.95+0.1*br), onRect(uv, vec2(22.,23.), vec2(42.,40.)));
|
||||||
|
col = addBevel( uv, vec2(22.,23.), vec2(42.,40.), 1., 0.2, -1., 1., col);
|
||||||
|
col = mix( col, mix(COL(2.,11.,74.), COL(3.,25.,122.), (uv.x-26.)/3.), onRect(uv, vec2(26.,23.), vec2(29.,29.)));
|
||||||
|
col = mix( col, mix(COL(2.,11.,74.), COL(3.,25.,122.), (uv.y-34.)/2.), onRect(uv, vec2(22.,34.), vec2(29.,36.)));
|
||||||
|
col = mix( col, mix(COL(2.,11.,74.), COL(3.,25.,122.), (uv.y-27.)/2.), onRect(uv, vec2(35.,27.), vec2(42.,29.)));
|
||||||
|
col = mix( col, mix(COL(2.,11.,74.), COL(3.,25.,122.), (uv.y-34.)/8.), onRect(uv, vec2(35.,34.), vec2(38.,42.)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// wooden wall
|
||||||
|
else if( material == 2 ) {
|
||||||
|
float mx = mod( uv.x, 64./5. );
|
||||||
|
float h1 = hash( floor(uv.x/(64./5.)) );
|
||||||
|
float h2 = hash( 1.+1431.16*floor(uv.x/(64./5.)) );
|
||||||
|
col = mix( COL(115.,75.,43.),COL( 71.,56.,26.), smoothstep( 0.2, 1., (0.7+h2)*abs(mod( h2-uv.y*(0.05+0.1*h2)+(1.+h1+h2)*sin(mx*(0.1+0.2*h2)), 2. )-1.) ) );
|
||||||
|
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.x)/2.), step(uv.x,2.) );
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.x-10.)/2.), step(10.,uv.x)*step(uv.x,12.) );
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.x-26.)/2.), step(26.,uv.x)*step(uv.x,28.) );
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.x-40.)/2.), step(40.,uv.x)*step(uv.x,42.) );
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.x-54.)/2.), step(54.,uv.x)*step(uv.x,56.) );
|
||||||
|
|
||||||
|
col = mix( col, mix(COL(83.,60.,31.), COL(142.,91.,56.), (uv.x- 8.)), step( 8.,uv.x)*step(uv.x,9.) );
|
||||||
|
col = mix( col, mix(COL(83.,60.,31.), COL(142.,91.,56.), (uv.x-24.)), step(24.,uv.x)*step(uv.x,25.) );
|
||||||
|
col = mix( col, mix(COL(83.,60.,31.), COL(142.,91.,56.), (uv.x-38.)), step(38.,uv.x)*step(uv.x,39.) );
|
||||||
|
col = mix( col, mix(COL(83.,60.,31.), COL(142.,91.,56.), (uv.x-52.)), step(52.,uv.x)*step(uv.x,53.) );
|
||||||
|
col = mix( col, mix(COL(83.,60.,31.), COL(142.,91.,56.), (uv.x-62.)), step(62.,uv.x) );
|
||||||
|
|
||||||
|
col = mix( col, mix(COL(40.,31.,13.), COL(142.,91.,56.), (uv.y)/2.), step(uv.y,2.) );
|
||||||
|
col *= 1.-0.3*stepeq(uv.y,3.);
|
||||||
|
}
|
||||||
|
// door
|
||||||
|
else if( material == MATERIAL_DOOR ) {
|
||||||
|
fgcol = COL(44., 176., 175.)*(0.95+0.15*sin(-0.25+ 4.*((-0.9-uvs.y)/(1.3-0.8*uvs.x)) ) );
|
||||||
|
fgcol = addBevel( uv, vec2(-1.,1.), vec2(62.,66.), 2., 0.4, -1., -1., fgcol);
|
||||||
|
fgcol = addBevel( uv, vec2( 6.,6.), vec2(57.,57.), 2.25, 0.5, -1., -1., fgcol);
|
||||||
|
fgcol = mix( addKnob( mod( uv, vec2(8.) ), vec2(3.5), 1.65, 0.5, fgcol ), fgcol, onRect( uv, vec2( 6.,6.), vec2(57.,57.)) ) ;
|
||||||
|
|
||||||
|
//knob
|
||||||
|
fgcol *= 1.-0.2*onRect( uv, vec2( 13.5, 28.5 ), vec2( 22.5, 44.5 ) );
|
||||||
|
fgcol = mix( fgcol, mix( COL(44.,44.,44.),COL(152.,152.,152.), ((uv.x+(43.-uv.y)-15.)/25. ) ), onRect( uv, vec2( 15., 27. ), vec2( 24., 43. ) ) );
|
||||||
|
fgcol = addBevel( uv, vec2( 15., 27. ), vec2( 24., 43. ), 1., 0.45, 1., 1., fgcol);
|
||||||
|
fgcol = mix( fgcol, addKnob( mod( uv, vec2(6.) ), vec2(4.25,5.5), 1.15, 0.75, fgcol ), onRect( uv, vec2( 15., 27. ), vec2( 24., 43. ) ) ) ;
|
||||||
|
|
||||||
|
fgcol *= 1.-0.5*onRect( uv, vec2( 16.5, 33.5 ), vec2( 20.5, 38.5 ) );
|
||||||
|
fgcol = mix( fgcol, mix( COL(88.,84.,11.),COL(251.,242.,53.), ((uv.x+(37.-uv.y)-18.)/7. ) ), onRect( uv, vec2( 18., 33. ), vec2( 21., 37. ) ) );
|
||||||
|
fgcol = mix( fgcol, COL(0.,0.,0.), onRect( uv, vec2( 19., 34. ), vec2( 20., 35.7 ) ) );
|
||||||
|
|
||||||
|
fgcol *= 1.-0.2*onRect( uv, vec2( 6.5, 29.5 ), vec2( 10.5, 41.5 ) );
|
||||||
|
fgcol = mix( fgcol, mix( COL(88.,84.,11.),COL(251.,242.,53.), ((uv.x+(40.-uv.y)-9.)/13. ) ), onRect( uv, vec2( 9., 29. ), vec2( 11., 40. ) ) );
|
||||||
|
fgcol = addBevel( uv, vec2( 9., 29. ), vec2( 11., 40. ), 0.75, 0.5, 1., 1., fgcol);
|
||||||
|
|
||||||
|
col = mix( basecol, fgcol, onRect( uv, vec2(1.,1.), vec2(62.,62.) ) );
|
||||||
|
}
|
||||||
|
// doorway
|
||||||
|
else if( material == MATERIAL_DOORWAY ) {
|
||||||
|
fgcol = COL(44., 176., 175.)*(0.95+0.15*sin(-0.25+ 4.*((-0.9-uvs.y)/(1.3-0.8*uvs.x)) ) );
|
||||||
|
vec2 uvhx = vec2( 32.-abs(uv.x-32.), uv.y );
|
||||||
|
fgcol = addBevel( uvhx, vec2(-1.,1.), vec2(28.,66.), 2., 0.4, -1., -1., fgcol);
|
||||||
|
fgcol = addBevel( uvhx, vec2( 6.,6.), vec2(23.,57.), 2.25, 0.5, -1., -1., fgcol);
|
||||||
|
fgcol = mix( addKnob( vec2( mod( uvhx.x, 22. ), mod( uvhx.y, 28. )), vec2(3.5), 1.65, 0.5, fgcol ), fgcol, onRect( uvhx, vec2( 6.,6.), vec2(24.,57.)) ) ;
|
||||||
|
fgcol = mix( fgcol, vec3(0.), onRect( uv, vec2( 29., 1.), vec2( 35., 63.) ) );
|
||||||
|
col = mix( basecol, fgcol, onRect( uv, vec2(1.,1.), vec2(62.,62.) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// prison door
|
||||||
|
if( decorationHash > 0.93 && material < (NUM_MATERIALS+1) ) {
|
||||||
|
vec4 prisoncoords = vec4(12.,14.,52.,62.);
|
||||||
|
// shadow
|
||||||
|
col *= 1.-0.5*onRect( uv, vec2( 11., 13. ), vec2( 53., 63. ) );
|
||||||
|
// hinge
|
||||||
|
col = mix( col, COL(72.,72.,72.), stepeq(uv.x, 53.)*step( mod(uv.y+2.,25.), 5.)*step(13.,uv.y) );
|
||||||
|
col = mix( col, COL(100.,100.,100.), stepeq(uv.x, 53.)*step( mod(uv.y+1.,25.), 3.)*step(13.,uv.y) );
|
||||||
|
|
||||||
|
vec3 pcol = vec3(0.)+COL(100.,100.,100.)*step( mod(uv.x-4., 7.), 0. );
|
||||||
|
pcol += COL(55.,55.,55.)*step( mod(uv.x-5., 7.), 0. );
|
||||||
|
pcol = addBevel(uv, vec2(0.,17.), vec2(63.,70.), 3., 0.8, 0., -1., pcol);
|
||||||
|
pcol = addBevel(uv, vec2(0.,45.), vec2(22.,70.), 3., 0.8, 0., -1., pcol);
|
||||||
|
|
||||||
|
fgcol = COL(72.,72.,72.);
|
||||||
|
fgcol = addBevel(uv, prisoncoords.xy, prisoncoords.zw+vec2(1.,1.), 1., 0.5, -1., 1., fgcol );
|
||||||
|
fgcol = addBevel(uv, prisoncoords.xy+vec2(3.,3.), prisoncoords.zw-vec2(2.,1.), 1., 0.5, 1., -1., fgcol );
|
||||||
|
fgcol = mix( fgcol, pcol, onRect( uv, prisoncoords.xy+vec2(3.,3.), prisoncoords.zw-vec2(3.,2.) ) );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onRect( uv, vec2(15.,32.5), vec2(21.,44.) ) );
|
||||||
|
|
||||||
|
fgcol = mix( fgcol, mix( COL(0.,0.,0.), COL(43.,43.,43.), (uv.y-37.) ), stepeq(uv.x, 15.)*step(37.,uv.y)*step(uv.y,38.) );
|
||||||
|
fgcol = mix( fgcol, mix( COL(0.,0.,0.), COL(43.,43.,43.), (uv.y-37.)/3. ), stepeq(uv.x, 17.)*step(37.,uv.y)*step(uv.y,40.) );
|
||||||
|
fgcol = mix( fgcol, COL(43.,43.,43.), stepeq(uv.x, 18.)*step(37.,uv.y)*step(uv.y,41.) );
|
||||||
|
fgcol = mix( fgcol, mix( COL(0.,0.,0.), COL(100.,100.,100.), (uv.y-37.)/3. ), stepeq(uv.x, 18.)*step(36.,uv.y)*step(uv.y,40.) );
|
||||||
|
fgcol = mix( fgcol, COL(43.,43.,43.), stepeq(uv.x, 19.)*step(37.,uv.y)*step(uv.y,40.) );
|
||||||
|
|
||||||
|
fgcol = mix( fgcol, mix( COL(84.,84.,84.), COL(108.,108.,108.), (uv.x-15.)/2. ), stepeq(uv.y, 32.)*step(15.,uv.x)*step(uv.x,17.) );
|
||||||
|
fgcol = mix( fgcol, COL(81.,81.,81.), stepeq(uv.y, 32.)*step(20.,uv.x)*step(uv.x,21.) );
|
||||||
|
|
||||||
|
col = mix( col, fgcol, onRect( uv, prisoncoords.xy, prisoncoords.zw ) );
|
||||||
|
}
|
||||||
|
// flag
|
||||||
|
else if( decorationHash > 0.63 && material < (NUM_MATERIALS+1) ) {
|
||||||
|
vec2 uvc = uv-vec2(32.,30.);
|
||||||
|
|
||||||
|
// shadow
|
||||||
|
vec4 shadowcoords = vec4( 14., 7.,
|
||||||
|
54., max( 56. + sin( uv.x*0.32-1. ),56.) );
|
||||||
|
col *= 1.-0.3*onRect( uv, vec2( 6., 6. ), vec2( 61., 7. ) );
|
||||||
|
col *= 1.-0.3*clamp( 0.25*(56.-uv.x), 0., 1.)*onRect( uv, shadowcoords.xy, shadowcoords.zw );
|
||||||
|
|
||||||
|
// rod
|
||||||
|
col = mix( col, COL(250.,167.,98.), onLineSegmentX( vec2( abs(uv.x-32.), uv.y ), 26., 4., 6.5 ) );
|
||||||
|
col = mix( col, COL(251.,242.,53.), onLineSegmentY( uv, 5., 4., 60. ) );
|
||||||
|
col = mix( col, COL(155.,76.,17.), onLineSegmentY( uv, 6., 4., 60. ) );
|
||||||
|
col = mix( col, COL(202.,96.,25.), onLineSegmentY( vec2( abs(uv.x-32.), uv.y ), 6., 26., 28. ) );
|
||||||
|
col = mix( col, COL(251.,242.,53.), onLineSegmentX( vec2( abs(uv.x-32.), uv.y ), 25., 3., 7. ) );
|
||||||
|
col = mix( col, COL(252.,252.,217.), onLineSegmentX( vec2( abs(uv.x-32.), uv.y ), 25., 4.3, 5.5 ) );
|
||||||
|
col = mix( col, COL(252.,252.,217.), onLineSegmentX( vec2( abs(uv.x-32.), uv.y ), 26., 5.3, 5.5 ) );
|
||||||
|
col = mix( col, COL(0.,0.,0.), onLineSegmentY( vec2( abs(uv.x-32.), uv.y ), 6., 18.3, 19.5 ) );
|
||||||
|
|
||||||
|
// flag
|
||||||
|
vec4 flagcoords = vec4( 13., min( 9.5 - pow(5.5* (uvs.x-0.5), 2.), 9. ),
|
||||||
|
51., max( 55. + sin( uv.x*0.4+2.7 ),55.) );
|
||||||
|
|
||||||
|
fgcol = COL(249.,41.,27.);
|
||||||
|
|
||||||
|
fgcol = mix( fgcol, COL(255.,255.,255.), onBand( min(abs(uvc.x), abs(uvc.y)), 2., 4. ) );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onLine( min(abs(uvc.x), abs(uvc.y)), 3. ) );
|
||||||
|
|
||||||
|
fgcol = mix( fgcol, COL(255.,255.,255.), onCircle( uv, vec2(32.,30.), 12.5 ) );
|
||||||
|
fgcol = mix( fgcol, COL(0.,0.,0.), onCircleLine( uv, vec2(32.,30.), 11. ) );
|
||||||
|
fgcol = mix( fgcol, COL(0.,0.,0.), onCircleLine( uv, vec2(32.,30.), 9. ) );
|
||||||
|
|
||||||
|
vec2 uvr = vec2( (uvc.x-uvc.y)*0.7071, (uvc.y+uvc.x)*0.7071)*sign( uvc.x+0.5 );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onRect( uvr, vec2(-1.,-1.), vec2(1.,4.) ) );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onRect( uvr, vec2(-4.2, 4.2), vec2(1.,6.15) ) );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onRect( uvr, vec2(-1.,-1.), vec2(4.,1.) ) );
|
||||||
|
fgcol = mix( fgcol, COL(72.,72.,72.), onRect( uvr, vec2( 4.2,-1.), vec2(6.15,4.2) ) );
|
||||||
|
|
||||||
|
fgcol *= (0.8+0.2*sin( uv.x*0.4+2.7 ));
|
||||||
|
fgcol *= (0.8+0.2*clamp( 0.5*(uv.y-7.), 0., 1.));
|
||||||
|
|
||||||
|
// mix flag on background
|
||||||
|
col = mix( col, fgcol, onRect( uv, flagcoords.xy, flagcoords.zw ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// fake 8-bit color palette and dithering
|
||||||
|
col = floor( (col+0.5*mod(uv.x+uv.y,2.)/32.)*32.)/32.;
|
||||||
|
}
|
||||||
|
bool getObjectColor( const int object, in vec2 uv, inout vec3 icol ) {
|
||||||
|
uv = floor( mod(uv, vec2(64.)) );
|
||||||
|
vec2 uvs = uv / 64.;
|
||||||
|
vec3 col = vec3(20./255.);
|
||||||
|
float d;
|
||||||
|
|
||||||
|
// only a lamp for now
|
||||||
|
|
||||||
|
// lamp top
|
||||||
|
d = distance( uv*vec2(1.,2.), vec2(28.1, 5.8)*vec2(1.,2.) );
|
||||||
|
col = mix( col, mix( COL(41.,250.,46.), COL(13.,99.,12.), clamp( d/8.-0.2, 0., 1.) ),
|
||||||
|
onCircle(uv, vec2(31.,13.6), 11.7 )*step( uv.y, 6. ));
|
||||||
|
col = mix( col, COL(9.,75.,6.), onCircleLine( uv, vec2(31.,14.), 11.6 ) *
|
||||||
|
step( length(uv-vec2(31.,13.6)), 11.7 )*step( uv.y, 6. ) );
|
||||||
|
col = mix( col, COL(100.,100.,100.), onLine( abs(uv.x-31.), 1. )*step( uv.y, 1. ) );
|
||||||
|
col = mix( col, COL(140.,140.,140.), onLine( abs(uv.x-31.), 0.25 )*step( uv.y, 1. )*step( 1., uv.y ) );
|
||||||
|
|
||||||
|
// lamp bottom
|
||||||
|
d = distance( uv*vec2(1.,2.), vec2(30.5, 6.5)*vec2(1.,2.) );
|
||||||
|
col = mix( col, mix( COL(41.,250.,46.), COL(13.,99.,12.), clamp( abs(uv.x-31.)/4.-1.25, 0., 1. )), step( abs(uv.x-31.), 9. )*stepeq( uv.y, 7.) );
|
||||||
|
col = mix( col, mix( COL(41.,250.,46.), COL(16.,123.,17.), clamp( abs(uv.x-31.)/4.-1.25, 0., 1. )), step( abs(uv.x-31.), 9. )*stepeq( uv.y, 8.) );
|
||||||
|
col = mix( col, mix( COL(133.,250.,130.), COL(22.,150.,23.), clamp( abs(uv.x-31.)/4.-0.75, 0., 1. )), step( abs(uv.x-31.), 7. )*stepeq( uv.y, 9.) );
|
||||||
|
|
||||||
|
col = mix( col, mix( COL(255.,251.,187.), col, clamp( d/4.5-0.6, 0., 1.) ),
|
||||||
|
onCircle(uv, vec2(31.,1.), 10.2 )*step( uv.y, 8. )*step( 7., uv.y ));
|
||||||
|
col = mix( col, mix( COL(255.,255.,255.), col, clamp( d/4.-0.7, 0., 1.) ),
|
||||||
|
onCircle(uv, vec2(31.,1.), 7.2 )*step( uv.y, 8. )*step( 7., uv.y ));
|
||||||
|
|
||||||
|
// floor
|
||||||
|
d = distance( vec2(mod(uv.x, 32.),uv.y)*vec2(1.5,30./3.), vec2(16., 61.5)*vec2(1.5,30./3.) );
|
||||||
|
col = mix( col, mix( COL(168.,168.,168.), COL(124.,124.,124.), clamp(d/15.-0.5, 0., 1.) ), step(d,24.5));
|
||||||
|
col = mix( col, mix( COL(124.,124.,124.), COL(140.,140.,140.), clamp((uv.y-59.)/1., 0., 1.)), step(59.,uv.y)*step(uv.x, 57.)*step(7.,uv.x));
|
||||||
|
col = mix( col, mix( COL(168.,168.,168.), COL(124.,124.,124.), clamp(abs(32.-uv.x)/10.-2., 0., 1.)), step(uv.y, 62.)*step(62.,uv.y)*step(uv.x, 61.)*step(3.,uv.x));
|
||||||
|
col = mix( col, mix( COL(152.,152.,152.), COL(124.,124.,124.), clamp(abs(32.-uv.x)/10.-2.25, 0., 1.)), step(uv.y, 61.)*step(61.,uv.y)*step(uv.x, 59.)*step(5.,uv.x));
|
||||||
|
|
||||||
|
col = floor( (col)*32.)/32.;
|
||||||
|
if( any(notEqual(col, vec3(floor((20./255.)*32.)/32.))) ) {
|
||||||
|
icol = col;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Proocedural MAP functions
|
||||||
|
|
||||||
|
bool isWall( const vec2 vos ) {
|
||||||
|
return vos.y<0.4*ROOM_SIZE || vos.y>2.75*ROOM_SIZE || any( equal( mod( vos, vec2( ROOM_SIZE ) ), vec2(0.,0.) ) );
|
||||||
|
}
|
||||||
|
bool isDoor( const vec2 vos ) {
|
||||||
|
return isWall(vos) && ((hash(vos)>0.75 && any( equal( mod( vos, vec2( ROOM_SIZE*0.5 ) ), vec2(2.) ) ))
|
||||||
|
|| any( equal( mod( vos, vec2( ROOM_SIZE ) ), vec2(ROOM_SIZE*0.5) ) ));
|
||||||
|
}
|
||||||
|
bool isObject( const vec2 vos ) {
|
||||||
|
return hash( vos*10. ) > 0.95;
|
||||||
|
}
|
||||||
|
bool map( const vec2 vos ) {
|
||||||
|
return isObject( vos ) || isWall( vos );
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Render MAP functions
|
||||||
|
|
||||||
|
bool intersectSprite( const vec3 ro, const vec3 rd, const vec3 vos, const vec3 nor, out vec2 uv ) {
|
||||||
|
float dist, u;
|
||||||
|
vec2 a = vos.xz + nor.zx*vec2(-0.5,0.5) + vec2(0.5, 0.5);
|
||||||
|
vec2 b = vos.xz - nor.zx*vec2(-0.5,0.5) + vec2(0.5, 0.5);
|
||||||
|
if( intersectSegment( ro, rd, a, b, dist, u) ) {
|
||||||
|
uv.x = u; uv.y = 1.-(ro+dist*rd).y;
|
||||||
|
if( sign(nor.x)<0. ) uv.x = 1.-uv.x;
|
||||||
|
return uv.y>0.&&uv.y<1.;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int getMaterialId( const vec2 vos ) {
|
||||||
|
return int( mod( 521.21 * hash( floor((vos-vec2(0.5))/ROOM_SIZE ) ), float(NUM_MATERIALS)) );
|
||||||
|
}
|
||||||
|
bool getColorForPosition( const vec3 ro, const vec3 rd, const vec3 vos, const vec3 pos, const vec3 nor, inout vec3 col ) {
|
||||||
|
vec2 uv;
|
||||||
|
|
||||||
|
if( isWall( vos.xz ) ) {
|
||||||
|
if( isDoor( vos.xz ) ) {
|
||||||
|
if( intersectSprite( ro, rd, vos+nor*0.03, nor, uv ) ) {
|
||||||
|
// open the door
|
||||||
|
uv.x -= clamp( 2.-0.75*distance( ro.xz, vos.xz+vec2(0.5) ), 0., 1.);
|
||||||
|
if( uv.x > 0. ) {
|
||||||
|
getMaterialColor( MATERIAL_DOOR, uv*64., 0., col );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// a wall is hit
|
||||||
|
if( pos.y <= 1. && pos.y >= 0. ) {
|
||||||
|
vec2 mpos = vec2( dot(vec3(-nor.z,0.0,nor.x),pos), -pos.y );
|
||||||
|
float sha = 0.6 + 0.4*abs(nor.z);
|
||||||
|
getMaterialColor( isDoor( vos.xz+nor.xz )?MATERIAL_DOORWAY:getMaterialId(vos.xz), mpos*64., hash( vos.xz ), col );
|
||||||
|
col *= sha;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if( isObject( vos.xz ) && !isWall( vos.xz+vec2(1.,0.) ) && !isWall( vos.xz+vec2(-1.,0.) )
|
||||||
|
&& !isWall( vos.xz+vec2(0.,-1.) ) && !isWall( vos.xz+vec2(0.,1.) ) &&
|
||||||
|
intersectSprite( ro, rd, vos, rdcenter, uv ) ) {
|
||||||
|
return getObjectColor( 0, uv*64., col );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool castRay( const vec3 ro, const vec3 rd, inout vec3 col ) {
|
||||||
|
vec3 pos = floor(ro);
|
||||||
|
vec3 ri = 1.0/rd;
|
||||||
|
vec3 rs = sign(rd);
|
||||||
|
vec3 dis = (pos-ro + 0.5 + rs*0.5) * ri;
|
||||||
|
|
||||||
|
float res = 0.0;
|
||||||
|
vec3 mm = vec3(0.0);
|
||||||
|
bool hit = false;
|
||||||
|
|
||||||
|
for( int i=0; i<MAXSTEPS; i++ ) {
|
||||||
|
if( hit ) continue;
|
||||||
|
|
||||||
|
mm = step(dis.xyz, dis.zyx);
|
||||||
|
dis += mm * rs * ri;
|
||||||
|
pos += mm * rs;
|
||||||
|
|
||||||
|
if( map(pos.xz) ) {
|
||||||
|
vec3 mini = (pos-ro + 0.5 - 0.5*vec3(rs))*ri;
|
||||||
|
float t = max ( mini.x, mini.z );
|
||||||
|
hit = getColorForPosition( ro, rd, pos, ro+rd*t, -mm*sign(rd), col );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Some really ugly code
|
||||||
|
|
||||||
|
#define CCOS(a) cos(clamp(a,0.,1.)*1.57079632679)
|
||||||
|
#define CSIN(a) sin(clamp(a,0.,1.)*1.57079632679)
|
||||||
|
vec3 path( const float t ) {
|
||||||
|
float tmod = mod( t/SECONDS_IN_ROOM, 8. );
|
||||||
|
float tfloor = floor( tmod );
|
||||||
|
|
||||||
|
vec3 pos = vec3( 4.*ROOM_SIZE*floor(t/(SECONDS_IN_ROOM*8.))+0.5, 0.5, 0.5*ROOM_SIZE+0.5 );
|
||||||
|
return pos + ROOM_SIZE*vec3(
|
||||||
|
clamp(tmod,0.,1.)+clamp(tmod-4.,0.,1.)+0.5*(2.+CSIN(tmod-1.)-CCOS(tmod-3.)+CSIN(tmod-5.)-CCOS(tmod-7.)), 0.,
|
||||||
|
clamp(tmod-2.,0.,1.)-clamp(tmod-6.,0.,1.)+0.5*(-CCOS(tmod-1.)+CSIN(tmod-3.)+CCOS(tmod-5.)-CSIN(tmod-7.)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Main
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 q = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = -1.0 + 2.0*q;
|
||||||
|
p.x *= iResolution.x/ iResolution.y;
|
||||||
|
|
||||||
|
vec3 ro = path( time );
|
||||||
|
vec3 ta = path( time+0.1 );
|
||||||
|
|
||||||
|
rdcenter = rotate( normalize( ta - ro), 0.3*cos(time*0.75) );
|
||||||
|
vec3 uu = normalize(cross( vec3(0.,1.,0.), rdcenter ));
|
||||||
|
vec3 vv = normalize(cross(rdcenter,uu));
|
||||||
|
vec3 rd = normalize( p.x*uu + p.y*vv + 2.5*rdcenter );
|
||||||
|
|
||||||
|
vec3 col = rd.y>0.?vec3(56./255.):vec3(112./255.);
|
||||||
|
castRay( ro, rd, col );
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*--------------------------------------------------------------------------------------
|
||||||
|
License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
|
||||||
|
To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers.
|
||||||
|
-Otavio Good
|
||||||
|
|
||||||
|
**************** Glorious Line Algorithm ****************
|
||||||
|
This is an attempt to solve everything anyone could want from a line in one function.
|
||||||
|
Glorious features:
|
||||||
|
- antialiasing
|
||||||
|
- rectangles, squares, lines, circles, rounded rectangles
|
||||||
|
- square or rounded endpoints
|
||||||
|
- outline shapes (might have some bugs still)
|
||||||
|
- dashed, animated lines
|
||||||
|
- resolution dependent or independent - some functions work in pixel units, some in UV coordinates.
|
||||||
|
- efficient
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Clamp [0..1] range
|
||||||
|
vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
|
||||||
|
vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
|
||||||
|
float saturate(float a) { return clamp(a, 0.0, 1.0); }
|
||||||
|
|
||||||
|
// Basically a triangle wave
|
||||||
|
float repeat(float x) { return abs(fract(x*0.5+0.5)-0.5)*2.0; }
|
||||||
|
|
||||||
|
// This is it... what you have been waiting for... _The_ Glorious Line Algorithm.
|
||||||
|
// This function will make a signed distance field that says how far you are from the edge
|
||||||
|
// of the line at any point U,V.
|
||||||
|
// Pass it UVs, line end points, line thickness (x is along the line and y is perpendicular),
|
||||||
|
// How rounded the end points should be (0.0 is rectangluar, setting rounded to thick.y will be circular),
|
||||||
|
// dashOn is just 1.0 or 0.0 to turn on the dashed lines.
|
||||||
|
float LineDistField(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded, float dashOn) {
|
||||||
|
// Don't let it get more round than circular.
|
||||||
|
rounded = min(thick.y, rounded);
|
||||||
|
// midpoint
|
||||||
|
vec2 mid = (pB + pA) * 0.5;
|
||||||
|
// vector from point A to B
|
||||||
|
vec2 delta = pB - pA;
|
||||||
|
// Distance between endpoints
|
||||||
|
float lenD = length(delta);
|
||||||
|
// unit vector pointing in the line's direction
|
||||||
|
vec2 unit = delta / lenD;
|
||||||
|
// Check for when line endpoints are the same
|
||||||
|
if (lenD < 0.0001) unit = vec2(1.0, 0.0); // if pA and pB are same
|
||||||
|
// Perpendicular vector to unit - also length 1.0
|
||||||
|
vec2 perp = unit.yx * vec2(-1.0, 1.0);
|
||||||
|
// position along line from midpoint
|
||||||
|
float dpx = dot(unit, uv - mid);
|
||||||
|
// distance away from line at a right angle
|
||||||
|
float dpy = dot(perp, uv - mid);
|
||||||
|
// Make a distance function that is 0 at the transition from black to white
|
||||||
|
float disty = abs(dpy) - thick.y + rounded;
|
||||||
|
float distx = abs(dpx) - lenD * 0.5 - thick.x + rounded;
|
||||||
|
|
||||||
|
// Too tired to remember what this does. Something like rounded endpoints for distance function.
|
||||||
|
float dist = length(vec2(max(0.0, distx), max(0.0,disty))) - rounded;
|
||||||
|
dist = min(dist, max(distx, disty));
|
||||||
|
|
||||||
|
// This is for animated dashed lines. Delete if you don't like dashes.
|
||||||
|
float dashScale = 2.0*thick.y;
|
||||||
|
// Make a distance function for the dashes
|
||||||
|
float dash = (repeat(dpx/dashScale + iGlobalTime)-0.5)*dashScale;
|
||||||
|
// Combine this distance function with the line's.
|
||||||
|
dist = max(dist, dash-(1.0-dashOn*1.0)*10000.0);
|
||||||
|
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes a filled line in pixel units. A 1.0 thick line will be 1 pixel thick.
|
||||||
|
float FillLinePix(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded) {
|
||||||
|
float scale = dFdy(uv).y;
|
||||||
|
thick = (thick * 0.5 - 0.5) * scale;
|
||||||
|
float df = LineDistField(uv, pA, pB, vec2(thick), rounded, 0.0);
|
||||||
|
return saturate(df / scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes an outlined line in pixel units. A 1.0 thick outline will be 1 pixel thick.
|
||||||
|
float DrawOutlinePix(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded, float outlineThick) {
|
||||||
|
float scale = dFdy(uv).y;
|
||||||
|
thick = (thick * 0.5 - 0.5) * scale;
|
||||||
|
rounded = (rounded * 0.5 - 0.5) * scale;
|
||||||
|
outlineThick = (outlineThick * 0.5 - 0.5) * scale;
|
||||||
|
float df = LineDistField(uv, pA, pB, vec2(thick), rounded, 0.0);
|
||||||
|
return saturate((abs(df + outlineThick) - outlineThick) / scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes a line in UV units. A 1.0 thick line will span a whole 0..1 in UV space.
|
||||||
|
float FillLine(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded) {
|
||||||
|
float df = LineDistField(uv, pA, pB, vec2(thick), rounded, 0.0);
|
||||||
|
return saturate(df / dFdy(uv).y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes a dashed line in UV units. A 1.0 thick line will span a whole 0..1 in UV space.
|
||||||
|
float FillLineDash(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded) {
|
||||||
|
float df = LineDistField(uv, pA, pB, vec2(thick), rounded, 1.0);
|
||||||
|
return saturate(df / dFdy(uv).y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This makes an outlined line in UV units. A 1.0 thick outline will span 0..1 in UV space.
|
||||||
|
float DrawOutline(vec2 uv, vec2 pA, vec2 pB, vec2 thick, float rounded, float outlineThick) {
|
||||||
|
float df = LineDistField(uv, pA, pB, vec2(thick), rounded, 0.0);
|
||||||
|
return saturate((abs(df + outlineThick) - outlineThick) / dFdy(uv).y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This just draws a point for debugging using a different technique that is less glorious.
|
||||||
|
void DrawPoint(vec2 uv, vec2 p, inout vec3 col) {
|
||||||
|
col = mix(col, vec3(1.0, 0.25, 0.25), saturate(dFdy(uv).y*8.0/distance(uv, p)-4.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// Adjust UV space so it's a nice size and square.
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
uv -= 0.5;
|
||||||
|
uv.x *= iResolution.x / iResolution.y;
|
||||||
|
uv *= 16.0;
|
||||||
|
|
||||||
|
// Make things that rotate with time.
|
||||||
|
vec2 rotA = vec2(cos(iGlobalTime*0.82), sin(iGlobalTime*0.82));
|
||||||
|
vec2 rotB = vec2(sin(iGlobalTime*0.82), -cos(iGlobalTime*0.82));
|
||||||
|
// Make a bunch of line endpoints to use.
|
||||||
|
vec2 pA = vec2(-4.0, 0.0) - rotA;
|
||||||
|
vec2 pB = vec2(4.0, 0.0) + rotA;
|
||||||
|
vec2 pC = pA + vec2(0.0, 4.0);
|
||||||
|
vec2 pD = pB + vec2(0.0, 4.0);
|
||||||
|
// Debugging code
|
||||||
|
//float df = LineDistField(uv, pA, pB, vec2(28.0 * dFdy(uv).y), 0.1, 0.0);
|
||||||
|
//float df = DistField(uv, pA, pB, 25.000625 * dFdx(uv).x, 0.5);
|
||||||
|
//vec3 finalColor = vec3(df*1.0, -df*1.0, 0.0);
|
||||||
|
//finalColor = vec3(1.0) * saturate(df / dFdy(uv).y);
|
||||||
|
//finalColor = vec3(1.0) * saturate((abs(df+0.009)-0.009) / dFdy(uv).y);
|
||||||
|
|
||||||
|
// Clear to white.
|
||||||
|
vec3 finalColor = vec3(1.0);
|
||||||
|
|
||||||
|
// Lots of sample lines
|
||||||
|
// 1 pixel thick regardless of screen scale.
|
||||||
|
finalColor *= FillLinePix(uv, pA, pB, vec2(0.0, 1.0), 0.0);
|
||||||
|
// Rounded rectangle outline, 1 pixel thick
|
||||||
|
finalColor *= DrawOutlinePix(uv, pA, pB, vec2(32.0), 16.0, 1.0);
|
||||||
|
// square-cornered rectangle outline, 1 pixel thick
|
||||||
|
finalColor *= DrawOutlinePix(uv, pA, pB, vec2(64.0), 0.0, 1.0);
|
||||||
|
// Fully rounded endpoint with outline 8 pixels thick
|
||||||
|
finalColor *= DrawOutlinePix(uv, pA, pB, vec2(128.0), 128.0, 8.0);
|
||||||
|
// Dashed line with rectangular endpoints that touch pC and pD, 0.5 radius thickness in UV units
|
||||||
|
finalColor *= FillLineDash(uv, pC, pD, vec2(0.0, 0.5), 0.0);
|
||||||
|
// Rounded endpoint dashed line with radius 0.125 in UV units
|
||||||
|
finalColor *= FillLineDash(uv, pC + vec2(0.0, 2.0), pD + vec2(0.0, 2.0), vec2(0.125), 1.0);
|
||||||
|
|
||||||
|
finalColor *= DrawOutline(uv, (pA + pB) * 0.5 + vec2(0.0, -4.5), (pA + pB) * 0.5 + vec2(0.0, -4.5), vec2(2.0, 2.0), 2.0, 0.8);
|
||||||
|
finalColor *= FillLine(uv, pA - vec2(4.0, 0.0), pC - vec2(4.0, 0.0)+rotA, vec2(0.125), 1.0);
|
||||||
|
finalColor *= FillLine(uv, pB + vec2(4.0, 0.0), pD + vec2(4.0, 0.0)-rotA, vec2(0.125), 1.0);
|
||||||
|
|
||||||
|
DrawPoint(uv, pA, finalColor);
|
||||||
|
DrawPoint(uv, pB, finalColor);
|
||||||
|
DrawPoint(uv, pC, finalColor);
|
||||||
|
DrawPoint(uv, pD, finalColor);
|
||||||
|
|
||||||
|
// Blue grid lines
|
||||||
|
finalColor -= vec3(1.0, 1.0, 0.2) * saturate(repeat(uv.x*2.0) - 0.92)*4.0;
|
||||||
|
finalColor -= vec3(1.0, 1.0, 0.2) * saturate(repeat(uv.y*2.0) - 0.92)*4.0;
|
||||||
|
//finalColor *= saturate(mod(fragCoord.y + 0.5, 2.0) + mod(fragCoord.x + 0.5, 2.0));
|
||||||
|
fragColor = vec4(sqrt(saturate(finalColor)), 1.0);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
// https://www.shadertoy.com/view/4tdSWr
|
||||||
|
|
||||||
|
const float cloudscale = 1.1;
|
||||||
|
const float speed = 0.03;
|
||||||
|
const float clouddark = 0.5;
|
||||||
|
const float cloudlight = 0.3;
|
||||||
|
const float cloudcover = 0.2;
|
||||||
|
const float cloudalpha = 8.0;
|
||||||
|
const float skytint = 0.5;
|
||||||
|
const vec3 skycolour1 = vec3(0.2, 0.4, 0.6);
|
||||||
|
const vec3 skycolour2 = vec3(0.4, 0.7, 1.0);
|
||||||
|
|
||||||
|
const mat2 m = mat2( 1.6, 1.2, -1.2, 1.6 );
|
||||||
|
|
||||||
|
vec2 hash( vec2 p ) {
|
||||||
|
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 ) {
|
||||||
|
const float K1 = 0.366025404; // (sqrt(3)-1)/2;
|
||||||
|
const float K2 = 0.211324865; // (3-sqrt(3))/6;
|
||||||
|
vec2 i = floor(p + (p.x+p.y)*K1);
|
||||||
|
vec2 a = p - i + (i.x+i.y)*K2;
|
||||||
|
vec2 o = (a.x>a.y) ? vec2(1.0,0.0) : vec2(0.0,1.0); //vec2 of = 0.5 + 0.5*vec2(sign(a.x-a.y), sign(a.y-a.x));
|
||||||
|
vec2 b = a - o + K2;
|
||||||
|
vec2 c = a - 1.0 + 2.0*K2;
|
||||||
|
vec3 h = max(0.5-vec3(dot(a,a), dot(b,b), dot(c,c) ), 0.0 );
|
||||||
|
vec3 n = h*h*h*h*vec3( dot(a,hash(i+0.0)), dot(b,hash(i+o)), dot(c,hash(i+1.0)));
|
||||||
|
return dot(n, vec3(70.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(vec2 n) {
|
||||||
|
float total = 0.0, amplitude = 0.1;
|
||||||
|
for (int i = 0; i < 7; i++) {
|
||||||
|
total += noise(n) * amplitude;
|
||||||
|
n = m * n;
|
||||||
|
amplitude *= 0.4;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 p = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 uv = p*vec2(iResolution.x/iResolution.y,1.0);
|
||||||
|
float time = iGlobalTime * speed;
|
||||||
|
float q = fbm(uv * cloudscale * 0.5);
|
||||||
|
|
||||||
|
//ridged noise shape
|
||||||
|
float r = 0.0;
|
||||||
|
uv *= cloudscale;
|
||||||
|
uv -= q - time;
|
||||||
|
float weight = 0.8;
|
||||||
|
for (int i=0; i<8; i++){
|
||||||
|
r += abs(weight*noise( uv ));
|
||||||
|
uv = m*uv + time;
|
||||||
|
weight *= 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noise shape
|
||||||
|
float f = 0.0;
|
||||||
|
uv = p*vec2(iResolution.x/iResolution.y,1.0);
|
||||||
|
uv *= cloudscale;
|
||||||
|
uv -= q - time;
|
||||||
|
weight = 0.7;
|
||||||
|
for (int i=0; i<8; i++){
|
||||||
|
f += weight*noise( uv );
|
||||||
|
uv = m*uv + time;
|
||||||
|
weight *= 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
f *= r + f;
|
||||||
|
|
||||||
|
//noise colour
|
||||||
|
float c = 0.0;
|
||||||
|
time = iGlobalTime * speed * 2.0;
|
||||||
|
uv = p*vec2(iResolution.x/iResolution.y,1.0);
|
||||||
|
uv *= cloudscale*2.0;
|
||||||
|
uv -= q - time;
|
||||||
|
weight = 0.4;
|
||||||
|
for (int i=0; i<7; i++){
|
||||||
|
c += weight*noise( uv );
|
||||||
|
uv = m*uv + time;
|
||||||
|
weight *= 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noise ridge colour
|
||||||
|
float c1 = 0.0;
|
||||||
|
time = iGlobalTime * speed * 3.0;
|
||||||
|
uv = p*vec2(iResolution.x/iResolution.y,1.0);
|
||||||
|
uv *= cloudscale*3.0;
|
||||||
|
uv -= q - time;
|
||||||
|
weight = 0.4;
|
||||||
|
for (int i=0; i<7; i++){
|
||||||
|
c1 += abs(weight*noise( uv ));
|
||||||
|
uv = m*uv + time;
|
||||||
|
weight *= 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
c += c1;
|
||||||
|
|
||||||
|
vec3 skycolour = mix(skycolour2, skycolour1, p.y);
|
||||||
|
vec3 cloudcolour = vec3(1.1, 1.1, 0.9) * clamp((clouddark + cloudlight*c), 0.0, 1.0);
|
||||||
|
|
||||||
|
f = cloudcover + cloudalpha*f*r;
|
||||||
|
|
||||||
|
vec3 result = mix(skycolour, clamp(skytint * skycolour + cloudcolour, 0.0, 1.0), clamp(f + c, 0.0, 1.0));
|
||||||
|
|
||||||
|
fragColor = vec4( result, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
//Xyptonjtroz by nimitz (twitter: @stormoid)
|
||||||
|
|
||||||
|
//Audio by Dave_Hoskins
|
||||||
|
|
||||||
|
#define ITR 100
|
||||||
|
#define FAR 30.
|
||||||
|
#define time iGlobalTime
|
||||||
|
|
||||||
|
/*
|
||||||
|
Believable animated volumetric dust storm in 7 samples,
|
||||||
|
blending each layer in based on geometry distance allows to
|
||||||
|
render it without visible seams. 3d Triangle noise is
|
||||||
|
used for the dust volume.
|
||||||
|
|
||||||
|
Also included is procedural bump mapping and glow based on
|
||||||
|
curvature*fresnel. (see: https://www.shadertoy.com/view/Xts3WM)
|
||||||
|
|
||||||
|
|
||||||
|
Further explanation of the dust generation (per Dave's request):
|
||||||
|
|
||||||
|
The basic idea is to have layers of gradient shaded volumetric
|
||||||
|
animated noise. The problem is when geometry is intersected
|
||||||
|
before the ray reaches the far plane. A way to smoothly blend
|
||||||
|
the low sampled noise is needed. So I am blending (smoothstep)
|
||||||
|
each dust layer based on current ray distance and the solid
|
||||||
|
interesction distance. I am also scaling the noise taps as a
|
||||||
|
function of the current distance so that the distant dust doesn't
|
||||||
|
appear too noisy and as a function of current height to get some
|
||||||
|
"ground hugging" effect.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);}
|
||||||
|
|
||||||
|
float height(in vec2 p)
|
||||||
|
{
|
||||||
|
p *= 0.2;
|
||||||
|
return sin(p.y)*0.4 + sin(p.x)*0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
//smooth min form iq
|
||||||
|
float smin( float a, float b)
|
||||||
|
{
|
||||||
|
const float k = 0.7;
|
||||||
|
float h = clamp( 0.5 + 0.5*(b-a)/k, 0.0, 1.0 );
|
||||||
|
return mix( b, a, h ) - k*h*(1.0-h);
|
||||||
|
}
|
||||||
|
|
||||||
|
//form Dave
|
||||||
|
vec2 hash22(vec2 p)
|
||||||
|
{
|
||||||
|
p = fract(p * vec2(5.3983, 5.4427));
|
||||||
|
p += dot(p.yx, p.xy + vec2(21.5351, 14.3137));
|
||||||
|
return fract(vec2(p.x * p.y * 95.4337, p.x * p.y * 97.597));
|
||||||
|
}
|
||||||
|
|
||||||
|
float vine(vec3 p, in float c, in float h)
|
||||||
|
{
|
||||||
|
p.y += sin(p.z*0.2625)*2.5;
|
||||||
|
p.x += cos(p.z*0.1575)*3.;
|
||||||
|
vec2 q = vec2(mod(p.x, c)-c/2., p.y);
|
||||||
|
return length(q) - h -sin(p.z*2.+sin(p.x*7.)*0.5+time*0.5)*0.13;
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(vec3 p)
|
||||||
|
{
|
||||||
|
p.y += height(p.zx);
|
||||||
|
|
||||||
|
vec3 bp = p;
|
||||||
|
vec2 hs = hash22(floor(p.zx/4.));
|
||||||
|
p.zx = mod(p.zx,4.)-2.;
|
||||||
|
|
||||||
|
float d = p.y+0.5;
|
||||||
|
p.y -= hs.x*0.4-0.15;
|
||||||
|
p.zx += hs*1.3;
|
||||||
|
d = smin(d, length(p)-hs.x*0.4);
|
||||||
|
|
||||||
|
d = smin(d, vine(bp+vec3(1.8,0.,0),15.,.8) );
|
||||||
|
d = smin(d, vine(bp.zyx+vec3(0.,0,17.),20.,0.75) );
|
||||||
|
|
||||||
|
return d*1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float march(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
float precis = 0.002;
|
||||||
|
float h=precis*2.0;
|
||||||
|
float d = 0.;
|
||||||
|
for( int i=0; i<ITR; i++ )
|
||||||
|
{
|
||||||
|
if( abs(h)<precis || d>FAR ) break;
|
||||||
|
d += h;
|
||||||
|
float res = map(ro+rd*d);
|
||||||
|
h = res;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float tri(in float x){return abs(fract(x)-.5);}
|
||||||
|
vec3 tri3(in vec3 p){return vec3( tri(p.z+tri(p.y*1.)), tri(p.z+tri(p.x*1.)), tri(p.y+tri(p.x*1.)));}
|
||||||
|
|
||||||
|
mat2 m2 = mat2(0.970, 0.242, -0.242, 0.970);
|
||||||
|
|
||||||
|
float triNoise3d(in vec3 p, in float spd)
|
||||||
|
{
|
||||||
|
float z=1.4;
|
||||||
|
float rz = 0.;
|
||||||
|
vec3 bp = p;
|
||||||
|
for (float i=0.; i<=3.; i++ )
|
||||||
|
{
|
||||||
|
vec3 dg = tri3(bp*2.);
|
||||||
|
p += (dg+time*spd);
|
||||||
|
|
||||||
|
bp *= 1.8;
|
||||||
|
z *= 1.5;
|
||||||
|
p *= 1.2;
|
||||||
|
//p.xz*= m2;
|
||||||
|
|
||||||
|
rz+= (tri(p.z+tri(p.x+tri(p.y))))/z;
|
||||||
|
bp += 0.14;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float fogmap(in vec3 p, in float d)
|
||||||
|
{
|
||||||
|
p.x += time*1.5;
|
||||||
|
p.z += sin(p.x*.5);
|
||||||
|
return triNoise3d(p*2.2/(d+20.),0.2)*(1.-smoothstep(0.,.7,p.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fog(in vec3 col, in vec3 ro, in vec3 rd, in float mt)
|
||||||
|
{
|
||||||
|
float d = .5;
|
||||||
|
for(int i=0; i<7; i++)
|
||||||
|
{
|
||||||
|
vec3 pos = ro + rd*d;
|
||||||
|
float rz = fogmap(pos, d);
|
||||||
|
float grd = clamp((rz - fogmap(pos+.8-float(i)*0.1,d))*3., 0.1, 1. );
|
||||||
|
vec3 col2 = (vec3(.1,0.8,.5)*.5 + .5*vec3(.5, .8, 1.)*(1.7-grd))*0.55;
|
||||||
|
col = mix(col,col2,clamp(rz*smoothstep(d-0.4,d+2.+d*.75,mt),0.,1.) );
|
||||||
|
d *= 1.5+0.3;
|
||||||
|
if (d>mt)break;
|
||||||
|
}
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal(in vec3 p)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(-1., 1.)*0.005;
|
||||||
|
return normalize(e.yxx*map(p + e.yxx) + e.xxy*map(p + e.xxy) +
|
||||||
|
e.xyx*map(p + e.xyx) + e.yyy*map(p + e.yyy) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float bnoise(in vec3 p)
|
||||||
|
{
|
||||||
|
float n = sin(triNoise3d(p*.3,0.0)*11.)*0.6+0.4;
|
||||||
|
n += sin(triNoise3d(p*1.,0.05)*40.)*0.1+0.9;
|
||||||
|
return (n*n)*0.003;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 bump(in vec3 p, in vec3 n, in float ds)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(.005,0);
|
||||||
|
float n0 = bnoise(p);
|
||||||
|
vec3 d = vec3(bnoise(p+e.xyy)-n0, bnoise(p+e.yxy)-n0, bnoise(p+e.yyx)-n0)/e.x;
|
||||||
|
n = normalize(n-d*2.5/sqrt(ds));
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
float shadow(in vec3 ro, in vec3 rd, in float mint, in float tmax)
|
||||||
|
{
|
||||||
|
float res = 1.0;
|
||||||
|
float t = mint;
|
||||||
|
for( int i=0; i<10; i++ )
|
||||||
|
{
|
||||||
|
float h = map(ro + rd*t);
|
||||||
|
res = min( res, 4.*h/t );
|
||||||
|
t += clamp( h, 0.05, .5 );
|
||||||
|
if(h<0.001 || t>tmax) break;
|
||||||
|
}
|
||||||
|
return clamp( res, 0.0, 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float curv(in vec3 p, in float w)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(-1., 1.)*w;
|
||||||
|
|
||||||
|
float t1 = map(p + e.yxx), t2 = map(p + e.xxy);
|
||||||
|
float t3 = map(p + e.xyx), t4 = map(p + e.yyy);
|
||||||
|
|
||||||
|
return .125/(e.x*e.x) *(t1 + t2 + t3 + t4 - 4. * map(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 p = fragCoord.xy/iResolution.xy-0.5;
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
p.x*=iResolution.x/iResolution.y;
|
||||||
|
vec2 mo = iMouse.xy / iResolution.xy-.5;
|
||||||
|
mo = (mo==vec2(-.5))?mo=vec2(-0.1,0.07):mo;
|
||||||
|
mo.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
vec3 ro = vec3(smoothstep(0.,1.,tri(time*.45)*2.)*0.1, smoothstep(0.,1.,tri(time*0.9)*2.)*0.07, -time*0.6);
|
||||||
|
ro.y -= height(ro.zx)+0.05;
|
||||||
|
mo.x += smoothstep(0.6,1.,sin(time*.6)*0.5+0.5)-1.5;
|
||||||
|
vec3 eyedir = normalize(vec3(cos(mo.x),mo.y*2.-0.2+sin(time*0.45*1.57)*0.1,sin(mo.x)));
|
||||||
|
vec3 rightdir = normalize(vec3(cos(mo.x+1.5708),0.,sin(mo.x+1.5708)));
|
||||||
|
vec3 updir = normalize(cross(rightdir,eyedir));
|
||||||
|
vec3 rd=normalize((p.x*rightdir+p.y*updir)*1.+eyedir);
|
||||||
|
|
||||||
|
vec3 ligt = normalize( vec3(.5, .05, -.2) );
|
||||||
|
vec3 ligt2 = normalize( vec3(.5, -.1, -.2) );
|
||||||
|
|
||||||
|
float rz = march(ro,rd);
|
||||||
|
|
||||||
|
vec3 fogb = mix(vec3(.7,.8,.8 )*0.3, vec3(1.,1.,.77)*.95, pow(dot(rd,ligt2)+1.2, 2.5)*.25);
|
||||||
|
fogb *= clamp(rd.y*.5+.6, 0., 1.);
|
||||||
|
vec3 col = fogb;
|
||||||
|
|
||||||
|
if ( rz < FAR )
|
||||||
|
{
|
||||||
|
vec3 pos = ro+rz*rd;
|
||||||
|
vec3 nor= normal( pos );
|
||||||
|
float d = distance(pos,ro);
|
||||||
|
nor = bump(pos,nor,d);
|
||||||
|
float crv = clamp(curv(pos, .4),.0,10.);
|
||||||
|
float shd = shadow(pos,ligt,0.1,3.);
|
||||||
|
float dif = clamp( dot( nor, ligt ), 0.0, 1.0 )*shd;
|
||||||
|
float spe = pow(clamp( dot( reflect(rd,nor), ligt ), 0.0, 1.0 ),50.)*shd;
|
||||||
|
float fre = pow( clamp(1.0+dot(nor,rd),0.0,1.0), 1.5 );
|
||||||
|
vec3 brdf = vec3(0.10,0.11,0.13);
|
||||||
|
brdf += 1.5*dif*vec3(1.00,0.90,0.7);
|
||||||
|
col = mix(vec3(0.1,0.2,1),vec3(.3,.5,1),pos.y*.5)*0.2+.1;
|
||||||
|
col *= (sin(bnoise(pos)*900.)*0.2+0.8);
|
||||||
|
col = col*brdf + col*spe*.5 + fre*vec3(.7,1.,0.2)*.3*crv;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ordinary distance fog first
|
||||||
|
col = mix(col, fogb, smoothstep(FAR-7.,FAR,rz));
|
||||||
|
|
||||||
|
//then volumetric fog
|
||||||
|
col = fog(col, ro, rd, rz);
|
||||||
|
|
||||||
|
//post
|
||||||
|
col = pow(col,vec3(0.8));
|
||||||
|
col *= 1.-smoothstep(0.1,2.,length(p));
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
// london.jpg
|
||||||
|
|
||||||
|
// I started working a bit on the colors of Remix 2, ended up with something like this. :)
|
||||||
|
// Remix 2 here: https://www.shadertoy.com/view/MtcGD7
|
||||||
|
// Remix 1 here: https://www.shadertoy.com/view/llc3DM
|
||||||
|
// Original here: https://www.shadertoy.com/view/XsXXRN
|
||||||
|
|
||||||
|
float rand(vec2 n) {
|
||||||
|
return fract(sin(cos(dot(n, vec2(12.9898,12.1414)))) * 83758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(vec2 n) {
|
||||||
|
const vec2 d = vec2(0.0, 1.0);
|
||||||
|
vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n));
|
||||||
|
return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(vec2 n) {
|
||||||
|
float total = 0.0, amplitude = 1.0;
|
||||||
|
for (int i = 0; i <5; i++) {
|
||||||
|
total += noise(n) * amplitude;
|
||||||
|
n += n*1.7;
|
||||||
|
amplitude *= 0.47;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
|
||||||
|
const vec3 c1 = vec3(0.5, 0.0, 0.1);
|
||||||
|
const vec3 c2 = vec3(0.9, 0.1, 0.0);
|
||||||
|
const vec3 c3 = vec3(0.2, 0.1, 0.7);
|
||||||
|
const vec3 c4 = vec3(1.0, 0.9, 0.1);
|
||||||
|
const vec3 c5 = vec3(0.1);
|
||||||
|
const vec3 c6 = vec3(0.9);
|
||||||
|
|
||||||
|
vec2 speed = vec2(0.1, 0.9);
|
||||||
|
float shift = 1.327+sin(iGlobalTime*2.0)/2.4;
|
||||||
|
float alpha = 1.0;
|
||||||
|
|
||||||
|
float dist = 3.5-sin(iGlobalTime*0.4)/1.89;
|
||||||
|
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = fragCoord.xy * dist / iResolution.xx;
|
||||||
|
p += sin(p.yx*4.0+vec2(.2,-.3)*iGlobalTime)*0.04;
|
||||||
|
p += sin(p.yx*8.0+vec2(.6,+.1)*iGlobalTime)*0.01;
|
||||||
|
|
||||||
|
p.x -= iGlobalTime/1.1;
|
||||||
|
float q = fbm(p - iGlobalTime * 0.3+1.0*sin(iGlobalTime+0.5)/2.0);
|
||||||
|
float qb = fbm(p - iGlobalTime * 0.4+0.1*cos(iGlobalTime)/2.0);
|
||||||
|
float q2 = fbm(p - iGlobalTime * 0.44 - 5.0*cos(iGlobalTime)/2.0) - 6.0;
|
||||||
|
float q3 = fbm(p - iGlobalTime * 0.9 - 10.0*cos(iGlobalTime)/15.0)-4.0;
|
||||||
|
float q4 = fbm(p - iGlobalTime * 1.4 - 20.0*sin(iGlobalTime)/14.0)+2.0;
|
||||||
|
q = (q + qb - .4 * q2 -2.0*q3 + .6*q4)/3.8;
|
||||||
|
vec2 r = vec2(fbm(p + q /2.0 + iGlobalTime * speed.x - p.x - p.y), fbm(p + q - iGlobalTime * speed.y));
|
||||||
|
vec3 c = mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y);
|
||||||
|
vec3 color = vec3(1.0/(pow(c+1.61,vec3(4.0))) * cos(shift * fragCoord.y / iResolution.y));
|
||||||
|
|
||||||
|
color=vec3(1.0,.2,.05)/(pow((r.y+r.y)* max(.0,p.y)+0.1, 4.0));;
|
||||||
|
color += (texture(iChannel0,uv*0.6+vec2(.5,.1)).xyz*0.01*pow((r.y+r.y)*.65,5.0)+0.055)*mix( vec3(.9,.4,.3),vec3(.7,.5,.2), uv.y);
|
||||||
|
color = color/(1.0+max(vec3(0),color));
|
||||||
|
fragColor = vec4(color.x, color.y, color.z, alpha);
|
||||||
|
}
|
|
@ -0,0 +1,309 @@
|
||||||
|
//Somewhere in 1993 by nimitz (twitter: @stormoid)
|
||||||
|
|
||||||
|
#define PALETTE 6.8
|
||||||
|
|
||||||
|
//3 to 5 works best
|
||||||
|
#define TERRAIN_COMPLEXITY 4.
|
||||||
|
#define ITR 100
|
||||||
|
#define FAR 700.
|
||||||
|
#define time mod(iGlobalTime,500.)
|
||||||
|
|
||||||
|
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,-s,s,c);}
|
||||||
|
float smoothfloor(const in float x, const in float w)
|
||||||
|
{
|
||||||
|
return floor(x)+smoothstep(w, 1.-w,fract(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 enpos()
|
||||||
|
{
|
||||||
|
return vec3(sin(time)*100.+50.,sin(time)*30.+30.,300.+sin(time*.9+sin(time*0.88+0.2))*100.);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
//---------------------------HUD--------------------------
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
float square(in vec2 p){ return max(abs(p.x),abs(p.y));}
|
||||||
|
float loz(in vec2 p){ return abs(p.x)+abs(p.y);}
|
||||||
|
|
||||||
|
//from Dave (https://www.shadertoy.com/view/4djSRW)
|
||||||
|
vec2 hash2(float p)
|
||||||
|
{
|
||||||
|
vec2 p2 = fract(p * vec2(5.3983, 5.4427));
|
||||||
|
p2 += dot(p2.yx, p2.xy + vec2(21.5351, 14.3137));
|
||||||
|
return fract(vec2(p2.x * p2.y * 95.4337, p2.x * p2.y * 97.597));
|
||||||
|
}
|
||||||
|
|
||||||
|
float line( in vec2 a, in vec2 b, in vec2 p )
|
||||||
|
{
|
||||||
|
vec2 pa = p - a, ba = b - a;
|
||||||
|
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1.0 );
|
||||||
|
return length( pa - ba*h );
|
||||||
|
}
|
||||||
|
|
||||||
|
float crosshair(in vec2 p , in float tk, in float rt)
|
||||||
|
{
|
||||||
|
float d = abs(p.x)+abs(p.y);
|
||||||
|
float a = atan(p.y,p.x);
|
||||||
|
float rz = smoothstep(0.03*tk,.04*tk,abs(d-0.5));
|
||||||
|
d = sin(a*3.+1.59-time*3.5-rt);
|
||||||
|
rz += smoothstep(0.0,.07*tk,d);
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
//inspired by otaviogood "runes" (https://www.shadertoy.com/view/MsXSRn)
|
||||||
|
float text2(in vec2 p)
|
||||||
|
{
|
||||||
|
p = (p+vec2(1.75,-.8))*7.;
|
||||||
|
p.x *= 1.5;
|
||||||
|
float sd = floor(time*8.);
|
||||||
|
vec2 p1 = vec2(0), p2 = hash2(sd);
|
||||||
|
float d= 1.;
|
||||||
|
vec2 fl = vec2(2.,2.);
|
||||||
|
for(float i=0.;i<7.;i++)
|
||||||
|
{
|
||||||
|
if(hash2(sd+i+10.).x<0.3)continue;
|
||||||
|
p1 = hash2(i+sd);
|
||||||
|
p2 = hash2(i+sd+1.);
|
||||||
|
p1 = (floor(p1*fl) + .5)/fl;
|
||||||
|
p2 = (floor(p2*fl) + .5)/fl;
|
||||||
|
if (p1 == p2) p2 = vec2(.5);
|
||||||
|
d = min(line(p1, p2, p), d);
|
||||||
|
p1 = p2;
|
||||||
|
p2 = hash2(i+sd+3.);
|
||||||
|
p2 = (floor(p2*fl) + .5)/fl;
|
||||||
|
d = min(line(p1, p2, p), d);
|
||||||
|
p1 = p2;
|
||||||
|
p2 = hash2(i+sd+5.);
|
||||||
|
p2 = (floor(p2*fl) + .5)/fl;
|
||||||
|
if (p1 == p2)
|
||||||
|
{
|
||||||
|
p2 = hash2(i+sd+7.);
|
||||||
|
p2 = (floor(p2*fl) + .5)/fl;
|
||||||
|
}
|
||||||
|
d = min(line(p1,p2,p),d);
|
||||||
|
p.x -= .8;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = smoothstep(0.03, .08,d);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 makeHud(in vec2 p, in float seek)
|
||||||
|
{
|
||||||
|
float sk1 = smoothstep(0.99, 1., seek);
|
||||||
|
float sk2 = step(1.-sk1, .5);
|
||||||
|
//lens deformation
|
||||||
|
float ll = abs(p.x)+abs(p.y)*0.25;
|
||||||
|
p *= ll * -.3+1.29;
|
||||||
|
p *= 2.;
|
||||||
|
vec3 col = vec3(0);
|
||||||
|
float d= 1.;
|
||||||
|
//crosshairs
|
||||||
|
float rz = crosshair(p*1.1, .9,1.+sk1);
|
||||||
|
rz = min(rz,crosshair(p*2.7,2., -time*6.5-1.1-sk1));
|
||||||
|
//minimap (top right)
|
||||||
|
float d2 = square(p+vec2(-1.45, -0.67))+0.02;
|
||||||
|
d = smoothstep(0.3,0.31,d2);
|
||||||
|
d = max(d,smoothstep(0.35,.55,min(sin(p.x*80.+1.9),sin(p.y*80.+time*15.))+1.4));
|
||||||
|
d = min(d,smoothstep(0.002,0.009,abs(d2-0.3)));
|
||||||
|
vec3 enp = enpos()/1000.;
|
||||||
|
enp.z = 1.-enp.z;
|
||||||
|
float en = smoothstep(0.025, 0.033, loz(enp.xz+p-vec2(1.47, 1.4))) ;
|
||||||
|
en += mod(floor(time*2.5), 2.);
|
||||||
|
d = min(d,en);
|
||||||
|
rz = min(d,rz);
|
||||||
|
//text (top left)
|
||||||
|
rz= min(rz,text2(p));
|
||||||
|
//altitude bars
|
||||||
|
d = min(rz,sin(p.y*100.+sin(time)*20.)*3.+3.);
|
||||||
|
d2 = max(d,(p.x+0.59)*200.);
|
||||||
|
d2 = max(d2,-(p.x+0.66)*200.);
|
||||||
|
float d3 = max(d,(p.x-0.66)*200.);
|
||||||
|
d3 = max(d3,-(p.x-.59)*200.);
|
||||||
|
d2 = min(d2,d3);
|
||||||
|
d2 += smoothstep(0.59, .6, -p.y);
|
||||||
|
d2 += smoothstep(0.59, .6, p.y);
|
||||||
|
rz = min(rz,d2);
|
||||||
|
//bottom left "status"
|
||||||
|
float num = mod(floor(time*12.),12.);
|
||||||
|
vec2 p2 = p+vec2(-1.32,.94);
|
||||||
|
d = 1.;
|
||||||
|
for(float i=0.;i<5.;i++)
|
||||||
|
{
|
||||||
|
d = min(d,length(p2)+float(num==i));
|
||||||
|
p2.x -= 0.1;
|
||||||
|
}
|
||||||
|
d = smoothstep(0.023,.03,d);
|
||||||
|
rz = min(d,rz);
|
||||||
|
|
||||||
|
vec3 hcol = (sin(vec3(0.35,0.4,0.48)*(3.35)*PALETTE)*0.5+.5);
|
||||||
|
hcol.gb -= sk2;
|
||||||
|
hcol.r += sk2;
|
||||||
|
return hcol*(1.-rz);
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------
|
||||||
|
//--------------------------------------------------------
|
||||||
|
//--------------------------------------------------------
|
||||||
|
|
||||||
|
float tri(in float x)
|
||||||
|
{
|
||||||
|
return abs(fract(x)-0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat2 m2 = mat2( 0.80, 0.60, -0.60, 0.80 );
|
||||||
|
float tnoise(in vec2 p)
|
||||||
|
{
|
||||||
|
p*=.008;
|
||||||
|
float z=2.;
|
||||||
|
float rz = 0.;
|
||||||
|
for (float i= 1.;i < TERRAIN_COMPLEXITY;i++ )
|
||||||
|
{
|
||||||
|
rz+= tri(p.x+tri(p.y*1.))/z;
|
||||||
|
z = z*2.;
|
||||||
|
p = p*1.8;
|
||||||
|
p*= m2;
|
||||||
|
}
|
||||||
|
return rz*9.;
|
||||||
|
}
|
||||||
|
|
||||||
|
float oct(in vec3 p){ return dot(vec3(0.5773),abs(p));}
|
||||||
|
vec2 ou( vec2 d1, vec2 d2 ){return (d1.x<d2.x) ? d1 : d2;}
|
||||||
|
|
||||||
|
vec3 roty(vec3 p, float a)
|
||||||
|
{
|
||||||
|
float s = sin(a), c = cos(a);
|
||||||
|
return vec3(c*p.x + s*p.z, p.y, -s*p.x + c*p.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 map(vec3 p)
|
||||||
|
{
|
||||||
|
//terrain
|
||||||
|
vec2 d = vec2(6.*tnoise(p.xz)+p.y+20.+(tri(p.z*0.001)-0.4)*22.,1.);
|
||||||
|
//xlog(x) seems to work nicely for a valley
|
||||||
|
d.x -= abs(p.x*0.5*log(abs(p.x)))*0.05-8.;
|
||||||
|
//flat water
|
||||||
|
d = ou(d,vec2(p.y+30., 2.));
|
||||||
|
//"enemy"
|
||||||
|
vec3 enp = enpos();
|
||||||
|
enp.z += time*50.;
|
||||||
|
d = ou(d,vec2((oct(roty(p-enp, time*2.5))-6.)*0.66,8.));
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 march(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
float precis = .1;
|
||||||
|
float h=precis*2.0;
|
||||||
|
float d = 0.;
|
||||||
|
float c = 1.;
|
||||||
|
for( int i=0; i<ITR; i++ )
|
||||||
|
{
|
||||||
|
if( abs(h)<precis || d>FAR ) break;
|
||||||
|
d += h;
|
||||||
|
vec2 res = map(ro+rd*d);
|
||||||
|
h = res.x*1.4;
|
||||||
|
c = res.y;
|
||||||
|
}
|
||||||
|
return vec2(d,c);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal(const in vec3 p)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(-1., 1.)*.1;
|
||||||
|
return normalize(e.yxx*map(p + e.yxx).x + e.xxy*map(p + e.xxy).x +
|
||||||
|
e.xyx*map(p + e.xyx).x + e.yyy*map(p + e.yyy).x );
|
||||||
|
}
|
||||||
|
|
||||||
|
//(from eiffie, who thought it was from iq, dont know who actually wrote it)
|
||||||
|
float segm(vec3 ro, vec3 rd, vec3 p1, vec3 p2)
|
||||||
|
{
|
||||||
|
vec3 p = p1-ro;
|
||||||
|
vec3 di = p2-ro-p;
|
||||||
|
float proj = dot(rd, di);
|
||||||
|
float m = clamp((dot(rd,p)*proj-dot(p,di))/(dot(di,di)-proj*proj), 0., 1.);
|
||||||
|
p += di*m;
|
||||||
|
p = dot(p, rd)*rd-p;
|
||||||
|
return smoothstep(0.9985,.999,1.-dot(p,p));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 p = fragCoord.xy/iResolution.xy-0.5;
|
||||||
|
vec2 bp = p+0.5;
|
||||||
|
p.x*=iResolution.x/iResolution.y;
|
||||||
|
vec2 um = vec2(0);
|
||||||
|
um.x = 0.5+(smoothstep(-2.,2.,sin(time*.7-0.1))-0.5)*.1;
|
||||||
|
um.y = sin(time+1.)*0.02;
|
||||||
|
|
||||||
|
//camera
|
||||||
|
vec3 ro = vec3((smoothstep(-2., 2., sin(time*0.7+1.57))-0.5)*50., sin(time)*5.-1., time*50.);
|
||||||
|
um.x *= 3.;
|
||||||
|
vec3 eye = normalize(vec3(cos(um.x),um.y*5.,sin(um.x)));
|
||||||
|
vec3 right = normalize(vec3(cos(um.x+1.5708),0.,sin(um.x+1.5708)));
|
||||||
|
mat2 ori = mm2( smoothstep(-.5,.5,sin(time*0.7+0.78))-.5 + smoothfloor(time*0.04,.45)*6.28 );
|
||||||
|
right.xy *= ori;
|
||||||
|
vec3 up = normalize(cross(right,eye));
|
||||||
|
vec3 rd=normalize((p.x*right+p.y*up)*.75+eye);
|
||||||
|
|
||||||
|
vec3 bg = sin(vec3(0.35,0.4,0.48)*11.3*PALETTE)*0.5+.5;
|
||||||
|
vec3 col = bg*floor(-rd.y*50.+6.)*0.06;
|
||||||
|
|
||||||
|
//march
|
||||||
|
vec2 rz = march(ro,rd);
|
||||||
|
if ( rz.x < FAR )
|
||||||
|
{
|
||||||
|
vec3 pos = ro+rz.x*rd;
|
||||||
|
vec3 nor = normal( pos );
|
||||||
|
vec3 ligt = normalize(vec3(-.7,0.2, 0.1));
|
||||||
|
float dif = clamp(dot(nor, ligt), 0., 1.);
|
||||||
|
float fre = pow(clamp(1. + dot(nor, rd), 0., 1.), 2.);
|
||||||
|
if (rz.y == 1.)
|
||||||
|
{
|
||||||
|
float mx = abs(pos.x*.1)-10.;
|
||||||
|
mx = smoothstep(-20.,10.,mx);
|
||||||
|
col = mix(vec3(0.,0.37,0),vec3(0.2,.17,0.15),mx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
col = sin(vec3(0.35,0.4,0.48)*rz.y*PALETTE)*0.5+.55;
|
||||||
|
col = col*dif + col*0.4 + .3*fre*col;
|
||||||
|
}
|
||||||
|
|
||||||
|
//lasers
|
||||||
|
vec3 enp =enpos();
|
||||||
|
enp.z += time*50.;
|
||||||
|
vec3 rn = enp - ro;
|
||||||
|
float tgt = dot(eye, normalize(rn));
|
||||||
|
if (tgt > .997)
|
||||||
|
{
|
||||||
|
vec3 ray1 = vec3(0.7, 1., -1);
|
||||||
|
vec3 ray2 = vec3(-0.7, 1., -1);
|
||||||
|
ray1.xy *= ori; ray2.xy *= ori;
|
||||||
|
float lz = segm(ro,rd,ro-ray1,up*0.5+ro+(eye-ray1*0.01)*30.);
|
||||||
|
lz += segm(ro,rd,ro-ray2,up*.5+ro+(eye-ray2*0.01)*30.);
|
||||||
|
float sw = mod(floor(time*20.),2.);
|
||||||
|
lz *= sw;
|
||||||
|
col = col*(1.-smoothstep(0.0,1.,lz))+lz*vec3(1.,0.,0.);
|
||||||
|
//hit (cant really have explosions since I don't have a function for hit times)
|
||||||
|
if (tgt > .999)
|
||||||
|
{
|
||||||
|
vec2 d = hash2(time);
|
||||||
|
rd.xy += d*0.03;
|
||||||
|
rn.xy += d*10.;
|
||||||
|
float s = sw*smoothstep(0.9998, .9999,dot(rd,normalize(rn)));
|
||||||
|
col = col*(1.-smoothstep(0., 1., s))+s*vec3(1.-d.x, .0, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//hud
|
||||||
|
float lk = 0.;
|
||||||
|
if (tgt > .99)lk = 4.;
|
||||||
|
vec3 hud = makeHud(p,tgt);
|
||||||
|
col = col*(1.-smoothstep(0., 1., hud.y+hud.x+hud.z))+hud;
|
||||||
|
//scanlines
|
||||||
|
col *= (sin(p.y*1.3*iResolution.x)*0.15)*(sin(p.y*10.+time*410.)*0.4)+1.;
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
// bwvideo.mp4
|
||||||
|
float sat( float t ) {
|
||||||
|
return clamp( t, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
vec2 sat( vec2 t ) {
|
||||||
|
return clamp( t, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
// vec3 sat( vec3 v ) {
|
||||||
|
// return clamp( v, 0.0f, 1.0f );
|
||||||
|
// }
|
||||||
|
|
||||||
|
//remaps inteval [a;b] to [0;1]
|
||||||
|
float remap( float t, float a, float b ) {
|
||||||
|
return sat( (t - a) / (b - a) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//note: /\ t=[0;0.5;1], y=[0;1;0]
|
||||||
|
float linterp( float t ) {
|
||||||
|
return sat( 1.0 - abs( 2.0*t - 1.0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
//note: [0;1]
|
||||||
|
float rand( vec2 n ) {
|
||||||
|
return fract(sin(dot(n.xy, vec2(12.9898, 78.233)))* 43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
//note: [-1;1]
|
||||||
|
float srand( vec2 n ) {
|
||||||
|
return rand(n) * 2.0 - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float mytrunc( float x, float num_levels )
|
||||||
|
{
|
||||||
|
return floor(x*num_levels) / num_levels;
|
||||||
|
}
|
||||||
|
vec2 mytrunc( vec2 x, vec2 num_levels )
|
||||||
|
{
|
||||||
|
return floor(x*num_levels) / num_levels;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 rgb2yuv( vec3 rgb )
|
||||||
|
{
|
||||||
|
vec3 yuv;
|
||||||
|
yuv.x = dot( rgb, vec3(0.299,0.587,0.114) );
|
||||||
|
yuv.y = dot( rgb, vec3(-0.14713, -0.28886, 0.436) );
|
||||||
|
yuv.z = dot( rgb, vec3(0.615, -0.51499, -0.10001) );
|
||||||
|
return yuv;
|
||||||
|
}
|
||||||
|
vec3 yuv2rgb( vec3 yuv )
|
||||||
|
{
|
||||||
|
vec3 rgb;
|
||||||
|
rgb.r = yuv.x + yuv.z * 1.13983;
|
||||||
|
rgb.g = yuv.x + dot( vec2(-0.39465, -0.58060), yuv.yz );
|
||||||
|
rgb.b = yuv.x + yuv.y * 2.03211;
|
||||||
|
return rgb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
float THRESHOLD = 0.1 + iMouse.x / iResolution.x;
|
||||||
|
float time_s = mod( iGlobalTime, 32.0 );
|
||||||
|
|
||||||
|
float glitch_threshold = 1.0 - THRESHOLD;
|
||||||
|
const float max_ofs_siz = 0.1; //TOOD: input
|
||||||
|
const float yuv_threshold = 0.5; //TODO: input, >1.0f == no distort
|
||||||
|
const float time_frq = 16.0;
|
||||||
|
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
uv.y = 1.0 - uv.y;
|
||||||
|
|
||||||
|
const float min_change_frq = 4.0;
|
||||||
|
float ct = mytrunc( time_s, min_change_frq );
|
||||||
|
float change_rnd = rand( mytrunc(uv.yy,vec2(16)) + 150.0 * ct );
|
||||||
|
|
||||||
|
float tf = time_frq*change_rnd;
|
||||||
|
|
||||||
|
float t = 5.0 * mytrunc( time_s, tf );
|
||||||
|
float vt_rnd = 0.5*rand( mytrunc(uv.yy + t, vec2(11)) );
|
||||||
|
vt_rnd += 0.5 * rand(mytrunc(uv.yy + t, vec2(7)));
|
||||||
|
vt_rnd = vt_rnd*2.0 - 1.0;
|
||||||
|
vt_rnd = sign(vt_rnd) * sat( ( abs(vt_rnd) - glitch_threshold) / (1.0-glitch_threshold) );
|
||||||
|
|
||||||
|
vec2 uv_nm = uv;
|
||||||
|
uv_nm = sat( uv_nm + vec2(max_ofs_siz*vt_rnd, 0) );
|
||||||
|
|
||||||
|
float rnd = rand( vec2( mytrunc( time_s, 8.0 )) );
|
||||||
|
uv_nm.y = (rnd>mix(1.0, 0.975, sat(THRESHOLD))) ? 1.0-uv_nm.y : uv_nm.y;
|
||||||
|
|
||||||
|
vec4 smpl = texture( iChannel0, uv_nm, -10.0 );
|
||||||
|
vec3 smpl_yuv = rgb2yuv( smpl.rgb );
|
||||||
|
smpl_yuv.y /= 1.0-3.0*abs(vt_rnd) * sat( yuv_threshold - vt_rnd );
|
||||||
|
smpl_yuv.z += 0.125 * vt_rnd * sat( vt_rnd - yuv_threshold );
|
||||||
|
fragColor = vec4( yuv2rgb(smpl_yuv), smpl.a );
|
||||||
|
}
|
|
@ -0,0 +1,184 @@
|
||||||
|
/*
|
||||||
|
* "Seascape" by Alexander Alekseev aka TDM - 2014
|
||||||
|
* License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
* Contact: tdmaav@gmail.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
const int NUM_STEPS = 8;
|
||||||
|
const float PI = 3.1415;
|
||||||
|
const float EPSILON = 1e-3;
|
||||||
|
#define EPSILON_NRM (0.1 / iResolution.x)
|
||||||
|
|
||||||
|
// sea
|
||||||
|
const int ITER_GEOMETRY = 3;
|
||||||
|
const int ITER_FRAGMENT = 5;
|
||||||
|
const float SEA_HEIGHT = 0.6;
|
||||||
|
const float SEA_CHOPPY = 4.0;
|
||||||
|
const float SEA_SPEED = 0.8;
|
||||||
|
const float SEA_FREQ = 0.16;
|
||||||
|
const vec3 SEA_BASE = vec3(0.1,0.19,0.22);
|
||||||
|
const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6);
|
||||||
|
#define SEA_TIME (1.0 + iGlobalTime * SEA_SPEED)
|
||||||
|
const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
|
||||||
|
|
||||||
|
// math
|
||||||
|
mat3 fromEuler(vec3 ang) {
|
||||||
|
vec2 a1 = vec2(sin(ang.x),cos(ang.x));
|
||||||
|
vec2 a2 = vec2(sin(ang.y),cos(ang.y));
|
||||||
|
vec2 a3 = vec2(sin(ang.z),cos(ang.z));
|
||||||
|
mat3 m;
|
||||||
|
m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
|
||||||
|
m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
|
||||||
|
m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
float hash( vec2 p ) {
|
||||||
|
float h = dot(p,vec2(127.1,311.7));
|
||||||
|
return fract(sin(h)*43758.5453123);
|
||||||
|
}
|
||||||
|
float noise( in vec2 p ) {
|
||||||
|
vec2 i = floor( p );
|
||||||
|
vec2 f = fract( p );
|
||||||
|
vec2 u = f*f*(3.0-2.0*f);
|
||||||
|
return -1.0+2.0*mix( mix( hash( i + vec2(0.0,0.0) ),
|
||||||
|
hash( i + vec2(1.0,0.0) ), u.x),
|
||||||
|
mix( hash( i + vec2(0.0,1.0) ),
|
||||||
|
hash( i + vec2(1.0,1.0) ), u.x), u.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// lighting
|
||||||
|
float diffuse(vec3 n,vec3 l,float p) {
|
||||||
|
return pow(dot(n,l) * 0.4 + 0.6,p);
|
||||||
|
}
|
||||||
|
float specular(vec3 n,vec3 l,vec3 e,float s) {
|
||||||
|
float nrm = (s + 8.0) / (3.1415 * 8.0);
|
||||||
|
return pow(max(dot(reflect(e,n),l),0.0),s) * nrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sky
|
||||||
|
vec3 getSkyColor(vec3 e) {
|
||||||
|
e.y = max(e.y,0.0);
|
||||||
|
return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sea
|
||||||
|
float sea_octave(vec2 uv, float choppy) {
|
||||||
|
uv += noise(uv);
|
||||||
|
vec2 wv = 1.0-abs(sin(uv));
|
||||||
|
vec2 swv = abs(cos(uv));
|
||||||
|
wv = mix(wv,swv,wv);
|
||||||
|
return pow(1.0-pow(wv.x * wv.y,0.65),choppy);
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(vec3 p) {
|
||||||
|
float freq = SEA_FREQ;
|
||||||
|
float amp = SEA_HEIGHT;
|
||||||
|
float choppy = SEA_CHOPPY;
|
||||||
|
vec2 uv = p.xz; uv.x *= 0.75;
|
||||||
|
|
||||||
|
float d, h = 0.0;
|
||||||
|
for(int i = 0; i < ITER_GEOMETRY; i++) {
|
||||||
|
d = sea_octave((uv+SEA_TIME)*freq,choppy);
|
||||||
|
d += sea_octave((uv-SEA_TIME)*freq,choppy);
|
||||||
|
h += d * amp;
|
||||||
|
uv *= octave_m; freq *= 1.9; amp *= 0.22;
|
||||||
|
choppy = mix(choppy,1.0,0.2);
|
||||||
|
}
|
||||||
|
return p.y - h;
|
||||||
|
}
|
||||||
|
|
||||||
|
float map_detailed(vec3 p) {
|
||||||
|
float freq = SEA_FREQ;
|
||||||
|
float amp = SEA_HEIGHT;
|
||||||
|
float choppy = SEA_CHOPPY;
|
||||||
|
vec2 uv = p.xz; uv.x *= 0.75;
|
||||||
|
|
||||||
|
float d, h = 0.0;
|
||||||
|
for(int i = 0; i < ITER_FRAGMENT; i++) {
|
||||||
|
d = sea_octave((uv+SEA_TIME)*freq,choppy);
|
||||||
|
d += sea_octave((uv-SEA_TIME)*freq,choppy);
|
||||||
|
h += d * amp;
|
||||||
|
uv *= octave_m; freq *= 1.9; amp *= 0.22;
|
||||||
|
choppy = mix(choppy,1.0,0.2);
|
||||||
|
}
|
||||||
|
return p.y - h;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
|
||||||
|
float fresnel = clamp(1.0 - dot(n,-eye), 0.0, 1.0);
|
||||||
|
fresnel = pow(fresnel,3.0) * 0.65;
|
||||||
|
|
||||||
|
vec3 reflected = getSkyColor(reflect(eye,n));
|
||||||
|
vec3 refracted = SEA_BASE + diffuse(n,l,80.0) * SEA_WATER_COLOR * 0.12;
|
||||||
|
|
||||||
|
vec3 color = mix(refracted,reflected,fresnel);
|
||||||
|
|
||||||
|
float atten = max(1.0 - dot(dist,dist) * 0.001, 0.0);
|
||||||
|
color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
|
||||||
|
|
||||||
|
color += vec3(specular(n,l,eye,60.0));
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tracing
|
||||||
|
vec3 getNormal(vec3 p, float eps) {
|
||||||
|
vec3 n;
|
||||||
|
n.y = map_detailed(p);
|
||||||
|
n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
|
||||||
|
n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
|
||||||
|
n.y = eps;
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
|
||||||
|
float tm = 0.0;
|
||||||
|
float tx = 1000.0;
|
||||||
|
float hx = map(ori + dir * tx);
|
||||||
|
if(hx > 0.0) return tx;
|
||||||
|
float hm = map(ori + dir * tm);
|
||||||
|
float tmid = 0.0;
|
||||||
|
for(int i = 0; i < NUM_STEPS; i++) {
|
||||||
|
tmid = mix(tm,tx, hm/(hm-hx));
|
||||||
|
p = ori + dir * tmid;
|
||||||
|
float hmid = map(p);
|
||||||
|
if(hmid < 0.0) {
|
||||||
|
tx = tmid;
|
||||||
|
hx = hmid;
|
||||||
|
} else {
|
||||||
|
tm = tmid;
|
||||||
|
hm = hmid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// main
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
uv = uv * 2.0 - 1.0;
|
||||||
|
uv.x *= iResolution.x / iResolution.y;
|
||||||
|
float time = iGlobalTime * 0.3 + iMouse.x*0.01;
|
||||||
|
|
||||||
|
// ray
|
||||||
|
vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time);
|
||||||
|
vec3 ori = vec3(0.0,3.5,time*5.0);
|
||||||
|
vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.15;
|
||||||
|
dir = normalize(dir) * fromEuler(ang);
|
||||||
|
|
||||||
|
// tracing
|
||||||
|
vec3 p;
|
||||||
|
heightMapTracing(ori,dir,p);
|
||||||
|
vec3 dist = p - ori;
|
||||||
|
vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
|
||||||
|
vec3 light = normalize(vec3(0.0,1.0,0.8));
|
||||||
|
|
||||||
|
// color
|
||||||
|
vec3 color = mix(
|
||||||
|
getSkyColor(dir),
|
||||||
|
getSeaColor(p,n,light,dir,dist),
|
||||||
|
pow(smoothstep(0.0,-0.05,dir.y),0.3));
|
||||||
|
|
||||||
|
// post
|
||||||
|
fragColor = vec4(pow(color,vec3(0.75)), 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*by mu6k, Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
I have no idea how I ended up here, but it demosceneish enough to publish.
|
||||||
|
You can use the mouse to rotate the camera around the 'object'.
|
||||||
|
If you can't see the shadows, increase occlusion_quality.
|
||||||
|
If it doesn't compile anymore decrease object_count and render_steps.
|
||||||
|
|
||||||
|
15/06/2013:
|
||||||
|
- published
|
||||||
|
|
||||||
|
16/06/2013:
|
||||||
|
- modified for better performance and compatibility
|
||||||
|
|
||||||
|
muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuusk!*/
|
||||||
|
|
||||||
|
#define occlusion_enabled
|
||||||
|
#define occlusion_quality 4
|
||||||
|
//#define occlusion_preview
|
||||||
|
|
||||||
|
#define noise_use_smoothstep
|
||||||
|
|
||||||
|
#define light_color vec3(0.1,0.4,0.6)
|
||||||
|
#define light_direction normalize(vec3(.2,1.0,-0.2))
|
||||||
|
#define light_speed_modifier 1.0
|
||||||
|
|
||||||
|
#define object_color vec3(0.9,0.1,0.1)
|
||||||
|
#define object_count 9
|
||||||
|
#define object_speed_modifier 1.0
|
||||||
|
|
||||||
|
#define render_steps 33
|
||||||
|
|
||||||
|
float hash(float x)
|
||||||
|
{
|
||||||
|
return fract(sin(x*.0127863)*17143.321);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hash(vec2 x)
|
||||||
|
{
|
||||||
|
return fract(cos(dot(x.xy,vec2(2.31,53.21))*124.123)*412.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 cc(vec3 color, float factor,float factor2) //a wierd color modifier
|
||||||
|
{
|
||||||
|
float w = color.x+color.y+color.z;
|
||||||
|
return mix(color,vec3(w)*factor,w*factor2);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hashmix(float x0, float x1, float interp)
|
||||||
|
{
|
||||||
|
x0 = hash(x0);
|
||||||
|
x1 = hash(x1);
|
||||||
|
#ifdef noise_use_smoothstep
|
||||||
|
interp = smoothstep(0.0,1.0,interp);
|
||||||
|
#endif
|
||||||
|
return mix(x0,x1,interp);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise(float p) // 1D noise
|
||||||
|
{
|
||||||
|
float pm = mod(p,1.0);
|
||||||
|
float pd = p-pm;
|
||||||
|
return hashmix(pd,pd+1.0,pm);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 rotate_y(vec3 v, float angle)
|
||||||
|
{
|
||||||
|
float ca = cos(angle); float sa = sin(angle);
|
||||||
|
return v*mat3(
|
||||||
|
+ca, +.0, -sa,
|
||||||
|
+.0,+1.0, +.0,
|
||||||
|
+sa, +.0, +ca);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 rotate_x(vec3 v, float angle)
|
||||||
|
{
|
||||||
|
float ca = cos(angle); float sa = sin(angle);
|
||||||
|
return v*mat3(
|
||||||
|
+1.0, +.0, +.0,
|
||||||
|
+.0, +ca, -sa,
|
||||||
|
+.0, +sa, +ca);
|
||||||
|
}
|
||||||
|
|
||||||
|
float max3(float a, float b, float c)//returns the maximum of 3 values
|
||||||
|
{
|
||||||
|
return max(a,max(b,c));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 bpos[object_count];//position for each metaball
|
||||||
|
|
||||||
|
float dist(vec3 p)//distance function
|
||||||
|
{
|
||||||
|
float d=1024.0;
|
||||||
|
float nd;
|
||||||
|
for (int i=0 ;i<object_count; i++)
|
||||||
|
{
|
||||||
|
vec3 np = p+bpos[i];
|
||||||
|
float shape0 = max3(abs(np.x),abs(np.y),abs(np.z))-1.0;
|
||||||
|
float shape1 = length(np)-1.0;
|
||||||
|
nd = shape0+(shape1-shape0)*2.0;
|
||||||
|
d = mix(d,nd,smoothstep(-1.0,+1.0,d-nd));
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal(vec3 p,float e) //returns the normal, uses the distance function
|
||||||
|
{
|
||||||
|
float d=dist(p);
|
||||||
|
return normalize(vec3(dist(p+vec3(e,0,0))-d,dist(p+vec3(0,e,0))-d,dist(p+vec3(0,0,e))-d));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 light = light_direction; //global variable that holds light direction
|
||||||
|
|
||||||
|
vec3 background(vec3 d)//render background
|
||||||
|
{
|
||||||
|
float t=iGlobalTime*0.5*light_speed_modifier;
|
||||||
|
float qq = dot(d,light)*.5+.5;
|
||||||
|
float bgl = qq;
|
||||||
|
float q = (bgl+noise(bgl*6.0+t)*.85+noise(bgl*12.0+t)*.85);
|
||||||
|
q+= pow(qq,32.0)*2.0;
|
||||||
|
vec3 sky = vec3(0.1,0.4,0.6)*q;
|
||||||
|
return sky;
|
||||||
|
}
|
||||||
|
|
||||||
|
float occlusion(vec3 p, vec3 d)//returns how much a point is visible from a given direction
|
||||||
|
{
|
||||||
|
float occ = 1.0;
|
||||||
|
p=p+d;
|
||||||
|
for (int i=0; i<occlusion_quality; i++)
|
||||||
|
{
|
||||||
|
float dd = dist(p);
|
||||||
|
p+=d*dd;
|
||||||
|
occ = min(occ,dd);
|
||||||
|
}
|
||||||
|
return max(.0,occ);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 object_material(vec3 p, vec3 d)
|
||||||
|
{
|
||||||
|
vec3 color = normalize(object_color*light_color);
|
||||||
|
vec3 n = normal(p,0.1);
|
||||||
|
vec3 r = reflect(d,n);
|
||||||
|
|
||||||
|
float reflectance = dot(d,r)*.5+.5;reflectance=pow(reflectance,2.0);
|
||||||
|
float diffuse = dot(light,n)*.5+.5; diffuse = max(.0,diffuse);
|
||||||
|
|
||||||
|
#ifdef occlusion_enabled
|
||||||
|
float oa = occlusion(p,n)*.4+.6;
|
||||||
|
float od = occlusion(p,light)*.95+.05;
|
||||||
|
float os = occlusion(p,r)*.95+.05;
|
||||||
|
#else
|
||||||
|
float oa=1.0;
|
||||||
|
float ob=1.0;
|
||||||
|
float oc=1.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef occlusion_preview
|
||||||
|
color =
|
||||||
|
color*oa*.2 + //ambient
|
||||||
|
color*diffuse*od*.7 + //diffuse
|
||||||
|
background(r)*os*reflectance*.7; //reflection
|
||||||
|
#else
|
||||||
|
color=vec3((oa+od+os)*.3);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define offset1 4.7
|
||||||
|
#define offset2 4.6
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy - 0.5;
|
||||||
|
uv.x *= iResolution.x/iResolution.y; //fix aspect ratio
|
||||||
|
vec3 mouse = vec3(iMouse.xy/iResolution.xy - 0.5,iMouse.z-.5);
|
||||||
|
|
||||||
|
float t = iGlobalTime*.5*object_speed_modifier + 2.0;
|
||||||
|
|
||||||
|
for (int i=0 ;i<object_count; i++) //position for each metaball
|
||||||
|
{
|
||||||
|
bpos[i] = 1.3*vec3(
|
||||||
|
sin(t*0.967+float(i)*42.0),
|
||||||
|
sin(t*.423+float(i)*152.0),
|
||||||
|
sin(t*.76321+float(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
//setup the camera
|
||||||
|
vec3 p = vec3(.0,0.0,-4.0);
|
||||||
|
p = rotate_x(p,mouse.y*9.0+offset1);
|
||||||
|
p = rotate_y(p,mouse.x*9.0+offset2);
|
||||||
|
vec3 d = vec3(uv,1.0);
|
||||||
|
d.z -= length(d)*.5; //lens distort
|
||||||
|
d = normalize(d);
|
||||||
|
d = rotate_x(d,mouse.y*9.0+offset1);
|
||||||
|
d = rotate_y(d,mouse.x*9.0+offset2);
|
||||||
|
|
||||||
|
//and action!
|
||||||
|
float dd;
|
||||||
|
vec3 color;
|
||||||
|
for (int i=0; i<render_steps; i++) //raymarch
|
||||||
|
{
|
||||||
|
dd = dist(p);
|
||||||
|
p+=d*dd*.7;
|
||||||
|
if (dd<.04 || dd>4.0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dd<0.5) //close enough
|
||||||
|
color = object_material(p,d);
|
||||||
|
else
|
||||||
|
color = background(d);
|
||||||
|
|
||||||
|
//post procesing
|
||||||
|
color *=.85;
|
||||||
|
color = mix(color,color*color,0.3);
|
||||||
|
color -= hash(color.xy+uv.xy)*.015;
|
||||||
|
color -= length(uv)*.1;
|
||||||
|
color =cc(color,.5,.6);
|
||||||
|
fragColor = vec4(color,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,393 @@
|
||||||
|
// Mt2GWD
|
||||||
|
// flyguy
|
||||||
|
|
||||||
|
#define DOWN_SCALE 1.0
|
||||||
|
|
||||||
|
#define MAX_INT_DIGITS 4
|
||||||
|
|
||||||
|
#define CHAR_SIZE vec2(8, 12)
|
||||||
|
#define CHAR_SPACING vec2(8, 12)
|
||||||
|
|
||||||
|
#define STRWIDTH(c) (c * CHAR_SPACING.x)
|
||||||
|
#define STRHEIGHT(c) (c * CHAR_SPACING.y)
|
||||||
|
|
||||||
|
#define NORMAL 0
|
||||||
|
#define INVERT 1
|
||||||
|
#define UNDERLINE 2
|
||||||
|
|
||||||
|
int TEXT_MODE = NORMAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
--------
|
||||||
|
-###----
|
||||||
|
##-##---
|
||||||
|
##-##---
|
||||||
|
-###----
|
||||||
|
#####-#-
|
||||||
|
##-####-
|
||||||
|
##--##--
|
||||||
|
##-###--
|
||||||
|
-###-##-
|
||||||
|
--------
|
||||||
|
--------
|
||||||
|
|
||||||
|
00000000
|
||||||
|
01110000
|
||||||
|
11011000
|
||||||
|
11011000
|
||||||
|
01110000
|
||||||
|
11111010
|
||||||
|
11011110
|
||||||
|
11001100
|
||||||
|
11011100
|
||||||
|
01110110
|
||||||
|
00000000
|
||||||
|
00000000
|
||||||
|
|
||||||
|
//Broken up into 4 8x3 (24 bit) chunks for each component of the vec4.
|
||||||
|
//Hexadecimal is being used to reduce clutter in the code but decimal still works.
|
||||||
|
|
||||||
|
00000000
|
||||||
|
01110000 -> 00000000 01110000 11011000 -> 0x0070D8
|
||||||
|
11011000
|
||||||
|
|
||||||
|
11011000
|
||||||
|
01110000 -> 11011000 01110000 11111010 -> 0xD870FA
|
||||||
|
11111010
|
||||||
|
|
||||||
|
11011110
|
||||||
|
11001100 -> 11011110 11001100 11011100 -> 0xDECCDC
|
||||||
|
11011100
|
||||||
|
|
||||||
|
01110110
|
||||||
|
00000000 -> 01110110 00000000 00000000 -> 0x760000
|
||||||
|
00000000
|
||||||
|
|
||||||
|
vec4(0x0070D8,0xD870FA,0xDECCDC,0x760000)
|
||||||
|
*/
|
||||||
|
|
||||||
|
//Automatically generated from the 8x12 font sheet here:
|
||||||
|
//http://www.massmind.org/techref/datafile/charset/extractor/charset_extractor.htm
|
||||||
|
|
||||||
|
vec4 ch_spc = vec4(0x000000,0x000000,0x000000,0x000000);
|
||||||
|
vec4 ch_exc = vec4(0x003078,0x787830,0x300030,0x300000);
|
||||||
|
vec4 ch_quo = vec4(0x006666,0x662400,0x000000,0x000000);
|
||||||
|
vec4 ch_hsh = vec4(0x006C6C,0xFE6C6C,0x6CFE6C,0x6C0000);
|
||||||
|
vec4 ch_dol = vec4(0x30307C,0xC0C078,0x0C0CF8,0x303000);
|
||||||
|
vec4 ch_pct = vec4(0x000000,0xC4CC18,0x3060CC,0x8C0000);
|
||||||
|
vec4 ch_amp = vec4(0x0070D8,0xD870FA,0xDECCDC,0x760000);
|
||||||
|
vec4 ch_apo = vec4(0x003030,0x306000,0x000000,0x000000);
|
||||||
|
vec4 ch_lbr = vec4(0x000C18,0x306060,0x603018,0x0C0000);
|
||||||
|
vec4 ch_rbr = vec4(0x006030,0x180C0C,0x0C1830,0x600000);
|
||||||
|
vec4 ch_ast = vec4(0x000000,0x663CFF,0x3C6600,0x000000);
|
||||||
|
vec4 ch_crs = vec4(0x000000,0x18187E,0x181800,0x000000);
|
||||||
|
vec4 ch_com = vec4(0x000000,0x000000,0x000038,0x386000);
|
||||||
|
vec4 ch_dsh = vec4(0x000000,0x0000FE,0x000000,0x000000);
|
||||||
|
vec4 ch_per = vec4(0x000000,0x000000,0x000038,0x380000);
|
||||||
|
vec4 ch_lsl = vec4(0x000002,0x060C18,0x3060C0,0x800000);
|
||||||
|
vec4 ch_0 = vec4(0x007CC6,0xD6D6D6,0xD6D6C6,0x7C0000);
|
||||||
|
vec4 ch_1 = vec4(0x001030,0xF03030,0x303030,0xFC0000);
|
||||||
|
vec4 ch_2 = vec4(0x0078CC,0xCC0C18,0x3060CC,0xFC0000);
|
||||||
|
vec4 ch_3 = vec4(0x0078CC,0x0C0C38,0x0C0CCC,0x780000);
|
||||||
|
vec4 ch_4 = vec4(0x000C1C,0x3C6CCC,0xFE0C0C,0x1E0000);
|
||||||
|
vec4 ch_5 = vec4(0x00FCC0,0xC0C0F8,0x0C0CCC,0x780000);
|
||||||
|
vec4 ch_6 = vec4(0x003860,0xC0C0F8,0xCCCCCC,0x780000);
|
||||||
|
vec4 ch_7 = vec4(0x00FEC6,0xC6060C,0x183030,0x300000);
|
||||||
|
vec4 ch_8 = vec4(0x0078CC,0xCCEC78,0xDCCCCC,0x780000);
|
||||||
|
vec4 ch_9 = vec4(0x0078CC,0xCCCC7C,0x181830,0x700000);
|
||||||
|
vec4 ch_col = vec4(0x000000,0x383800,0x003838,0x000000);
|
||||||
|
vec4 ch_scl = vec4(0x000000,0x383800,0x003838,0x183000);
|
||||||
|
vec4 ch_les = vec4(0x000C18,0x3060C0,0x603018,0x0C0000);
|
||||||
|
vec4 ch_equ = vec4(0x000000,0x007E00,0x7E0000,0x000000);
|
||||||
|
vec4 ch_grt = vec4(0x006030,0x180C06,0x0C1830,0x600000);
|
||||||
|
vec4 ch_que = vec4(0x0078CC,0x0C1830,0x300030,0x300000);
|
||||||
|
vec4 ch_ats = vec4(0x007CC6,0xC6DEDE,0xDEC0C0,0x7C0000);
|
||||||
|
vec4 ch_A = vec4(0x003078,0xCCCCCC,0xFCCCCC,0xCC0000);
|
||||||
|
vec4 ch_B = vec4(0x00FC66,0x66667C,0x666666,0xFC0000);
|
||||||
|
vec4 ch_C = vec4(0x003C66,0xC6C0C0,0xC0C666,0x3C0000);
|
||||||
|
vec4 ch_D = vec4(0x00F86C,0x666666,0x66666C,0xF80000);
|
||||||
|
vec4 ch_E = vec4(0x00FE62,0x60647C,0x646062,0xFE0000);
|
||||||
|
vec4 ch_F = vec4(0x00FE66,0x62647C,0x646060,0xF00000);
|
||||||
|
vec4 ch_G = vec4(0x003C66,0xC6C0C0,0xCEC666,0x3E0000);
|
||||||
|
vec4 ch_H = vec4(0x00CCCC,0xCCCCFC,0xCCCCCC,0xCC0000);
|
||||||
|
vec4 ch_I = vec4(0x007830,0x303030,0x303030,0x780000);
|
||||||
|
vec4 ch_J = vec4(0x001E0C,0x0C0C0C,0xCCCCCC,0x780000);
|
||||||
|
vec4 ch_K = vec4(0x00E666,0x6C6C78,0x6C6C66,0xE60000);
|
||||||
|
vec4 ch_L = vec4(0x00F060,0x606060,0x626666,0xFE0000);
|
||||||
|
vec4 ch_M = vec4(0x00C6EE,0xFEFED6,0xC6C6C6,0xC60000);
|
||||||
|
vec4 ch_N = vec4(0x00C6C6,0xE6F6FE,0xDECEC6,0xC60000);
|
||||||
|
vec4 ch_O = vec4(0x00386C,0xC6C6C6,0xC6C66C,0x380000);
|
||||||
|
vec4 ch_P = vec4(0x00FC66,0x66667C,0x606060,0xF00000);
|
||||||
|
vec4 ch_Q = vec4(0x00386C,0xC6C6C6,0xCEDE7C,0x0C1E00);
|
||||||
|
vec4 ch_R = vec4(0x00FC66,0x66667C,0x6C6666,0xE60000);
|
||||||
|
vec4 ch_S = vec4(0x0078CC,0xCCC070,0x18CCCC,0x780000);
|
||||||
|
vec4 ch_T = vec4(0x00FCB4,0x303030,0x303030,0x780000);
|
||||||
|
vec4 ch_U = vec4(0x00CCCC,0xCCCCCC,0xCCCCCC,0x780000);
|
||||||
|
vec4 ch_V = vec4(0x00CCCC,0xCCCCCC,0xCCCC78,0x300000);
|
||||||
|
vec4 ch_W = vec4(0x00C6C6,0xC6C6D6,0xD66C6C,0x6C0000);
|
||||||
|
vec4 ch_X = vec4(0x00CCCC,0xCC7830,0x78CCCC,0xCC0000);
|
||||||
|
vec4 ch_Y = vec4(0x00CCCC,0xCCCC78,0x303030,0x780000);
|
||||||
|
vec4 ch_Z = vec4(0x00FECE,0x981830,0x6062C6,0xFE0000);
|
||||||
|
vec4 ch_lsb = vec4(0x003C30,0x303030,0x303030,0x3C0000);
|
||||||
|
vec4 ch_rsl = vec4(0x000080,0xC06030,0x180C06,0x020000);
|
||||||
|
vec4 ch_rsb = vec4(0x003C0C,0x0C0C0C,0x0C0C0C,0x3C0000);
|
||||||
|
vec4 ch_pow = vec4(0x10386C,0xC60000,0x000000,0x000000);
|
||||||
|
vec4 ch_usc = vec4(0x000000,0x000000,0x000000,0x00FF00);
|
||||||
|
vec4 ch_a = vec4(0x000000,0x00780C,0x7CCCCC,0x760000);
|
||||||
|
vec4 ch_b = vec4(0x00E060,0x607C66,0x666666,0xDC0000);
|
||||||
|
vec4 ch_c = vec4(0x000000,0x0078CC,0xC0C0CC,0x780000);
|
||||||
|
vec4 ch_d = vec4(0x001C0C,0x0C7CCC,0xCCCCCC,0x760000);
|
||||||
|
vec4 ch_e = vec4(0x000000,0x0078CC,0xFCC0CC,0x780000);
|
||||||
|
vec4 ch_f = vec4(0x00386C,0x6060F8,0x606060,0xF00000);
|
||||||
|
vec4 ch_g = vec4(0x000000,0x0076CC,0xCCCC7C,0x0CCC78);
|
||||||
|
vec4 ch_h = vec4(0x00E060,0x606C76,0x666666,0xE60000);
|
||||||
|
vec4 ch_i = vec4(0x001818,0x007818,0x181818,0x7E0000);
|
||||||
|
vec4 ch_j = vec4(0x000C0C,0x003C0C,0x0C0C0C,0xCCCC78);
|
||||||
|
vec4 ch_k = vec4(0x00E060,0x60666C,0x786C66,0xE60000);
|
||||||
|
vec4 ch_l = vec4(0x007818,0x181818,0x181818,0x7E0000);
|
||||||
|
vec4 ch_m = vec4(0x000000,0x00FCD6,0xD6D6D6,0xC60000);
|
||||||
|
vec4 ch_n = vec4(0x000000,0x00F8CC,0xCCCCCC,0xCC0000);
|
||||||
|
vec4 ch_o = vec4(0x000000,0x0078CC,0xCCCCCC,0x780000);
|
||||||
|
vec4 ch_p = vec4(0x000000,0x00DC66,0x666666,0x7C60F0);
|
||||||
|
vec4 ch_q = vec4(0x000000,0x0076CC,0xCCCCCC,0x7C0C1E);
|
||||||
|
vec4 ch_r = vec4(0x000000,0x00EC6E,0x766060,0xF00000);
|
||||||
|
vec4 ch_s = vec4(0x000000,0x0078CC,0x6018CC,0x780000);
|
||||||
|
vec4 ch_t = vec4(0x000020,0x60FC60,0x60606C,0x380000);
|
||||||
|
vec4 ch_u = vec4(0x000000,0x00CCCC,0xCCCCCC,0x760000);
|
||||||
|
vec4 ch_v = vec4(0x000000,0x00CCCC,0xCCCC78,0x300000);
|
||||||
|
vec4 ch_w = vec4(0x000000,0x00C6C6,0xD6D66C,0x6C0000);
|
||||||
|
vec4 ch_x = vec4(0x000000,0x00C66C,0x38386C,0xC60000);
|
||||||
|
vec4 ch_y = vec4(0x000000,0x006666,0x66663C,0x0C18F0);
|
||||||
|
vec4 ch_z = vec4(0x000000,0x00FC8C,0x1860C4,0xFC0000);
|
||||||
|
vec4 ch_lpa = vec4(0x001C30,0x3060C0,0x603030,0x1C0000);
|
||||||
|
vec4 ch_bar = vec4(0x001818,0x181800,0x181818,0x180000);
|
||||||
|
vec4 ch_rpa = vec4(0x00E030,0x30180C,0x183030,0xE00000);
|
||||||
|
vec4 ch_tid = vec4(0x0073DA,0xCE0000,0x000000,0x000000);
|
||||||
|
vec4 ch_lar = vec4(0x000000,0x10386C,0xC6C6FE,0x000000);
|
||||||
|
|
||||||
|
vec2 res = vec2(0);
|
||||||
|
vec2 print_pos = vec2(0);
|
||||||
|
|
||||||
|
//Extracts bit b from the given number.
|
||||||
|
//Shifts bits right (num / 2^bit) then ANDs the result with 1 (mod(result,2.0)).
|
||||||
|
float extract_bit(float n, float b)
|
||||||
|
{
|
||||||
|
b = clamp(b,-1.0,24.0);
|
||||||
|
return floor(mod(floor(n / pow(2.0,floor(b))),2.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns the pixel at uv in the given bit-packed sprite.
|
||||||
|
float sprite(vec4 spr, vec2 size, vec2 uv)
|
||||||
|
{
|
||||||
|
uv = floor(uv);
|
||||||
|
|
||||||
|
//Calculate the bit to extract (x + y * width) (flipped on x-axis)
|
||||||
|
float bit = (size.x-uv.x-1.0) + uv.y * size.x;
|
||||||
|
|
||||||
|
//Clipping bound to remove garbage outside the sprite's boundaries.
|
||||||
|
bool bounds = all(greaterThanEqual(uv,vec2(0))) && all(lessThan(uv,size));
|
||||||
|
|
||||||
|
float pixels = 0.0;
|
||||||
|
pixels += extract_bit(spr.x, bit - 72.0);
|
||||||
|
pixels += extract_bit(spr.y, bit - 48.0);
|
||||||
|
pixels += extract_bit(spr.z, bit - 24.0);
|
||||||
|
pixels += extract_bit(spr.w, bit - 00.0);
|
||||||
|
|
||||||
|
return bounds ? pixels : 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Prints a character and moves the print position forward by 1 character width.
|
||||||
|
float char_(vec4 ch, vec2 uv)
|
||||||
|
{
|
||||||
|
if( TEXT_MODE == INVERT )
|
||||||
|
{
|
||||||
|
//Inverts all of the bits in the character.
|
||||||
|
ch = pow(2.0,24.0)-1.0-ch;
|
||||||
|
}
|
||||||
|
if( TEXT_MODE == UNDERLINE )
|
||||||
|
{
|
||||||
|
//Makes the bottom 8 bits all 1.
|
||||||
|
//Shifts the bottom chunk right 8 bits to drop the lowest 8 bits,
|
||||||
|
//then shifts it left 8 bits and adds 255 (binary 11111111).
|
||||||
|
ch.w = floor(ch.w/256.0)*256.0 + 255.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float px = sprite(ch, CHAR_SIZE, uv - print_pos);
|
||||||
|
print_pos.x += CHAR_SPACING.x;
|
||||||
|
return px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Returns the digit sprite for the given number.
|
||||||
|
vec4 get_digit(float d)
|
||||||
|
{
|
||||||
|
d = floor(d);
|
||||||
|
|
||||||
|
if(d == 0.0) return ch_0;
|
||||||
|
if(d == 1.0) return ch_1;
|
||||||
|
if(d == 2.0) return ch_2;
|
||||||
|
if(d == 3.0) return ch_3;
|
||||||
|
if(d == 4.0) return ch_4;
|
||||||
|
if(d == 5.0) return ch_5;
|
||||||
|
if(d == 6.0) return ch_6;
|
||||||
|
if(d == 7.0) return ch_7;
|
||||||
|
if(d == 8.0) return ch_8;
|
||||||
|
if(d == 9.0) return ch_9;
|
||||||
|
return vec4(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Prints out the given number starting at pos.
|
||||||
|
float print_number(float number, vec2 uv)
|
||||||
|
{
|
||||||
|
float result = 0.0;
|
||||||
|
|
||||||
|
for(int i = 3;i >= -1;i--)
|
||||||
|
{
|
||||||
|
float digit = mod( number / pow(10.0, float(i)) , 10.0);
|
||||||
|
|
||||||
|
if(i == -1) //Add a decimal point.
|
||||||
|
{
|
||||||
|
result += char_(ch_per,uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(abs(number) > pow(10.0, float(i)) || i == 0) //Clip off leading zeros.
|
||||||
|
{
|
||||||
|
result += char_(get_digit(digit),uv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float print_integer(float number, int zeros, vec2 uv)
|
||||||
|
{
|
||||||
|
float result = 0.0;
|
||||||
|
|
||||||
|
for(int i = MAX_INT_DIGITS;i >= 0;i--)
|
||||||
|
{
|
||||||
|
float digit = mod( number / pow(10.0, float(i)) , 10.0);
|
||||||
|
|
||||||
|
if(abs(number) > pow(10.0, float(i)) || zeros > i || i == 0) //Clip off leading zeros.
|
||||||
|
{
|
||||||
|
result += char_(get_digit(digit),uv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float text(vec2 uv)
|
||||||
|
{
|
||||||
|
float col = 0.0;
|
||||||
|
|
||||||
|
vec2 center = res/2.0;
|
||||||
|
|
||||||
|
float hour = floor(iDate.w/60.0/60.0);
|
||||||
|
float minute = floor(mod(iDate.w/60.0,60.0));
|
||||||
|
float second = floor(mod(iDate.w,60.0));
|
||||||
|
|
||||||
|
//Greeting Text
|
||||||
|
|
||||||
|
print_pos = floor(center - vec2(STRWIDTH(17.0),STRHEIGHT(1.0))/2.0);
|
||||||
|
|
||||||
|
col += char_(ch_H,uv);
|
||||||
|
col += char_(ch_e,uv);
|
||||||
|
col += char_(ch_l,uv);
|
||||||
|
col += char_(ch_l,uv);
|
||||||
|
col += char_(ch_o,uv);
|
||||||
|
col += char_(ch_com,uv);
|
||||||
|
|
||||||
|
col += char_(ch_spc,uv);
|
||||||
|
|
||||||
|
col += char_(ch_S,uv);
|
||||||
|
col += char_(ch_h,uv);
|
||||||
|
col += char_(ch_a,uv);
|
||||||
|
col += char_(ch_d,uv);
|
||||||
|
col += char_(ch_e,uv);
|
||||||
|
col += char_(ch_r,uv);
|
||||||
|
col += char_(ch_t,uv);
|
||||||
|
col += char_(ch_o,uv);
|
||||||
|
col += char_(ch_y,uv);
|
||||||
|
col += char_(ch_exc,uv);
|
||||||
|
|
||||||
|
//Date Text
|
||||||
|
|
||||||
|
print_pos = vec2(2, 2.0 + STRHEIGHT(2.0));
|
||||||
|
|
||||||
|
TEXT_MODE = INVERT;
|
||||||
|
col += char_(ch_D,uv);
|
||||||
|
col += char_(ch_a,uv);
|
||||||
|
col += char_(ch_t,uv);
|
||||||
|
col += char_(ch_e,uv);
|
||||||
|
|
||||||
|
TEXT_MODE = NORMAL;
|
||||||
|
col += char_(ch_col,uv);
|
||||||
|
|
||||||
|
TEXT_MODE = UNDERLINE;
|
||||||
|
col += print_integer(iDate.z,2,uv);
|
||||||
|
col += char_(ch_lsl,uv);
|
||||||
|
col += print_integer(iDate.y+1.0,2,uv);
|
||||||
|
col += char_(ch_lsl,uv);
|
||||||
|
col += print_integer(iDate.x,4,uv);
|
||||||
|
|
||||||
|
//Time Text
|
||||||
|
|
||||||
|
print_pos = vec2(2, 2.0 + STRHEIGHT(1.0));
|
||||||
|
|
||||||
|
TEXT_MODE = INVERT;
|
||||||
|
col += char_(ch_T, uv);
|
||||||
|
col += char_(ch_i, uv);
|
||||||
|
col += char_(ch_m, uv);
|
||||||
|
col += char_(ch_e, uv);
|
||||||
|
|
||||||
|
TEXT_MODE = NORMAL;
|
||||||
|
col += char_(ch_col, uv);
|
||||||
|
|
||||||
|
TEXT_MODE = UNDERLINE;
|
||||||
|
|
||||||
|
col += print_integer(hour,2, uv);
|
||||||
|
col += char_(ch_col, uv);
|
||||||
|
col += print_integer(minute,2, uv);
|
||||||
|
col += char_(ch_col, uv);
|
||||||
|
col += print_integer(second,2, uv);
|
||||||
|
|
||||||
|
//Resolution Text
|
||||||
|
|
||||||
|
print_pos = vec2(2, 2.0 + STRHEIGHT(0.0));
|
||||||
|
|
||||||
|
TEXT_MODE = INVERT;
|
||||||
|
col += char_(ch_R,uv);
|
||||||
|
col += char_(ch_e,uv);
|
||||||
|
col += char_(ch_s,uv);
|
||||||
|
col += char_(ch_o,uv);
|
||||||
|
col += char_(ch_l,uv);
|
||||||
|
col += char_(ch_u,uv);
|
||||||
|
col += char_(ch_t,uv);
|
||||||
|
col += char_(ch_i,uv);
|
||||||
|
col += char_(ch_o,uv);
|
||||||
|
col += char_(ch_n,uv);
|
||||||
|
|
||||||
|
TEXT_MODE = NORMAL;
|
||||||
|
col += char_(ch_col,uv);
|
||||||
|
|
||||||
|
TEXT_MODE = UNDERLINE;
|
||||||
|
col += print_integer(iResolution.x,0,uv);
|
||||||
|
col += char_(ch_x,uv);
|
||||||
|
col += print_integer(iResolution.y,0,uv);
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
res = iResolution.xy / DOWN_SCALE;
|
||||||
|
vec2 uv = fragCoord.xy / DOWN_SCALE;
|
||||||
|
vec2 duv = floor(fragCoord.xy / DOWN_SCALE);
|
||||||
|
|
||||||
|
float pixel = text(duv);
|
||||||
|
|
||||||
|
//Shading stuff
|
||||||
|
vec3 col = vec3(1);
|
||||||
|
col *= (1.-distance(mod(uv,vec2(1.0)),vec2(0.65)))*1.2;
|
||||||
|
col *= mix(vec3(0.2),vec3(0,1,0),pixel);
|
||||||
|
|
||||||
|
fragColor = vec4(vec3(col), 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,106 @@
|
||||||
|
// cube02_0.jpg
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
// Created by S. Guillitte 2015
|
||||||
|
|
||||||
|
float zoom=1.;
|
||||||
|
|
||||||
|
vec2 cmul( vec2 a, vec2 b ) { return vec2( a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x ); }
|
||||||
|
vec2 csqr( vec2 a ) { return vec2( a.x*a.x - a.y*a.y, 2.*a.x*a.y ); }
|
||||||
|
|
||||||
|
|
||||||
|
mat2 rot(float a) {
|
||||||
|
return mat2(cos(a),sin(a),-sin(a),cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 iSphere( in vec3 ro, in vec3 rd, in vec4 sph )//from iq
|
||||||
|
{
|
||||||
|
vec3 oc = ro - sph.xyz;
|
||||||
|
float b = dot( oc, rd );
|
||||||
|
float c = dot( oc, oc ) - sph.w*sph.w;
|
||||||
|
float h = b*b - c;
|
||||||
|
if( h<0.0 ) return vec2(-1.0);
|
||||||
|
h = sqrt(h);
|
||||||
|
return vec2(-b-h, -b+h );
|
||||||
|
}
|
||||||
|
|
||||||
|
float map(in vec3 p) {
|
||||||
|
|
||||||
|
float res = 0.;
|
||||||
|
|
||||||
|
vec3 c = p;
|
||||||
|
for (int i = 0; i < 10; ++i) {
|
||||||
|
p =.7*abs(p)/dot(p,p) -.7;
|
||||||
|
p.yz= csqr(p.yz);
|
||||||
|
p=p.zxy;
|
||||||
|
res += exp(-19. * abs(dot(p,c)));
|
||||||
|
|
||||||
|
}
|
||||||
|
return res/2.;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
vec3 raymarch( in vec3 ro, vec3 rd, vec2 tminmax )
|
||||||
|
{
|
||||||
|
float t = tminmax.x;
|
||||||
|
float dt = .02;
|
||||||
|
//float dt = .2 - .195*cos(iGlobalTime*.05);//animated
|
||||||
|
vec3 col= vec3(0.);
|
||||||
|
float c = 0.;
|
||||||
|
for( int i=0; i<64; i++ )
|
||||||
|
{
|
||||||
|
t+=dt*exp(-2.*c);
|
||||||
|
if(t>tminmax.y)break;
|
||||||
|
vec3 pos = ro+t*rd;
|
||||||
|
|
||||||
|
c = map(ro+t*rd);
|
||||||
|
|
||||||
|
col = .99*col+ .08*vec3(c*c, c, c*c*c);//green
|
||||||
|
//col = .99*col+ .08*vec3(c*c*c, c*c, c);//blue
|
||||||
|
}
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
float time = iGlobalTime;
|
||||||
|
vec2 q = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = -1.0 + 2.0 * q;
|
||||||
|
p.x *= iResolution.x/iResolution.y;
|
||||||
|
vec2 m = vec2(0.);
|
||||||
|
if( iMouse.z>0.0 )m = iMouse.xy/iResolution.xy*3.14;
|
||||||
|
m-=.5;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
|
||||||
|
vec3 ro = zoom*vec3(4.);
|
||||||
|
ro.yz*=rot(m.y);
|
||||||
|
ro.xz*=rot(m.x+ 0.1*time);
|
||||||
|
vec3 ta = vec3( 0.0 , 0.0, 0.0 );
|
||||||
|
vec3 ww = normalize( ta - ro );
|
||||||
|
vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
|
||||||
|
vec3 vv = normalize( cross(uu,ww));
|
||||||
|
vec3 rd = normalize( p.x*uu + p.y*vv + 4.0*ww );
|
||||||
|
|
||||||
|
|
||||||
|
vec2 tmm = iSphere( ro, rd, vec4(0.,0.,0.,2.) );
|
||||||
|
|
||||||
|
// raymarch
|
||||||
|
vec3 col = raymarch(ro,rd,tmm);
|
||||||
|
if (tmm.x<0.)col = texture(iChannel0, rd.rg).rgb;
|
||||||
|
else {
|
||||||
|
vec3 nor=(ro+tmm.x*rd)/2.;
|
||||||
|
nor = reflect(rd, nor);
|
||||||
|
float fre = pow(.5+ clamp(dot(nor,rd),0.0,1.0), 3. )*1.3;
|
||||||
|
col += texture(iChannel0, nor.rg).rgb * fre;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// shade
|
||||||
|
|
||||||
|
col = .5 *(log(1.+col));
|
||||||
|
col = clamp(col,0.,1.);
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,465 @@
|
||||||
|
// https://www.shadertoy.com/view/WtXyW4
|
||||||
|
|
||||||
|
// License CC0: Alien Waterworld
|
||||||
|
// Been working on space themed shaders
|
||||||
|
// Code "borrowed" from the usual suspects
|
||||||
|
|
||||||
|
#define PI 3.141592654
|
||||||
|
#define TAU (2.0*PI)
|
||||||
|
|
||||||
|
#define TOLERANCE 0.00001
|
||||||
|
#define MAX_ITER 55
|
||||||
|
#define MAX_DISTANCE 31.0
|
||||||
|
#define PERIOD 45.0
|
||||||
|
#define TIME mod(iTime, PERIOD)
|
||||||
|
|
||||||
|
const vec3 skyCol1 = vec3(0.35, 0.45, 0.6);
|
||||||
|
const vec3 skyCol2 = skyCol1*skyCol1*skyCol1*3.0;
|
||||||
|
const vec3 sunCol1 = vec3(1.0,0.9,0.8);
|
||||||
|
const vec3 sunCol2 = vec3(1.0,0.9,0.8);
|
||||||
|
const vec3 smallSunCol1 = vec3(1.0,0.5,0.25)*0.5;
|
||||||
|
const vec3 smallSunCol2 = vec3(1.0,0.5,0.25)*0.5;
|
||||||
|
const vec3 ringColor = sqrt(vec3(0.95, 0.65, 0.45));
|
||||||
|
const vec4 planet = vec4(80.0, -20.0, 100.0, 50.0)*1000.0;
|
||||||
|
const vec3 planetCol = sqrt(vec3(0.9, 0.8, 0.7));
|
||||||
|
const vec3 ringsNormal = normalize(vec3(1.0, 1.25, 0.0));
|
||||||
|
const vec4 rings = vec4(ringsNormal, -dot(ringsNormal, planet.xyz));
|
||||||
|
|
||||||
|
void rot(inout vec2 p, float a) {
|
||||||
|
float c = cos(a);
|
||||||
|
float s = sin(a);
|
||||||
|
p = vec2(p.x*c + p.y*s, -p.x*s + p.y*c);
|
||||||
|
}
|
||||||
|
|
||||||
|
float psin(float f) {
|
||||||
|
return 0.5 + 0.5*sin(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 toRect(vec2 p) {
|
||||||
|
return p.x*vec2(cos(p.y), sin(p.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 toPolar(vec2 p) {
|
||||||
|
return vec2(length(p), atan(p.y, p.x));
|
||||||
|
}
|
||||||
|
|
||||||
|
float mod1(inout float p, float size) {
|
||||||
|
float halfsize = size*0.5;
|
||||||
|
float c = floor((p + halfsize)/size);
|
||||||
|
p = mod(p + halfsize, size) - halfsize;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
float circle(vec2 p, float r) {
|
||||||
|
return length(p) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float rayPlane(vec3 ro, vec3 rd, vec4 p) {
|
||||||
|
return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere)
|
||||||
|
{
|
||||||
|
vec3 ce = sphere.xyz;
|
||||||
|
float ra = sphere.w;
|
||||||
|
vec3 oc = ro - ce;
|
||||||
|
float b = dot( oc, rd );
|
||||||
|
float c = dot( oc, oc ) - ra*ra;
|
||||||
|
float h = b*b - c;
|
||||||
|
if( h<0.0 ) return vec2(-1.0); // no intersection
|
||||||
|
h = sqrt( h );
|
||||||
|
return vec2( -b-h, -b+h );
|
||||||
|
}
|
||||||
|
|
||||||
|
float hash(in vec2 co) {
|
||||||
|
return fract(sin(dot(co.xy ,vec2(12.9898,58.233))) * 13758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float noise2(vec2 x) {
|
||||||
|
vec2 i = floor(x);
|
||||||
|
vec2 w = fract(x);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
// quintic interpolation
|
||||||
|
vec2 u = w*w*w*(w*(w*6.0-15.0)+10.0);
|
||||||
|
#else
|
||||||
|
// cubic interpolation
|
||||||
|
vec2 u = w*w*(3.0-2.0*w);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float a = hash(i+vec2(0.0,0.0));
|
||||||
|
float b = hash(i+vec2(1.0,0.0));
|
||||||
|
float c = hash(i+vec2(0.0,1.0));
|
||||||
|
float d = hash(i+vec2(1.0,1.0));
|
||||||
|
|
||||||
|
float k0 = a;
|
||||||
|
float k1 = b - a;
|
||||||
|
float k2 = c - a;
|
||||||
|
float k3 = d - c + a - b;
|
||||||
|
|
||||||
|
return k0 + k1*u.x + k2*u.y + k3*u.x*u.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float smoother(float d, float s) {
|
||||||
|
return s*tanh(d/s);
|
||||||
|
}
|
||||||
|
|
||||||
|
float heightMod(vec2 p) {
|
||||||
|
vec2 pp = toPolar(p);
|
||||||
|
pp.y += -pp.x*0.2;
|
||||||
|
p = toRect(pp);
|
||||||
|
return pow((psin(1.0*p.x)*psin(1.0*p.y)), max(0.25, pp.x*0.20))*0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
float loheight(vec2 p, float d) {
|
||||||
|
const float aa = 0.5;
|
||||||
|
const float ff = 2.03;
|
||||||
|
const float tt = 1.3;
|
||||||
|
const float oo = 0.93;
|
||||||
|
|
||||||
|
float hm = heightMod(p);
|
||||||
|
|
||||||
|
vec2 s = vec2(0.0);
|
||||||
|
float a = 1.0;
|
||||||
|
float o = 0.2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
float nn = a*(noise2(2.0*p));
|
||||||
|
s.x += nn;
|
||||||
|
s.y += abs(a);
|
||||||
|
p += o;
|
||||||
|
a *= aa;
|
||||||
|
p *= ff;
|
||||||
|
o *= oo;
|
||||||
|
rot(p, tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.x /= s.y;
|
||||||
|
s.x -= 1.0;
|
||||||
|
s.x += 0.7*hm;
|
||||||
|
s.x = smoother(s.x, 0.125);
|
||||||
|
|
||||||
|
return max(s.x+0.125, 0.0)*0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
float height(vec2 p, float d) {
|
||||||
|
const float aa = 0.5;
|
||||||
|
const float ff = 2.03;
|
||||||
|
const float tt = 1.3;
|
||||||
|
const float oo = 0.93;
|
||||||
|
|
||||||
|
float hm = heightMod(p);
|
||||||
|
|
||||||
|
vec2 s = vec2(0.0);
|
||||||
|
float a = 1.0;
|
||||||
|
float o = 0.2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
float nn = a*(noise2(2.0*p));
|
||||||
|
s.x += nn;
|
||||||
|
s.y += abs(a);
|
||||||
|
p += o;
|
||||||
|
a *= aa;
|
||||||
|
p *= ff;
|
||||||
|
o *= oo;
|
||||||
|
rot(p, tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.x /= s.y;
|
||||||
|
s.x -= 1.0;
|
||||||
|
s.x += 0.7*hm;
|
||||||
|
s.x = smoother(s.x, 0.125);
|
||||||
|
|
||||||
|
return max(s.x+0.125, 0.0)*0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
float hiheight(vec2 p, float d) {
|
||||||
|
const float aa = 0.5;
|
||||||
|
const float ff = 2.03;
|
||||||
|
const float tt = 1.3;
|
||||||
|
const float oo = 0.93;
|
||||||
|
|
||||||
|
float hm = heightMod(p);
|
||||||
|
|
||||||
|
vec2 s = vec2(0.0);
|
||||||
|
float a = 1.0;
|
||||||
|
float o = 0.2;
|
||||||
|
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
float nn = a*(noise2(2.0*p));
|
||||||
|
s.x += nn;
|
||||||
|
s.y += abs(a);
|
||||||
|
p += o;
|
||||||
|
a *= aa;
|
||||||
|
p *= ff;
|
||||||
|
o *= oo;
|
||||||
|
rot(p, tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
s.x /= s.y;
|
||||||
|
s.x -= 1.0;
|
||||||
|
s.x += 0.7*hm;
|
||||||
|
s.x = smoother(s.x, 0.125);
|
||||||
|
|
||||||
|
return max(s.x+0.125, 0.0)*0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal(vec2 p, float d) {
|
||||||
|
vec2 eps = vec2(0.000125, 0.0);
|
||||||
|
|
||||||
|
vec3 n;
|
||||||
|
|
||||||
|
n.x = (hiheight(p - eps.xy, d) - hiheight(p + eps.xy, d));
|
||||||
|
n.y = 2.0*eps.x;
|
||||||
|
n.z = (hiheight(p - eps.yx, d) - hiheight(p + eps.yx, d));
|
||||||
|
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
float march(vec3 ro, vec3 rd, float id, out int max_iter) {
|
||||||
|
float dt = 0.1;
|
||||||
|
float d = id;
|
||||||
|
int currentStep = 0;
|
||||||
|
float lastd = d;
|
||||||
|
for (int i = 0; i < MAX_ITER; ++i) {
|
||||||
|
vec3 p = ro + d*rd;
|
||||||
|
float h = height(p.xz, d);
|
||||||
|
|
||||||
|
if (d > MAX_DISTANCE) {
|
||||||
|
max_iter = i;
|
||||||
|
return MAX_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
float hd = p.y - h;
|
||||||
|
|
||||||
|
if (hd < TOLERANCE) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sl = 0.9;
|
||||||
|
|
||||||
|
dt = max(hd*sl, TOLERANCE+0.0005*d);
|
||||||
|
lastd = d;
|
||||||
|
d += dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_iter = MAX_ITER;
|
||||||
|
return MAX_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sunDirection() {
|
||||||
|
return normalize(vec3(-0.5, 0.2, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 smallSunDirection() {
|
||||||
|
return normalize(vec3(-0.2, -0.05, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 skyColor(vec3 ro, vec3 rd) {
|
||||||
|
vec3 sunDir = sunDirection();
|
||||||
|
vec3 smallSunDir = smallSunDirection();
|
||||||
|
|
||||||
|
float sunDot = max(dot(rd, sunDir), 0.0);
|
||||||
|
float smallSunDot = max(dot(rd, smallSunDir), 0.0);
|
||||||
|
|
||||||
|
float angle = atan(rd.y, length(rd.xz))*2.0/PI;
|
||||||
|
|
||||||
|
vec3 sunCol = 0.5*sunCol1*pow(sunDot, 20.0) + 8.0*sunCol2*pow(sunDot, 2000.0);
|
||||||
|
vec3 smallSunCol = 0.5*smallSunCol1*pow(smallSunDot, 200.0) + 8.0*smallSunCol2*pow(smallSunDot, 20000.0);
|
||||||
|
|
||||||
|
|
||||||
|
vec2 si = raySphere(ro, rd, planet);
|
||||||
|
float pi = rayPlane(ro, rd, rings);
|
||||||
|
|
||||||
|
float dustTransparency = smoothstep(-0.15, 0.075, rd.y);
|
||||||
|
|
||||||
|
vec3 skyCol = mix(skyCol1, skyCol2, sqrt(dustTransparency));
|
||||||
|
skyCol *= (1.0-dustTransparency);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 planetSurface = ro + si.x*rd;
|
||||||
|
vec3 planetNormal = normalize(planetSurface - planet.xyz);
|
||||||
|
float planetDiff = max(dot(planetNormal, sunDir), 0.0);
|
||||||
|
float planetBorder = max(dot(planetNormal, -rd), 0.0);
|
||||||
|
float planetLat = (planetSurface.x+planetSurface.y)*0.0005;
|
||||||
|
vec3 planetCol = mix(1.3*planetCol, 0.3*planetCol, pow(psin(planetLat+1.0)*psin(sqrt(2.0)*planetLat+2.0)*psin(sqrt(3.5)*planetLat+3.0), 0.5));
|
||||||
|
|
||||||
|
vec3 ringsSurface = ro + pi*rd;
|
||||||
|
|
||||||
|
float borderTransparency = smoothstep(0.0, 0.1, planetBorder);
|
||||||
|
|
||||||
|
float ringsDist = length(ringsSurface - planet.xyz)*1.0;
|
||||||
|
float ringsPeriod = ringsDist*0.001;
|
||||||
|
const float ringsMax = 150000.0*0.655;
|
||||||
|
const float ringsMin = 100000.0*0.666;
|
||||||
|
float ringsMul = pow(psin(ringsPeriod+1.0)*psin(sqrt(0.5)*ringsPeriod+2.0)*psin(sqrt(0.45)*ringsPeriod+4.0)*psin(sqrt(0.35)*ringsPeriod+5.0), 0.25);
|
||||||
|
float ringsMix = psin(ringsPeriod*10.0)*psin(ringsPeriod*10.0*sqrt(2.0))*(1.0 - smoothstep(50000.0, 200000.0, pi));
|
||||||
|
|
||||||
|
vec3 ringsCol = mix(vec3(0.125), 0.75*ringColor, ringsMix)*step(-pi, 0.0)*step(ringsDist, ringsMax)*step(-ringsDist, -ringsMin)*ringsMul;
|
||||||
|
|
||||||
|
vec3 final = vec3(0.0);
|
||||||
|
|
||||||
|
final += ringsCol*(step(pi, si.x) + step(si.x, 0.0));
|
||||||
|
|
||||||
|
final += step(0.0, si.x)*pow(planetDiff, 0.75)*mix(planetCol, ringsCol, 0.0)*dustTransparency*borderTransparency + ringsCol*(1.0 - borderTransparency);
|
||||||
|
|
||||||
|
final += skyCol + sunCol + smallSunCol;
|
||||||
|
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 shipColor(vec2 p) {
|
||||||
|
vec2 pp = toPolar(p);
|
||||||
|
pp.y += pp.x*0.05;
|
||||||
|
p = toRect(pp);
|
||||||
|
|
||||||
|
float n = mod1(p.x, 0.15);
|
||||||
|
p.y += 3.0-TIME*0.5+0.05*abs(n*n);
|
||||||
|
|
||||||
|
float td = abs(p.x) - (0.005-p.y*0.002);
|
||||||
|
td = abs(td) - (0.02*pow(-p.y, 0.25));
|
||||||
|
float sd = circle(p, 0.05);
|
||||||
|
|
||||||
|
vec3 trailCol = vec3(0.5)*smoothstep(-5.0, 0.0, p.y)*step(p.y, 0.0)*smoothstep(0.0, 0.025, -td);
|
||||||
|
vec3 shipCol = vec3(0.5+smoothstep(-1.0, 1.0, sin(TIME*15.0*TAU+n)))*smoothstep(0.0, 0.075, -sd);
|
||||||
|
|
||||||
|
vec3 col = trailCol;
|
||||||
|
col += shipCol;
|
||||||
|
|
||||||
|
float sm = step(abs(n), 2.0);
|
||||||
|
|
||||||
|
return col*sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getColor(vec3 ro, vec3 rd) {
|
||||||
|
int max_iter = 0;
|
||||||
|
vec3 skyCol = skyColor(ro, rd);
|
||||||
|
vec3 col = vec3(0);
|
||||||
|
|
||||||
|
const float shipHeight = 1.0;
|
||||||
|
const float seaHeight = 0.0;
|
||||||
|
const float cloudHeight = 0.2;
|
||||||
|
const float upperCloudHeight = 0.5;
|
||||||
|
|
||||||
|
float id = (cloudHeight - ro.y)/rd.y;
|
||||||
|
|
||||||
|
if (id > 0.0) {
|
||||||
|
float d = march(ro, rd, id, max_iter);
|
||||||
|
vec3 sunDir = sunDirection();
|
||||||
|
vec3 osunDir = sunDir*vec3(-1.0, 1.0, -1.0);
|
||||||
|
vec3 p = ro + d*rd;
|
||||||
|
|
||||||
|
float loh = loheight(p.xz, d);
|
||||||
|
float loh2 = loheight(p.xz+sunDir.xz*0.05, d);
|
||||||
|
float hih = hiheight(p.xz, d);
|
||||||
|
vec3 normal = normal(p.xz, d);
|
||||||
|
|
||||||
|
float ud = (upperCloudHeight - 4.0*loh - ro.y)/rd.y;
|
||||||
|
|
||||||
|
float sd = (seaHeight - ro.y)/rd.y;
|
||||||
|
vec3 sp = ro + sd*rd;
|
||||||
|
float scd = (cloudHeight - sp.y)/sunDir.y;
|
||||||
|
vec3 scp = sp + sunDir*scd;
|
||||||
|
|
||||||
|
float sloh = loheight(scp.xz, d);
|
||||||
|
float cshd = exp(-15.0*sloh);
|
||||||
|
|
||||||
|
float amb = 0.3;
|
||||||
|
|
||||||
|
vec3 seaNormal = normalize(vec3(0.0, 1.0, 0.0));
|
||||||
|
vec3 seaRef = reflect(rd, seaNormal);
|
||||||
|
vec3 seaCol = .25*skyColor(p, seaRef);
|
||||||
|
seaCol += pow(max(dot(seaNormal, sunDir), 0.0), 2.0);
|
||||||
|
seaCol *= cshd;
|
||||||
|
seaCol += 0.075*pow(vec3(0.1, 1.3, 4.0), vec3(max(dot(seaNormal, seaRef), 0.0)));
|
||||||
|
|
||||||
|
float spe = pow(max(dot(sunDir, reflect(rd, normal)), 0.0), 3.0);
|
||||||
|
float fre = pow(1.0-dot(normal, -rd), 2.0);
|
||||||
|
|
||||||
|
col = seaCol;
|
||||||
|
|
||||||
|
|
||||||
|
const float level = 0.00;
|
||||||
|
const float level2 = 0.3;
|
||||||
|
// REALLY fake shadows and lighting
|
||||||
|
vec3 scol = sunCol1*(smoothstep(level, level2, hih) - smoothstep(level, level2, loh2));
|
||||||
|
col = mix(vec3(1.0), col, exp(-17.0*(hih-0.25*loh)));
|
||||||
|
col = mix(vec3(.75), col, exp(-10.0*loh*(max(d-ud, 0.0))));
|
||||||
|
col += scol;
|
||||||
|
|
||||||
|
col += vec3(0.5)*spe*fre;
|
||||||
|
|
||||||
|
float ssd = (shipHeight - ro.y)/rd.y;
|
||||||
|
|
||||||
|
col += shipColor((ro + rd*ssd).xz);
|
||||||
|
|
||||||
|
col = mix(col, skyCol, smoothstep(0.5*MAX_DISTANCE, 1.*MAX_DISTANCE, d));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
col = skyCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
// col += vec3(1.1, 0.0, 0.0)* smoothstep(0.25, 1.0,(float(max_iter)/float(MAX_ITER)));
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 postProcess(in vec3 col, in vec2 q)
|
||||||
|
{
|
||||||
|
//col = saturate(col);
|
||||||
|
col=pow(clamp(col,0.0,1.0),vec3(0.75));
|
||||||
|
col=col*0.6+0.4*col*col*(3.0-2.0*col); // contrast
|
||||||
|
col=mix(col, vec3(dot(col, vec3(0.33))), -0.4); // satuation
|
||||||
|
col*=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); // vigneting
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSample1(vec2 p, float time) {
|
||||||
|
vec3 ro = vec3(0.5, 5.5, -2.0);
|
||||||
|
vec3 la = ro + vec3(0.0, -1.+0.9*TIME/PERIOD, 1.0);
|
||||||
|
|
||||||
|
vec3 ww = normalize(la - ro);
|
||||||
|
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
|
||||||
|
vec3 vv = normalize(cross(ww, uu));
|
||||||
|
vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
|
||||||
|
|
||||||
|
vec3 col = getColor(ro, rd) ;
|
||||||
|
|
||||||
|
return col;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSample2(vec2 p, float time) {
|
||||||
|
p.y-=time*0.25;
|
||||||
|
float h = height(p, 0.0);
|
||||||
|
vec3 n = normal(p, 0.0);
|
||||||
|
|
||||||
|
vec3 lp = vec3(10.0, -1.2, 0.0);
|
||||||
|
|
||||||
|
vec3 ld = normalize(vec3(p.x, h, p.y)- lp);
|
||||||
|
|
||||||
|
float d = max(dot(ld, n), 0.0);
|
||||||
|
|
||||||
|
vec3 col = vec3(0.0);
|
||||||
|
|
||||||
|
col = vec3(1.0)*(h+0.1);
|
||||||
|
col += vec3(1.5)*pow(d, 0.75);
|
||||||
|
|
||||||
|
return col;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
vec2 p = -1.0 + 2.0*q;
|
||||||
|
p.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
vec3 col = getSample1(p, TIME);
|
||||||
|
|
||||||
|
col = postProcess(col, q);
|
||||||
|
|
||||||
|
col *= smoothstep(0.0, 2.0, TIME);
|
||||||
|
col *= 1.0-smoothstep(PERIOD-2.0, PERIOD, TIME);
|
||||||
|
|
||||||
|
fragColor = vec4(col, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,461 @@
|
||||||
|
// noise3.jpg, stars.jpg
|
||||||
|
// Ben Quantock 2014
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
// parameters
|
||||||
|
const float SSradius = 200.0; // Okay, it's actually a lot smaller than the Stanford Torus, but it's a cool name.
|
||||||
|
const float SSthickness = 16.0;
|
||||||
|
|
||||||
|
const float angularSpeed = .221; // g = r*w^2, e.g. w = sqrt(9.81/200) = .221
|
||||||
|
|
||||||
|
vec3 SunDir = vec3(1,1,-1.5);
|
||||||
|
|
||||||
|
const float tau = 6.28318530717958647692;
|
||||||
|
|
||||||
|
vec2 Noise( in vec3 x )
|
||||||
|
{
|
||||||
|
vec3 p = floor(x), f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
|
||||||
|
vec4 rg = textureLod( iChannel0, (uv+0.5)/256.0, 0.0 );
|
||||||
|
return mix( rg.yw, rg.xz, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX 1000.0
|
||||||
|
|
||||||
|
float Foliage( vec3 pos )
|
||||||
|
{
|
||||||
|
return
|
||||||
|
max(
|
||||||
|
abs(pos.z)-SSthickness,
|
||||||
|
abs(length(pos.xy)-SSradius-2.0 + Noise(pos/16.0).x*2.0 + 2.0*abs(pos.z)/SSthickness - 1.0)-1.0
|
||||||
|
);
|
||||||
|
// todo: leafiness
|
||||||
|
}
|
||||||
|
|
||||||
|
float Water( vec3 pos )
|
||||||
|
{
|
||||||
|
return max( abs(pos.z)-SSthickness, abs(length(pos.xy)-SSradius-1.0)-1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Building( vec3 pos, float seed )
|
||||||
|
{
|
||||||
|
if ( seed < .1 )
|
||||||
|
return length(vec3(pos.x,max(abs(pos.y)-2.0,0.0),pos.z))-2.0;
|
||||||
|
|
||||||
|
vec3 p = pos;
|
||||||
|
p.y += (seed-.5)*p.z;
|
||||||
|
p = abs(p)-vec3(2,3,2);
|
||||||
|
vec3 p2 = abs(pos+vec3(0,1.67,0))-vec3(1,.67,1);
|
||||||
|
return max(max(max(p.x,p.y),p.z),-max(p2.z,p2.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Solid( vec3 pos )
|
||||||
|
{
|
||||||
|
float r = length(pos.xy);
|
||||||
|
|
||||||
|
vec2 polar = vec2(atan(pos.x,-pos.y),length(pos.xy));
|
||||||
|
|
||||||
|
vec3 spokep = pos;
|
||||||
|
const float spokeangle = tau/5.0;
|
||||||
|
float spokea = (fract(polar.x/spokeangle)-.5)*spokeangle;
|
||||||
|
spokep.xy = polar.y*vec2(sin(spokea),-cos(spokea));
|
||||||
|
|
||||||
|
return
|
||||||
|
min(min(
|
||||||
|
// ring
|
||||||
|
max(max(
|
||||||
|
// outer torus
|
||||||
|
abs( length(vec2(pos.z, r-SSradius))-SSthickness-.5 )-.5,
|
||||||
|
// window-gap
|
||||||
|
5.0-abs(r-(SSradius-6.0))),
|
||||||
|
// top gap
|
||||||
|
min(
|
||||||
|
6.0-abs(pos.z), //todo: close bottom
|
||||||
|
SSradius-r
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// buildings
|
||||||
|
//length( vec3((fract(polar.x*40.0)-.5)*polar.y/40.0,polar.y+1.0-SSradius,pos.z+30.0*(fract(pow(floor(polar.x*40.0)*.777,2.0))-.5) ) ) - .5
|
||||||
|
//length( vec3((fract(polar.x*20.0)-.5)*polar.y/20.0,polar.y-SSradius,pos.z+30.0*(fract(pow(floor(polar.x*20.0)*.444,2.0))-.5) ) ) - 2.0
|
||||||
|
Building( vec3((fract(polar.x*20.0)-.5)*polar.y/20.0,polar.y-SSradius,pos.z+30.0*(fract(pow((floor(polar.x*20.0)+5.0)*.444,2.0))-.5) ), fract(pow(floor(polar.x*20.0)*.777,2.0)) )
|
||||||
|
// could do roads connecting them, by drawing 2 for every position
|
||||||
|
),
|
||||||
|
max(
|
||||||
|
min( min(
|
||||||
|
// spokes
|
||||||
|
max(
|
||||||
|
-SSradius-spokep.y,
|
||||||
|
length(spokep.xz)-2.0
|
||||||
|
),
|
||||||
|
// hub
|
||||||
|
max(
|
||||||
|
r-20.0,
|
||||||
|
abs(pos.z)-7.0
|
||||||
|
)),
|
||||||
|
max(
|
||||||
|
r-17.0,
|
||||||
|
abs(pos.z)-9.0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// dock
|
||||||
|
min(
|
||||||
|
8.0-abs(pos.x),
|
||||||
|
3.0-abs(pos.y)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// smooth min, to prevent hard edges when I use union of lights
|
||||||
|
bool domin;
|
||||||
|
float smin ( float a, float b )
|
||||||
|
{
|
||||||
|
/*const float s = 1.0;
|
||||||
|
return -log2(exp2(-a/s)+exp2(-b/s))*s;*/
|
||||||
|
if ( domin )
|
||||||
|
{
|
||||||
|
return min( a, b );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 1.0/(1.0/a+1.0/b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Lights( vec3 pos )
|
||||||
|
{
|
||||||
|
return
|
||||||
|
smin(smin(//smin(
|
||||||
|
// ring light
|
||||||
|
sqrt( pow(length(vec2(pos.z, length(pos.xy)-188.0)),2.0) + pow(max(.0,dot(pos.xy,vec2(sin(iGlobalTime*.3),cos(iGlobalTime*.3)))),2.0) )-.5,
|
||||||
|
|
||||||
|
// landing lights
|
||||||
|
//length( vec3( abs(pos.x)-8.0, max(vec2(0),abs(pos.yz)-vec2(3,8.5)) ) )-.1),
|
||||||
|
|
||||||
|
// moving lights to test fake lighting/shadows
|
||||||
|
length(pos-vec3(-sin(iGlobalTime*.2)*20.0+8.0,-197,12.0*sin(iGlobalTime)))-.3),
|
||||||
|
length(pos-vec3(-sin(iGlobalTime*.22)*30.0,-197.0+4.0*sin(iGlobalTime*.7),12.0*sin(iGlobalTime*.87)))-2.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 SampleLights( vec3 pos )
|
||||||
|
{
|
||||||
|
domin = false;
|
||||||
|
|
||||||
|
// like then Normal calc
|
||||||
|
float r = .1;
|
||||||
|
vec2 d = vec2(-1,1) * r;
|
||||||
|
vec3 p0 = pos+d.xxx; // tetrahedral offsets
|
||||||
|
vec3 p1 = pos+d.xyy;
|
||||||
|
vec3 p2 = pos+d.yxy;
|
||||||
|
vec3 p3 = pos+d.yyx;
|
||||||
|
|
||||||
|
float f0 = Lights(p0);
|
||||||
|
float f1 = Lights(p1);
|
||||||
|
float f2 = Lights(p2);
|
||||||
|
float f3 = Lights(p3);
|
||||||
|
|
||||||
|
// this direction is completely innaccurrate for hard-edged intersections!
|
||||||
|
// it gets one or other surface normal, rather than a smoothed result
|
||||||
|
// so, build smooth light shapes
|
||||||
|
|
||||||
|
return vec4(
|
||||||
|
-normalize( p0*f0+p1*f1+p2*f2+p3*f3 - pos*(f0+f1+f2+f3) ),// /r, should be possible to use non-normalized value, for more realistic effect
|
||||||
|
(f0+f1+f2+f3)/4.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float DistanceField( vec3 pos )
|
||||||
|
{
|
||||||
|
domin = true;
|
||||||
|
|
||||||
|
return min( min( min(
|
||||||
|
Foliage( pos ),
|
||||||
|
Water( pos ) ),
|
||||||
|
Solid( pos ) ),
|
||||||
|
Lights( pos )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float DistanceFieldNoLights( vec3 pos )
|
||||||
|
{
|
||||||
|
return min( min(
|
||||||
|
Foliage( pos ),
|
||||||
|
Water( pos ) ),
|
||||||
|
Solid( pos )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct ShadeData { vec3 pos, ray, normal; float shadow; float t; };
|
||||||
|
ShadeData SetShadeData( vec3 pos, vec3 ray, vec3 normal, float shadow, float t )
|
||||||
|
{
|
||||||
|
ShadeData s;
|
||||||
|
s.pos = pos;
|
||||||
|
s.ray = ray;
|
||||||
|
s.normal = normal;
|
||||||
|
s.shadow = shadow;
|
||||||
|
s.t = t;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 DiffuseLight( ShadeData s )
|
||||||
|
{
|
||||||
|
// sunlight
|
||||||
|
vec3 sun = vec3(1)*2.0*max(.0,dot(s.normal,SunDir))*s.shadow;
|
||||||
|
|
||||||
|
// local soft light sources
|
||||||
|
// Actually sample the lights!!
|
||||||
|
vec4 sl = SampleLights( s.pos );
|
||||||
|
// float fade = 1.0/sl.w; // point lights should be 1/(w*w), line lights are 1/w, infinite area lights are 1
|
||||||
|
//vec3 local = vec3(.4,.7,1)*5.0*(dot(sl.xyz,s.normal)*.5+.5)*fade;
|
||||||
|
vec3 local = vec3(.4,.7,1)*2.0*(dot(sl.xyz,s.normal)+1.0)/sl.w;
|
||||||
|
|
||||||
|
// like ambient occlusion, but towards the light
|
||||||
|
vec3 l = normalize(sl.xyz);
|
||||||
|
float d = 2.0;//s.t/20.0;
|
||||||
|
//shadow strength should depend on strength of SH vector
|
||||||
|
local *= .3+.7*min( 1.0, max( 0.0, (DistanceFieldNoLights(s.pos+l*d)/d)) );// /max(.001,dot(s.normal,l)) );
|
||||||
|
|
||||||
|
// ambient
|
||||||
|
vec3 ambient = vec3(0) + local;
|
||||||
|
// this ambient occlusion trick works ridiculously well
|
||||||
|
// sample the distance field at a point in front of the surface
|
||||||
|
// if there's a nearby concave surface the value will be less than the distance to the sample point
|
||||||
|
float aoRange = s.t/20.0;
|
||||||
|
float occlusion = max( 0.0, 1.0 - DistanceFieldNoLights( s.pos + s.normal*aoRange )/aoRange ); // can be > 1.0
|
||||||
|
ambient *= exp2( -2.0*pow(occlusion,2.0) ); // tweak the curve
|
||||||
|
|
||||||
|
return ambient;//+sun;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ShadeFoliage( ShadeData s )
|
||||||
|
{
|
||||||
|
vec3 albedo = mix( vec3(.05,.02,.01), vec3(.1,.5,.0), Noise(s.pos*20.0).x*.3+.7 );
|
||||||
|
|
||||||
|
return albedo*DiffuseLight(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ShadeWater( ShadeData s )
|
||||||
|
{
|
||||||
|
const float albedoScale = 4.0;
|
||||||
|
float rad = (SSradius+1.0)/albedoScale;
|
||||||
|
rad = floor( rad*tau+.5 )/tau; // round it so we get a whole number of texture repeats
|
||||||
|
vec2 uv = vec2(s.pos.z/albedoScale,atan(s.pos.x,s.pos.y)*rad);
|
||||||
|
|
||||||
|
vec3 base = vec3(.05,.1,.2)*DiffuseLight(s);
|
||||||
|
|
||||||
|
// normal map
|
||||||
|
vec2 noise = (Noise( s.pos*2.0+iGlobalTime*vec3(-4,4,0) )*2.0-1.0)*.1;
|
||||||
|
vec3 tangent = normalize(vec3(s.pos.y,-s.pos.x,0));
|
||||||
|
vec3 binormal = vec3(0,0,1);
|
||||||
|
vec3 normal = s.normal + tangent*noise.x + binormal*noise.y;
|
||||||
|
|
||||||
|
float fresnel = dot(normal,s.ray);
|
||||||
|
vec3 reflection = s.ray-2.0*fresnel*normal;
|
||||||
|
fresnel = pow( 1.0-abs(fresnel), 5.0 );
|
||||||
|
float up = dot( reflection, normal );
|
||||||
|
float across = dot( reflection, binormal );
|
||||||
|
vec3 refcol = vec3(.4,.7,1)*1.0*pow(1.0-abs(across),40.0);
|
||||||
|
|
||||||
|
return mix( base, refcol, fresnel );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ShadeSolid( ShadeData s )
|
||||||
|
{
|
||||||
|
return vec3(.8) * DiffuseLight(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ShadeLights( ShadeData s )
|
||||||
|
{
|
||||||
|
return vec3(.4,.7,1)*8.0*abs(dot(s.ray,s.normal)); // draw the lightbulb
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Shade( ShadeData s )
|
||||||
|
{
|
||||||
|
float foliage = Foliage(s.pos);
|
||||||
|
float water = Water(s.pos);
|
||||||
|
float solid = Solid(s.pos);
|
||||||
|
float lights = Lights(s.pos);
|
||||||
|
float dist = min(min(min(foliage, water),solid),lights);
|
||||||
|
|
||||||
|
if ( lights == dist )
|
||||||
|
return ShadeLights(s);
|
||||||
|
|
||||||
|
#if (1) // test lighting
|
||||||
|
return DiffuseLight(s)*.8;
|
||||||
|
#else
|
||||||
|
else if ( foliage == dist )
|
||||||
|
return ShadeFoliage(s);
|
||||||
|
else if ( water == dist )
|
||||||
|
return ShadeWater(s);
|
||||||
|
else
|
||||||
|
return ShadeSolid(s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//Compute the surface normal
|
||||||
|
vec3 Normal( vec3 pos )
|
||||||
|
{
|
||||||
|
// in theory we should be able to get a good gradient using just 4 points
|
||||||
|
vec2 d = vec2(-1,1) * .01;
|
||||||
|
vec3 p0 = pos+d.xxx; // tetrahedral offsets
|
||||||
|
vec3 p1 = pos+d.xyy;
|
||||||
|
vec3 p2 = pos+d.yxy;
|
||||||
|
vec3 p3 = pos+d.yyx;
|
||||||
|
|
||||||
|
float f0 = DistanceField(p0);
|
||||||
|
float f1 = DistanceField(p1);
|
||||||
|
float f2 = DistanceField(p2);
|
||||||
|
float f3 = DistanceField(p3);
|
||||||
|
|
||||||
|
return normalize( p0*f0+p1*f1+p2*f2+p3*f3 - pos*(f0+f1+f2+f3) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Camera { vec3 pos, target, up; float zoom; };
|
||||||
|
|
||||||
|
Camera SetCam( vec3 pos, vec3 target, vec3 up, float zoom )
|
||||||
|
{
|
||||||
|
Camera cam;
|
||||||
|
cam.pos = pos;
|
||||||
|
cam.target = target;
|
||||||
|
cam.up = up;
|
||||||
|
cam.zoom = zoom;
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera MixCam( Camera a, Camera b, float c )
|
||||||
|
{
|
||||||
|
Camera cam;
|
||||||
|
cam.pos = mix( a.pos, b.pos, c );
|
||||||
|
cam.target = mix( a.target, b.target, c );
|
||||||
|
cam.up = mix( a.up, b.up, c );
|
||||||
|
cam.zoom = mix( a.zoom, b.zoom, c );
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 BGRot( in vec3 v, in vec3 cs )
|
||||||
|
{
|
||||||
|
return vec3(v.xy*cs.x + v.yx*cs.yz, v.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Trace( vec3 pos, vec3 ray, vec2 interval )
|
||||||
|
{
|
||||||
|
float t = interval.x;
|
||||||
|
float h;
|
||||||
|
for( int i=0; i<200; i++ )
|
||||||
|
{
|
||||||
|
h = DistanceField( pos + t*ray );
|
||||||
|
if ( h < .01 || t > interval.y )
|
||||||
|
break;
|
||||||
|
t += h;
|
||||||
|
}
|
||||||
|
return vec2(t,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// rotate background
|
||||||
|
float a = iGlobalTime*angularSpeed; // radians per second
|
||||||
|
vec3 cs = vec3( cos(a), sin(a)*vec2(1,-1) );
|
||||||
|
SunDir = normalize( BGRot( SunDir, cs ) );
|
||||||
|
|
||||||
|
// todo: animate camera between pairs of keyframes
|
||||||
|
Camera camKeys[8];
|
||||||
|
camKeys[0] = SetCam( vec3(-400,-300,-300), vec3(0,0,0), vec3(0,.5,-1), .8 );
|
||||||
|
camKeys[1] = SetCam( vec3(-20,3.0-SSradius,-16), vec3(SSradius,-130,0), vec3(0,1,1), .7 );
|
||||||
|
camKeys[2] = SetCam( vec3(-10,2.0-SSradius,16), vec3(0,-SSradius,0), vec3(0,1,0), .8 );
|
||||||
|
camKeys[3] = SetCam( vec3(30,2.5-SSradius,5), vec3(-SSradius,40.0-SSradius,-50), vec3(0,1,0), .8 );
|
||||||
|
camKeys[4] = SetCam( vec3(30,2.5-SSradius,5), vec3(-SSradius,40.0-SSradius,-50), vec3(0,1,0), .8 );
|
||||||
|
camKeys[5] = SetCam( vec3(-10,2.5-SSradius,2), vec3(0,SSradius,0), vec3(.5,3,1), 1.2 );
|
||||||
|
camKeys[6] = SetCam( vec3(200,-150,400), vec3(0,0,0), vec3(0,.5,1), .8 );
|
||||||
|
camKeys[7] = SetCam( vec3(0,0,50), vec3(0,0,0), vec3(cs.y,-cs.x,0), .8 );
|
||||||
|
|
||||||
|
// pick a pair of cameras using time
|
||||||
|
// todo: could manually pick cam using all combinations of "iop", shown on screen when auto-cycling (cam: io)
|
||||||
|
// mouse moves cam along path, and target up/down (by up*length(target-pos))
|
||||||
|
float T = fract(iGlobalTime/52.0)*4.0;
|
||||||
|
Camera cam1, cam2;
|
||||||
|
bool rotCam = false;
|
||||||
|
if ( T < 1.0 ) { cam1 = camKeys[0]; cam2 = camKeys[1]; rotCam = true; }
|
||||||
|
else if ( T < 2.0 ) { cam1 = camKeys[2]; cam2 = camKeys[3]; }
|
||||||
|
else if ( T < 3.0 ) { cam1 = camKeys[4]; cam2 = camKeys[5]; }
|
||||||
|
else { cam1 = camKeys[6]; cam2 = camKeys[7]; rotCam = true; }
|
||||||
|
|
||||||
|
// mix between them
|
||||||
|
//T = smoothstep( .15, .85, fract(T) );
|
||||||
|
T = fract(T);
|
||||||
|
float T2 = T*T;
|
||||||
|
T = (6.0*T2 - 15.0*T + 10.0)*T2*T;
|
||||||
|
Camera cam = MixCam( cam1, cam2, T );
|
||||||
|
|
||||||
|
//rotCam = true; cam = camKeys[1];
|
||||||
|
rotCam = false; cam = camKeys[3];
|
||||||
|
|
||||||
|
//Camera cam = SetCam( vec3(500.0*(iMouse.xy/iResolution.xy-.5),0)+vec3(0,-300,-300), vec3(0,-100,0), vec3(0,1,0), .7 );
|
||||||
|
|
||||||
|
// fire a ray from the camera
|
||||||
|
vec3 pos = cam.pos;
|
||||||
|
vec3 forward = normalize(cam.target-cam.pos);
|
||||||
|
vec3 right = normalize(cross(cam.up,forward));
|
||||||
|
vec3 up = normalize(cross(forward,right));
|
||||||
|
vec3 ray = normalize(vec3( fragCoord.xy-iResolution.xy*.5, iResolution.x*cam.zoom ));
|
||||||
|
ray = right*ray.x + up*ray.y + forward*ray.z;
|
||||||
|
|
||||||
|
if ( rotCam )
|
||||||
|
{
|
||||||
|
pos = BGRot( pos, cs );
|
||||||
|
ray = BGRot( ray, cs );
|
||||||
|
}
|
||||||
|
|
||||||
|
// intersect that ray with isosurface bounding volume
|
||||||
|
vec2 interval = vec2(0,1000);
|
||||||
|
|
||||||
|
// march isosurface
|
||||||
|
vec2 th = Trace( pos, ray, interval );
|
||||||
|
|
||||||
|
// shading
|
||||||
|
vec3 col;
|
||||||
|
|
||||||
|
if ( th.y < 1.0 ) // shade some near misses to reduce artefacts
|
||||||
|
{
|
||||||
|
vec3 p = pos + th.x*ray;
|
||||||
|
vec3 n = Normal(p);
|
||||||
|
|
||||||
|
float shadowBias = mix ( 1.0, .1, abs(dot( n, SunDir )) );
|
||||||
|
|
||||||
|
float shadow = Trace( p, SunDir, vec2(shadowBias, 1000.0) ).y;
|
||||||
|
|
||||||
|
shadow = smoothstep( .01, 4.0, shadow );
|
||||||
|
|
||||||
|
col = Shade( SetShadeData(p,ray,n,shadow,th.x) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// draw background
|
||||||
|
ray = BGRot( ray, cs.xzy );
|
||||||
|
float s = 1.3;
|
||||||
|
vec3 X = texture( iChannel1, ray.yz*s ).rgb;
|
||||||
|
vec3 Y = texture( iChannel1, ray.xz*s ).rgb;
|
||||||
|
vec3 Z = texture( iChannel1, ray.xy*s ).rgb;
|
||||||
|
col = mix( X, Y, smoothstep(-.3,.3,abs(ray.y)-abs(ray.x)) );
|
||||||
|
col = mix( col, Z, smoothstep(-.3,.3,abs(ray.z)-max(abs(ray.x),abs(ray.y))) );
|
||||||
|
col = pow(col,vec3(7,5,3))*.1;
|
||||||
|
|
||||||
|
col = vec3(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(pow(col,vec3(1.0/2.2)),1.0);
|
||||||
|
}
|
|
@ -0,0 +1,423 @@
|
||||||
|
// noise3.jpg,
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
const float tau = 6.28318530717958647692;
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
#define GAMMA (2.2)
|
||||||
|
|
||||||
|
vec3 ToLinear( in vec3 col )
|
||||||
|
{
|
||||||
|
// simulate a monitor, converting colour values into light values
|
||||||
|
return pow( col, vec3(GAMMA) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ToGamma( in vec3 col )
|
||||||
|
{
|
||||||
|
// convert back into colour values, so the correct light will come out of the monitor
|
||||||
|
return pow( col, vec3(1.0/GAMMA) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 localRay;
|
||||||
|
|
||||||
|
// Set up a camera looking at the scene.
|
||||||
|
// origin - camera is positioned relative to, and looking at, this point
|
||||||
|
// distance - how far camera is from origin
|
||||||
|
// rotation - about x & y axes, by left-hand screw rule, relative to camera looking along +z
|
||||||
|
// zoom - the relative length of the lens
|
||||||
|
void CamPolar( out vec3 pos, out vec3 ray, in vec3 origin, in vec2 rotation, in float distance, in float zoom, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// get rotation coefficients
|
||||||
|
vec2 c = vec2(cos(rotation.x),cos(rotation.y));
|
||||||
|
vec4 s;
|
||||||
|
s.xy = vec2(sin(rotation.x),sin(rotation.y)); // worth testing if this is faster as sin or sqrt(1.0-cos);
|
||||||
|
s.zw = -s.xy;
|
||||||
|
|
||||||
|
// ray in view space
|
||||||
|
ray.xy = fragCoord.xy - iResolution.xy*.5;
|
||||||
|
ray.z = iResolution.y*zoom;
|
||||||
|
ray = normalize(ray);
|
||||||
|
localRay = ray;
|
||||||
|
|
||||||
|
// rotate ray
|
||||||
|
ray.yz = ray.yz*c.xx + ray.zy*s.zx;
|
||||||
|
ray.xz = ray.xz*c.yy + ray.zx*s.yw;
|
||||||
|
|
||||||
|
// position camera
|
||||||
|
pos = origin - distance*vec3(c.x*s.y,s.z,c.x*c.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Noise functions, distinguished by variable types
|
||||||
|
|
||||||
|
vec2 Noise( in vec3 x )
|
||||||
|
{
|
||||||
|
vec3 p = floor(x);
|
||||||
|
vec3 f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);
|
||||||
|
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z);
|
||||||
|
|
||||||
|
vec4 rg = textureLod( iChannel0, (uv+f.xy+0.5)/256.0, 0.0 );
|
||||||
|
|
||||||
|
return mix( rg.yw, rg.xz, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 NoisePrecise( in vec3 x )
|
||||||
|
{
|
||||||
|
vec3 p = floor(x);
|
||||||
|
vec3 f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);
|
||||||
|
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z);
|
||||||
|
|
||||||
|
vec4 rg = mix( mix(
|
||||||
|
textureLod( iChannel0, (uv+0.5)/256.0, 0.0 ),
|
||||||
|
textureLod( iChannel0, (uv+vec2(1,0)+0.5)/256.0, 0.0 ),
|
||||||
|
f.x ),
|
||||||
|
mix(
|
||||||
|
textureLod( iChannel0, (uv+vec2(0,1)+0.5)/256.0, 0.0 ),
|
||||||
|
textureLod( iChannel0, (uv+1.5)/256.0, 0.0 ),
|
||||||
|
f.x ),
|
||||||
|
f.y );
|
||||||
|
|
||||||
|
|
||||||
|
return mix( rg.yw, rg.xz, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 Noise( in vec2 x )
|
||||||
|
{
|
||||||
|
vec2 p = floor(x.xy);
|
||||||
|
vec2 f = fract(x.xy);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);
|
||||||
|
|
||||||
|
vec2 uv = p.xy + f.xy;
|
||||||
|
return textureLod( iChannel0, (uv+0.5)/256.0, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 Noise( in ivec2 x )
|
||||||
|
{
|
||||||
|
return textureLod( iChannel0, (vec2(x)+0.5)/256.0, 0.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Noise( in ivec3 x )
|
||||||
|
{
|
||||||
|
vec2 uv = vec2(x.xy)+vec2(37.0,17.0)*float(x.z);
|
||||||
|
return textureLod( iChannel0, (uv+0.5)/256.0, 0.0 ).xz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Waves( vec3 pos )
|
||||||
|
{
|
||||||
|
pos *= .2*vec3(1,1,1);
|
||||||
|
|
||||||
|
const int octaves = 5;
|
||||||
|
float f = 0.0;
|
||||||
|
|
||||||
|
// need to do the octaves from large to small, otherwise things don't line up
|
||||||
|
// (because I rotate by 45 degrees on each octave)
|
||||||
|
pos += iGlobalTime*vec3(0,.1,.1);
|
||||||
|
for ( int i=0; i < octaves; i++ )
|
||||||
|
{
|
||||||
|
pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);
|
||||||
|
f = f*2.0+abs(Noise(pos).x-.5)*2.0;
|
||||||
|
pos *= 2.0;
|
||||||
|
}
|
||||||
|
f /= exp2(float(octaves));
|
||||||
|
|
||||||
|
return (.5-f)*1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float WavesDetail( vec3 pos )
|
||||||
|
{
|
||||||
|
pos *= .2*vec3(1,1,1);
|
||||||
|
|
||||||
|
const int octaves = 8;
|
||||||
|
float f = 0.0;
|
||||||
|
|
||||||
|
// need to do the octaves from large to small, otherwise things don't line up
|
||||||
|
// (because I rotate by 45 degrees on each octave)
|
||||||
|
pos += iGlobalTime*vec3(0,.1,.1);
|
||||||
|
for ( int i=0; i < octaves; i++ )
|
||||||
|
{
|
||||||
|
pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);
|
||||||
|
f = f*2.0+abs(NoisePrecise(pos).x-.5)*2.0;
|
||||||
|
pos *= 2.0;
|
||||||
|
}
|
||||||
|
f /= exp2(float(octaves));
|
||||||
|
|
||||||
|
return (.5-f)*1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float WavesSmooth( vec3 pos )
|
||||||
|
{
|
||||||
|
pos *= .2*vec3(1,1,1);
|
||||||
|
|
||||||
|
const int octaves = 2;
|
||||||
|
float f = 0.0;
|
||||||
|
|
||||||
|
// need to do the octaves from large to small, otherwise things don't line up
|
||||||
|
// (because I rotate by 45 degrees on each octave)
|
||||||
|
pos += iGlobalTime*vec3(0,.1,.1);
|
||||||
|
for ( int i=0; i < octaves; i++ )
|
||||||
|
{
|
||||||
|
pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);
|
||||||
|
//f = f*2.0+abs(Noise(pos).x-.5)*2.0;
|
||||||
|
f = f*2.0+sqrt(pow(NoisePrecise(pos).x-.5,2.0)+.01)*2.0;
|
||||||
|
pos *= 2.0;
|
||||||
|
}
|
||||||
|
f /= exp2(float(octaves));
|
||||||
|
|
||||||
|
return (.5-f)*1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float WaveCrests( vec3 ipos, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec3 pos = ipos;
|
||||||
|
pos *= .2*vec3(1,1,1);
|
||||||
|
|
||||||
|
const int octaves1 = 6;
|
||||||
|
const int octaves2 = 16;
|
||||||
|
float f = 0.0;
|
||||||
|
|
||||||
|
// need to do the octaves from large to small, otherwise things don't line up
|
||||||
|
// (because I rotate by 45 degrees on each octave)
|
||||||
|
pos += iGlobalTime*vec3(0,.1,.1);
|
||||||
|
vec3 pos2 = pos;
|
||||||
|
for ( int i=0; i < octaves1; i++ )
|
||||||
|
{
|
||||||
|
pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);
|
||||||
|
f = f*1.5+abs(Noise(pos).x-.5)*2.0;
|
||||||
|
pos *= 2.0;
|
||||||
|
}
|
||||||
|
pos = pos2 * exp2(float(octaves1));
|
||||||
|
pos.y = -.05*iGlobalTime;
|
||||||
|
for ( int i=octaves1; i < octaves2; i++ )
|
||||||
|
{
|
||||||
|
pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);
|
||||||
|
f = f*1.5+pow(abs(Noise(pos).x-.5)*2.0,1.0);
|
||||||
|
pos *= 2.0;
|
||||||
|
}
|
||||||
|
f /= 1500.0;
|
||||||
|
|
||||||
|
f -= Noise(ivec2(fragCoord.xy)).x*.01;
|
||||||
|
|
||||||
|
return pow(smoothstep(.4,-.1,f),6.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 Sky( vec3 ray )
|
||||||
|
{
|
||||||
|
return vec3(.4,.45,.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 boatRight, boatUp, boatForward;
|
||||||
|
vec3 boatPosition;
|
||||||
|
|
||||||
|
void ComputeBoatTransform( void )
|
||||||
|
{
|
||||||
|
vec3 samples[5];
|
||||||
|
|
||||||
|
samples[0] = vec3(0,0, 0);
|
||||||
|
samples[1] = vec3(0,0, .5);
|
||||||
|
samples[2] = vec3(0,0,-.5);
|
||||||
|
samples[3] = vec3( .5,0,0);
|
||||||
|
samples[4] = vec3(-.5,0,0);
|
||||||
|
|
||||||
|
samples[0].y = WavesSmooth(samples[0]);
|
||||||
|
samples[1].y = WavesSmooth(samples[1]);
|
||||||
|
samples[2].y = WavesSmooth(samples[2]);
|
||||||
|
samples[3].y = WavesSmooth(samples[3]);
|
||||||
|
samples[4].y = WavesSmooth(samples[4]);
|
||||||
|
|
||||||
|
boatPosition = (samples[0]+samples[1]+samples[2]+samples[3]+samples[4])/5.0;
|
||||||
|
|
||||||
|
boatRight = samples[3]-samples[4];
|
||||||
|
boatForward = samples[1]-samples[2];
|
||||||
|
boatUp = normalize(cross(boatForward,boatRight));
|
||||||
|
boatRight = normalize(cross(boatUp,boatForward));
|
||||||
|
boatForward = normalize(boatForward);
|
||||||
|
|
||||||
|
boatPosition += .0*boatUp;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 BoatToWorld( vec3 dir )
|
||||||
|
{
|
||||||
|
return dir.x*boatRight+dir.x*boatUp+dir.x*boatForward;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 WorldToBoat( vec3 dir )
|
||||||
|
{
|
||||||
|
return vec3( dot(dir,boatRight), dot(dir,boatUp), dot(dir,boatForward) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float TraceBoat( vec3 pos, vec3 ray )
|
||||||
|
{
|
||||||
|
vec3 c = boatPosition;
|
||||||
|
float r = 1.0;
|
||||||
|
|
||||||
|
c -= pos;
|
||||||
|
|
||||||
|
float t = dot(c,ray);
|
||||||
|
|
||||||
|
float p = length(c-t*ray);
|
||||||
|
if ( p > r )
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return t-sqrt(r*r-p*p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ShadeBoat( vec3 pos, vec3 ray )
|
||||||
|
{
|
||||||
|
pos -= boatPosition;
|
||||||
|
vec3 norm = normalize(pos);
|
||||||
|
pos = WorldToBoat(pos);
|
||||||
|
|
||||||
|
vec3 lightDir = normalize(vec3(-2,3,1));
|
||||||
|
float ndotl = dot(norm,lightDir);
|
||||||
|
|
||||||
|
// allow some light bleed, as if it's subsurface scattering through plastic
|
||||||
|
vec3 light = smoothstep(-.1,1.0,ndotl)*vec3(1.0,.9,.8)+vec3(.06,.1,.1);
|
||||||
|
|
||||||
|
// anti-alias the albedo
|
||||||
|
float aa = 4.0/iResolution.x;
|
||||||
|
|
||||||
|
//vec3 albedo = ((fract(pos.x)-.5)*(fract(pos.y)-.5)*(fract(pos.z)-.5) < 0.0) ? vec3(0) : vec3(1);
|
||||||
|
vec3 albedo = vec3(1,.01,0);
|
||||||
|
albedo = mix( vec3(.04), albedo, smoothstep( .25-aa, .25, abs(pos.y) ) );
|
||||||
|
albedo = mix( mix( vec3(1), vec3(.04), smoothstep(-aa*4.0,aa*4.0,cos(atan(pos.x,pos.z)*6.0)) ), albedo, smoothstep( .2-aa*1.5, .2, abs(pos.y) ) );
|
||||||
|
albedo = mix( vec3(.04), albedo, smoothstep( .05-aa*1.0, .05, abs(abs(pos.y)-.6) ) );
|
||||||
|
albedo = mix( vec3(1,.8,.08), albedo, smoothstep( .05-aa*1.0, .05, abs(abs(pos.y)-.65) ) );
|
||||||
|
|
||||||
|
vec3 col = albedo*light;
|
||||||
|
|
||||||
|
// specular
|
||||||
|
vec3 h = normalize(lightDir-ray);
|
||||||
|
float s = pow(max(0.0,dot(norm,h)),100.0)*100.0/32.0;
|
||||||
|
|
||||||
|
vec3 specular = s*vec3(1,1,1);
|
||||||
|
|
||||||
|
vec3 rr = reflect(ray,norm);
|
||||||
|
specular += mix( vec3(0,.04,.04), Sky(rr), smoothstep( -.1, .1, rr.y ) );
|
||||||
|
|
||||||
|
float ndotr = dot(norm,ray);
|
||||||
|
float fresnel = pow(1.0-abs(ndotr),5.0);
|
||||||
|
fresnel = mix( .001, 1.0, fresnel );
|
||||||
|
|
||||||
|
col = mix( col, specular, fresnel );
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float OceanDistanceField( vec3 pos )
|
||||||
|
{
|
||||||
|
return pos.y - Waves(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
float OceanDistanceFieldDetail( vec3 pos )
|
||||||
|
{
|
||||||
|
return pos.y - WavesDetail(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 OceanNormal( vec3 pos )
|
||||||
|
{
|
||||||
|
vec3 norm;
|
||||||
|
vec2 d = vec2(.01*length(pos),0);
|
||||||
|
|
||||||
|
norm.x = OceanDistanceFieldDetail( pos+d.xyy )-OceanDistanceFieldDetail( pos-d.xyy );
|
||||||
|
norm.y = OceanDistanceFieldDetail( pos+d.yxy )-OceanDistanceFieldDetail( pos-d.yxy );
|
||||||
|
norm.z = OceanDistanceFieldDetail( pos+d.yyx )-OceanDistanceFieldDetail( pos-d.yyx );
|
||||||
|
|
||||||
|
return normalize(norm);
|
||||||
|
}
|
||||||
|
|
||||||
|
float TraceOcean( vec3 pos, vec3 ray )
|
||||||
|
{
|
||||||
|
float h = 1.0;
|
||||||
|
float t = 0.0;
|
||||||
|
for ( int i=0; i < 100; i++ )
|
||||||
|
{
|
||||||
|
if ( h < .01 || t > 100.0 )
|
||||||
|
break;
|
||||||
|
h = OceanDistanceField( pos+t*ray );
|
||||||
|
t += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( h > .1 )
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ShadeOcean( vec3 pos, vec3 ray, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec3 norm = OceanNormal(pos);
|
||||||
|
float ndotr = dot(ray,norm);
|
||||||
|
|
||||||
|
float fresnel = pow(1.0-abs(ndotr),5.0);
|
||||||
|
|
||||||
|
vec3 reflectedRay = ray-2.0*norm*ndotr;
|
||||||
|
vec3 refractedRay = ray+(-cos(1.33*acos(-ndotr))-ndotr)*norm;
|
||||||
|
refractedRay = normalize(refractedRay);
|
||||||
|
|
||||||
|
const float crackFudge = .0;
|
||||||
|
|
||||||
|
// reflection
|
||||||
|
vec3 reflection = Sky(reflectedRay);
|
||||||
|
float t=TraceBoat( pos-crackFudge*reflectedRay, reflectedRay );
|
||||||
|
|
||||||
|
if ( t > 0.0 )
|
||||||
|
{
|
||||||
|
reflection = ShadeBoat( pos+(t-crackFudge)*reflectedRay, reflectedRay );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// refraction
|
||||||
|
t=TraceBoat( pos-crackFudge*refractedRay, refractedRay );
|
||||||
|
|
||||||
|
vec3 col = vec3(0,.04,.04); // under-sea colour
|
||||||
|
if ( t > 0.0 )
|
||||||
|
{
|
||||||
|
col = mix( col, ShadeBoat( pos+(t-crackFudge)*refractedRay, refractedRay ), exp(-t) );
|
||||||
|
}
|
||||||
|
|
||||||
|
col = mix( col, reflection, fresnel );
|
||||||
|
|
||||||
|
// foam
|
||||||
|
col = mix( col, vec3(1), WaveCrests(pos,fragCoord) );
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
ComputeBoatTransform();
|
||||||
|
|
||||||
|
vec2 camRot = vec2(.5,.5)+vec2(-.35,4.5)*(iMouse.yx/iResolution.yx);
|
||||||
|
vec3 pos, ray;
|
||||||
|
CamPolar( pos, ray, vec3(0), camRot, 3.0, 1.0, fragCoord );
|
||||||
|
|
||||||
|
float to = TraceOcean( pos, ray );
|
||||||
|
float tb = TraceBoat( pos, ray );
|
||||||
|
|
||||||
|
vec3 result;
|
||||||
|
if ( to > 0.0 && ( to < tb || tb == 0.0 ) )
|
||||||
|
result = ShadeOcean( pos+ray*to, ray, fragCoord );
|
||||||
|
else if ( tb > 0.0 )
|
||||||
|
result = ShadeBoat( pos+ray*tb, ray );
|
||||||
|
else
|
||||||
|
result = Sky( ray );
|
||||||
|
|
||||||
|
// vignette effect
|
||||||
|
result *= 1.1*smoothstep( .35, 1.0, localRay.z );
|
||||||
|
|
||||||
|
fragColor = vec4(ToGamma(result),1.0);
|
||||||
|
}
|
|
@ -0,0 +1,954 @@
|
||||||
|
// river.jpg
|
||||||
|
|
||||||
|
// Where the River Goes
|
||||||
|
// @P_Malin
|
||||||
|
|
||||||
|
// What started as a hacked flow and advection experiment turned into something nice.
|
||||||
|
|
||||||
|
// Placeholder audio https://www.youtube.com/watch?v=gmar4gh5nIw suggested by @qthund on twitter
|
||||||
|
|
||||||
|
//#define ENABLE_ULTRA_QUALITY
|
||||||
|
|
||||||
|
#define ENABLE_WATER
|
||||||
|
#define ENABLE_FOAM
|
||||||
|
#define ENABLE_WATER_RECEIVE_SHADOW
|
||||||
|
#define ENABLE_CONE_STEPPING
|
||||||
|
|
||||||
|
|
||||||
|
// Textureless version
|
||||||
|
//#define ENABLE_NIMITZ_TRIANGLE_NOISE
|
||||||
|
|
||||||
|
//#define ENABLE_LANDSCAPE_RECEIVE_SHADOW
|
||||||
|
|
||||||
|
//#define ENABLE_SCREENSHOT_MODE
|
||||||
|
const float k_screenshotTime = 13.0;
|
||||||
|
|
||||||
|
#if defined(ENABLE_SCREENSHOT_MODE) || defined(ENABLE_ULTRA_QUALITY)
|
||||||
|
#define ENABLE_SUPERSAMPLE_MODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ENABLE_SCREENSHOT_MODE
|
||||||
|
#ifdef ENABLE_ULTRA_QUALITY
|
||||||
|
const int k_raymarchSteps = 96;
|
||||||
|
const int k_fmbSteps = 6;
|
||||||
|
const int k_superSampleCount = 6;
|
||||||
|
#else
|
||||||
|
const int k_raymarchSteps = 64;
|
||||||
|
const int k_fmbSteps = 3;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
const int k_raymarchSteps = 96;
|
||||||
|
const int k_fmbSteps = 5;
|
||||||
|
const int k_superSampleCount = 10;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const int k_fmbWaterSteps = 4;
|
||||||
|
|
||||||
|
#define OBJ_ID_SKY 0.0
|
||||||
|
#define OBJ_ID_GROUND 1.0
|
||||||
|
|
||||||
|
float g_fTime;
|
||||||
|
|
||||||
|
const vec3 g_vSunDir = vec3( -1.0, 0.7, 0.25 );
|
||||||
|
vec3 GetSunDir() { return normalize( g_vSunDir ); }
|
||||||
|
|
||||||
|
const vec3 g_sunColour = vec3( 1.0, 0.85, 0.5 ) * 5.0;
|
||||||
|
const vec3 g_skyColour = vec3( 0.1, 0.5, 1.0 ) * 1.0;
|
||||||
|
|
||||||
|
const vec3 k_bgSkyColourUp = g_skyColour * 4.0;
|
||||||
|
const vec3 k_bgSkyColourDown = g_skyColour * 6.0;
|
||||||
|
|
||||||
|
const vec3 k_envFloorColor = vec3(0.3, 0.2, 0.2);
|
||||||
|
|
||||||
|
const vec3 k_vFogExt = vec3(0.01, 0.015, 0.015) * 3.0;
|
||||||
|
const vec3 k_vFogIn = vec3(1.0, 0.9, 0.8) * 0.015;
|
||||||
|
|
||||||
|
|
||||||
|
const float k_fFarClip = 20.0;
|
||||||
|
|
||||||
|
#define MOD2 vec2(4.438975,3.972973)
|
||||||
|
|
||||||
|
float Hash( float p )
|
||||||
|
{
|
||||||
|
// https://www.shadertoy.com/view/4djSRW - Dave Hoskins
|
||||||
|
vec2 p2 = fract(vec2(p) * MOD2);
|
||||||
|
p2 += dot(p2.yx, p2.xy+19.19);
|
||||||
|
return fract(p2.x * p2.y);
|
||||||
|
//return fract(sin(n)*43758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
float SmoothNoise(in vec2 o)
|
||||||
|
{
|
||||||
|
vec2 p = floor(o);
|
||||||
|
vec2 f = fract(o);
|
||||||
|
|
||||||
|
float n = p.x + p.y*57.0;
|
||||||
|
|
||||||
|
float a = Hash(n+ 0.0);
|
||||||
|
float b = Hash(n+ 1.0);
|
||||||
|
float c = Hash(n+ 57.0);
|
||||||
|
float d = Hash(n+ 58.0);
|
||||||
|
|
||||||
|
vec2 f2 = f * f;
|
||||||
|
vec2 f3 = f2 * f;
|
||||||
|
|
||||||
|
vec2 t = 3.0 * f2 - 2.0 * f3;
|
||||||
|
|
||||||
|
float u = t.x;
|
||||||
|
float v = t.y;
|
||||||
|
|
||||||
|
float res = a + (b-a)*u +(c-a)*v + (a-b+d-c)*u*v;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FBM( vec2 p, float ps ) {
|
||||||
|
float f = 0.0;
|
||||||
|
float tot = 0.0;
|
||||||
|
float a = 1.0;
|
||||||
|
for( int i=0; i<k_fmbSteps; i++)
|
||||||
|
{
|
||||||
|
f += SmoothNoise( p ) * a;
|
||||||
|
p *= 2.0;
|
||||||
|
tot += a;
|
||||||
|
a *= ps;
|
||||||
|
}
|
||||||
|
return f / tot;
|
||||||
|
}
|
||||||
|
|
||||||
|
float FBM_Simple( vec2 p, float ps ) {
|
||||||
|
float f = 0.0;
|
||||||
|
float tot = 0.0;
|
||||||
|
float a = 1.0;
|
||||||
|
for( int i=0; i<3; i++)
|
||||||
|
{
|
||||||
|
f += SmoothNoise( p ) * a;
|
||||||
|
p *= 2.0;
|
||||||
|
tot += a;
|
||||||
|
a *= ps;
|
||||||
|
}
|
||||||
|
return f / tot;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 SmoothNoise_DXY(in vec2 o)
|
||||||
|
{
|
||||||
|
vec2 p = floor(o);
|
||||||
|
vec2 f = fract(o);
|
||||||
|
|
||||||
|
float n = p.x + p.y*57.0;
|
||||||
|
|
||||||
|
float a = Hash(n+ 0.0);
|
||||||
|
float b = Hash(n+ 1.0);
|
||||||
|
float c = Hash(n+ 57.0);
|
||||||
|
float d = Hash(n+ 58.0);
|
||||||
|
|
||||||
|
vec2 f2 = f * f;
|
||||||
|
vec2 f3 = f2 * f;
|
||||||
|
|
||||||
|
vec2 t = 3.0 * f2 - 2.0 * f3;
|
||||||
|
vec2 dt = 6.0 * f - 6.0 * f2;
|
||||||
|
|
||||||
|
float u = t.x;
|
||||||
|
float v = t.y;
|
||||||
|
float du = dt.x;
|
||||||
|
float dv = dt.y;
|
||||||
|
|
||||||
|
float res = a + (b-a)*u +(c-a)*v + (a-b+d-c)*u*v;
|
||||||
|
|
||||||
|
float dx = (b-a)*du + (a-b+d-c)*du*v;
|
||||||
|
float dy = (c-a)*dv + (a-b+d-c)*u*dv;
|
||||||
|
|
||||||
|
return vec3(dx, dy, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 FBM_DXY( vec2 p, vec2 flow, float ps, float df ) {
|
||||||
|
vec3 f = vec3(0.0);
|
||||||
|
float tot = 0.0;
|
||||||
|
float a = 1.0;
|
||||||
|
//flow *= 0.6;
|
||||||
|
for( int i=0; i<k_fmbWaterSteps; i++)
|
||||||
|
{
|
||||||
|
p += flow;
|
||||||
|
flow *= -0.75; // modify flow for each octave - negating this is fun
|
||||||
|
vec3 v = SmoothNoise_DXY( p );
|
||||||
|
f += v * a;
|
||||||
|
p += v.xy * df;
|
||||||
|
p *= 2.0;
|
||||||
|
tot += a;
|
||||||
|
a *= ps;
|
||||||
|
}
|
||||||
|
return f / tot;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetRiverMeander( const float x )
|
||||||
|
{
|
||||||
|
return sin(x * 0.3) * 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetRiverMeanderDx( const float x )
|
||||||
|
{
|
||||||
|
return cos(x * 0.3) * 1.5 * 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetRiverBedOffset( const vec3 vPos )
|
||||||
|
{
|
||||||
|
float fRiverBedDepth = 0.3 + (0.5 + 0.5 * sin( vPos.x * 0.001 + 3.0)) * 0.4;
|
||||||
|
float fRiverBedWidth = 2.0 + cos( vPos.x * 0.1 ) * 1.0;;
|
||||||
|
|
||||||
|
float fRiverBedAmount = smoothstep( fRiverBedWidth, fRiverBedWidth * 0.5, abs(vPos.z - GetRiverMeander(vPos.x)) );
|
||||||
|
|
||||||
|
return fRiverBedAmount * fRiverBedDepth;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetTerrainHeight( const vec3 vPos )
|
||||||
|
{
|
||||||
|
float fbm = FBM( vPos.xz * vec2(0.5, 1.0), 0.5 );
|
||||||
|
float fTerrainHeight = fbm * fbm;
|
||||||
|
|
||||||
|
fTerrainHeight -= GetRiverBedOffset(vPos);
|
||||||
|
|
||||||
|
return fTerrainHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetTerrainHeightSimple( const vec3 vPos )
|
||||||
|
{
|
||||||
|
float fbm = FBM_Simple( vPos.xz * vec2(0.5, 1.0), 0.5 );
|
||||||
|
float fTerrainHeight = fbm * fbm;
|
||||||
|
|
||||||
|
fTerrainHeight -= GetRiverBedOffset(vPos);
|
||||||
|
|
||||||
|
return fTerrainHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float GetSceneDistance( const vec3 vPos )
|
||||||
|
{
|
||||||
|
return vPos.y - GetTerrainHeight( vPos );
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetFlowDistance( const vec2 vPos )
|
||||||
|
{
|
||||||
|
return -GetTerrainHeightSimple( vec3( vPos.x, 0.0, vPos.y ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 GetBaseFlow( const vec2 vPos )
|
||||||
|
{
|
||||||
|
return vec2( 1.0, GetRiverMeanderDx(vPos.x) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 GetGradient( const vec2 vPos )
|
||||||
|
{
|
||||||
|
vec2 vDelta = vec2(0.01, 0.00);
|
||||||
|
float dx = GetFlowDistance( vPos + vDelta.xy ) - GetFlowDistance( vPos - vDelta.xy );
|
||||||
|
float dy = GetFlowDistance( vPos + vDelta.yx ) - GetFlowDistance( vPos - vDelta.yx );
|
||||||
|
return vec2( dx, dy );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetFlowRate( const vec2 vPos )
|
||||||
|
{
|
||||||
|
vec2 vBaseFlow = GetBaseFlow( vPos );
|
||||||
|
|
||||||
|
vec2 vFlow = vBaseFlow;
|
||||||
|
|
||||||
|
float fFoam = 0.0;
|
||||||
|
|
||||||
|
float fDepth = -GetTerrainHeightSimple( vec3(vPos.x, 0.0, vPos.y) );
|
||||||
|
float fDist = GetFlowDistance( vPos );
|
||||||
|
vec2 vGradient = GetGradient( vPos );
|
||||||
|
|
||||||
|
vFlow += -vGradient * 40.0 / (1.0 + fDist * 1.5);
|
||||||
|
vFlow *= 1.0 / (1.0 + fDist * 0.5);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
float fBehindObstacle = 0.5 - dot( normalize(vGradient), -normalize(vFlow)) * 0.5;
|
||||||
|
float fSlowDist = clamp( fDepth * 5.0, 0.0, 1.0);
|
||||||
|
fSlowDist = mix(fSlowDist * 0.9 + 0.1, 1.0, fBehindObstacle * 0.9);
|
||||||
|
//vFlow += vGradient * 10.0 * (1.0 - fSlowDist);
|
||||||
|
fSlowDist = 0.5 + fSlowDist * 0.5;
|
||||||
|
vFlow *= fSlowDist;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float fFoamScale1 =0.5;
|
||||||
|
float fFoamCutoff = 0.4;
|
||||||
|
float fFoamScale2 = 0.35;
|
||||||
|
|
||||||
|
fFoam = abs(length( vFlow )) * fFoamScale1;// - length( vBaseFlow ));
|
||||||
|
fFoam += clamp( fFoam - fFoamCutoff, 0.0, 1.0 );
|
||||||
|
//fFoam = fFoam* fFoam;
|
||||||
|
fFoam = 1.0 - pow( fDist, fFoam * fFoamScale2 );
|
||||||
|
//fFoam = fFoam / fDist;
|
||||||
|
return vec3( vFlow * 0.6, fFoam );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 SampleWaterNormal( vec2 vUV, vec2 vFlowOffset, float fMag, float fFoam )
|
||||||
|
{
|
||||||
|
vec2 vFilterWidth = max(abs(dFdx(vUV)), abs(dFdy(vUV)));
|
||||||
|
float fFilterWidth= max(vFilterWidth.x, vFilterWidth.y);
|
||||||
|
|
||||||
|
float fScale = (1.0 / (1.0 + fFilterWidth * fFilterWidth * 2000.0));
|
||||||
|
float fGradientAscent = 0.25 + (fFoam * -1.5);
|
||||||
|
vec3 dxy = FBM_DXY(vUV * 20.0, vFlowOffset * 20.0, 0.75 + fFoam * 0.25, fGradientAscent);
|
||||||
|
fScale *= max(0.25, 1.0 - fFoam * 5.0); // flatten normal in foam
|
||||||
|
vec3 vBlended = mix( vec3(0.0, 1.0, 0.0), normalize( vec3(dxy.x, fMag, dxy.y) ), fScale );
|
||||||
|
return vec4( normalize( vBlended ), dxy.z * fScale );
|
||||||
|
}
|
||||||
|
|
||||||
|
float SampleWaterFoam( vec2 vUV, vec2 vFlowOffset, float fFoam )
|
||||||
|
{
|
||||||
|
float f = FBM_DXY(vUV * 30.0, vFlowOffset * 50.0, 0.8, -0.5 ).z;
|
||||||
|
float fAmount = 0.2;
|
||||||
|
f = max( 0.0, (f - fAmount) / fAmount );
|
||||||
|
return pow( 0.5, f );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec4 SampleFlowingNormal( const vec2 vUV, const vec2 vFlowRate, const float fFoam, const float time, out float fOutFoamTex )
|
||||||
|
{
|
||||||
|
float fMag = 2.5 / (1.0 + dot( vFlowRate, vFlowRate ) * 5.0);
|
||||||
|
float t0 = fract( time );
|
||||||
|
float t1 = fract( time + 0.5 );
|
||||||
|
|
||||||
|
float o0 = t0 - 0.5;
|
||||||
|
float o1 = t1 - 0.5;
|
||||||
|
|
||||||
|
vec4 sample0 = SampleWaterNormal( vUV, vFlowRate * o0, fMag, fFoam );
|
||||||
|
vec4 sample1 = SampleWaterNormal( vUV, vFlowRate * o1, fMag, fFoam );
|
||||||
|
|
||||||
|
float weight = abs( t0 - 0.5 ) * 2.0;
|
||||||
|
//weight = smoothstep( 0.0, 1.0, weight );
|
||||||
|
|
||||||
|
float foam0 = SampleWaterFoam( vUV, vFlowRate * o0 * 0.25, fFoam );
|
||||||
|
float foam1 = SampleWaterFoam( vUV, vFlowRate * o1 * 0.25, fFoam );
|
||||||
|
|
||||||
|
vec4 result= mix( sample0, sample1, weight );
|
||||||
|
result.xyz = normalize(result.xyz);
|
||||||
|
|
||||||
|
fOutFoamTex = mix( foam0, foam1, weight );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 GetWindowCoord( const in vec2 vUV )
|
||||||
|
{
|
||||||
|
vec2 vWindow = vUV * 2.0 - 1.0;
|
||||||
|
vWindow.x *= iResolution.x / iResolution.y;
|
||||||
|
|
||||||
|
return vWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetCameraRayDir( const in vec2 vWindow, const in vec3 vCameraPos, const in vec3 vCameraTarget )
|
||||||
|
{
|
||||||
|
vec3 vForward = normalize(vCameraTarget - vCameraPos);
|
||||||
|
vec3 vRight = normalize(cross(vec3(0.0, 1.0, 0.0), vForward));
|
||||||
|
vec3 vUp = normalize(cross(vForward, vRight));
|
||||||
|
|
||||||
|
vec3 vDir = normalize(vWindow.x * vRight + vWindow.y * vUp + vForward * 2.0);
|
||||||
|
|
||||||
|
return vDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ApplyVignetting( const in vec2 vUV, const in vec3 vInput )
|
||||||
|
{
|
||||||
|
vec2 vOffset = (vUV - 0.5) * sqrt(2.0);
|
||||||
|
|
||||||
|
float fDist = dot(vOffset, vOffset);
|
||||||
|
|
||||||
|
const float kStrength = 0.8;
|
||||||
|
|
||||||
|
float fShade = mix( 1.0, 1.0 - kStrength, fDist );
|
||||||
|
|
||||||
|
return vInput * fShade;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Tonemap( vec3 x )
|
||||||
|
{
|
||||||
|
float a = 0.010;
|
||||||
|
float b = 0.132;
|
||||||
|
float c = 0.010;
|
||||||
|
float d = 0.163;
|
||||||
|
float e = 0.101;
|
||||||
|
|
||||||
|
return ( x * ( a * x + b ) ) / ( x * ( c * x + d ) + e );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Intersection
|
||||||
|
{
|
||||||
|
float m_dist;
|
||||||
|
float m_objId;
|
||||||
|
vec3 m_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
void RaymarchScene( vec3 vRayOrigin, vec3 vRayDir, out Intersection intersection )
|
||||||
|
{
|
||||||
|
float stepScale = 1.0;
|
||||||
|
#ifdef ENABLE_CONE_STEPPING
|
||||||
|
vec2 vRayProfile = vec2( sqrt(dot(vRayDir.xz, vRayDir.xz) ), vRayDir.y );
|
||||||
|
vec2 vGradVec = normalize( vec2( 1.0, 2.0 ) ); // represents the biggest gradient in our heightfield
|
||||||
|
vec2 vGradPerp = vec2( vGradVec.y, -vGradVec.x );
|
||||||
|
|
||||||
|
float fRdotG = dot( vRayProfile, vGradPerp );
|
||||||
|
float fOdotG = dot( vec2(0.0, 1.0), vGradPerp );
|
||||||
|
|
||||||
|
stepScale = -fOdotG / fRdotG;
|
||||||
|
|
||||||
|
if ( stepScale < 0.0 )
|
||||||
|
{
|
||||||
|
intersection.m_objId = OBJ_ID_SKY;
|
||||||
|
intersection.m_dist = k_fFarClip;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
intersection.m_dist = 0.01;
|
||||||
|
intersection.m_objId = OBJ_ID_SKY;
|
||||||
|
|
||||||
|
float fSceneDist = 0.0;
|
||||||
|
|
||||||
|
float oldT = 0.01;
|
||||||
|
for( int iter = 0; iter < k_raymarchSteps; iter++ )
|
||||||
|
{
|
||||||
|
vec3 vPos = vRayOrigin + vRayDir * intersection.m_dist;
|
||||||
|
|
||||||
|
// into sky - early out
|
||||||
|
if ( vRayDir.y > 0.0 )
|
||||||
|
{
|
||||||
|
if( vPos.y > 1.0 )
|
||||||
|
{
|
||||||
|
intersection.m_objId = OBJ_ID_SKY;
|
||||||
|
intersection.m_dist = k_fFarClip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fSceneDist = GetSceneDistance( vPos );
|
||||||
|
|
||||||
|
oldT = intersection.m_dist;
|
||||||
|
intersection.m_dist += fSceneDist * stepScale;
|
||||||
|
|
||||||
|
intersection.m_objId = OBJ_ID_GROUND;
|
||||||
|
if ( fSceneDist <= 0.01 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( intersection.m_dist > k_fFarClip )
|
||||||
|
{
|
||||||
|
intersection.m_objId = OBJ_ID_SKY;
|
||||||
|
intersection.m_dist = k_fFarClip;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection.m_pos = vRayOrigin + vRayDir * intersection.m_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetSceneNormal(const in vec3 vPos)
|
||||||
|
{
|
||||||
|
const float fDelta = 0.001;
|
||||||
|
|
||||||
|
vec3 vDir1 = vec3( 1.0, 0.0, -1.0);
|
||||||
|
vec3 vDir2 = vec3(-1.0, 0.0, 1.0);
|
||||||
|
vec3 vDir3 = vec3(-1.0, 0.0, -1.0);
|
||||||
|
|
||||||
|
vec3 vOffset1 = vDir1 * fDelta;
|
||||||
|
vec3 vOffset2 = vDir2 * fDelta;
|
||||||
|
vec3 vOffset3 = vDir3 * fDelta;
|
||||||
|
|
||||||
|
vec3 vPos1 = vPos + vOffset1;
|
||||||
|
vec3 vPos2 = vPos + vOffset2;
|
||||||
|
vec3 vPos3 = vPos + vOffset3;
|
||||||
|
|
||||||
|
float f1 = GetSceneDistance( vPos1 );
|
||||||
|
float f2 = GetSceneDistance( vPos2 );
|
||||||
|
float f3 = GetSceneDistance( vPos3 );
|
||||||
|
|
||||||
|
vPos1.y -= f1;
|
||||||
|
vPos2.y -= f2;
|
||||||
|
vPos3.y -= f3;
|
||||||
|
|
||||||
|
vec3 vNormal = cross( vPos1 - vPos2, vPos3 - vPos2 );
|
||||||
|
|
||||||
|
return normalize( vNormal );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TraceWater( vec3 vRayOrigin, vec3 vRayDir, out Intersection intersection )
|
||||||
|
{
|
||||||
|
intersection.m_dist = k_fFarClip;
|
||||||
|
|
||||||
|
float t = -vRayOrigin.y / vRayDir.y;
|
||||||
|
if ( t > 0.0 )
|
||||||
|
{
|
||||||
|
intersection.m_dist = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
intersection.m_pos = vRayOrigin + vRayDir * intersection.m_dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Surface
|
||||||
|
{
|
||||||
|
vec3 m_pos;
|
||||||
|
vec3 m_normal;
|
||||||
|
vec3 m_albedo;
|
||||||
|
vec3 m_specR0;
|
||||||
|
float m_gloss;
|
||||||
|
float m_specScale;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef ENABLE_NIMITZ_TRIANGLE_NOISE
|
||||||
|
// https://www.shadertoy.com/view/4ts3z2
|
||||||
|
|
||||||
|
float tri(in float x){return abs(fract(x)-.5);}
|
||||||
|
vec3 tri3(in vec3 p){return vec3( tri(p.z+tri(p.y)), tri(p.z+tri(p.x)), tri(p.y+tri(p.x)));}
|
||||||
|
|
||||||
|
float triNoise(in vec3 p)
|
||||||
|
{
|
||||||
|
float z=1.4;
|
||||||
|
float rz = 0.;
|
||||||
|
vec3 bp = p;
|
||||||
|
for (float i=0.; i<=4.; i++ )
|
||||||
|
{
|
||||||
|
vec3 dg = tri3(bp*2.);
|
||||||
|
p += dg;
|
||||||
|
|
||||||
|
bp *= 1.8;
|
||||||
|
z *= 1.5;
|
||||||
|
p *= 1.2;
|
||||||
|
|
||||||
|
rz+= (tri(p.z+tri(p.x+tri(p.y))))/z;
|
||||||
|
bp += 0.14;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void GetSurfaceInfo( Intersection intersection, out Surface surface )
|
||||||
|
{
|
||||||
|
surface.m_pos = intersection.m_pos;
|
||||||
|
surface.m_normal = GetSceneNormal(intersection.m_pos);
|
||||||
|
|
||||||
|
#ifdef ENABLE_NIMITZ_TRIANGLE_NOISE
|
||||||
|
vec3 vNoisePos = surface.m_pos * vec3(0.4, 0.3, 1.0);
|
||||||
|
surface.m_normal = normalize(surface.m_normal +triNoise(vNoisePos));
|
||||||
|
float fNoise = triNoise(vNoisePos);
|
||||||
|
fNoise = pow( fNoise, 0.15);
|
||||||
|
surface.m_albedo = mix(vec3(.7,.8,.95), vec3(.1, .1,.05), fNoise );
|
||||||
|
#else
|
||||||
|
#if 0
|
||||||
|
surface.m_albedo = texture( iChannel0, intersection.m_pos.xz ).rgb;
|
||||||
|
surface.m_albedo = surface.m_albedo * surface.m_albedo;
|
||||||
|
#else
|
||||||
|
vec3 vWeights = surface.m_normal * surface.m_normal;
|
||||||
|
vec3 col = vec3(0.0);
|
||||||
|
vec3 _sample;
|
||||||
|
_sample = texture( iChannel0, intersection.m_pos.xz ).rgb;
|
||||||
|
col += _sample * _sample * vWeights.y;
|
||||||
|
_sample = texture( iChannel0, intersection.m_pos.xy ).rgb;
|
||||||
|
col += _sample * _sample * vWeights.z;
|
||||||
|
_sample = texture( iChannel0, intersection.m_pos.yz ).rgb;
|
||||||
|
col += _sample * _sample * vWeights.x;
|
||||||
|
col /= vWeights.x + vWeights.y + vWeights.z;
|
||||||
|
surface.m_albedo = col;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
surface.m_specR0 = vec3(0.001);
|
||||||
|
surface.m_gloss = 0.0;
|
||||||
|
surface.m_specScale = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GIV( float dotNV, float k)
|
||||||
|
{
|
||||||
|
return 1.0 / ((dotNV + 0.0001) * (1.0 - k)+k);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetSunShadow( const vec3 vPos )
|
||||||
|
{
|
||||||
|
vec3 vSunDir = GetSunDir();
|
||||||
|
|
||||||
|
Intersection shadowInt;
|
||||||
|
float k_fShadowDist = 2.0;
|
||||||
|
RaymarchScene( vPos + vSunDir * k_fShadowDist, -vSunDir, shadowInt );
|
||||||
|
|
||||||
|
float fShadowFactor = 1.0;
|
||||||
|
if( shadowInt.m_dist < (k_fShadowDist - 0.1) )
|
||||||
|
{
|
||||||
|
fShadowFactor = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fShadowFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSunLight( Surface surf, const vec3 vViewDir, const float fShadowFactor, inout vec3 vDiffuse, inout vec3 vSpecular )
|
||||||
|
{
|
||||||
|
vec3 vSunDir = GetSunDir();
|
||||||
|
|
||||||
|
vec3 vH = normalize( vViewDir + vSunDir );
|
||||||
|
float fNdotL = clamp(dot(GetSunDir(), surf.m_normal), 0.0, 1.0);
|
||||||
|
float fNdotV = clamp(dot(vViewDir, surf.m_normal), 0.0, 1.0);
|
||||||
|
float fNdotH = clamp(dot(surf.m_normal, vH), 0.0, 1.0);
|
||||||
|
|
||||||
|
float diffuseIntensity = fNdotL;
|
||||||
|
|
||||||
|
vDiffuse += g_sunColour * diffuseIntensity * fShadowFactor;
|
||||||
|
//vDiffuse = fShadowFactor * vec3(100.0);
|
||||||
|
|
||||||
|
float alpha = 1.0 - surf.m_gloss;
|
||||||
|
// D
|
||||||
|
|
||||||
|
float alphaSqr = alpha * alpha;
|
||||||
|
float pi = 3.14159;
|
||||||
|
float denom = fNdotH * fNdotH * (alphaSqr - 1.0) + 1.0;
|
||||||
|
float d = alphaSqr / (pi * denom * denom);
|
||||||
|
|
||||||
|
float k = alpha / 2.0;
|
||||||
|
float vis = GIV(fNdotL, k) * GIV(fNdotV, k);
|
||||||
|
|
||||||
|
float fSpecularIntensity = d * vis * fNdotL;
|
||||||
|
vSpecular += g_sunColour * fSpecularIntensity * fShadowFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddSkyLight( Surface surf, inout vec3 vDiffuse, inout vec3 vSpecular )
|
||||||
|
{
|
||||||
|
float skyIntensity = max( 0.0, surf.m_normal.y * 0.3 + 0.7 );
|
||||||
|
vDiffuse += g_skyColour * skyIntensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetFresnel( vec3 vView, vec3 vNormal, vec3 vR0, float fGloss )
|
||||||
|
{
|
||||||
|
float NdotV = max( 0.0, dot( vView, vNormal ) );
|
||||||
|
|
||||||
|
return vR0 + (vec3(1.0) - vR0) * pow( 1.0 - NdotV, 5.0 ) * pow( fGloss, 20.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetWaterExtinction( float dist )
|
||||||
|
{
|
||||||
|
float fOpticalDepth = dist * 6.0;
|
||||||
|
|
||||||
|
vec3 vExtinctCol = 1.0 - vec3(0.5, 0.4, 0.1);
|
||||||
|
vec3 vExtinction = exp2( -fOpticalDepth * vExtinctCol );
|
||||||
|
|
||||||
|
return vExtinction;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetSkyColour( vec3 vRayDir )
|
||||||
|
{
|
||||||
|
vec3 vSkyColour = mix( k_bgSkyColourDown, k_bgSkyColourUp, clamp( vRayDir.y, 0.0, 1.0 ) );
|
||||||
|
float fSunDotV = dot(GetSunDir(), vRayDir);
|
||||||
|
float fDirDot = clamp(fSunDotV * 0.5 + 0.5, 0.0, 1.0);
|
||||||
|
vSkyColour += g_sunColour * (1.0 - exp2(fDirDot * -0.5)) * 2.0;
|
||||||
|
|
||||||
|
return vSkyColour;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetEnvColour( vec3 vRayDir, float fGloss )
|
||||||
|
{
|
||||||
|
return mix( k_envFloorColor, k_bgSkyColourUp, clamp( vRayDir.y * (1.0 - fGloss * 0.5) * 0.5 + 0.5, 0.0, 1.0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 GetRayColour( const in vec3 vRayOrigin, const in vec3 vRayDir, out Intersection intersection )
|
||||||
|
{
|
||||||
|
RaymarchScene( vRayOrigin, vRayDir, intersection );
|
||||||
|
|
||||||
|
if ( intersection.m_objId == OBJ_ID_SKY )
|
||||||
|
{
|
||||||
|
return GetSkyColour( vRayDir );
|
||||||
|
}
|
||||||
|
|
||||||
|
Surface surface;
|
||||||
|
GetSurfaceInfo( intersection, surface );
|
||||||
|
|
||||||
|
vec3 vIgnore = vec3(0.0);
|
||||||
|
vec3 vResult = vec3(0.0);
|
||||||
|
float fSunShadow = 1.0;
|
||||||
|
AddSunLight( surface, -vRayDir, fSunShadow, vResult, vIgnore );
|
||||||
|
AddSkyLight( surface, vResult, vIgnore);
|
||||||
|
return vResult * surface.m_albedo;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetRayColour( const in vec3 vRayOrigin, const in vec3 vRayDir )
|
||||||
|
{
|
||||||
|
Intersection intersection;
|
||||||
|
return GetRayColour( vRayOrigin, vRayDir, intersection );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 GetSceneColour( const in vec3 vRayOrigin, const in vec3 vRayDir )
|
||||||
|
{
|
||||||
|
Intersection primaryInt;
|
||||||
|
RaymarchScene( vRayOrigin, vRayDir, primaryInt );
|
||||||
|
|
||||||
|
float fFogDistance = 0.0;
|
||||||
|
vec3 vResult = vec3( 0.0 );
|
||||||
|
|
||||||
|
float fSunDotV = dot(GetSunDir(), vRayDir);
|
||||||
|
|
||||||
|
if ( primaryInt.m_objId == OBJ_ID_SKY )
|
||||||
|
{
|
||||||
|
vResult = GetSkyColour( vRayDir );
|
||||||
|
fFogDistance = k_fFarClip;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Intersection waterInt;
|
||||||
|
TraceWater( vRayOrigin, vRayDir, waterInt );
|
||||||
|
|
||||||
|
vec3 vReflectRayOrigin;
|
||||||
|
vec3 vSpecNormal;
|
||||||
|
vec3 vTransmitLight;
|
||||||
|
|
||||||
|
Surface specSurface;
|
||||||
|
vec3 vSpecularLight = vec3(0.0);
|
||||||
|
|
||||||
|
#ifdef ENABLE_WATER
|
||||||
|
vec3 vFlowRateAndFoam = GetFlowRate( waterInt.m_pos.xz );
|
||||||
|
vec2 vFlowRate = vFlowRateAndFoam.xy;
|
||||||
|
#ifdef ENABLE_FOAM
|
||||||
|
float fFoam = vFlowRateAndFoam.z;
|
||||||
|
float fFoamScale = 1.5;
|
||||||
|
float fFoamOffset = 0.2;
|
||||||
|
fFoam = clamp( (fFoam - fFoamOffset) * fFoamScale, 0.0, 1.0 );
|
||||||
|
fFoam = fFoam * fFoam * 0.5;
|
||||||
|
#else
|
||||||
|
float fFoam = 0.0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float fWaterFoamTex = 1.0;
|
||||||
|
vec4 vWaterNormalAndHeight = SampleFlowingNormal( waterInt.m_pos.xz, vFlowRate, fFoam, g_fTime, fWaterFoamTex );
|
||||||
|
|
||||||
|
if( vRayDir.y < -0.01 )
|
||||||
|
{
|
||||||
|
// lie about the water intersection depth
|
||||||
|
waterInt.m_dist -= (0.04 * (1.0 - vWaterNormalAndHeight.w) / vRayDir.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( waterInt.m_dist < primaryInt.m_dist )
|
||||||
|
{
|
||||||
|
fFogDistance = waterInt.m_dist;
|
||||||
|
vec3 vWaterNormal = vWaterNormalAndHeight.xyz;
|
||||||
|
|
||||||
|
vReflectRayOrigin = waterInt.m_pos;
|
||||||
|
vSpecNormal = vWaterNormal;
|
||||||
|
|
||||||
|
vec3 vRefractRayOrigin = waterInt.m_pos;
|
||||||
|
vec3 vRefractRayDir = refract( vRayDir, vWaterNormal, 1.0 / 1.3333 );
|
||||||
|
|
||||||
|
Intersection refractInt;
|
||||||
|
vec3 vRefractLight = GetRayColour( vRefractRayOrigin, vRefractRayDir, refractInt ); // note : dont need sky
|
||||||
|
|
||||||
|
float fEdgeAlpha = clamp( (1.0 + vWaterNormalAndHeight.w * 0.25) - refractInt.m_dist * 10.0, 0.0, 1.0 );
|
||||||
|
fFoam *= 1.0 - fEdgeAlpha;
|
||||||
|
|
||||||
|
// add extra extinction for the light travelling to the point underwater
|
||||||
|
vec3 vExtinction = GetWaterExtinction( refractInt.m_dist + abs( refractInt.m_pos.y ) );
|
||||||
|
|
||||||
|
specSurface.m_pos = waterInt.m_pos;
|
||||||
|
specSurface.m_normal = normalize( vWaterNormal + GetSunDir() * fFoam ); // would rather have SSS for foam
|
||||||
|
specSurface.m_albedo = vec3(1.0);
|
||||||
|
specSurface.m_specR0 = vec3( 0.01, 0.01, 0.01 );
|
||||||
|
|
||||||
|
vec2 vFilterWidth = max(abs(dFdx(waterInt.m_pos.xz)), abs(dFdy(waterInt.m_pos.xz)));
|
||||||
|
float fFilterWidth= max(vFilterWidth.x, vFilterWidth.y);
|
||||||
|
float fGlossFactor = exp2( -fFilterWidth * 0.3 );
|
||||||
|
specSurface.m_gloss = 0.99 * fGlossFactor;
|
||||||
|
specSurface.m_specScale = 1.0;
|
||||||
|
|
||||||
|
vec3 vSurfaceDiffuse = vec3(0.0);
|
||||||
|
|
||||||
|
float fSunShadow = 1.0;
|
||||||
|
#ifdef ENABLE_WATER_RECEIVE_SHADOW
|
||||||
|
fSunShadow = GetSunShadow( waterInt.m_pos );
|
||||||
|
#endif
|
||||||
|
AddSunLight( specSurface, -vRayDir, fSunShadow, vSurfaceDiffuse, vSpecularLight);
|
||||||
|
AddSkyLight( specSurface, vSurfaceDiffuse, vSpecularLight);
|
||||||
|
|
||||||
|
vec3 vInscatter = vSurfaceDiffuse * (1.0 - exp( -refractInt.m_dist * 0.1 )) * (1.0 + fSunDotV);
|
||||||
|
vTransmitLight = vRefractLight.rgb;
|
||||||
|
vTransmitLight += vInscatter;
|
||||||
|
vTransmitLight *= vExtinction;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef ENABLE_FOAM
|
||||||
|
float fFoamBlend = 1.0 - pow( fWaterFoamTex, fFoam * 5.0);// * (1.0 - fWaterFoamTex));
|
||||||
|
vTransmitLight = mix(vTransmitLight, vSurfaceDiffuse * 0.8, fFoamBlend );
|
||||||
|
specSurface.m_specScale = clamp(1.0 - fFoamBlend * 4.0, 0.0, 1.0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif // #ifdef ENABLE_WATER
|
||||||
|
{
|
||||||
|
fFogDistance = primaryInt.m_dist;
|
||||||
|
|
||||||
|
Surface primarySurface;
|
||||||
|
GetSurfaceInfo( primaryInt, primarySurface );
|
||||||
|
|
||||||
|
vSpecNormal = primarySurface.m_normal;
|
||||||
|
vReflectRayOrigin = primaryInt.m_pos;
|
||||||
|
|
||||||
|
float fWetness = 1.0 - clamp( (vReflectRayOrigin.y + 0.025) * 5.0, 0.0, 1.0);
|
||||||
|
primarySurface.m_gloss = mix( primarySurface.m_albedo.r, 1.0, fWetness );
|
||||||
|
primarySurface.m_albedo = mix( primarySurface.m_albedo, primarySurface.m_albedo * 0.8, fWetness );
|
||||||
|
|
||||||
|
vTransmitLight = vec3(0.0);
|
||||||
|
float fSunShadow = 1.0;
|
||||||
|
#ifdef ENABLE_LANDSCAPE_RECEIVE_SHADOW
|
||||||
|
fSunShadow = GetSunShadow( primaryInt.m_pos );
|
||||||
|
#endif
|
||||||
|
AddSunLight( primarySurface, -vRayDir, fSunShadow, vTransmitLight, vSpecularLight);
|
||||||
|
AddSkyLight( primarySurface, vTransmitLight, vSpecularLight);
|
||||||
|
vTransmitLight *= primarySurface.m_albedo;
|
||||||
|
specSurface = primarySurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 vReflectRayDir = reflect( vRayDir, vSpecNormal );
|
||||||
|
vec3 vReflectLight = GetRayColour( vReflectRayOrigin, vReflectRayDir );
|
||||||
|
|
||||||
|
vReflectLight = mix( GetEnvColour(vReflectRayDir, specSurface.m_gloss), vReflectLight, pow( specSurface.m_gloss, 40.0) );
|
||||||
|
|
||||||
|
vec3 vFresnel = GetFresnel( -vRayDir, vSpecNormal, specSurface.m_specR0, specSurface.m_gloss );
|
||||||
|
|
||||||
|
vSpecularLight += vReflectLight;
|
||||||
|
vResult = mix(vTransmitLight, vSpecularLight, vFresnel * specSurface.m_specScale );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ( fFogDistance >= k_fFarClip )
|
||||||
|
{
|
||||||
|
fFogDistance = 100.0;
|
||||||
|
vResult = smoothstep( 0.9995, 0.9999, fSunDotV ) * g_sunColour * 200.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 vFogColour = GetSkyColour(vRayDir);
|
||||||
|
|
||||||
|
vec3 vFogExtCol = exp2( k_vFogExt * -fFogDistance );
|
||||||
|
vec3 vFogInCol = exp2( k_vFogIn * -fFogDistance );
|
||||||
|
vResult = vResult*(vFogExtCol) + vFogColour*(1.0-vFogInCol);
|
||||||
|
|
||||||
|
return vResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Code from https://www.shadertoy.com/view/ltlSWf
|
||||||
|
void BlockRender(in vec2 fragCoord)
|
||||||
|
{
|
||||||
|
const float blockRate = 15.0;
|
||||||
|
const float blockSize = 64.0;
|
||||||
|
float frame = floor(iGlobalTime * blockRate);
|
||||||
|
vec2 blockRes = floor(iResolution.xy / blockSize) + vec2(1.0);
|
||||||
|
float blockX = fract(frame / blockRes.x) * blockRes.x;
|
||||||
|
float blockY = fract(floor(frame / blockRes.x) / blockRes.y) * blockRes.y;
|
||||||
|
// Don't draw anything outside the current block.
|
||||||
|
if ((fragCoord.x - blockX * blockSize >= blockSize) ||
|
||||||
|
(fragCoord.x - (blockX - 1.0) * blockSize < blockSize) ||
|
||||||
|
(fragCoord.y - blockY * blockSize >= blockSize) ||
|
||||||
|
(fragCoord.y - (blockY - 1.0) * blockSize < blockSize))
|
||||||
|
{
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
g_fTime = iGlobalTime;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SCREENSHOT_MODE
|
||||||
|
BlockRender( fragCoord.xy );
|
||||||
|
float fBaseTime = k_screenshotTime;
|
||||||
|
#else
|
||||||
|
float fBaseTime = iGlobalTime;
|
||||||
|
#endif
|
||||||
|
g_fTime = fBaseTime;
|
||||||
|
|
||||||
|
float fCameraTime = g_fTime;
|
||||||
|
|
||||||
|
// Static camera locations
|
||||||
|
//fCameraTime = 146.0; // some rocks
|
||||||
|
|
||||||
|
vec2 vUV = fragCoord.xy / iResolution.xy;
|
||||||
|
|
||||||
|
vec3 vCameraTarget = vec3(0.0, -0.5, 0.0);
|
||||||
|
|
||||||
|
vCameraTarget.x -= fCameraTime * 0.5;
|
||||||
|
|
||||||
|
vec3 vCameraPos = vCameraTarget + vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
float fHeading = fCameraTime * 0.1;
|
||||||
|
float fDist = 1.5 - cos(fCameraTime * 0.1 + 2.0) * 0.8;
|
||||||
|
|
||||||
|
if( iMouse.z > 0.0 )
|
||||||
|
{
|
||||||
|
fHeading = iMouse.x * 10.0 / iResolution.x;
|
||||||
|
fDist = 5.0 - iMouse.y * 5.0 / iResolution.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
vCameraPos.y += 1.0 + fDist * fDist * 0.01;
|
||||||
|
|
||||||
|
vCameraPos.x += sin( fHeading ) * fDist;
|
||||||
|
vCameraPos.z += cos( fHeading ) * fDist;
|
||||||
|
|
||||||
|
vCameraTarget.z += GetRiverMeander( vCameraTarget.x );
|
||||||
|
vCameraPos.z += GetRiverMeander( vCameraPos.x );
|
||||||
|
|
||||||
|
vCameraPos.y = max( vCameraPos.y, GetTerrainHeightSimple( vCameraPos ) + 0.2 );
|
||||||
|
|
||||||
|
vec3 vRayOrigin = vCameraPos;
|
||||||
|
vec3 vRayDir = GetCameraRayDir( GetWindowCoord(vUV), vCameraPos, vCameraTarget );
|
||||||
|
|
||||||
|
#ifndef ENABLE_SUPERSAMPLE_MODE
|
||||||
|
vec3 vResult = GetSceneColour(vRayOrigin, vRayDir);
|
||||||
|
#else
|
||||||
|
vec3 vResult = vec3(0.0);
|
||||||
|
float fTot = 0.0;
|
||||||
|
for(int i=0; i<k_superSampleCount; i++)
|
||||||
|
{
|
||||||
|
g_fTime = fBaseTime + (fTot / 10.0) / 30.0;
|
||||||
|
vec3 vCurrRayDir = vRayDir;
|
||||||
|
vec3 vRandom = vec3( SmoothNoise( fragCoord.xy + fTot ),
|
||||||
|
SmoothNoise( fragCoord.yx + fTot + 42.0 ),
|
||||||
|
SmoothNoise( fragCoord.xx + fragCoord.yy + fTot + 42.0 ) ) * 2.0 - 1.0;
|
||||||
|
vRandom = normalize( vRandom );
|
||||||
|
vCurrRayDir += vRandom * 0.001;
|
||||||
|
vCurrRayDir = normalize(vCurrRayDir);
|
||||||
|
vResult += GetSceneColour(vRayOrigin, vCurrRayDir);
|
||||||
|
fTot += 1.0;
|
||||||
|
}
|
||||||
|
vResult /= fTot;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vResult = ApplyVignetting( vUV, vResult );
|
||||||
|
|
||||||
|
vec3 vFinal = Tonemap(vResult * 3.0);
|
||||||
|
|
||||||
|
vFinal = vFinal * 1.1 - 0.1;
|
||||||
|
|
||||||
|
fragColor = vec4(vFinal, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
|
||||||
|
{
|
||||||
|
g_fTime = iGlobalTime;
|
||||||
|
|
||||||
|
fragRayOri = fragRayOri.zyx;
|
||||||
|
fragRayDir = fragRayDir.zyx;
|
||||||
|
|
||||||
|
fragRayOri.z *= -1.0;
|
||||||
|
fragRayDir.z *= -1.0;
|
||||||
|
|
||||||
|
fragRayOri *= 0.1;
|
||||||
|
|
||||||
|
fragRayOri.y += 0.2;
|
||||||
|
|
||||||
|
fragRayOri.x -= g_fTime * 0.1;
|
||||||
|
fragRayOri.z += GetRiverMeander( fragRayOri.x );
|
||||||
|
|
||||||
|
|
||||||
|
vec3 vResult = GetSceneColour(fragRayOri, fragRayDir);
|
||||||
|
|
||||||
|
vec3 vFinal = Tonemap(vResult * 3.0);
|
||||||
|
|
||||||
|
vFinal = vFinal * 1.1 - 0.1;
|
||||||
|
|
||||||
|
fragColor = vec4(vFinal, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
//noise3.jpg
|
||||||
|
//Magnetismic by nimitz (twitter: @stormoid)
|
||||||
|
|
||||||
|
//Getting 60fps here at high quality
|
||||||
|
#define HIGH_QUALITY
|
||||||
|
|
||||||
|
#ifdef HIGH_QUALITY
|
||||||
|
#define STEPS 100
|
||||||
|
#define ALPHA_WEIGHT 0.025
|
||||||
|
#define BASE_STEP 0.05
|
||||||
|
#else
|
||||||
|
#define STEPS 50
|
||||||
|
#define ALPHA_WEIGHT 0.05
|
||||||
|
#define BASE_STEP 0.1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define time iGlobalTime
|
||||||
|
vec2 mo;
|
||||||
|
vec2 rot(in vec2 p, in float a){float c = cos(a), s = sin(a);return p*mat2(c,s,-s,c);}
|
||||||
|
float hash21(in vec2 n){ return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); }
|
||||||
|
float noise(in vec3 p) //iq's ubiquitous 3d noise
|
||||||
|
{
|
||||||
|
vec3 ip = floor(p), f = fract(p);
|
||||||
|
#ifdef HIGH_QUALITY
|
||||||
|
f = f*f*f*(f*(f*6. - 15.) + 10.); //Quintic smoothing
|
||||||
|
#else
|
||||||
|
f = f*f*(3.0-2.0*f); //Cubic smoothing
|
||||||
|
#endif
|
||||||
|
vec2 uv = (ip.xy+vec2(37.0,17.0)*ip.z) + f.xy;
|
||||||
|
vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0.0 ).yx;
|
||||||
|
return mix(rg.x, rg.y, f.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(in vec3 p, in float sr)
|
||||||
|
{
|
||||||
|
p *= 3.5;
|
||||||
|
float rz = 0., z = 1.;
|
||||||
|
for(int i=0;i<4;i++)
|
||||||
|
{
|
||||||
|
float n = noise(p-time*.6);
|
||||||
|
rz += (sin(n*4.4)-.45)*z;
|
||||||
|
z *= .47;
|
||||||
|
p *= 3.5;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 map(in vec3 p)
|
||||||
|
{
|
||||||
|
float dtp = dot(p,p);
|
||||||
|
p = .5*p/(dtp + .2);
|
||||||
|
p.xz = rot(p.xz, p.y*2.5);
|
||||||
|
p.xy = rot(p.xz, p.y*2.);
|
||||||
|
|
||||||
|
float dtp2 = dot(p, p);
|
||||||
|
p = (mo.y + .6)*3.*p/(dtp2 - 5.);
|
||||||
|
float r = clamp(fbm(p, dtp*0.1)*1.5-dtp*(.35-sin(time*0.3)*0.15), 0. ,1.);
|
||||||
|
vec4 col = vec4(.5,1.7,.5,.96)*r;
|
||||||
|
|
||||||
|
float grd = clamp((dtp+.7)*0.4,0.,1.);
|
||||||
|
col.b += grd*.6;
|
||||||
|
col.r -= grd*.5;
|
||||||
|
vec3 lv = mix(p,vec3(0.3),2.);
|
||||||
|
grd = clamp((col.w - fbm(p+lv*.05,1.))*2., 0.01, 1.5 );
|
||||||
|
col.rgb *= vec3(.5, 0.4, .6)*grd + vec3(4.,0.,.4);
|
||||||
|
col.a *= clamp(dtp*2.-1.,0.,1.)*0.07+0.93;
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 vmarch(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
vec4 rz = vec4(0);
|
||||||
|
float t = 2.5;
|
||||||
|
t += 0.03*hash21(gl_FragCoord.xy);
|
||||||
|
for(int i=0; i<STEPS; i++)
|
||||||
|
{
|
||||||
|
if(rz.a > 0.99 || t > 6.)break;
|
||||||
|
vec3 pos = ro + t*rd;
|
||||||
|
vec4 col = map(pos);
|
||||||
|
float den = col.a;
|
||||||
|
col.a *= ALPHA_WEIGHT;
|
||||||
|
col.rgb *= col.a*1.7;
|
||||||
|
rz += col*(1. - rz.a);
|
||||||
|
t += BASE_STEP - den*(BASE_STEP-BASE_STEP*0.015);
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage(out vec4 fragColor, in vec2 fragCoord)
|
||||||
|
{
|
||||||
|
vec2 p = fragCoord.xy/iResolution.xy*2. - 1.;
|
||||||
|
p.x *= iResolution.x/iResolution.y*0.95;
|
||||||
|
mo = 2.0*iMouse.xy/iResolution.xy;
|
||||||
|
mo = (mo==vec2(.0))?mo=vec2(0.5,1.):mo;
|
||||||
|
|
||||||
|
vec3 ro = 4.*normalize(vec3(cos(2.75-2.0*(mo.x+time*0.05)), sin(time*0.22)*0.2, sin(2.75-2.0*(mo.x+time*0.05))));
|
||||||
|
vec3 eye = normalize(vec3(0) - ro);
|
||||||
|
vec3 rgt = normalize(cross(vec3(0,1,0), eye));
|
||||||
|
vec3 up = cross(eye,rgt);
|
||||||
|
vec3 rd = normalize(p.x*rgt + p.y*up + (3.3-sin(time*0.3)*.7)*eye);
|
||||||
|
|
||||||
|
vec4 col = vmarch(ro, rd);
|
||||||
|
fragColor = vec4(col.rgb, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,499 @@
|
||||||
|
// https://www.shadertoy.com/view/XsBSDm
|
||||||
|
|
||||||
|
float g_cw = 15.; // char width in normalized units
|
||||||
|
float g_ch = 30.; // char height in normalized units
|
||||||
|
|
||||||
|
float g_cwb = .6; // character width buffer as a percentage of char width
|
||||||
|
float g_chb = .5; // line buffer as a percentage of char height
|
||||||
|
|
||||||
|
// vertical segment with the bottom of the segment being s
|
||||||
|
// and having length d
|
||||||
|
float vd( vec2 s, float d, vec2 uv )
|
||||||
|
{
|
||||||
|
float t = (d * (uv.y - s.y)) / (d*d);
|
||||||
|
t = clamp(t, 0., 1.);
|
||||||
|
return .1 * length((s + t * vec2(0., d)) - uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// horizontal segment with the left of the segment being s
|
||||||
|
// and having length d
|
||||||
|
float hd( vec2 s, float d, vec2 uv )
|
||||||
|
{
|
||||||
|
float t = (d * (uv.x - s.x)) / (d*d);
|
||||||
|
t = clamp(t, 0., 1.);
|
||||||
|
return .1 * length((s + t * vec2(d, 0.)) - uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// divide the experience into cells.
|
||||||
|
vec2 mod_uv(vec2 uv)
|
||||||
|
{
|
||||||
|
return vec2(mod(uv.x, g_cw * (1. + g_cwb)),
|
||||||
|
mod(uv.y, g_ch * (1. + g_chb)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// ALPHABET
|
||||||
|
float a(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch * .9, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch * .9, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float b(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, hd(vec2(.0, g_ch), g_cw, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .7), g_ch * .3, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch * .5, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float c(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .1), g_ch * .8, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .9, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw * .9, uv));
|
||||||
|
r = min(r, hd(vec2(.0, g_ch), g_cw * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float e(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(.0, g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(0.), g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float f(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(0.), g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float g(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv);
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, .1 * g_ch), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .5, g_ch * .6), g_cw * .4, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float h(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(.0, g_ch * .6), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float i(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0.), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, 0.), g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float j(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(g_cw, g_ch * .1), g_ch * .9, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .1), g_ch * .2, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float k(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch*.7), g_ch * .3, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch * .5, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float l(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, hd(vec2(0.), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float m(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch), g_cw * .3, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .6), .3 * g_ch, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .7, g_ch), g_cw * .3, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float n(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .1, g_ch * .9), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .3, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .5), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .7, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .9, 0.), g_ch * .2, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float o(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .1), g_ch * .8, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float p(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, hd(vec2(0., g_ch), g_cw, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .7), g_ch * .3, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float q(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .1), g_ch * .8, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .7, g_ch * -.05), g_cw * .4, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float r(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, hd(vec2(.0, g_ch), g_cw, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .7), g_ch * .3, uv));
|
||||||
|
r = min(r, hd(vec2(0., g_ch * .6), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch * .5, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float s(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0.), g_cw * .9, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .7, uv));
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .7), g_ch * .2, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch), g_cw * .8, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float t(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, 0.), g_ch, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float u(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .1), g_ch * .9, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float v(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .5), g_ch * .5, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .5), g_ch * .5, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .2, g_ch * .2), g_ch * .2, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .8, g_ch * .2), g_ch * .2, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, 0.), g_ch * .1, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float w(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .1), g_ch * .3, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw * .3, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .7, 0.), g_cw * .3, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float x(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .9), g_ch * .1, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .2, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .5), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .8, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch * .2, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .9), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .8, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .2, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(0.), g_ch * .2, uv));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float y(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .8), g_ch * .2, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .2, g_ch * .6), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .8, g_ch * .6), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .8), g_ch * .2, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, 0.), g_ch * .5, uv));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float z(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .9, g_ch * .9), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .7, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .5), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .3, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .1, g_ch * .1), g_ch * .1, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// NUMBERS
|
||||||
|
|
||||||
|
float n1(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(g_cw * .3, g_ch), g_cw * .2, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, 0.) , g_ch, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float n2(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), .9 * g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch*.7), g_ch * .2, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .7, uv));
|
||||||
|
r = min(r, vd(vec2(0.), g_ch * .5, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n3(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), .9 * g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .7, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .7), g_ch * .2, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n4(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .6), g_ch * .4, uv);
|
||||||
|
r = min(r, hd(vec2(.0, g_ch * .6), g_cw, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, 0.), g_ch, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float n5(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(0., g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(0., g_ch*.6), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch * .6), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(0.), g_cw * .9, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n6(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(g_cw * .1, g_ch), g_cw * .9, uv);
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .7, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n7(vec2 uv)
|
||||||
|
{
|
||||||
|
|
||||||
|
float r = hd(vec2(0., g_ch), g_cw, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw * .9, g_ch * .9), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .7, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .5), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .3, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .1, 0.), g_ch * .2, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float n8(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(g_cw * .1, 0.), g_cw * .8, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .7, uv));
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .1), g_ch * .4, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), .8 * g_cw, uv));
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .7), g_ch * .2, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .7), g_ch * .2, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n9(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = hd(vec2(g_cw * .1, 0.), g_cw * .8, uv);
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .2, g_ch * .6), g_cw * .6, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(0., g_ch * .7), g_ch * .2, uv));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
float n0(vec2 uv)
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0., g_ch * .1), g_ch * .8, uv);
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, g_ch), g_cw * .8, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw, g_ch * .1), g_ch * .8, uv));
|
||||||
|
r = min(r, hd(vec2(g_cw * .1, 0.), g_cw * .8, uv));
|
||||||
|
|
||||||
|
r = min(r, vd(vec2(g_cw * .9, g_ch * .9), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .7, g_ch * .7), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .5, g_ch * .5), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .3, g_ch * .3), g_ch * .1, uv));
|
||||||
|
r = min(r, vd(vec2(g_cw * .1, g_ch * .1), g_ch * .1, uv));
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// SPECIAL CHARACTERS
|
||||||
|
|
||||||
|
float pe(vec2 uv) // period
|
||||||
|
{
|
||||||
|
float r = vd(vec2(0.), g_ch * .02, uv);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// MACROS
|
||||||
|
|
||||||
|
#define A if (cs == idx) { tx = min(tx, a(uv)); } idx++;
|
||||||
|
#define B if (cs == idx) { tx = min(tx, b(uv)); } idx++;
|
||||||
|
#define C if (cs == idx) { tx = min(tx, c(uv)); } idx++;
|
||||||
|
#define D if (cs == idx) { tx = min(tx, d(uv)); } idx++;
|
||||||
|
#define E if (cs == idx) { tx = min(tx, e(uv)); } idx++;
|
||||||
|
#define F if (cs == idx) { tx = min(tx, f(uv)); } idx++;
|
||||||
|
#define G if (cs == idx) { tx = min(tx, g(uv)); } idx++;
|
||||||
|
#define H if (cs == idx) { tx = min(tx, h(uv)); } idx++;
|
||||||
|
#define I if (cs == idx) { tx = min(tx, i(uv)); } idx++;
|
||||||
|
#define J if (cs == idx) { tx = min(tx, j(uv)); } idx++;
|
||||||
|
#define K if (cs == idx) { tx = min(tx, k(uv)); } idx++;
|
||||||
|
#define L if (cs == idx) { tx = min(tx, l(uv)); } idx++;
|
||||||
|
#define M if (cs == idx) { tx = min(tx, m(uv)); } idx++;
|
||||||
|
#define N if (cs == idx) { tx = min(tx, n(uv)); } idx++;
|
||||||
|
#define O if (cs == idx) { tx = min(tx, o(uv)); } idx++;
|
||||||
|
#define P if (cs == idx) { tx = min(tx, p(uv)); } idx++;
|
||||||
|
#define Q if (cs == idx) { tx = min(tx, q(uv)); } idx++;
|
||||||
|
#define R if (cs == idx) { tx = min(tx, r(uv)); } idx++;
|
||||||
|
#define S if (cs == idx) { tx = min(tx, s(uv)); } idx++;
|
||||||
|
#define T if (cs == idx) { tx = min(tx, t(uv)); } idx++;
|
||||||
|
#define U if (cs == idx) { tx = min(tx, u(uv)); } idx++;
|
||||||
|
#define V if (cs == idx) { tx = min(tx, v(uv)); } idx++;
|
||||||
|
#define W if (cs == idx) { tx = min(tx, w(uv)); } idx++;
|
||||||
|
#define X if (cs == idx) { tx = min(tx, x(uv)); } idx++;
|
||||||
|
#define Y if (cs == idx) { tx = min(tx, y(uv)); } idx++;
|
||||||
|
#define Z if (cs == idx) { tx = min(tx, z(uv)); } idx++;
|
||||||
|
#define N1 if (cs == idx) { tx = min(tx, n1(uv)); } idx++;
|
||||||
|
#define N2 if (cs == idx) { tx = min(tx, n2(uv)); } idx++;
|
||||||
|
#define N3 if (cs == idx) { tx = min(tx, n3(uv)); } idx++;
|
||||||
|
#define N4 if (cs == idx) { tx = min(tx, n4(uv)); } idx++;
|
||||||
|
#define N5 if (cs == idx) { tx = min(tx, n5(uv)); } idx++;
|
||||||
|
#define N6 if (cs == idx) { tx = min(tx, n6(uv)); } idx++;
|
||||||
|
#define N7 if (cs == idx) { tx = min(tx, n7(uv)); } idx++;
|
||||||
|
#define N8 if (cs == idx) { tx = min(tx, n8(uv)); } idx++;
|
||||||
|
#define N9 if (cs == idx) { tx = min(tx, n9(uv)); } idx++;
|
||||||
|
#define N0 if (cs == idx) { tx = min(tx, n0(uv)); } idx++;
|
||||||
|
#define PE if (cs == idx) { tx = min(tx, pe(uv)); } idx++;
|
||||||
|
#define SP idx++;
|
||||||
|
#define NL idx+=int(cc - mod(float(idx), cc));
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
// Periodic saw tooth function that repeats with a period of
|
||||||
|
// 4 and ranges from [-1, 1].
|
||||||
|
// The function starts out at 0 for x=0,
|
||||||
|
// raises to 1 for x=1,
|
||||||
|
// drops to 0 for x=2,
|
||||||
|
// continues to -1 for x=3,
|
||||||
|
// and then rises back to 0 for x=4
|
||||||
|
// to complete the period
|
||||||
|
|
||||||
|
float sawtooth( float x )
|
||||||
|
{
|
||||||
|
float xmod = mod(x+3.0, 4.);
|
||||||
|
return abs(xmod-2.0) - 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
|
||||||
|
float display_width = 1010.;
|
||||||
|
float cc = floor(display_width / (g_cw * (1. + g_cwb))); // character count per line
|
||||||
|
|
||||||
|
vec2 uv = (fragCoord.xy) / iResolution.xx;
|
||||||
|
uv.y = iResolution.y/iResolution.x - uv.y; // type from top to bottom, left to right
|
||||||
|
uv *= display_width;
|
||||||
|
|
||||||
|
int cs = int(floor(uv.x / (g_cw * (1. + g_cwb))) + cc * floor(uv.y/(g_ch * (1. + g_chb))));
|
||||||
|
|
||||||
|
uv = mod_uv(uv);
|
||||||
|
uv.y = g_ch * (1. + g_chb) - uv.y; // paint the character from the bottom left corner
|
||||||
|
vec3 ccol = .35 * vec3(.1, .3, .2) * max(smoothstep(3., 0., uv.x), smoothstep(5., 0., uv.y));
|
||||||
|
uv -= vec2(g_cw * g_cwb * .5, g_ch * g_chb * .5);
|
||||||
|
|
||||||
|
float tx = 10000.;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
//A B C D E F G H I J K L M N O P Q R S T U V W X Y Z N1 N2 N3 N4 N5 N6 N7 N8 N9 N0 PE NL
|
||||||
|
|
||||||
|
NL
|
||||||
|
NL
|
||||||
|
SP I N SP T H E SP N O T SP T O O SP D I S T A N T SP F U T U R E NL
|
||||||
|
SP W A Y SP D O W N SP I N SP D E E P SP N1 N3 NL
|
||||||
|
SP D R PE SP F O R R E S T E R SP A N D SP T V S SP F R A N K NL
|
||||||
|
SP W E R E SP H A T C H I N G SP A N SP E V I L SP S C H E M E PE NL
|
||||||
|
SP T H E Y SP H I R E D SP A SP T E M P SP B Y SP T H E SP N A M E SP O F SP M I K E NL
|
||||||
|
SP J U S T SP A SP R E G U L A R SP J O E SP T H E Y SP D I D N T SP L I K E PE NL
|
||||||
|
SP T H E I R SP E X P E R I M E N T SP N E E D E D SP A SP G O O D SP T E S T SP C A S E NL
|
||||||
|
SP S O SP T H E Y SP C O N K E D SP H I M SP O N SP T H E SP N O G G I N NL
|
||||||
|
SP A N D SP T H E Y SP S H O T SP H I M SP I N T O SP S P A C E SP PE PE PE
|
||||||
|
|
||||||
|
float throb = .4 + .2 * (.5 * sin(4. * iGlobalTime - .05 * float(cs)) + .5);
|
||||||
|
vec3 tcol = vec3(.7, 1., .8) * smoothstep(.2, .0, tx);
|
||||||
|
vec3 tglow = vec3(.7, 1., .8) * (.3 * throb + .7 * mix(.6, 1., throb) * smoothstep(throb, .1, tx));
|
||||||
|
|
||||||
|
vec3 terminal_color = ccol + tcol + tglow;
|
||||||
|
vec3 simple_color = vec3(max(0., 1. - tx));
|
||||||
|
float trans = smoothstep(-.1, .1, sawtooth(.3 * iGlobalTime - 1.));
|
||||||
|
|
||||||
|
fragColor = vec4(mix(terminal_color, simple_color, trans), 1.0);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
#define NUM_LIGHTS 6
|
||||||
|
#define WALL_COLOR vec3(1.0, 0.5, 0.1)
|
||||||
|
#define FLOOR_COLOR vec3(0.4, 0.4, 0.4)
|
||||||
|
#define AMBIENT_LIGHT vec3(0.1, 0.1, 0.1)
|
||||||
|
//#define SHOW_SHADOWMAP
|
||||||
|
|
||||||
|
#define INF 1e8
|
||||||
|
#define EPS 1e-3
|
||||||
|
float tau = atan(1.0)*8.0;
|
||||||
|
|
||||||
|
//Globals
|
||||||
|
vec2 res = vec2(0); //Y-Normalized resolution
|
||||||
|
vec2 mouse = vec2(0); //Mouse coords (form center)
|
||||||
|
float psz = 0.0; //Pixel size
|
||||||
|
vec2 hpo = vec2(0); //Half pixel offset
|
||||||
|
|
||||||
|
// Shapes
|
||||||
|
float sdCircle(float r, vec2 uv)
|
||||||
|
{
|
||||||
|
return length(uv) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdRing(float ir, float or, vec2 uv)
|
||||||
|
{
|
||||||
|
return abs(length(uv) - (ir+or)/2.0) - (or - ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdBox(float s, vec2 uv)
|
||||||
|
{
|
||||||
|
return max(abs(uv.x), abs(uv.y)) - s;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdRect(vec2 s, vec2 uv)
|
||||||
|
{
|
||||||
|
uv = abs(uv) - s;
|
||||||
|
return max(uv.x, uv.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdPlane(vec2 dir, vec2 uv)
|
||||||
|
{
|
||||||
|
return dot(normalize(dir), uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Operations
|
||||||
|
float opU(float a, float b)
|
||||||
|
{
|
||||||
|
return min(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
float opI(float a, float b)
|
||||||
|
{
|
||||||
|
return max(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
float opS(float a, float b)
|
||||||
|
{
|
||||||
|
return max(-a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Domain modifiers
|
||||||
|
mat2 Rotate(float a)
|
||||||
|
{
|
||||||
|
return mat2(cos(a), sin(a),-sin(a), cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Rep1(vec2 uv, float r)
|
||||||
|
{
|
||||||
|
uv.x = mod(uv.x, r) - r/2.0;
|
||||||
|
return uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Rep2(vec2 uv, vec2 r)
|
||||||
|
{
|
||||||
|
return mod(uv, r) - r/2.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scene function (must be changed in both tabs)
|
||||||
|
float Scene(vec2 uv)
|
||||||
|
{
|
||||||
|
float d = -sdRect(res/2.0 - 0.05, uv);
|
||||||
|
|
||||||
|
vec2 rp = Rep2(uv, vec2(0.2));
|
||||||
|
|
||||||
|
d = opU(sdCircle(0.02, rp), d);
|
||||||
|
|
||||||
|
rp = Rep1(uv, 0.2);
|
||||||
|
|
||||||
|
d = opU(sdRect(vec2(0.005,0.1), rp), d);
|
||||||
|
|
||||||
|
d = opS(sdBox(0.2, uv), d);
|
||||||
|
|
||||||
|
d = opU(sdRing(0.08, 0.09, uv), d);
|
||||||
|
|
||||||
|
d = opS(sdRect(vec2(0.11,0.03), uv * Rotate(iGlobalTime)), d);
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 LightOrigin(int id)
|
||||||
|
{
|
||||||
|
return texture(iChannel0,vec2(0, float(id))/iResolution.xy + hpo).yz;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 LightColor(int id)
|
||||||
|
{
|
||||||
|
return texture(iChannel0,vec2(1, float(id))/iResolution.xy + hpo).yzw;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SampleShadow(int id, vec2 uv)
|
||||||
|
{
|
||||||
|
float a = atan(uv.y, uv.x)/tau + 0.5;
|
||||||
|
float r = length(uv);
|
||||||
|
|
||||||
|
float idn = float(id)/iResolution.y;
|
||||||
|
|
||||||
|
float s = texture(iChannel0, vec2(a, idn) + hpo).x;
|
||||||
|
|
||||||
|
return 1.0-smoothstep(s, s+0.02, length(uv));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Reads lights from light buffer and combines them.
|
||||||
|
vec3 MixLights(vec2 uv)
|
||||||
|
{
|
||||||
|
vec3 b = AMBIENT_LIGHT;
|
||||||
|
|
||||||
|
for(int i = 0;i < NUM_LIGHTS;i++)
|
||||||
|
{
|
||||||
|
vec2 o = LightOrigin(i);
|
||||||
|
vec3 c = LightColor(i);
|
||||||
|
|
||||||
|
float l = 0.01 / pow(length(vec3(uv - o, 0.1)), 2.0);
|
||||||
|
l *= SampleShadow(i, uv-o);
|
||||||
|
b += c * l;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
hpo = 0.5 / iResolution.xy;
|
||||||
|
res = iResolution.xy / iResolution.y;
|
||||||
|
psz = 1.0 / iResolution.y;
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.y - res/2.0;
|
||||||
|
|
||||||
|
mouse = iMouse.xy / iResolution.y - res/2.0;
|
||||||
|
|
||||||
|
vec3 col = vec3(0);
|
||||||
|
|
||||||
|
float d = Scene(uv);
|
||||||
|
|
||||||
|
col = mix(FLOOR_COLOR, WALL_COLOR, smoothstep(psz, 0.0, d));
|
||||||
|
|
||||||
|
col *= MixLights(uv);
|
||||||
|
|
||||||
|
#ifdef SHOW_SHADOWMAP
|
||||||
|
col = texture(iChannel0, fragCoord/iResolution.xy).rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fragColor = vec4(col, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,396 @@
|
||||||
|
// stone.jpg
|
||||||
|
// Abandoned base. Created by Reinder Nijhoff 2014
|
||||||
|
// @reindernijhoff
|
||||||
|
//
|
||||||
|
// https://www.shadertoy.com/view/XsSSRW
|
||||||
|
//
|
||||||
|
|
||||||
|
// #define GOLD
|
||||||
|
#define BUMPMAP
|
||||||
|
#define MARCHSTEPS 128
|
||||||
|
#define MARCHSTEPSREFLECTION 64
|
||||||
|
#define SPHERE
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
const vec2 dropPosition = vec2(1.05,2.1);
|
||||||
|
const vec3 backgroundColor = vec3(0.9,0.5,0.2);
|
||||||
|
#define time iGlobalTime
|
||||||
|
#define stime2 sin(time*2.)
|
||||||
|
#define ctime2 cos(time*2.)
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// noises
|
||||||
|
|
||||||
|
float hash( float n ) {
|
||||||
|
return fract(sin(n)*43758.5453123);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise( in vec2 x ) {
|
||||||
|
vec2 p = floor(x);
|
||||||
|
vec2 f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
float n = p.x + p.y*157.0;
|
||||||
|
return mix(mix( hash(n+ 0.0), hash(n+ 1.0),f.x),
|
||||||
|
mix( hash(n+157.0), hash(n+158.0),f.x),f.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mat2 m2 = mat2( 0.80, -0.60, 0.60, 0.80 );
|
||||||
|
|
||||||
|
float fbm( vec2 p ) {
|
||||||
|
float f = 0.0;
|
||||||
|
f += 0.5000*noise( p ); p = m2*p*2.02;
|
||||||
|
f += 0.2500*noise( p ); p = m2*p*2.03;
|
||||||
|
f += 0.1250*noise( p ); p = m2*p*2.01;
|
||||||
|
f += 0.0625*noise( p );
|
||||||
|
|
||||||
|
return f/0.9375;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat2 rot(const in float a) {
|
||||||
|
return mat2(cos(a),sin(a),-sin(a),cos(a));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// distance primitives
|
||||||
|
|
||||||
|
float sdBox( in vec3 p, in vec3 b ) {
|
||||||
|
vec3 d = abs(p) - b;
|
||||||
|
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdSphere( in vec3 p, in float s ) {
|
||||||
|
return length(p)-s;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdCylinder( in vec3 p, in vec2 h ) {
|
||||||
|
vec2 d = abs(vec2(length(p.xz),p.y)) - h;
|
||||||
|
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdPipe( in vec3 p, in vec3 h ) {
|
||||||
|
return length(h.xy-p.xy) - h.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdPPipe( in vec3 p, in vec3 h ) {
|
||||||
|
return length(h.xy-p.xy) - h.z - 0.02*(max(sin(p.z*20.)-0.8,0.));
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// distance operators
|
||||||
|
|
||||||
|
float opU( float d2, float d1 ) { return min( d1,d2); }
|
||||||
|
float opS( float d2, float d1 ) { return max(-d1,d2); }
|
||||||
|
vec2 opU( vec2 d2, vec2 d1 ) { return mix(d1,d2,step(d2.x,d1.x)); }//( d2.x<d1.x)? d2:d1; }
|
||||||
|
vec2 opS( vec2 d2, vec2 d1 ) { return mix(-d1,d2,step(-d1.x,d2.x)); }//(-d1.x>d2.x)?-d1:d2; }
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Map functions
|
||||||
|
|
||||||
|
#ifdef SPHERE
|
||||||
|
vec3 sP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float xoffset( float z) {
|
||||||
|
return 2.1*sin(z*0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 getSectorId( float z ) {
|
||||||
|
float id = floor( (z+6.)/12.);
|
||||||
|
return vec2( id, hash(id) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float map( vec3 p ) {
|
||||||
|
float zorig = p.z;
|
||||||
|
p = vec3( p.x+xoffset(p.z), p.y-2., mod( p.z + 6., 12. ) - 6.);
|
||||||
|
|
||||||
|
float x = p.x*2., y = p.y-0.8, z = p.z;
|
||||||
|
float d = -sdBox( vec3((x+y)*0.7071, (y-x)*0.7071, z), vec3(3.8,3.8,20.) );
|
||||||
|
|
||||||
|
d = opS( d, sdBox( p, vec3( 2.5, 2., 5.75 ) ) );
|
||||||
|
d = opU( d, sdPPipe( vec3(abs(p.x),p.y,p.z), vec3( 2.2, -1.7, 0.25 ) ) );
|
||||||
|
d = opU( d, sdPipe( vec3(p.x,abs(p.y-0.2),p.z), vec3( 2.4, 1.5, 0.1 ) ) );
|
||||||
|
d = opU( d, sdPipe( vec3(p.x,p.y+0.6*cos(p.z*3.1415926/12.),p.z), vec3( -2.4, 1.8, 0.12 ) ) );
|
||||||
|
|
||||||
|
d = opU( d, 2.2-p.y );
|
||||||
|
float l = distance( p.xz, dropPosition );
|
||||||
|
p.y += 0.003*sin(40.*l-6.*time)*exp(-4.*l);
|
||||||
|
|
||||||
|
d = opU( d, p.y+2.03 );
|
||||||
|
d = opU( d, sdSphere( vec3( p.x, p.y-2.3, p.z*0.3), 0.2) );
|
||||||
|
|
||||||
|
if( getSectorId(zorig).y > 0.75 ) {
|
||||||
|
d = opS( d, sdCylinder( vec3(p.x, p.y-9., p.z), vec2(1.5,10.) ) );
|
||||||
|
|
||||||
|
vec3 pr = vec3( stime2*p.x+ctime2*p.z, p.y-2.4, stime2*p.z-ctime2*p.x);
|
||||||
|
d = opU( d, sdBox( pr, vec3(3.0,0.1,0.1) ) );
|
||||||
|
d = opU( d, sdBox( pr, vec3(0.1,0.1,3.0) ) );
|
||||||
|
}
|
||||||
|
#ifdef SPHERE
|
||||||
|
d = opU( d, sdSphere( vec3( p.x, p.y, zorig)-sP, 0.2) );
|
||||||
|
#endif
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float mapMaterial( vec3 p ) {
|
||||||
|
float zorig = p.z;
|
||||||
|
p = vec3( p.x+xoffset(p.z), p.y-2., mod( p.z + 6., 12. ) - 6.);
|
||||||
|
|
||||||
|
float x = p.x*2., y = p.y-0.8, z = p.z;
|
||||||
|
vec2 d = vec2( -sdBox( vec3((x+y)*0.7071, (y-x)*0.7071, z), vec3(3.8,3.8,20.) ), 5.);
|
||||||
|
|
||||||
|
d = opS( d, vec2( sdBox( p, vec3( 2.5, 2., 5.75 ) ), 3. ) );
|
||||||
|
d = opU( d, vec2( sdPPipe( vec3(abs(p.x),p.y,p.z), vec3( 2.2, -1.7, 0.25 ) ), 1. ) );
|
||||||
|
d = opU( d, vec2( sdPipe( vec3(p.x,abs(p.y-0.2),p.z), vec3( 2.4, 1.5, 0.1 ) ), 4. ) );
|
||||||
|
d = opU( d, vec2( sdPipe( vec3(p.x,p.y+0.6*cos(p.z*3.1415926/12.),p.z), vec3( -2.4, 1.8, 0.12 ) ), 4. ) );
|
||||||
|
|
||||||
|
|
||||||
|
d = opU( d, vec2( 2.2-p.y, 5. ) );
|
||||||
|
d = opU( d, vec2( p.y+2.03, 2. ) );
|
||||||
|
d = opU( d, vec2( sdSphere( vec3( p.x, p.y-2.3, p.z*0.3), 0.2), 6.) );
|
||||||
|
|
||||||
|
if( getSectorId(zorig).y > 0.75 ) {
|
||||||
|
d = opS( d, vec2( sdCylinder( vec3(p.x, p.y-4., p.z), vec2(1.5,2.) ), 5.) );
|
||||||
|
|
||||||
|
vec3 pr = vec3( stime2*p.x+ctime2*p.z, p.y-2.4, stime2*p.z-ctime2*p.x);
|
||||||
|
d = opU( d, vec2( sdBox( pr, vec3(3.0,0.1,0.1) ), 4.) );
|
||||||
|
d = opU( d, vec2( sdBox( pr, vec3(0.1,0.1,3.0) ), 4.) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SPHERE
|
||||||
|
d = opU( d, vec2( sdSphere( vec3( p.x, p.y, zorig)-sP, 0.2), 7.) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return abs(d.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
vec3 calcNormal( in vec3 pos ) {
|
||||||
|
const vec2 e = vec2(1.0,-1.0)*0.005;
|
||||||
|
|
||||||
|
vec3 n = normalize( e.xyy*map( pos + e.xyy ) +
|
||||||
|
e.yyx*map( pos + e.yyx ) +
|
||||||
|
e.yxy*map( pos + e.yxy ) +
|
||||||
|
e.xxx*map( pos + e.xxx ) );
|
||||||
|
|
||||||
|
#ifdef BUMPMAP
|
||||||
|
vec3 p = pos * 20.;
|
||||||
|
if( abs(pos.x+xoffset(pos.z))>2.48 )n = normalize( n + 0.1*vec3(0.,fbm(p.yz)-0.5,fbm(p.zy)-0.5));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 int1, int2;
|
||||||
|
|
||||||
|
float intersect( in vec3 ro, in vec3 rd ) {
|
||||||
|
const float maxd = 60.0;
|
||||||
|
const float precis = 0.001;
|
||||||
|
float h = precis*2.0;
|
||||||
|
float t = 0.;
|
||||||
|
int1.z = -1.;
|
||||||
|
|
||||||
|
for( int i=0; i < MARCHSTEPS; i++ ) {
|
||||||
|
if( h < precis ) {
|
||||||
|
int1 = ro+rd*t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h = map( ro+rd*t );
|
||||||
|
t += h;
|
||||||
|
}
|
||||||
|
if( int1.z < 0. ) return -1.;
|
||||||
|
|
||||||
|
ro = ro + rd*t;
|
||||||
|
vec3 nor = calcNormal(ro);
|
||||||
|
rd = reflect( rd, nor );
|
||||||
|
ro += 0.1 * nor;
|
||||||
|
t = 0.0;
|
||||||
|
h = precis*2.0;
|
||||||
|
|
||||||
|
for( int i=0; i < MARCHSTEPSREFLECTION; i++ ) {
|
||||||
|
if( h < precis ) {
|
||||||
|
int2 = ro+rd*t;
|
||||||
|
return 1.;
|
||||||
|
}
|
||||||
|
h = map( ro+rd*t );
|
||||||
|
t += h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.;
|
||||||
|
}
|
||||||
|
|
||||||
|
float softshadow( in vec3 ro, in vec3 rd, in float mint, in float maxt, in float k ) {
|
||||||
|
float res = 1.0;
|
||||||
|
float t = mint;
|
||||||
|
for( int i=0; i<16; i++ ) {
|
||||||
|
if( t>maxt ) break;
|
||||||
|
float h = map( ro + rd*t );
|
||||||
|
res = min( res, k*h/t );
|
||||||
|
t += 0.03 + h;
|
||||||
|
}
|
||||||
|
return clamp( res, 0.0, 1.0 );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float calcOcc( in vec3 pos, in vec3 nor ) {
|
||||||
|
float totao = 0.0;
|
||||||
|
float sca = 1.0;
|
||||||
|
for( int i=0; i<5; i++ )
|
||||||
|
{
|
||||||
|
float h = 0.02 + float(i)/4.0;
|
||||||
|
float d = map( pos + h*nor );
|
||||||
|
totao += clamp(h-d,0.0,1.0)*sca;
|
||||||
|
sca *= 0.4;
|
||||||
|
}
|
||||||
|
return clamp( 1.0 - 2.0*totao, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// shade
|
||||||
|
|
||||||
|
vec4 texcube( sampler2D sam, in vec3 p, in vec3 n )
|
||||||
|
{
|
||||||
|
vec4 x = texture( sam, p.yz );
|
||||||
|
vec4 y = texture( sam, p.zx );
|
||||||
|
vec4 z = texture( sam, p.xy );
|
||||||
|
return x*abs(n.x) + y*abs(n.y) + z*abs(n.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float calcLightning( in vec3 pos, in vec3 light, in vec3 nor, in float maxDist, in bool shadow ) {
|
||||||
|
float sh = 1.;
|
||||||
|
vec3 lig = ( light-pos );
|
||||||
|
float im = length( lig );
|
||||||
|
lig /= im;
|
||||||
|
if(shadow) sh = softshadow( pos, lig, 1.02, im, 32.0 );
|
||||||
|
sh /= im;
|
||||||
|
sh *= clamp(dot(nor,lig),0.,1.);
|
||||||
|
return sh * (1.-smoothstep(0.,maxDist,im));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 shade( in vec3 ro, in vec3 pos, in bool shadow, in float m, in float r ) {
|
||||||
|
vec3 light, col = vec3(0.);
|
||||||
|
vec3 nor = calcNormal(pos);
|
||||||
|
|
||||||
|
vec2 id = getSectorId(pos.z);
|
||||||
|
|
||||||
|
float occ = calcOcc( pos, nor );
|
||||||
|
float dist, sh = 1., xo = xoffset(pos.z);
|
||||||
|
|
||||||
|
float rc = hash(id.x+43.);
|
||||||
|
float gc = hash(id.x+153.);
|
||||||
|
vec3 lc = normalize(vec3( max(rc,gc), min(rc,gc), 0.1 ) );
|
||||||
|
|
||||||
|
if( id.y > 0.75 ) {
|
||||||
|
light = vec3( -xo, 6.5, id*12. );
|
||||||
|
light.xz += vec2( hash(id.x+56423.), hash(id.x+124.) ) - 0.5;
|
||||||
|
sh = 8.;
|
||||||
|
dist = 8.;
|
||||||
|
} else {
|
||||||
|
light = vec3( -xo, 3.9, id*12. );
|
||||||
|
sh = 3.;
|
||||||
|
dist = 5.3;
|
||||||
|
if( hash(id.x+234.) < 0.15 ) lc *= 1.-clamp( 10.*(fbm( vec2(time*10., id.x) )-2.5*id.y), 0., 1.);
|
||||||
|
if( pos.y > 4. ) sh*=0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
sh *= calcLightning( pos, light, nor, dist, shadow );
|
||||||
|
|
||||||
|
|
||||||
|
if( m < 6.5 ) col = texcube( iChannel0, pos*0.5, nor ).xyz;
|
||||||
|
if( m == 1. ) col *= 0.05;
|
||||||
|
if( m == 4. && pos.y > 2. ) col *= vec3(0.1,0.,0.);
|
||||||
|
if( m == 4. && pos.y < 2. ) col *= vec3(0.1,0.4,1.2);
|
||||||
|
|
||||||
|
if( m == 5. ) col *= (1.+0.5*fbm(pos.yz*2.))*vec3(0.2,0.1,0.05);
|
||||||
|
if( m == 2. ) col *= vec3(0.8,0.6,0.4);
|
||||||
|
|
||||||
|
col *= lc * occ * sh;
|
||||||
|
|
||||||
|
if( m == 6. ) col = mix( 0.1*col, col*fbm(pos.xz*10.) + 0.8*lc,
|
||||||
|
(1.-smoothstep( 4.15, 4.2,pos.y)) *
|
||||||
|
smoothstep( 0.01, 0.04,abs(mod(pos.z+0.15,0.3)-0.15)) *
|
||||||
|
smoothstep( 0.01, 0.02,abs(pos.x+xo)));
|
||||||
|
|
||||||
|
col *= clamp(1.-2.*r, 0.65, 1.);
|
||||||
|
|
||||||
|
col = mix( 0.05*backgroundColor, col, exp( -0.04*distance(pos, ro) ) );
|
||||||
|
|
||||||
|
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// main
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
vec2 q = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = -1.0 + 2.0*q;
|
||||||
|
p.x *= iResolution.x / iResolution.y;
|
||||||
|
|
||||||
|
if (q.y < .12 || q.y >= .88) {
|
||||||
|
fragColor=vec4(0.,0.,0.,1.);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// camera
|
||||||
|
float o = 0.2*noise(vec2(time,0.));
|
||||||
|
float z = 2.*time+o;
|
||||||
|
float x = -0.95*xoffset(z);
|
||||||
|
vec3 ro = vec3(x,1.7+0.02*sin(time*1.13*2.*3.1415926+o), z-1.);
|
||||||
|
vec3 ta = vec3(x,1.7, z+5.);
|
||||||
|
|
||||||
|
#ifdef SPHERE
|
||||||
|
sP = vec3(sin(time), 1.6*cos(time*0.4), ro.z+9.+6.*sin(time*0.15) );
|
||||||
|
// ta = mix(ta,sP+vec3(0.,2.,0.),0.2);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (iMouse.z>=1.) {
|
||||||
|
ta.yz *= rot( -(0.5-iMouse.y/iResolution.y)*0.15 );
|
||||||
|
ta.xz *= rot( -(0.5-iMouse.x/iResolution.x)*0.5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ww = normalize( ta - ro );
|
||||||
|
vec3 uu = normalize( cross(ww,vec3(0.0,1.0,0.0) ) );
|
||||||
|
vec3 vv = normalize( cross(uu,ww));
|
||||||
|
vec3 rd = normalize( -p.x*uu + p.y*vv + 2.2*ww );
|
||||||
|
|
||||||
|
vec3 col = 0.035*backgroundColor;
|
||||||
|
|
||||||
|
// raymarch
|
||||||
|
float ints = intersect(ro ,rd );
|
||||||
|
if( ints > -0.5 ) {
|
||||||
|
float m = mapMaterial(int1);
|
||||||
|
|
||||||
|
#ifdef GOLD
|
||||||
|
float r = .8;
|
||||||
|
#else
|
||||||
|
float xo = xoffset(int1.z);
|
||||||
|
vec3 p = vec3( int1.x+xo, int1.y-2., mod( int1.z + 6., 12. ) - 6.);
|
||||||
|
float l = m == 2.?exp(-2.*distance( p.xz, dropPosition )):0.;
|
||||||
|
|
||||||
|
float r = 0.6 * clamp(2.*(fbm( int1.xz )-0.6+l), 0.0125, 1.)*clamp(2.-int1.y, 0., 1.);
|
||||||
|
if(m == 1.) r = 0.05+0.3 * fbm( int1.xz * 20. );
|
||||||
|
if(m == 7.) r = .8;
|
||||||
|
|
||||||
|
if(abs(int1.x+xo) > 2.49) {
|
||||||
|
r = fbm(int1.yz*0.5)*0.4*
|
||||||
|
clamp(2.*(fbm( int1.yz*vec2(3.2,24.)+vec2(0.5*time,0.) )-0.5+l), 0.0, 1.)
|
||||||
|
*clamp(0.5*int1.y, 0., 1.);
|
||||||
|
}
|
||||||
|
if(m == 4.) { r = 0.1; }
|
||||||
|
#endif
|
||||||
|
col = shade( ro, int1.xyz, true, m, r );
|
||||||
|
|
||||||
|
if( ints > 0.5 ) {
|
||||||
|
col += r * shade( int1.xyz, int2.xyz, false, mapMaterial(int2), 0. );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// gamma
|
||||||
|
col = pow( clamp(col*2.,0.0,1.0), vec3(0.4545) );
|
||||||
|
col *= 1.2*vec3(1.,0.99,0.95);
|
||||||
|
col = clamp(1.06*col-0.03, 0., 1.);
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
float time=iGlobalTime*1.0;
|
||||||
|
vec2 uv = (fragCoord.xy / iResolution.xx-0.5)*8.0;
|
||||||
|
vec2 uv0=uv;
|
||||||
|
float i0=1.0;
|
||||||
|
float i1=1.0;
|
||||||
|
float i2=1.0;
|
||||||
|
float i4=0.0;
|
||||||
|
for(int s=0;s<7;s++)
|
||||||
|
{
|
||||||
|
vec2 r;
|
||||||
|
r=vec2(cos(uv.y*i0-i4+time/i1),sin(uv.x*i0-i4+time/i1))/i2;
|
||||||
|
r+=vec2(-r.y,r.x)*0.3;
|
||||||
|
uv.xy+=r;
|
||||||
|
|
||||||
|
i0*=1.93;
|
||||||
|
i1*=1.15;
|
||||||
|
i2*=1.7;
|
||||||
|
i4+=0.05+0.1*time*i1;
|
||||||
|
}
|
||||||
|
float r=sin(uv.x-time)*0.5+0.5;
|
||||||
|
float b=sin(uv.y+time)*0.5+0.5;
|
||||||
|
float g=sin((uv.x+uv.y+sin(time*0.5))*0.5)*0.5+0.5;
|
||||||
|
fragColor = vec4(r,g,b,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,594 @@
|
||||||
|
// Ben Weston - 15/08/2013
|
||||||
|
|
||||||
|
/*
|
||||||
|
Eye ball effects:
|
||||||
|
• Ray-marched shape
|
||||||
|
• Ray-traced iris refraction
|
||||||
|
• Fake photon mapping on iris
|
||||||
|
• Subsurface scattering on sclera
|
||||||
|
• HDR reflections with fresnel
|
||||||
|
• Eyelid reflection occlusion
|
||||||
|
• Eyelid ambient occlusion
|
||||||
|
• Procedural textures
|
||||||
|
• Procedural animation
|
||||||
|
*/
|
||||||
|
|
||||||
|
// KEY CONTROLS - (click on eye to give keyboard focus)
|
||||||
|
const int Key_M = 77; // mouse controls camera / eye direction
|
||||||
|
|
||||||
|
const int Key_E = 69; // refraction on/off
|
||||||
|
const int Key_P = 80; // photon mapping on/off
|
||||||
|
const int Key_L = 76; // change photon mapping technique (both fake, but one is imitating reality and the other is prettier)
|
||||||
|
|
||||||
|
const int Key_S = 83; // subsurface scattering on/off
|
||||||
|
const int Key_A = 65; // ambient occlusion on/off
|
||||||
|
|
||||||
|
const int Key_R = 82; // reflection on/off
|
||||||
|
const int Key_O = 79; // reflection eyelid occlusion on/off
|
||||||
|
|
||||||
|
const int Key_C = 67; // iris colour
|
||||||
|
const int Key_N = 78; // iris normal
|
||||||
|
|
||||||
|
|
||||||
|
// Lights
|
||||||
|
#if (1)
|
||||||
|
// High-contrast light edge-on
|
||||||
|
const vec3 lightDir = vec3(-2,2,.5);
|
||||||
|
const vec3 lightColour = vec3(1.0);
|
||||||
|
const vec3 fillLightDir = vec3(0,1,0);
|
||||||
|
const vec3 fillLightColour = vec3(.65,.7,.8)*.7;//vec3(.15,.2,.25);
|
||||||
|
#else
|
||||||
|
// more neutral "good" lighting (doesn't show off the effects)
|
||||||
|
const vec3 lightDir = vec3(-2,2,-1);
|
||||||
|
const vec3 lightColour = vec3(.83,.8,.78);
|
||||||
|
const vec3 fillLightDir = vec3(0,1,0);
|
||||||
|
const vec3 fillLightColour = vec3(.65,.7,.8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const float tau = 6.28318530717958647692;
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
float Noise( in vec3 x );
|
||||||
|
vec2 Noise2( in vec3 x );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Gamma correction
|
||||||
|
#define GAMMA (2.2)
|
||||||
|
|
||||||
|
vec3 ToLinear( in vec3 col )
|
||||||
|
{
|
||||||
|
// simulate a monitor, converting colour values into light values
|
||||||
|
return pow( col, vec3(GAMMA) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ToGamma( in vec3 col )
|
||||||
|
{
|
||||||
|
// convert back into colour values, so the correct light will come out of the monitor
|
||||||
|
return pow( col, vec3(1.0/GAMMA) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// key is javascript keycode: http://www.webonweboff.com/tips/js/event_key_codes.aspx
|
||||||
|
bool ReadKey( int key, bool toggle )
|
||||||
|
{
|
||||||
|
float keyVal = texture( iChannel3, vec2( (float(key)+.5)/256.0, toggle?.75:.25 ) ).x;
|
||||||
|
return (keyVal>.5)?true:false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ------- EDIT THESE THINGS! -------
|
||||||
|
|
||||||
|
// Camera (also rotated by mouse)
|
||||||
|
const vec3 CamPos = vec3(0,0.0,-250.0);
|
||||||
|
const vec3 CamLook = vec3(0,0,0);
|
||||||
|
const float CamZoom = 10.0;
|
||||||
|
const float NearPlane = 0.0; // actually not needed
|
||||||
|
const float drawDistance = 1000.0;
|
||||||
|
|
||||||
|
const vec3 SkyColour = vec3(.4,.25,.2);//fillLightColour*.5;//vec3(.1,.3,.5);
|
||||||
|
|
||||||
|
vec3 SkyDome( vec3 rd )
|
||||||
|
{
|
||||||
|
//the cube maps have lines in, and aren't HDR, so make our own shapes
|
||||||
|
|
||||||
|
// random variation
|
||||||
|
vec3 result = ToLinear(SkyColour)*2.0*Noise(rd);
|
||||||
|
|
||||||
|
// square sky-light
|
||||||
|
result = mix( result, vec3(8), smoothstep(.8,1.0,rd.y/max((rd.x+1.0),abs(rd.z))) );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eye params
|
||||||
|
const float IrisAng = tau/12.0;
|
||||||
|
const float PupilAng = (1.6*IrisAng/5.0);
|
||||||
|
const float EyeRadius = 10.0;
|
||||||
|
const float BulgeRadius = 6.0; // used for photon trace, must be bigger than EyeRadius*sin(IrisAng)
|
||||||
|
|
||||||
|
|
||||||
|
vec4 ComputeEyeRotation()
|
||||||
|
{
|
||||||
|
vec2 rot;
|
||||||
|
if ( !ReadKey( Key_M, true ) && iMouse.w > .00001 )
|
||||||
|
rot = .25*vec2(1.0,1.0)*tau*(iMouse.xy-iResolution.xy*.5)/iResolution.x;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float time = iGlobalTime/2.0;
|
||||||
|
time += Noise(vec3(0,time,0)); // add noise to time (this adds SO MUCH character!)
|
||||||
|
float flick = floor(time)+smoothstep(0.0,0.05,fract(time));
|
||||||
|
rot = vec2(.2,.1)*tau*(texture( iChannel0, vec2((flick+.5)/256.0,.5), -100.0 ).rb-.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vec4(cos(rot.x),sin(rot.x),cos(rot.y),sin(rot.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ApplyEyeRotation( vec3 pos, vec4 rotation )
|
||||||
|
{
|
||||||
|
pos.yz = rotation.z*pos.yz + rotation.w*pos.zy*vec2(1,-1);
|
||||||
|
pos.xz = rotation.x*pos.xz + rotation.y*pos.zx*vec2(1,-1);
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Shape
|
||||||
|
// This should return continuous positive values when outside and negative values inside,
|
||||||
|
// which roughly indicate the distance of the nearest surface.
|
||||||
|
float Isosurface( vec3 pos, vec4 eyeRotation )
|
||||||
|
{
|
||||||
|
pos = ApplyEyeRotation(pos,eyeRotation);
|
||||||
|
|
||||||
|
/* float f = length(pos)-EyeRadius;
|
||||||
|
|
||||||
|
// f += Noise(pos*3.0)*.008;
|
||||||
|
|
||||||
|
// cornea bulge
|
||||||
|
float o = EyeRadius*cos(IrisAng)-sqrt(BulgeRadius*BulgeRadius-EyeRadius*EyeRadius*pow(sin(IrisAng),2.0));
|
||||||
|
float g = length(pos-vec3(0,0,-o))-BulgeRadius;
|
||||||
|
|
||||||
|
//g += Noise(pos/2.0)*.5;
|
||||||
|
|
||||||
|
return min(f,g);
|
||||||
|
//return -log(exp(-g*2.0)+exp(-f*2.0))/2.0;*/
|
||||||
|
|
||||||
|
vec2 slice = vec2(length(pos.xy),pos.z);
|
||||||
|
|
||||||
|
float aa = atan(slice.x,-slice.y);
|
||||||
|
float bulge = cos(tau*.2*aa/IrisAng);
|
||||||
|
bulge = bulge*.8-.8;
|
||||||
|
bulge *= smoothstep(tau*.25,0.0,aa);
|
||||||
|
|
||||||
|
// sharp-edged bulge
|
||||||
|
// if ( aa < IrisAng )
|
||||||
|
// bulge += cos(tau*.25*aa/IrisAng)*.5;
|
||||||
|
bulge += cos(tau*.25*aa/IrisAng)*.5 * smoothstep(-.02,.1,IrisAng-aa); // slightly softer
|
||||||
|
|
||||||
|
return length(slice) - EyeRadius - bulge;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float GetEyelidMask( vec3 pos, vec4 eyeRotation )
|
||||||
|
{
|
||||||
|
vec3 eyelidPos = pos;
|
||||||
|
float eyelidTilt = -.05;
|
||||||
|
eyelidPos.xy = cos(eyelidTilt)*pos.xy + sin(eyelidTilt)*pos.yx*vec2(1,-1);
|
||||||
|
|
||||||
|
float highLid = tan(max(tau*.05,asin(eyeRotation.w)+IrisAng+.05));
|
||||||
|
float lowLid = tan(tau*.1);
|
||||||
|
|
||||||
|
float blink = smoothstep(.0,.02,abs(Noise(vec3(iGlobalTime*.2,0,0))-.5 ));
|
||||||
|
highLid *= blink;
|
||||||
|
lowLid *= blink;
|
||||||
|
|
||||||
|
return min(
|
||||||
|
(-eyelidPos.z-2.0) - (-eyelidPos.y/lowLid),
|
||||||
|
(-eyelidPos.z-2.0) - (eyelidPos.y/highLid)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetIrisPattern( vec2 uv )
|
||||||
|
{
|
||||||
|
return Noise( vec3( 10.0*uv/pow(length(uv),.7), 0 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Colour
|
||||||
|
vec3 Shading( vec3 worldPos, vec3 norm, float shadow, vec3 rd, vec4 eyeRotation )
|
||||||
|
{
|
||||||
|
vec3 view = normalize(-rd);
|
||||||
|
|
||||||
|
// eyelids - just match BG colour
|
||||||
|
float eyelidMask = GetEyelidMask(worldPos, eyeRotation);
|
||||||
|
|
||||||
|
if ( eyelidMask < 0.0 || (-worldPos.z-3.0) < (worldPos.x/tan(tau*.23)) )
|
||||||
|
{
|
||||||
|
return ToLinear(SkyColour);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 pos = ApplyEyeRotation(worldPos,eyeRotation);
|
||||||
|
|
||||||
|
float lenposxy = length(pos.xy);
|
||||||
|
float ang = atan(lenposxy/(-pos.z));
|
||||||
|
if ( ang < 0.0 )
|
||||||
|
ang += tau/2.0;
|
||||||
|
|
||||||
|
|
||||||
|
// refract ray
|
||||||
|
vec3 irisRay = ApplyEyeRotation(-view,eyeRotation);
|
||||||
|
vec3 localNorm = ApplyEyeRotation(norm,eyeRotation);
|
||||||
|
float a = dot(irisRay,localNorm);
|
||||||
|
float b = cos(acos(a)*1.33);
|
||||||
|
if ( !ReadKey( Key_E, true ) )
|
||||||
|
irisRay += localNorm*(b-a);
|
||||||
|
irisRay = normalize(irisRay);
|
||||||
|
|
||||||
|
// intersect with plane
|
||||||
|
float planeDist = -cos(IrisAng)*EyeRadius;
|
||||||
|
float t = (planeDist-pos.z)/irisRay.z;
|
||||||
|
|
||||||
|
vec3 ppos = t*irisRay+pos;
|
||||||
|
|
||||||
|
|
||||||
|
// polar coord map
|
||||||
|
float rad = length(ppos.xy);
|
||||||
|
float pupilr = EyeRadius*sin(PupilAng);
|
||||||
|
float irisr = EyeRadius*sin(IrisAng);
|
||||||
|
|
||||||
|
float irisPattern = GetIrisPattern(ppos.xy); // reduce contrast of this now we have actual lighting!
|
||||||
|
|
||||||
|
/* vec3 iris = mix( mix( vec3(.3,.1,.1)*.5+.5*vec3(.6,.4,.1), vec3(.6,.4,.1), irisPattern ), // hazel
|
||||||
|
mix( vec3(.2,.2,.2)*.5+.5*vec3(.5,.45,.2), vec3(.5,.45,.2), irisPattern ),*/
|
||||||
|
|
||||||
|
/* vec3 iris = mix( mix( vec3(.1,.1,.4), vec3(.7,.9,1), irisPattern ), // blue
|
||||||
|
mix( vec3(.1,.1,.4), vec3(.3,.4,.7), irisPattern ),*/
|
||||||
|
|
||||||
|
// smoothstep(pupilr*2.0,irisr,rad));
|
||||||
|
|
||||||
|
vec3 iris = ToLinear( mix( pow( vec3(.65,.82,.85), 2.0*vec3(1.2-sqrt(irisPattern)) ),
|
||||||
|
vec3(1,.5,.2), .7*pow( mix( smoothstep(pupilr,irisr,rad), Noise(ppos), .7), 2.0) ));
|
||||||
|
|
||||||
|
if ( ReadKey( Key_C, true ) )
|
||||||
|
iris = vec3(1);
|
||||||
|
|
||||||
|
// darken outer
|
||||||
|
iris *= pow( smoothstep( irisr+1.0, irisr-1.5, rad ), GAMMA );
|
||||||
|
|
||||||
|
|
||||||
|
vec3 irisNorm;
|
||||||
|
irisNorm.x = GetIrisPattern(ppos.xy+vec2(-.001,0)) - GetIrisPattern(ppos.xy+vec2(.001,0));
|
||||||
|
irisNorm.y = GetIrisPattern(ppos.xy+vec2(0,-.001)) - GetIrisPattern(ppos.xy+vec2(0,.001));
|
||||||
|
|
||||||
|
// add a radial lump
|
||||||
|
irisNorm.xy += -.01*normalize(ppos.xy)*sin(1.*tau*rad/irisr);
|
||||||
|
|
||||||
|
irisNorm.z = -.15; // adjust severity of bumps
|
||||||
|
irisNorm = normalize(irisNorm);
|
||||||
|
|
||||||
|
if ( ReadKey( Key_N, true ) )
|
||||||
|
irisNorm = vec3(0,0,-1);
|
||||||
|
|
||||||
|
|
||||||
|
// lighting
|
||||||
|
// fake photon mapping by crudely sampling the photon density
|
||||||
|
|
||||||
|
// apply lighting with this modified normal
|
||||||
|
vec3 lightDirN = normalize(lightDir);
|
||||||
|
vec3 localLightDir = ApplyEyeRotation(lightDirN,eyeRotation);
|
||||||
|
|
||||||
|
vec3 fillLightDirN = normalize(fillLightDir);
|
||||||
|
vec3 localFillLightDir = ApplyEyeRotation(fillLightDirN,eyeRotation);
|
||||||
|
|
||||||
|
// Bend the light, imitating results of offline photon-mapping
|
||||||
|
// Jimenez's paper makes this seem very complex, because their mapping used a non-flat receiver
|
||||||
|
// but the self-shadowing was negligible, so the main effect was just like premultiplying by a normal
|
||||||
|
// where we'd get better results by using the actual normal.
|
||||||
|
|
||||||
|
float photonsL, photonsFL;
|
||||||
|
|
||||||
|
if ( !ReadKey( Key_P, true ) )
|
||||||
|
{
|
||||||
|
if ( !ReadKey( Key_L, true ) )
|
||||||
|
{
|
||||||
|
// Nice retro-reflective effect, but not correct
|
||||||
|
vec3 nn = normalize(vec3( ppos.xy, -sqrt(max(0.0,BulgeRadius*BulgeRadius-rad*rad)) ));
|
||||||
|
|
||||||
|
vec3 irisLDir = localLightDir;
|
||||||
|
vec3 irisFLDir = localFillLightDir;
|
||||||
|
// irisLDir.z = -cos(acos(-irisLDir.z)/1.33); // experiments showed it cuts out at 120 degrees, i.e. 1.33*the usual 90 degree cutoff
|
||||||
|
// irisFLDir.z = -cos(acos(-irisFLDir.z)/1.33); // experiments showed it cuts out at 120 degrees, i.e. 1.33*the usual 90 degree cutoff
|
||||||
|
float d = dot(nn,irisLDir);
|
||||||
|
irisLDir += nn*(cos(acos(d)/1.33) - d);
|
||||||
|
d = dot(nn,irisFLDir);
|
||||||
|
irisFLDir += nn*(cos(acos(d)/1.33) - d);
|
||||||
|
irisLDir = normalize(irisLDir);
|
||||||
|
irisFLDir = normalize(irisFLDir);
|
||||||
|
photonsL = smoothstep(0.0,1.0,dot(irisNorm,irisLDir)); //soften terminator
|
||||||
|
photonsFL = (dot(irisNorm,irisFLDir)*.5+.5);
|
||||||
|
//Seriously, this^ looks really nice, but not like reality. Bah!
|
||||||
|
|
||||||
|
/* reverse it, to make it look a lot like the accurate version - meh
|
||||||
|
vec3 nn = normalize(vec3( -ppos.xy, -sqrt(max(0.0,BulgeRadius*BulgeRadius-rad*rad)) ));
|
||||||
|
|
||||||
|
vec3 irisLDir = localLightDir;
|
||||||
|
vec3 irisFLDir = localFillLightDir;
|
||||||
|
float d = dot(nn,irisLDir);
|
||||||
|
irisLDir += nn*(cos(acos(d)/1.33) - d);
|
||||||
|
d = dot(nn,irisFLDir);
|
||||||
|
irisFLDir += nn*(cos(acos(d)/1.33) - d);
|
||||||
|
irisLDir = normalize(irisLDir);
|
||||||
|
irisFLDir = normalize(irisFLDir);
|
||||||
|
|
||||||
|
float photonsL = smoothstep(0.0,1.0,dot(irisNorm,irisLDir)); // soften the terminator
|
||||||
|
float photonsFL = (dot(irisNorm,irisFLDir)*.5+.5);
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//this is a reasonable match to the dark crescent effect seen in photos and offline photon mapping, but it looks wrong to me.
|
||||||
|
vec3 irisLDir = localLightDir;
|
||||||
|
vec3 irisFLDir = localFillLightDir;
|
||||||
|
irisLDir.z = -cos(acos(-irisLDir.z)/1.5); // experiments showed it cuts out at 120 degrees, i.e. 1.33*the usual 90 degree cutoff
|
||||||
|
irisFLDir.z = -cos(acos(-irisFLDir.z)/1.5); // experiments showed it cuts out at 120 degrees, i.e. 1.33*the usual 90 degree cutoff
|
||||||
|
irisLDir = normalize(irisLDir);
|
||||||
|
irisFLDir = normalize(irisFLDir);
|
||||||
|
|
||||||
|
photonsL = smoothstep(0.0,1.0,dot(irisNorm,irisLDir)); // soften the terminator
|
||||||
|
photonsFL = (dot(irisNorm,irisFLDir)*.5+.5);
|
||||||
|
|
||||||
|
// dark caustic ring
|
||||||
|
photonsL *= .3+.7*smoothstep( 1.2, .9, length(ppos.xy/irisr+.2*irisLDir.xy/(irisLDir.z-.05)) );
|
||||||
|
// photonsFL *= ...;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// no photons
|
||||||
|
photonsL = max( 0.0, dot(irisNorm,localLightDir) );
|
||||||
|
photonsFL = .5+.5*dot(irisNorm,localLightDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 l = ToLinear(lightColour)*photonsL;
|
||||||
|
vec3 fl = ToLinear(fillLightColour)*photonsFL;
|
||||||
|
|
||||||
|
vec3 ambientOcclusion = vec3(1);
|
||||||
|
vec3 eyelidShadow = vec3(1);
|
||||||
|
if ( !ReadKey( Key_A, true ) )
|
||||||
|
{
|
||||||
|
// ambient occlusion on fill light
|
||||||
|
ambientOcclusion = mix( vec3(1), ToLinear(vec3(.8,.7,.68)), pow(smoothstep( 5.0, 0.0, eyelidMask ),1.0) );
|
||||||
|
|
||||||
|
// shadow on actual light
|
||||||
|
eyelidShadow = mix( vec3(1), ToLinear(vec3(.8,.7,.68)), smoothstep( 2.0, -2.0, GetEyelidMask( worldPos+lightDir*1.0, eyeRotation ) ) );
|
||||||
|
}
|
||||||
|
fl *= ambientOcclusion;
|
||||||
|
l *= eyelidShadow;
|
||||||
|
|
||||||
|
iris *= l+fl;
|
||||||
|
|
||||||
|
// darken pupil
|
||||||
|
iris *= smoothstep( pupilr-.01, pupilr+.5, rad );
|
||||||
|
|
||||||
|
|
||||||
|
// veins
|
||||||
|
float theta = atan(pos.x,pos.y);
|
||||||
|
theta += Noise(pos*1.0)*tau*.03;
|
||||||
|
float veins = (sin(theta*60.0)*.5+.5);
|
||||||
|
veins *= veins;
|
||||||
|
veins *= (sin(theta*13.0)*.5+.5);
|
||||||
|
veins *= smoothstep( IrisAng, tau*.2, ang );
|
||||||
|
veins *= veins;
|
||||||
|
veins *= .5;
|
||||||
|
|
||||||
|
vec3 sclera = mix( ToLinear(vec3(1,.98,.96)), ToLinear(vec3(.9,.1,0)), veins );
|
||||||
|
|
||||||
|
float ndotl = dot(norm,lightDirN);
|
||||||
|
|
||||||
|
// subsurface scattering
|
||||||
|
// float subsurface = max(0.0,-2.0*ndotl*EyeRadius);
|
||||||
|
// l = pow(ToLinear(vec3(.5,.3,.25)),vec3(subsurface*.2)); // more intense the further light had to travel
|
||||||
|
|
||||||
|
// fake, because that^ approximation gives a hard terminator
|
||||||
|
l = pow(ToLinear(vec3(.5,.3,.25)), vec3(mix( 3.0, 0.0, smoothstep(-1.0,.2,ndotl) )) );
|
||||||
|
|
||||||
|
if ( ReadKey( Key_S, true ) )
|
||||||
|
// l = mix( l, vec3(max(0.0,ndotl)), 0.5 );
|
||||||
|
// else
|
||||||
|
l = vec3(max(0.0,ndotl));
|
||||||
|
|
||||||
|
l *= ToLinear(lightColour);
|
||||||
|
|
||||||
|
fl = ToLinear(fillLightColour)*(dot(norm,fillLightDirN)*.5+.5);
|
||||||
|
|
||||||
|
fl *= ambientOcclusion;
|
||||||
|
l *= eyelidShadow;
|
||||||
|
|
||||||
|
|
||||||
|
sclera *= l+fl;
|
||||||
|
|
||||||
|
// blend between them
|
||||||
|
float blend = smoothstep(-.1,.1,ang-IrisAng);
|
||||||
|
vec3 result = mix(iris,sclera,blend);
|
||||||
|
|
||||||
|
|
||||||
|
// eyelid ambient occlusion/radiosity
|
||||||
|
// if ( !ReadKey( Key_A, true ) )
|
||||||
|
//result *= mix( vec3(1), ToLinear(vec3(.65,.55,.55)), exp2(-eyelidMask*2.0) );
|
||||||
|
// result *= mix( vec3(1), ToLinear(vec3(.8,.7,.68)), pow(smoothstep( 5.0, 0.0, eyelidMask ),1.0) );
|
||||||
|
|
||||||
|
|
||||||
|
// bumps - in specular only to help sub-surface scattering look smooth
|
||||||
|
vec3 bumps;
|
||||||
|
bumps.xy = .7*Noise2( pos*3.0 );
|
||||||
|
bumps.z = sqrt(1.0-dot(bumps.xy,bumps.xy));
|
||||||
|
|
||||||
|
bumps = mix( vec3(0,0,1), bumps, blend );
|
||||||
|
|
||||||
|
norm.xy += bumps.xy*.1;
|
||||||
|
norm = normalize(norm);
|
||||||
|
|
||||||
|
float glossiness = mix(.7,1.0,bumps.z);
|
||||||
|
|
||||||
|
// reflection map
|
||||||
|
float ndoti = dot( view, norm );
|
||||||
|
vec3 rr = -view+2.0*ndoti*norm;
|
||||||
|
vec3 reflection = SkyDome( rr );
|
||||||
|
|
||||||
|
// specular
|
||||||
|
vec3 h = normalize(view+lightDir);
|
||||||
|
float specular = pow(max(0.0,dot(h,norm)),2000.0);
|
||||||
|
|
||||||
|
// should fresnel affect specular? or should it just be added?
|
||||||
|
reflection += specular*32.0*glossiness*ToLinear(lightColour);
|
||||||
|
|
||||||
|
// reflection of eyelids
|
||||||
|
//float eyelidReflection = smoothstep( 1.8, 2.0, eyelidMask );
|
||||||
|
// apply some parallax (subtle improvement when looking up/down at eye)
|
||||||
|
float eyelidReflection = smoothstep( .8, 1.0, GetEyelidMask( normalize(worldPos + rd*2.0)*EyeRadius, eyeRotation ) );
|
||||||
|
if ( !ReadKey( Key_O, true ) )
|
||||||
|
reflection *= eyelidReflection;
|
||||||
|
|
||||||
|
// fresnel
|
||||||
|
float fresnel = mix(.04*glossiness,1.0,pow(1.0-ndoti,5.0));
|
||||||
|
|
||||||
|
if ( !ReadKey( Key_R, true ) )
|
||||||
|
result = mix ( result, reflection, fresnel );
|
||||||
|
|
||||||
|
|
||||||
|
//anti-alias the edge
|
||||||
|
float mask2 = min( eyelidMask, (-worldPos.z-3.0) - (worldPos.x/tan(tau*.23)) );
|
||||||
|
result = mix( ToLinear(SkyColour), result, smoothstep(.0,.3,mask2) );
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Precision controls
|
||||||
|
const float epsilon = .003;
|
||||||
|
const float normalPrecision = .1;
|
||||||
|
const float shadowOffset = .1;
|
||||||
|
const int traceDepth = 100; // takes time
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------- BACK-END CODE -------
|
||||||
|
|
||||||
|
vec2 Noise2( in vec3 x )
|
||||||
|
{
|
||||||
|
vec3 p = floor(x.xzy);
|
||||||
|
vec3 f = fract(x.xzy);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);
|
||||||
|
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
|
||||||
|
vec4 rg = textureLod( iChannel0, (uv+0.5)/256.0, 0.0 );
|
||||||
|
return mix( rg.yw, rg.xz, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
float Noise( in vec3 x )
|
||||||
|
{
|
||||||
|
return Noise2(x).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Trace( vec3 ro, vec3 rd, vec4 eyeRotation )
|
||||||
|
{
|
||||||
|
float t = 0.0;
|
||||||
|
float dist = 1.0;
|
||||||
|
for ( int i=0; i < traceDepth; i++ )
|
||||||
|
{
|
||||||
|
if ( abs(dist) < epsilon || t > drawDistance || t < 0.0 )
|
||||||
|
continue;
|
||||||
|
dist = Isosurface( ro+rd*t, eyeRotation );
|
||||||
|
t = t+dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;//vec4(ro+rd*t,dist);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get normal
|
||||||
|
vec3 GetNormal( vec3 pos, vec4 eyeRotation )
|
||||||
|
{
|
||||||
|
const vec2 delta = vec2(normalPrecision, 0);
|
||||||
|
|
||||||
|
vec3 n;
|
||||||
|
|
||||||
|
// it's important this is centred on the pos, it fixes a lot of errors
|
||||||
|
n.x = Isosurface( pos + delta.xyy, eyeRotation ) - Isosurface( pos - delta.xyy, eyeRotation );
|
||||||
|
n.y = Isosurface( pos + delta.yxy, eyeRotation ) - Isosurface( pos - delta.yxy, eyeRotation );
|
||||||
|
n.z = Isosurface( pos + delta.yyx, eyeRotation ) - Isosurface( pos - delta.yyx, eyeRotation );
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// camera function by TekF
|
||||||
|
// compute ray from camera parameters
|
||||||
|
vec3 GetRay( vec3 dir, float zoom, vec2 uv )
|
||||||
|
{
|
||||||
|
uv = uv - .5;
|
||||||
|
uv.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
dir = zoom*normalize(dir);
|
||||||
|
vec3 right = normalize(cross(vec3(0,1,0),dir));
|
||||||
|
vec3 up = normalize(cross(dir,right));
|
||||||
|
|
||||||
|
return dir + right*uv.x + up*uv.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
|
||||||
|
vec3 camPos = CamPos;
|
||||||
|
vec3 camLook = CamLook;
|
||||||
|
|
||||||
|
vec2 camRot = .5*tau*(iMouse.xy-iResolution.xy*.5)/iResolution.x;
|
||||||
|
if ( !ReadKey( Key_M, true ) )
|
||||||
|
camRot = vec2(0,0);
|
||||||
|
camPos.yz = cos(camRot.y)*camPos.yz + sin(camRot.y)*camPos.zy*vec2(1,-1);
|
||||||
|
camPos.xz = cos(camRot.x)*camPos.xz + sin(camRot.x)*camPos.zx*vec2(1,-1);
|
||||||
|
|
||||||
|
vec4 eyeRotation = ComputeEyeRotation();
|
||||||
|
|
||||||
|
if ( Isosurface(camPos, eyeRotation) <= 0.0 )
|
||||||
|
{
|
||||||
|
// camera inside ground
|
||||||
|
fragColor = vec4(0,0,0,0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ro = camPos;
|
||||||
|
vec3 rd;
|
||||||
|
rd = GetRay( camLook-camPos, CamZoom, uv );
|
||||||
|
|
||||||
|
ro += rd*(NearPlane/CamZoom);
|
||||||
|
|
||||||
|
rd = normalize(rd);
|
||||||
|
|
||||||
|
float t = Trace(ro,rd,eyeRotation);
|
||||||
|
|
||||||
|
vec3 result = ToLinear(SkyColour);
|
||||||
|
if ( t > 0.0 && t < drawDistance )
|
||||||
|
{
|
||||||
|
vec3 pos = ro+t*rd;
|
||||||
|
|
||||||
|
vec3 norm = GetNormal(pos,eyeRotation);
|
||||||
|
|
||||||
|
// shadow test
|
||||||
|
float shadow = 1.0;
|
||||||
|
if ( Trace( pos+lightDir*shadowOffset, lightDir, eyeRotation ) < drawDistance )
|
||||||
|
shadow = 0.0;
|
||||||
|
|
||||||
|
result = Shading( pos, norm, shadow, rd, eyeRotation );
|
||||||
|
|
||||||
|
// fog
|
||||||
|
// result = mix ( SkyColour, result, exp(-t*t*.0002) );
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4( ToGamma( result ), 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,200 @@
|
||||||
|
//noise3.jpg
|
||||||
|
//Plasma Globe by nimitz (twitter: @stormoid)
|
||||||
|
|
||||||
|
//looks best with around 25 rays
|
||||||
|
#define NUM_RAYS 13.
|
||||||
|
|
||||||
|
#define VOLUMETRIC_STEPS 19
|
||||||
|
|
||||||
|
#define MAX_ITER 35
|
||||||
|
#define FAR 6.
|
||||||
|
|
||||||
|
#define time iGlobalTime*1.1
|
||||||
|
|
||||||
|
|
||||||
|
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,-s,s,c);}
|
||||||
|
float noise( in float x ){return textureLod(iChannel0, vec2(x*.01,1.),0.0).x;}
|
||||||
|
|
||||||
|
float hash( float n ){return fract(sin(n)*43758.5453);}
|
||||||
|
|
||||||
|
//iq's ubiquitous 3d noise
|
||||||
|
float noise(in vec3 p)
|
||||||
|
{
|
||||||
|
vec3 ip = floor(p);
|
||||||
|
vec3 f = fract(p);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
|
||||||
|
vec2 uv = (ip.xy+vec2(37.0,17.0)*ip.z) + f.xy;
|
||||||
|
vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0.0 ).yx;
|
||||||
|
return mix(rg.x, rg.y, f.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 m3 = mat3( 0.00, 0.80, 0.60,
|
||||||
|
-0.80, 0.36, -0.48,
|
||||||
|
-0.60, -0.48, 0.64 );
|
||||||
|
|
||||||
|
|
||||||
|
//See: https://www.shadertoy.com/view/XdfXRj
|
||||||
|
float flow(in vec3 p, in float t)
|
||||||
|
{
|
||||||
|
float z=2.;
|
||||||
|
float rz = 0.;
|
||||||
|
vec3 bp = p;
|
||||||
|
for (float i= 1.;i < 5.;i++ )
|
||||||
|
{
|
||||||
|
p += time*.1;
|
||||||
|
rz+= (sin(noise(p+t*0.8)*6.)*0.5+0.5) /z;
|
||||||
|
p = mix(bp,p,0.6);
|
||||||
|
z *= 2.;
|
||||||
|
p *= 2.01;
|
||||||
|
p*= m3;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
//could be improved
|
||||||
|
float sins(in float x)
|
||||||
|
{
|
||||||
|
float rz = 0.;
|
||||||
|
float z = 2.;
|
||||||
|
for (float i= 0.;i < 3.;i++ )
|
||||||
|
{
|
||||||
|
rz += abs(fract(x*1.4)-0.5)/z;
|
||||||
|
x *= 1.3;
|
||||||
|
z *= 1.15;
|
||||||
|
x -= time*.65*z;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float segm( vec3 p, vec3 a, vec3 b)
|
||||||
|
{
|
||||||
|
vec3 pa = p - a;
|
||||||
|
vec3 ba = b - a;
|
||||||
|
float h = clamp( dot(pa,ba)/dot(ba,ba), 0.0, 1. );
|
||||||
|
return length( pa - ba*h )*.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 path(in float i, in float d)
|
||||||
|
{
|
||||||
|
vec3 en = vec3(0.,0.,1.);
|
||||||
|
float sns2 = sins(d+i*0.5)*0.22;
|
||||||
|
float sns = sins(d+i*.6)*0.21;
|
||||||
|
en.xz *= mm2((hash(i*10.569)-.5)*6.2+sns2);
|
||||||
|
en.xy *= mm2((hash(i*4.732)-.5)*6.2+sns);
|
||||||
|
return en;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 map(vec3 p, float i)
|
||||||
|
{
|
||||||
|
float lp = length(p);
|
||||||
|
vec3 bg = vec3(0.);
|
||||||
|
vec3 en = path(i,lp);
|
||||||
|
|
||||||
|
float ins = smoothstep(0.11,.46,lp);
|
||||||
|
float outs = .15+smoothstep(.0,.15,abs(lp-1.));
|
||||||
|
p *= ins*outs;
|
||||||
|
float id = ins*outs;
|
||||||
|
|
||||||
|
float rz = segm(p, bg, en)-0.011;
|
||||||
|
return vec2(rz,id);
|
||||||
|
}
|
||||||
|
|
||||||
|
float march(in vec3 ro, in vec3 rd, in float startf, in float maxd, in float j)
|
||||||
|
{
|
||||||
|
float precis = 0.001;
|
||||||
|
float h=0.5;
|
||||||
|
float d = startf;
|
||||||
|
for( int i=0; i<MAX_ITER; i++ )
|
||||||
|
{
|
||||||
|
if( abs(h)<precis||d>maxd ) break;
|
||||||
|
d += h*1.2;
|
||||||
|
float res = map(ro+rd*d, j).x;
|
||||||
|
h = res;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
//volumetric marching
|
||||||
|
vec3 vmarch(in vec3 ro, in vec3 rd, in float j, in vec3 orig)
|
||||||
|
{
|
||||||
|
vec3 p = ro;
|
||||||
|
vec2 r = vec2(0.);
|
||||||
|
vec3 sum = vec3(0);
|
||||||
|
float w = 0.;
|
||||||
|
for( int i=0; i<VOLUMETRIC_STEPS; i++ )
|
||||||
|
{
|
||||||
|
r = map(p,j);
|
||||||
|
p += rd*.03;
|
||||||
|
float lp = length(p);
|
||||||
|
|
||||||
|
vec3 col = sin(vec3(1.05,2.5,1.52)*3.94+r.y)*.85+0.4;
|
||||||
|
col.rgb *= smoothstep(.0,.015,-r.x);
|
||||||
|
col *= smoothstep(0.04,.2,abs(lp-1.1));
|
||||||
|
col *= smoothstep(0.1,.34,lp);
|
||||||
|
sum += abs(col)*5. * (1.2-noise(lp*2.+j*13.+time*5.)*1.1) / (log(distance(p,orig)-2.)+.75);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns both collision dists of unit sphere
|
||||||
|
vec2 iSphere2(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
vec3 oc = ro;
|
||||||
|
float b = dot(oc, rd);
|
||||||
|
float c = dot(oc,oc) - 1.;
|
||||||
|
float h = b*b - c;
|
||||||
|
if(h <0.0) return vec2(-1.);
|
||||||
|
else return vec2((-b - sqrt(h)), (-b + sqrt(h)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 p = fragCoord.xy/iResolution.xy-0.5;
|
||||||
|
p.x*=iResolution.x/iResolution.y;
|
||||||
|
vec2 um = iMouse.xy / iResolution.xy-.5;
|
||||||
|
|
||||||
|
//camera
|
||||||
|
vec3 ro = vec3(0.,0.,5.);
|
||||||
|
vec3 rd = normalize(vec3(p*.7,-1.5));
|
||||||
|
mat2 mx = mm2(time*.4+um.x*6.);
|
||||||
|
mat2 my = mm2(time*0.3+um.y*6.);
|
||||||
|
ro.xz *= mx;rd.xz *= mx;
|
||||||
|
ro.xy *= my;rd.xy *= my;
|
||||||
|
|
||||||
|
vec3 bro = ro;
|
||||||
|
vec3 brd = rd;
|
||||||
|
|
||||||
|
vec3 col = vec3(0.0125,0.,0.025);
|
||||||
|
#if 1
|
||||||
|
for (float j = 1.;j<NUM_RAYS+1.;j++)
|
||||||
|
{
|
||||||
|
ro = bro;
|
||||||
|
rd = brd;
|
||||||
|
mat2 mm = mm2((time*0.1+((j+1.)*5.1))*j*0.25);
|
||||||
|
ro.xy *= mm;rd.xy *= mm;
|
||||||
|
ro.xz *= mm;rd.xz *= mm;
|
||||||
|
float rz = march(ro,rd,2.5,FAR,j);
|
||||||
|
if ( rz >= FAR)continue;
|
||||||
|
vec3 pos = ro+rz*rd;
|
||||||
|
col = max(col,vmarch(pos,rd,j, bro));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ro = bro;
|
||||||
|
rd = brd;
|
||||||
|
vec2 sph = iSphere2(ro,rd);
|
||||||
|
|
||||||
|
if (sph.x > 0.)
|
||||||
|
{
|
||||||
|
vec3 pos = ro+rd*sph.x;
|
||||||
|
vec3 pos2 = ro+rd*sph.y;
|
||||||
|
vec3 rf = reflect( rd, pos );
|
||||||
|
vec3 rf2 = reflect( rd, pos2 );
|
||||||
|
float nz = (-log(abs(flow(rf*1.2,time)-.01)));
|
||||||
|
float nz2 = (-log(abs(flow(rf2*1.2,-time)-.01)));
|
||||||
|
col += (0.1*nz*nz* vec3(0.12,0.12,.5) + 0.05*nz2*nz2*vec3(0.55,0.2,.55))*0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(col*1.3, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
// noise3.jpg
|
||||||
|
// Created by inigo quilez - iq/2013
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
|
||||||
|
|
||||||
|
// Volumetric clouds. It performs level of detail (LOD) for faster rendering
|
||||||
|
|
||||||
|
float noise( in vec3 x )
|
||||||
|
{
|
||||||
|
vec3 p = floor(x);
|
||||||
|
vec3 f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
|
||||||
|
vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0. ).yx;
|
||||||
|
#else
|
||||||
|
ivec3 q = ivec3(p);
|
||||||
|
ivec2 uv = q.xy + ivec2(37,17)*q.z;
|
||||||
|
|
||||||
|
vec2 rg = mix( mix( texelFetch( iChannel0, (uv )&255, 0 ),
|
||||||
|
texelFetch( iChannel0, (uv+ivec2(1,0))&255, 0 ), f.x ),
|
||||||
|
mix( texelFetch( iChannel0, (uv+ivec2(0,1))&255, 0 ),
|
||||||
|
texelFetch( iChannel0, (uv+ivec2(1,1))&255, 0 ), f.x ), f.y ).yx;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1.0+2.0*mix( rg.x, rg.y, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
float map5( in vec3 p )
|
||||||
|
{
|
||||||
|
vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
|
||||||
|
float f;
|
||||||
|
f = 0.50000*noise( q ); q = q*2.02;
|
||||||
|
f += 0.25000*noise( q ); q = q*2.03;
|
||||||
|
f += 0.12500*noise( q ); q = q*2.01;
|
||||||
|
f += 0.06250*noise( q ); q = q*2.02;
|
||||||
|
f += 0.03125*noise( q );
|
||||||
|
return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
float map4( in vec3 p )
|
||||||
|
{
|
||||||
|
vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
|
||||||
|
float f;
|
||||||
|
f = 0.50000*noise( q ); q = q*2.02;
|
||||||
|
f += 0.25000*noise( q ); q = q*2.03;
|
||||||
|
f += 0.12500*noise( q ); q = q*2.01;
|
||||||
|
f += 0.06250*noise( q );
|
||||||
|
return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
float map3( in vec3 p )
|
||||||
|
{
|
||||||
|
vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
|
||||||
|
float f;
|
||||||
|
f = 0.50000*noise( q ); q = q*2.02;
|
||||||
|
f += 0.25000*noise( q ); q = q*2.03;
|
||||||
|
f += 0.12500*noise( q );
|
||||||
|
return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
float map2( in vec3 p )
|
||||||
|
{
|
||||||
|
vec3 q = p - vec3(0.0,0.1,1.0)*iGlobalTime;
|
||||||
|
float f;
|
||||||
|
f = 0.50000*noise( q ); q = q*2.02;
|
||||||
|
f += 0.25000*noise( q );;
|
||||||
|
return clamp( 1.5 - p.y - 2.0 + 1.75*f, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sundir = normalize( vec3(-1.0,0.0,-1.0) );
|
||||||
|
|
||||||
|
vec4 integrate( in vec4 sum, in float dif, in float den, in vec3 bgcol, in float t )
|
||||||
|
{
|
||||||
|
// lighting
|
||||||
|
vec3 lin = vec3(0.65,0.7,0.75)*1.4 + vec3(1.0, 0.6, 0.3)*dif;
|
||||||
|
vec4 col = vec4( mix( vec3(1.0,0.95,0.8), vec3(0.25,0.3,0.35), den ), den );
|
||||||
|
col.xyz *= lin;
|
||||||
|
col.xyz = mix( col.xyz, bgcol, 1.0-exp(-0.003*t*t) );
|
||||||
|
// front to back blending
|
||||||
|
col.a *= 0.4;
|
||||||
|
col.rgb *= col.a;
|
||||||
|
return sum + col*(1.0-sum.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MARCH(STEPS,MAPLOD) for(int i=0; i<STEPS; i++) { vec3 pos = ro + t*rd; if( pos.y<-3.0 || pos.y>2.0 || sum.a > 0.99 ) break; float den = MAPLOD( pos ); if( den>0.01 ) { float dif = clamp((den - MAPLOD(pos+0.3*sundir))/0.6, 0.0, 1.0 ); sum = integrate( sum, dif, den, bgcol, t ); } t += max(0.05,0.02*t); }
|
||||||
|
|
||||||
|
vec4 raymarch( in vec3 ro, in vec3 rd, in vec3 bgcol, in ivec2 px )
|
||||||
|
{
|
||||||
|
vec4 sum = vec4(0.0);
|
||||||
|
|
||||||
|
float t = 0.05*texelFetch( iChannel0, px&255, 0 ).x;
|
||||||
|
|
||||||
|
MARCH(30,map5);
|
||||||
|
MARCH(30,map4);
|
||||||
|
MARCH(30,map3);
|
||||||
|
MARCH(30,map2);
|
||||||
|
|
||||||
|
return clamp( sum, 0.0, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 setCamera( in vec3 ro, in vec3 ta, float cr )
|
||||||
|
{
|
||||||
|
vec3 cw = normalize(ta-ro);
|
||||||
|
vec3 cp = vec3(sin(cr), cos(cr),0.0);
|
||||||
|
vec3 cu = normalize( cross(cw,cp) );
|
||||||
|
vec3 cv = normalize( cross(cu,cw) );
|
||||||
|
return mat3( cu, cv, cw );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 render( in vec3 ro, in vec3 rd, in ivec2 px )
|
||||||
|
{
|
||||||
|
// background sky
|
||||||
|
float sun = clamp( dot(sundir,rd), 0.0, 1.0 );
|
||||||
|
vec3 col = vec3(0.6,0.71,0.75) - rd.y*0.2*vec3(1.0,0.5,1.0) + 0.15*0.5;
|
||||||
|
col += 0.2*vec3(1.0,.6,0.1)*pow( sun, 8.0 );
|
||||||
|
|
||||||
|
// clouds
|
||||||
|
vec4 res = raymarch( ro, rd, col, px );
|
||||||
|
col = col*(1.0-res.w) + res.xyz;
|
||||||
|
|
||||||
|
// sun glare
|
||||||
|
col += 0.2*vec3(1.0,0.4,0.2)*pow( sun, 3.0 );
|
||||||
|
|
||||||
|
return vec4( col, 1.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 p = (-iResolution.xy + 2.0*fragCoord.xy)/ iResolution.y;
|
||||||
|
|
||||||
|
vec2 m = iMouse.xy/iResolution.xy;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
vec3 ro = 4.0*normalize(vec3(sin(3.0*m.x), 0.4*m.y, cos(3.0*m.x)));
|
||||||
|
vec3 ta = vec3(0.0, -1.0, 0.0);
|
||||||
|
mat3 ca = setCamera( ro, ta, 0.0 );
|
||||||
|
// ray
|
||||||
|
vec3 rd = ca * normalize( vec3(p.xy,1.5));
|
||||||
|
|
||||||
|
fragColor = render( ro, rd, ivec2(fragCoord-0.5) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainVR( out vec4 fragColor, in vec2 fragCoord, in vec3 fragRayOri, in vec3 fragRayDir )
|
||||||
|
{
|
||||||
|
fragColor = render( fragRayOri, fragRayDir, ivec2(fragCoord-0.5) );
|
||||||
|
}
|
|
@ -0,0 +1,168 @@
|
||||||
|
// Auroras by nimitz 2017 (twitter: @stormoid)
|
||||||
|
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
|
||||||
|
// Contact the author for other licensing options
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
There are two main hurdles I encountered rendering this effect.
|
||||||
|
First, the nature of the texture that needs to be generated to get a believable effect
|
||||||
|
needs to be very specific, with large scale band-like structures, small scale non-smooth variations
|
||||||
|
to create the trail-like effect, a method for animating said texture smoothly and finally doing all
|
||||||
|
of this cheaply enough to be able to evaluate it several times per fragment/pixel.
|
||||||
|
|
||||||
|
The second obstacle is the need to render a large volume while keeping the computational cost low.
|
||||||
|
Since the effect requires the trails to extend way up in the atmosphere to look good, this means
|
||||||
|
that the evaluated volume cannot be as constrained as with cloud effects. My solution was to make
|
||||||
|
the sample stride increase polynomially, which works very well as long as the trails are lower opcaity than
|
||||||
|
the rest of the effect. Which is always the case for auroras.
|
||||||
|
|
||||||
|
After that, there were some issues with getting the correct emission curves and removing banding at lowered
|
||||||
|
sample densities, this was fixed by a combination of sample number influenced dithering and slight sample blending.
|
||||||
|
|
||||||
|
N.B. the base setup is from an old shader and ideally the effect would take an arbitrary ray origin and
|
||||||
|
direction. But this was not required for this demo and would be trivial to fix.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define time iTime
|
||||||
|
|
||||||
|
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);}
|
||||||
|
mat2 m2 = mat2(0.95534, 0.29552, -0.29552, 0.95534);
|
||||||
|
float tri(in float x){return clamp(abs(fract(x)-.5),0.01,0.49);}
|
||||||
|
vec2 tri2(in vec2 p){return vec2(tri(p.x)+tri(p.y),tri(p.y+tri(p.x)));}
|
||||||
|
|
||||||
|
float triNoise2d(in vec2 p, float spd)
|
||||||
|
{
|
||||||
|
float z=1.8;
|
||||||
|
float z2=2.5;
|
||||||
|
float rz = 0.;
|
||||||
|
p *= mm2(p.x*0.06);
|
||||||
|
vec2 bp = p;
|
||||||
|
for (float i=0.; i<5.; i++ )
|
||||||
|
{
|
||||||
|
vec2 dg = tri2(bp*1.85)*.75;
|
||||||
|
dg *= mm2(time*spd);
|
||||||
|
p -= dg/z2;
|
||||||
|
|
||||||
|
bp *= 1.3;
|
||||||
|
z2 *= .45;
|
||||||
|
z *= .42;
|
||||||
|
p *= 1.21 + (rz-1.0)*.02;
|
||||||
|
|
||||||
|
rz += tri(p.x+tri(p.y))*z;
|
||||||
|
p*= -m2;
|
||||||
|
}
|
||||||
|
return clamp(1./pow(rz*29., 1.3),0.,.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hash21(in vec2 n){ return fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); }
|
||||||
|
vec4 aurora(vec3 ro, vec3 rd)
|
||||||
|
{
|
||||||
|
vec4 col = vec4(0);
|
||||||
|
vec4 avgCol = vec4(0);
|
||||||
|
|
||||||
|
for(float i=0.;i<50.;i++)
|
||||||
|
{
|
||||||
|
float of = 0.006*hash21(gl_FragCoord.xy)*smoothstep(0.,15., i);
|
||||||
|
float pt = ((.8+pow(i,1.4)*.002)-ro.y)/(rd.y*2.+0.4);
|
||||||
|
pt -= of;
|
||||||
|
vec3 bpos = ro + pt*rd;
|
||||||
|
vec2 p = bpos.zx;
|
||||||
|
float rzt = triNoise2d(p, 0.06);
|
||||||
|
vec4 col2 = vec4(0,0,0, rzt);
|
||||||
|
col2.rgb = (sin(1.-vec3(2.15,-.5, 1.2)+i*0.043)*0.5+0.5)*rzt;
|
||||||
|
avgCol = mix(avgCol, col2, .5);
|
||||||
|
col += avgCol*exp2(-i*0.065 - 2.5)*smoothstep(0.,5., i);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
col *= (clamp(rd.y*15.+.4,0.,1.));
|
||||||
|
|
||||||
|
|
||||||
|
//return clamp(pow(col,vec4(1.3))*1.5,0.,1.);
|
||||||
|
//return clamp(pow(col,vec4(1.7))*2.,0.,1.);
|
||||||
|
//return clamp(pow(col,vec4(1.5))*2.5,0.,1.);
|
||||||
|
//return clamp(pow(col,vec4(1.8))*1.5,0.,1.);
|
||||||
|
|
||||||
|
//return smoothstep(0.,1.1,pow(col,vec4(1.))*1.5);
|
||||||
|
return col*1.8;
|
||||||
|
//return pow(col,vec4(1.))*2.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------Background and Stars--------------------
|
||||||
|
|
||||||
|
vec3 nmzHash33(vec3 q)
|
||||||
|
{
|
||||||
|
uvec3 p = uvec3(ivec3(q));
|
||||||
|
p = p*uvec3(374761393U, 1103515245U, 668265263U) + p.zxy + p.yzx;
|
||||||
|
p = p.yzx*(p.zxy^(p >> 3U));
|
||||||
|
return vec3(p^(p >> 16U))*(1.0/vec3(0xffffffffU));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 stars(in vec3 p)
|
||||||
|
{
|
||||||
|
vec3 c = vec3(0.);
|
||||||
|
float res = iResolution.x*1.;
|
||||||
|
|
||||||
|
for (float i=0.;i<4.;i++)
|
||||||
|
{
|
||||||
|
vec3 q = fract(p*(.15*res))-0.5;
|
||||||
|
vec3 id = floor(p*(.15*res));
|
||||||
|
vec2 rn = nmzHash33(id).xy;
|
||||||
|
float c2 = 1.-smoothstep(0.,.6,length(q));
|
||||||
|
c2 *= step(rn.x,.0005+i*i*0.001);
|
||||||
|
c += c2*(mix(vec3(1.0,0.49,0.1),vec3(0.75,0.9,1.),rn.y)*0.1+0.9);
|
||||||
|
p *= 1.3;
|
||||||
|
}
|
||||||
|
return c*c*.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 bg(in vec3 rd)
|
||||||
|
{
|
||||||
|
float sd = dot(normalize(vec3(-0.5, -0.6, 0.9)), rd)*0.5+0.5;
|
||||||
|
sd = pow(sd, 5.);
|
||||||
|
vec3 col = mix(vec3(0.05,0.1,0.2), vec3(0.1,0.05,0.2), sd);
|
||||||
|
return col*.63;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 q = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = q - 0.5;
|
||||||
|
p.x*=iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
vec3 ro = vec3(0,0,-6.7);
|
||||||
|
vec3 rd = normalize(vec3(p,1.3));
|
||||||
|
vec2 mo = iMouse.xy / iResolution.xy-.5;
|
||||||
|
mo = (mo==vec2(-.5))?mo=vec2(-0.1,0.1):mo;
|
||||||
|
mo.x *= iResolution.x/iResolution.y;
|
||||||
|
rd.yz *= mm2(mo.y);
|
||||||
|
rd.xz *= mm2(mo.x + sin(time*0.05)*0.2);
|
||||||
|
|
||||||
|
vec3 col = vec3(0.);
|
||||||
|
vec3 brd = rd;
|
||||||
|
float fade = smoothstep(0.,0.01,abs(brd.y))*0.1+0.9;
|
||||||
|
|
||||||
|
col = bg(rd)*fade;
|
||||||
|
|
||||||
|
if (rd.y > 0.){
|
||||||
|
vec4 aur = smoothstep(0.,1.5,aurora(ro,rd))*fade;
|
||||||
|
col += stars(rd);
|
||||||
|
col = col*(1.-aur.a) + aur.rgb;
|
||||||
|
}
|
||||||
|
else //Reflections
|
||||||
|
{
|
||||||
|
rd.y = abs(rd.y);
|
||||||
|
col = bg(rd)*fade*0.6;
|
||||||
|
vec4 aur = smoothstep(0.0,2.5,aurora(ro,rd));
|
||||||
|
col += stars(rd)*0.1;
|
||||||
|
col = col*(1.-aur.a) + aur.rgb;
|
||||||
|
vec3 pos = ro + ((0.5-ro.y)/rd.y)*rd;
|
||||||
|
float nz2 = triNoise2d(pos.xz*vec2(.5,.7), 0.);
|
||||||
|
col += mix(vec3(0.2,0.25,0.5)*0.08,vec3(0.3,0.3,0.5)*0.7, nz2*0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(col, 1.);
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
// Viridis approximation, Jerome Liard, August 2016
|
||||||
|
// https://www.shadertoy.com/view/XtGGzG
|
||||||
|
|
||||||
|
// Applied polynomial regression to viridis color palettes so I could easily use them in shaders.
|
||||||
|
// Degree 5 seems to be a good fit (doesn't capture all details but...)
|
||||||
|
//
|
||||||
|
// Some credits/reference links about viridis palettes and why they are good, and some use examples:
|
||||||
|
//
|
||||||
|
// https://bids.github.io/colormap/ (says license is CC0)
|
||||||
|
// https://github.com/sjmgarnier/viridis#references @sjmgarnier
|
||||||
|
// https://cran.r-project.org/web/packages/viridis/vignettes/intro-to-viridis.html
|
||||||
|
//
|
||||||
|
// I learned about the existence of this palette via via https://www.mrao.cam.ac.uk/~dag/CUBEHELIX/ via @kenpex
|
||||||
|
|
||||||
|
//#define PLOT_CURVES
|
||||||
|
#define BLACK_BANDS
|
||||||
|
|
||||||
|
float saturate( float x ) { return clamp( x, 0.0, 1.0 ); }
|
||||||
|
|
||||||
|
vec3 viridis_quintic( float x )
|
||||||
|
{
|
||||||
|
x = saturate( x );
|
||||||
|
vec4 x1 = vec4( 1.0, x, x * x, x * x * x ); // 1 x x2 x3
|
||||||
|
vec4 x2 = x1 * x1.w * x; // x4 x5 x6 x7
|
||||||
|
return vec3(
|
||||||
|
dot( x1.xyzw, vec4( +0.280268003, -0.143510503, +2.225793877, -14.815088879 ) ) + dot( x2.xy, vec2( +25.212752309, -11.772589584 ) ),
|
||||||
|
dot( x1.xyzw, vec4( -0.002117546, +1.617109353, -1.909305070, +2.701152864 ) ) + dot( x2.xy, vec2( -1.685288385, +0.178738871 ) ),
|
||||||
|
dot( x1.xyzw, vec4( +0.300805501, +2.614650302, -12.019139090, +28.933559110 ) ) + dot( x2.xy, vec2( -33.491294770, +13.762053843 ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 inferno_quintic( float x )
|
||||||
|
{
|
||||||
|
x = saturate( x );
|
||||||
|
vec4 x1 = vec4( 1.0, x, x * x, x * x * x ); // 1 x x2 x3
|
||||||
|
vec4 x2 = x1 * x1.w * x; // x4 x5 x6 x7
|
||||||
|
return vec3(
|
||||||
|
dot( x1.xyzw, vec4( -0.027780558, +1.228188385, +0.278906882, +3.892783760 ) ) + dot( x2.xy, vec2( -8.490712758, +4.069046086 ) ),
|
||||||
|
dot( x1.xyzw, vec4( +0.014065206, +0.015360518, +1.605395918, -4.821108251 ) ) + dot( x2.xy, vec2( +8.389314011, -4.193858954 ) ),
|
||||||
|
dot( x1.xyzw, vec4( -0.019628385, +3.122510347, -5.893222355, +2.798380308 ) ) + dot( x2.xy, vec2( -3.608884658, +4.324996022 ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 magma_quintic( float x )
|
||||||
|
{
|
||||||
|
x = saturate( x );
|
||||||
|
vec4 x1 = vec4( 1.0, x, x * x, x * x * x ); // 1 x x2 x3
|
||||||
|
vec4 x2 = x1 * x1.w * x; // x4 x5 x6 x7
|
||||||
|
return vec3(
|
||||||
|
dot( x1.xyzw, vec4( -0.023226960, +1.087154378, -0.109964741, +6.333665763 ) ) + dot( x2.xy, vec2( -11.640596589, +5.337625354 ) ),
|
||||||
|
dot( x1.xyzw, vec4( +0.010680993, +0.176613780, +1.638227448, -6.743522237 ) ) + dot( x2.xy, vec2( +11.426396979, -5.523236379 ) ),
|
||||||
|
dot( x1.xyzw, vec4( -0.008260782, +2.244286052, +3.005587601, -24.279769818 ) ) + dot( x2.xy, vec2( +32.484310068, -12.688259703 ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 plasma_quintic( float x )
|
||||||
|
{
|
||||||
|
x = saturate( x );
|
||||||
|
vec4 x1 = vec4( 1.0, x, x * x, x * x * x ); // 1 x x2 x3
|
||||||
|
vec4 x2 = x1 * x1.w * x; // x4 x5 x6 x7
|
||||||
|
return vec3(
|
||||||
|
dot( x1.xyzw, vec4( +0.063861086, +1.992659096, -1.023901152, -0.490832805 ) ) + dot( x2.xy, vec2( +1.308442123, -0.914547012 ) ),
|
||||||
|
dot( x1.xyzw, vec4( +0.049718590, -0.791144343, +2.892305078, +0.811726816 ) ) + dot( x2.xy, vec2( -4.686502417, +2.717794514 ) ),
|
||||||
|
dot( x1.xyzw, vec4( +0.513275779, +1.580255060, -5.164414457, +4.559573646 ) ) + dot( x2.xy, vec2( -1.916810682, +0.570638854 ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float tri( float x ) { return 1.0 - abs( fract( x * 0.5 ) - 0.5 ) * 2.0; }
|
||||||
|
vec3 smoothstep_unchecked( vec3 x ) { return ( x * x ) * ( 3.0 - x * 2.0 ); }
|
||||||
|
vec3 smoothbump( vec3 a, vec3 r, vec3 x ) { return 1.0 - smoothstep_unchecked( min( abs( x - a ), r ) / r ); }
|
||||||
|
|
||||||
|
#ifdef SHADERTOY_STANDALONE
|
||||||
|
void main()
|
||||||
|
#else
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
fragColor.a = 1.0;
|
||||||
|
|
||||||
|
vec2 uv = fragCoord.xy / iResolution.xy;
|
||||||
|
|
||||||
|
if ( uv.y > 0.75 ) fragColor.xyz = viridis_quintic( uv.x );
|
||||||
|
else if ( uv.y > 0.5 ) fragColor.xyz = inferno_quintic( uv.x );
|
||||||
|
else if ( uv.y > 0.25 ) fragColor.xyz = magma_quintic( uv.x );
|
||||||
|
else if ( uv.y > 0.0 ) fragColor.xyz = plasma_quintic( uv.x );
|
||||||
|
|
||||||
|
#ifdef BLACK_BANDS
|
||||||
|
float r = 32.0 / iResolution.y;
|
||||||
|
fragColor.xyz *= step( r, tri( uv.y / 0.125 ) );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PLOT_CURVES
|
||||||
|
float y = fract( uv.y / 0.25 );
|
||||||
|
float r = 6.0 / iResolution.y;
|
||||||
|
fragColor.xyz += smoothbump( vec3( 0.0 ), vec3( r ), vec3( y ) - fragColor.xyz );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
//Cloud Ten by nimitz (twitter: @stormoid) noise3.jpg
|
||||||
|
|
||||||
|
#define time iGlobalTime
|
||||||
|
mat2 mm2(in float a){float c = cos(a), s = sin(a);return mat2(c,s,-s,c);}
|
||||||
|
float noise(float t){return textureLod(iChannel0,vec2(t,.0)/iChannelResolution[0].xy,0.0).x;}
|
||||||
|
float moy = 0.;
|
||||||
|
|
||||||
|
float noise(in vec3 x) //3d noise from iq
|
||||||
|
{
|
||||||
|
vec3 p = floor(x);
|
||||||
|
vec3 f = fract(x);
|
||||||
|
f = f*f*(3.0-2.0*f);
|
||||||
|
vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;
|
||||||
|
vec2 rg = textureLod( iChannel0, (uv+ 0.5)/256.0, 0.0 ).yx;
|
||||||
|
return mix( rg.x, rg.y, f.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
float fbm(in vec3 x)
|
||||||
|
{
|
||||||
|
float rz = 0.;
|
||||||
|
float a = .35;
|
||||||
|
for (int i = 0; i<2; i++)
|
||||||
|
{
|
||||||
|
rz += noise(x)*a;
|
||||||
|
a*=.35;
|
||||||
|
x*= 4.;
|
||||||
|
}
|
||||||
|
return rz;
|
||||||
|
}
|
||||||
|
|
||||||
|
float path(in float x){ return sin(x*0.01-3.1415)*28.+6.5; }
|
||||||
|
float map(vec3 p){
|
||||||
|
return p.y*0.07 + (fbm(p*0.3)-0.1) + sin(p.x*0.24 + sin(p.z*.01)*7.)*0.22+0.15 + sin(p.z*0.08)*0.05;
|
||||||
|
}
|
||||||
|
|
||||||
|
float march(in vec3 ro, in vec3 rd)
|
||||||
|
{
|
||||||
|
float precis = .3;
|
||||||
|
float h= 1.;
|
||||||
|
float d = 0.;
|
||||||
|
for( int i=0; i<17; i++ )
|
||||||
|
{
|
||||||
|
if( abs(h)<precis || d>70. ) break;
|
||||||
|
d += h;
|
||||||
|
vec3 pos = ro+rd*d;
|
||||||
|
pos.y += .5;
|
||||||
|
float res = map(pos)*7.;
|
||||||
|
h = res;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 lgt = vec3(0);
|
||||||
|
float mapV( vec3 p ){ return clamp(-map(p), 0., 1.);}
|
||||||
|
vec4 marchV(in vec3 ro, in vec3 rd, in float t, in vec3 bgc)
|
||||||
|
{
|
||||||
|
vec4 rz = vec4( 0.0 );
|
||||||
|
|
||||||
|
for( int i=0; i<150; i++ )
|
||||||
|
{
|
||||||
|
if(rz.a > 0.99 || t > 200.) break;
|
||||||
|
|
||||||
|
vec3 pos = ro + t*rd;
|
||||||
|
float den = mapV(pos);
|
||||||
|
|
||||||
|
vec4 col = vec4(mix( vec3(.8,.75,.85), vec3(.0), den ),den);
|
||||||
|
col.xyz *= mix(bgc*bgc*2.5, mix(vec3(0.1,0.2,0.55),vec3(.8,.85,.9),moy*0.4), clamp( -(den*40.+0.)*pos.y*.03-moy*0.5, 0., 1. ) );
|
||||||
|
col.rgb += clamp((1.-den*6.) + pos.y*0.13 +.55, 0., 1.)*0.35*mix(bgc,vec3(1),0.7); //Fringes
|
||||||
|
col += clamp(den*pos.y*.15, -.02, .0); //Depth occlusion
|
||||||
|
col *= smoothstep(0.2+moy*0.05,.0,mapV(pos+1.*lgt))*.85+0.15; //Shadows
|
||||||
|
|
||||||
|
col.a *= .9;
|
||||||
|
col.rgb *= col.a;
|
||||||
|
rz = rz + col*(1.0 - rz.a);
|
||||||
|
|
||||||
|
t += max(.4,(2.-den*30.)*t*0.011);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clamp(rz, 0., 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
float pent(in vec2 p){
|
||||||
|
vec2 q = abs(p);
|
||||||
|
return max(max(q.x*1.176-p.y*0.385, q.x*0.727+p.y), -p.y*1.237)*1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 flare(vec2 p, vec2 pos) //Inspired by mu6k's lens flare (https://www.shadertoy.com/view/4sX3Rs)
|
||||||
|
{
|
||||||
|
vec2 q = p-pos;
|
||||||
|
vec2 pds = p*(length(p))*0.75;
|
||||||
|
float a = atan(q.x,q.y);
|
||||||
|
|
||||||
|
float rz = .55*(pow(abs(fract(a*.8+.12)-0.5),3.)*(noise(a*15.)*0.9+.1)*exp2((-dot(q,q)*4.))); //Spokes
|
||||||
|
|
||||||
|
rz += max(1.0/(1.0+32.0*pent(pds+0.8*pos)),.0)*00.2; //Projected ghost (main lens)
|
||||||
|
vec2 p2 = mix(p,pds,-.5); //Reverse distort
|
||||||
|
rz += max(0.01-pow(pent(p2 + 0.4*pos),2.2),.0)*3.0;
|
||||||
|
rz += max(0.01-pow(pent(p2 + 0.2*pos),5.5),.0)*3.0;
|
||||||
|
rz += max(0.01-pow(pent(p2 - 0.1*pos),1.6),.0)*4.0;
|
||||||
|
rz += max(0.01-pow(pent(-(p2 + 1.*pos)),2.5),.0)*5.0;
|
||||||
|
rz += max(0.01-pow(pent(-(p2 - .5*pos)),2.),.0)*4.0;
|
||||||
|
rz += max(0.01-pow(pent(-(p2 + .7*pos)),5.),.0)*3.0;
|
||||||
|
|
||||||
|
return vec3(clamp(rz,0.,1.));
|
||||||
|
}
|
||||||
|
|
||||||
|
mat3 rot_x(float a){float sa = sin(a); float ca = cos(a); return mat3(1.,.0,.0, .0,ca,sa, .0,-sa,ca);}
|
||||||
|
mat3 rot_y(float a){float sa = sin(a); float ca = cos(a); return mat3(ca,.0,sa, .0,1.,.0, -sa,.0,ca);}
|
||||||
|
mat3 rot_z(float a){float sa = sin(a); float ca = cos(a); return mat3(ca,sa,.0, -sa,ca,.0, .0,.0,1.);}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
vec2 q = fragCoord.xy / iResolution.xy;
|
||||||
|
vec2 p = q - 0.5;
|
||||||
|
float asp =iResolution.x/iResolution.y;
|
||||||
|
p.x *= asp;
|
||||||
|
vec2 mo = iMouse.xy / iResolution.xy;
|
||||||
|
moy = mo.y;
|
||||||
|
float st = sin(time*0.3-1.3)*0.2;
|
||||||
|
vec3 ro = vec3(0.,-2.+sin(time*.3-1.)*2.,time*30.);
|
||||||
|
ro.x = path(ro.z);
|
||||||
|
vec3 ta = ro + vec3(0,0,1);
|
||||||
|
vec3 fw = normalize( ta - ro);
|
||||||
|
vec3 uu = normalize(cross( vec3(0.0,1.0,0.0), fw ));
|
||||||
|
vec3 vv = normalize(cross(fw,uu));
|
||||||
|
const float zoom = 1.;
|
||||||
|
vec3 rd = normalize( p.x*uu + p.y*vv + -zoom*fw );
|
||||||
|
|
||||||
|
float rox = sin(time*0.2)*0.8+2.9;
|
||||||
|
rox += smoothstep(0.6,1.2,sin(time*0.25))*3.5;
|
||||||
|
float roy = sin(time*0.5)*0.2;
|
||||||
|
mat3 rotation = rot_x(-roy)*rot_y(-rox+st*1.5)*rot_z(st);
|
||||||
|
mat3 inv_rotation = rot_z(-st)*rot_y(rox-st*1.5)*rot_x(roy);
|
||||||
|
rd *= rotation;
|
||||||
|
rd.y -= dot(p,p)*0.06;
|
||||||
|
rd = normalize(rd);
|
||||||
|
|
||||||
|
vec3 col = vec3(0.);
|
||||||
|
lgt = normalize(vec3(-0.3,mo.y+0.1,1.));
|
||||||
|
float rdl = clamp(dot(rd, lgt),0.,1.);
|
||||||
|
|
||||||
|
vec3 hor = mix( vec3(.9,.6,.7)*0.35, vec3(.5,0.05,0.05), rdl );
|
||||||
|
hor = mix(hor, vec3(.5,.8,1),mo.y);
|
||||||
|
col += mix( vec3(.2,.2,.6), hor, exp2(-(1.+ 3.*(1.-rdl))*max(abs(rd.y),0.)) )*.6;
|
||||||
|
col += .8*vec3(1.,.9,.9)*exp2(rdl*650.-650.);
|
||||||
|
col += .3*vec3(1.,1.,0.1)*exp2(rdl*100.-100.);
|
||||||
|
col += .5*vec3(1.,.7,0.)*exp2(rdl*50.-50.);
|
||||||
|
col += .4*vec3(1.,0.,0.05)*exp2(rdl*10.-10.);
|
||||||
|
vec3 bgc = col;
|
||||||
|
|
||||||
|
float rz = march(ro,rd);
|
||||||
|
|
||||||
|
if (rz < 70.)
|
||||||
|
{
|
||||||
|
vec4 res = marchV(ro, rd, rz-5., bgc);
|
||||||
|
col = col*(1.0-res.w) + res.xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 projected_flare = (-lgt*inv_rotation);
|
||||||
|
col += 1.4*vec3(0.7,0.7,0.4)*max(flare(p,-projected_flare.xy/projected_flare.z*zoom)*projected_flare.z,0.);
|
||||||
|
|
||||||
|
float g = smoothstep(0.03,.97,mo.x);
|
||||||
|
col = mix(mix(col,col.brg*vec3(1,0.75,1),clamp(g*2.,0.0,1.0)), col.bgr, clamp((g-0.5)*2.,0.0,1.));
|
||||||
|
|
||||||
|
col = clamp(col, 0., 1.);
|
||||||
|
col = col*0.5 + 0.5*col*col*(3.0-2.0*col); //saturation
|
||||||
|
col = pow(col, vec3(0.416667))*1.055 - 0.055; //sRGB
|
||||||
|
col *= pow( 16.0*q.x*q.y*(1.0-q.x)*(1.0-q.y), 0.12 ); //Vign
|
||||||
|
|
||||||
|
fragColor = vec4( col, 1.0 );
|
||||||
|
}
|
|
@ -0,0 +1,251 @@
|
||||||
|
float sdSphere(vec3 p, float r)
|
||||||
|
{
|
||||||
|
return length(p) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdCapsule(vec3 p, float h, float r)
|
||||||
|
{
|
||||||
|
return length(vec3(p.x, max(0.0, abs(p.y) - 0.5*h), p.z)) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sdCylinder( vec3 p, float h, float r )
|
||||||
|
{
|
||||||
|
vec2 d = abs(vec2(length(p.xz),p.y)) - vec2(r,h);
|
||||||
|
return min(max(d.x,d.y),0.0) + length(max(d,0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Scene
|
||||||
|
{
|
||||||
|
vec2 rot;
|
||||||
|
vec2 stre;
|
||||||
|
};
|
||||||
|
|
||||||
|
mat2 rot2(float theta)
|
||||||
|
{
|
||||||
|
float c = cos(theta);
|
||||||
|
float s = sin(theta);
|
||||||
|
return mat2(
|
||||||
|
c, -s,
|
||||||
|
s, c
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 apply_rot(vec3 p, vec2 rot)
|
||||||
|
{
|
||||||
|
p.xy *= rot2(rot.x);
|
||||||
|
p.yz *= rot2(rot.y);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
float smax(float a, float b, float k)
|
||||||
|
{
|
||||||
|
float dist = abs(a - b);
|
||||||
|
float res = max(a, b);
|
||||||
|
if (dist < k)
|
||||||
|
{
|
||||||
|
res += (1.0/(4.0*k))*(k-dist)*(k-dist);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
float smin(float a, float b, float k)
|
||||||
|
{
|
||||||
|
float dist = abs(a - b);
|
||||||
|
float res = min(a, b);
|
||||||
|
if (dist < k)
|
||||||
|
{
|
||||||
|
res -= (1.0/(4.0*k))*(k-dist)*(k-dist);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
float map_shell(Scene scene, vec3 p)
|
||||||
|
{
|
||||||
|
p = apply_rot(p, scene.rot);
|
||||||
|
float dist = sdCapsule(p-vec3(0,-0.4,0), 1.3, 0.43);
|
||||||
|
dist = smin(dist, sdCylinder(p-vec3(0,0.6,0), 0.6, 0.12), 0.03);
|
||||||
|
dist = smax(dist, -p.y-1.1, 0.02);
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 calc_normal_shell(Scene scene, vec3 p)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(0, 0.0001);
|
||||||
|
return normalize(vec3(map_shell(scene, p+e.yxx),
|
||||||
|
map_shell(scene, p+e.xyx),
|
||||||
|
map_shell(scene, p+e.xxy)) -
|
||||||
|
vec3(map_shell(scene, p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float map_body(Scene scene, vec3 p)
|
||||||
|
{
|
||||||
|
float dist = map_shell(scene, p)+0.04;
|
||||||
|
|
||||||
|
vec3 surfaceN = vec3(0,1,0);
|
||||||
|
// surface wobble
|
||||||
|
surfaceN.yz *= rot2(scene.stre.y*sin(10.0*iTime));
|
||||||
|
surfaceN.xy *= rot2(scene.stre.x*sin(10.0*iTime));
|
||||||
|
// travelling waves
|
||||||
|
float perturb = 0.1*(scene.stre.x*sin(4.0*(p.x+sign(scene.stre.x)*5.0*iTime)) +
|
||||||
|
scene.stre.y*sin(4.0*(p.z+sign(scene.stre.y)*5.0*iTime)));
|
||||||
|
// TODO: SDF is completely ruined if I remove the *0.1 here, why?
|
||||||
|
// does this screw up the SDF that badly?
|
||||||
|
dist = 0.1*max(dist, dot(p,surfaceN)-(0.0+perturb));
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 calc_normal_body(Scene scene, vec3 p)
|
||||||
|
{
|
||||||
|
vec2 e = vec2(0, 0.0001);
|
||||||
|
return normalize(vec3(map_body(scene,p+e.yxx),
|
||||||
|
map_body(scene,p+e.xyx),
|
||||||
|
map_body(scene,p+e.xxy)) -
|
||||||
|
vec3(map_body(scene,p)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 render(Scene scene, vec2 uv)
|
||||||
|
{
|
||||||
|
float cam_angle = 0.0 * 6.28;
|
||||||
|
vec3 ro = 2.0*vec3(sin(cam_angle), 0.2, -cos(cam_angle));
|
||||||
|
vec3 at = vec3(0);
|
||||||
|
vec3 cam_z = normalize(at - ro);
|
||||||
|
vec3 cam_x = normalize(cross(vec3(0, 1, 0), cam_z));
|
||||||
|
vec3 cam_y = cross(cam_z, cam_x);
|
||||||
|
vec3 rd = normalize(uv.x * cam_x + uv.y * cam_y + 1.3 * cam_z);
|
||||||
|
|
||||||
|
bool hit = false;
|
||||||
|
float t = 0.0;
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
vec3 p = ro + t * rd;
|
||||||
|
float dist = 0.1*map_shell(scene, p);
|
||||||
|
if (dist < 0.001)
|
||||||
|
{
|
||||||
|
hit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t += dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hit_inner = false;
|
||||||
|
float t_inner = 0.0;
|
||||||
|
for (int i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
vec3 p = ro + t_inner * rd;
|
||||||
|
float dist = map_body(scene, p);
|
||||||
|
if (dist < 0.001)
|
||||||
|
{
|
||||||
|
hit_inner = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
t_inner += dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 glass_f0 = vec3(0.5);
|
||||||
|
vec3 water_f0 = vec3(0.3);
|
||||||
|
vec3 keyLightCol = 1.5*vec3(1);//vec3(0.3, 0.5, 1.1);
|
||||||
|
vec3 keyLightDir = normalize(vec3(0.0,0.9,0.5));
|
||||||
|
vec3 waterDifCol = 1.3*vec3(0.3,0.6,0.8);
|
||||||
|
|
||||||
|
vec3 bgCol = texture(iChannel0, rd).rgb;
|
||||||
|
bgCol = bgCol * bgCol; // gamma -> linear
|
||||||
|
|
||||||
|
vec3 col = bgCol;
|
||||||
|
vec3 glass_fre = vec3(1);
|
||||||
|
if (hit)
|
||||||
|
{
|
||||||
|
vec3 p = ro + t * rd;
|
||||||
|
vec3 n = calc_normal_shell(scene, p);
|
||||||
|
vec3 l = rd - 2.0 * dot(rd, n) * n;
|
||||||
|
glass_fre = glass_f0 + (vec3(1) - glass_f0) * pow(1.0 - dot(n, l), 5.0);
|
||||||
|
|
||||||
|
{
|
||||||
|
float keyLightCos = dot(keyLightDir, l);
|
||||||
|
|
||||||
|
vec3 keyLight = texture(iChannel1, l).rgb;
|
||||||
|
vec3 spe = keyLight * glass_fre;
|
||||||
|
col = spe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hit_inner)
|
||||||
|
{
|
||||||
|
vec3 p = ro + t_inner * rd;
|
||||||
|
vec3 n = calc_normal_body(scene, p);
|
||||||
|
vec3 l = rd - 2.0 * dot(rd, n) * n;
|
||||||
|
vec3 fre = water_f0 + (vec3(1) - water_f0) * pow(1.0 - dot(n, l), 5.0);
|
||||||
|
|
||||||
|
{
|
||||||
|
float keyLightCos = dot(keyLightDir, l);
|
||||||
|
|
||||||
|
vec3 keyLight = texture(iChannel1, l).rgb;
|
||||||
|
vec3 spe = keyLight * fre;
|
||||||
|
vec3 dif = waterDifCol * keyLightCol * (0.05 + 0.3 * (0.5 + 0.5 * keyLightCos));
|
||||||
|
col = mix(col, spe + dif, 1.0-glass_fre);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
col = mix(col, bgCol,1.0-glass_fre);
|
||||||
|
}
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
// Normalized pixel coordinates (from 0 to 1)
|
||||||
|
vec2 uv = fragCoord/iResolution.xy;
|
||||||
|
uv = 2.0 * uv - 1.0;
|
||||||
|
uv.x *= iResolution.x / iResolution.y;
|
||||||
|
|
||||||
|
#define SIM1_DATA_IDX 0
|
||||||
|
#define SIM2_DATA_IDX 1
|
||||||
|
#define DATA_STRIDE 2
|
||||||
|
// simulation data stored in double-buffered packs of floats for persistent storage
|
||||||
|
int currPackIdx = iFrame & 1;
|
||||||
|
int nextPackIdx = (iFrame + 1) & 1;
|
||||||
|
vec4 sim1Data = texelFetch(iChannel2, ivec2(DATA_STRIDE*currPackIdx + SIM1_DATA_IDX, 0), 0);
|
||||||
|
vec4 sim2Data = texelFetch(iChannel2, ivec2(DATA_STRIDE*currPackIdx + SIM2_DATA_IDX, 0), 0);
|
||||||
|
|
||||||
|
vec2 prevMouseCoord = sim1Data.xy;
|
||||||
|
vec2 prevRot = sim1Data.zw;
|
||||||
|
vec2 prevStre = sim2Data.xy;
|
||||||
|
|
||||||
|
// reference: https://shadertoyunofficial.wordpress.com/2016/07/20/special-shadertoy-features/
|
||||||
|
bool mouseDown = iMouse.z > 0. && iMouse.w < 0.;
|
||||||
|
|
||||||
|
// compute current rotation
|
||||||
|
vec2 deltaRot = vec2(0);
|
||||||
|
if (iMouse.x > 0. && mouseDown)
|
||||||
|
deltaRot.x = (iMouse.x - prevMouseCoord.x) / 800.0 * 6.28;
|
||||||
|
if (iMouse.y > 0. && mouseDown)
|
||||||
|
deltaRot.y -= (iMouse.y - prevMouseCoord.y) / 450.0 * 6.28;
|
||||||
|
vec2 currRot = prevRot + deltaRot;
|
||||||
|
// dampening oscillation
|
||||||
|
vec2 stre = 0.3*abs(deltaRot) + 0.987*prevStre;
|
||||||
|
stre = min(vec2(0.5), stre);
|
||||||
|
|
||||||
|
// special routine for data pixels (not color pixels)
|
||||||
|
ivec2 iFragCoord = ivec2(fragCoord);
|
||||||
|
int nextPackBegin = nextPackIdx * DATA_STRIDE;
|
||||||
|
int nextPackEnd = nextPackBegin + DATA_STRIDE;
|
||||||
|
if (iFragCoord.x >= nextPackBegin && iFragCoord.y < nextPackEnd && iFragCoord.y == 0)
|
||||||
|
{
|
||||||
|
int dataIdx = iFragCoord.x - nextPackBegin;
|
||||||
|
if (dataIdx == SIM1_DATA_IDX)
|
||||||
|
fragColor = vec4(iMouse.xy, currRot);
|
||||||
|
if (dataIdx == SIM2_DATA_IDX)
|
||||||
|
fragColor = vec4(stre, 0, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene scene;
|
||||||
|
scene.rot = currRot;
|
||||||
|
scene.stre = stre;
|
||||||
|
|
||||||
|
vec3 col = render(scene, uv);
|
||||||
|
|
||||||
|
col = sqrt(col);
|
||||||
|
fragColor = vec4(col,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,306 @@
|
||||||
|
#define line1 h_ e_ l_ l_ o_ _ s_ h_ a_ d_ e_ r_ t_ o_ y_ crlf
|
||||||
|
#define line2 t_ h_ i_ s_ _ i_ s_ _ m_ y_ _ f_ o_ n_ t_ crlf
|
||||||
|
#define line3 h_ o_ p_ e_ _ y_ o_ u_ _ l_ i_ k_ e_ _ i_ t_ crlf
|
||||||
|
#define line4 f_ e_ e_ l_ _ f_ r_ e_ e_ _ t_ o_ _ u_ s_ e_ crlf
|
||||||
|
#define line5 _ a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ crlf
|
||||||
|
#define line6 _ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_
|
||||||
|
|
||||||
|
//======Start shared code for state
|
||||||
|
#define pz_stateYOffset 0.0
|
||||||
|
#define pz_stateBuf 0
|
||||||
|
#define pz_stateSample(x) texture(iChannel0,x)
|
||||||
|
vec2 pz_realBufferResolution;
|
||||||
|
vec2 pz_originalBufferResolution;
|
||||||
|
float pz_scale;
|
||||||
|
|
||||||
|
void pz_initializeState() {
|
||||||
|
pz_realBufferResolution = iChannelResolution[pz_stateBuf].xy;
|
||||||
|
pz_originalBufferResolution = pz_stateSample(.5/pz_realBufferResolution).xy;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pz_nr2vec(float nr) {
|
||||||
|
return vec2(mod(nr, pz_originalBufferResolution.x)
|
||||||
|
, pz_stateYOffset+floor(nr / pz_originalBufferResolution.x))+.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 pz_readState(float nr) {
|
||||||
|
return pz_stateSample(pz_nr2vec(nr)/pz_realBufferResolution);
|
||||||
|
}
|
||||||
|
|
||||||
|
float pz_resetCount() {
|
||||||
|
return pz_readState(1.).z;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 pz_position() {
|
||||||
|
return pz_readState(3.).xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 pz_initializeState(vec2 fragCoord) {
|
||||||
|
pz_initializeState();
|
||||||
|
|
||||||
|
vec3 position = pz_position();
|
||||||
|
fragCoord -= 0.5*iResolution.xy;
|
||||||
|
fragCoord *= pz_scale = position.z;
|
||||||
|
fragCoord += (0.5 + position.xy) * iResolution.xy ;
|
||||||
|
|
||||||
|
return fragCoord;
|
||||||
|
}
|
||||||
|
//======End shared code for state
|
||||||
|
|
||||||
|
// line function, used in k, s, v, w, x, y, z
|
||||||
|
float line(vec2 p, vec2 a, vec2 b)
|
||||||
|
{
|
||||||
|
vec2 pa = p - a;
|
||||||
|
vec2 ba = b - a;
|
||||||
|
float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0);
|
||||||
|
return length(pa - ba * h);
|
||||||
|
}
|
||||||
|
|
||||||
|
//These functions are re-used by multiple letters
|
||||||
|
float _u(vec2 uv,float w,float v) {
|
||||||
|
return length(vec2(
|
||||||
|
abs(length(vec2(uv.x,
|
||||||
|
max(0.0,-(.4-v)-uv.y) ))-w)
|
||||||
|
,max(0.,uv.y-.4))) +.4;
|
||||||
|
}
|
||||||
|
float _i(vec2 uv) {
|
||||||
|
return length(vec2(uv.x,max(0.,abs(uv.y)-.4)))+.4;
|
||||||
|
}
|
||||||
|
float _j(vec2 uv) {
|
||||||
|
uv.x+=.2;
|
||||||
|
float t = _u(uv,.25,-.15);
|
||||||
|
float x = uv.x>0.?t:length(vec2(uv.x,uv.y+.8))+.4;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float _l(vec2 uv) {
|
||||||
|
uv.y -= .2;
|
||||||
|
return length(vec2(uv.x,max(0.,abs(uv.y)-.6)))+.4;
|
||||||
|
}
|
||||||
|
float _o(vec2 uv) {
|
||||||
|
return abs(length(vec2(uv.x,max(0.,abs(uv.y)-.15)))-.25)+.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here is the alphabet
|
||||||
|
float aa(vec2 uv) {
|
||||||
|
uv = -uv;
|
||||||
|
float x = abs(length(vec2(max(0.,abs(uv.x)-.05),uv.y-.2))-.2)+.4;
|
||||||
|
x = min(x,length(vec2(uv.x+.25,max(0.,abs(uv.y-.2)-.2)))+.4);
|
||||||
|
return min(x,(uv.x<0.?uv.y<0.:atan(uv.x,uv.y+0.15)>2.)?_o(uv):length(vec2(uv.x-.22734,uv.y+.254))+.4);
|
||||||
|
}
|
||||||
|
float bb(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.x += .25;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float cc(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.y= abs(uv.y);
|
||||||
|
return uv.x<0.||atan(uv.x,uv.y-0.15)<1.14?x:length(vec2(uv.x-.22734,uv.y-.254))+.4;
|
||||||
|
}
|
||||||
|
float dd(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
return bb(uv);
|
||||||
|
}
|
||||||
|
float ee(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
return min(uv.x<0.||uv.y>.05||atan(uv.x,uv.y+0.15)>2.?x:length(vec2(uv.x-.22734,uv.y+.254))+.4,
|
||||||
|
length(vec2(max(0.,abs(uv.x)-.25),uv.y-.05))+.4);
|
||||||
|
}
|
||||||
|
float ff(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
uv.x += .05;
|
||||||
|
float x = _j(vec2(uv.x,-uv.y));
|
||||||
|
uv.y -= .4;
|
||||||
|
x = min(x,length(vec2(max(0.,abs(uv.x-.05)-.25),uv.y))+.4);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float gg(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
return min(x,uv.x>0.||uv.y<-.65?_u(uv,0.25,-0.2):length(vec2(uv.x+0.25,uv.y+.65))+.4 );
|
||||||
|
}
|
||||||
|
float hh(vec2 uv) {
|
||||||
|
uv.y *= -1.;
|
||||||
|
float x = _u(uv,.25,.25);
|
||||||
|
uv.x += .25;
|
||||||
|
uv.y *= -1.;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float ii(vec2 uv) {
|
||||||
|
return min(_i(uv),length(vec2(uv.x,uv.y-.7))+.4);
|
||||||
|
}
|
||||||
|
float jj(vec2 uv) {
|
||||||
|
uv.x += .05;
|
||||||
|
return min(_j(uv),length(vec2(uv.x-.05,uv.y-.7))+.4);
|
||||||
|
}
|
||||||
|
float kk(vec2 uv) {
|
||||||
|
float x = line(uv,vec2(-.25,-.1), vec2(0.25,0.4))+.4;
|
||||||
|
x = min(x,line(uv,vec2(-.15,.0), vec2(0.25,-0.4))+.4);
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float ll(vec2 uv) {
|
||||||
|
return _l(uv);
|
||||||
|
}
|
||||||
|
float mm(vec2 uv) {
|
||||||
|
//uv.x *= 1.4;
|
||||||
|
uv.y *= -1.;
|
||||||
|
uv.x-=.175;
|
||||||
|
float x = _u(uv,.175,.175);
|
||||||
|
uv.x+=.35;
|
||||||
|
x = min(x,_u(uv,.175,.175));
|
||||||
|
uv.x+=.175;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float nn(vec2 uv) {
|
||||||
|
uv.y *= -1.;
|
||||||
|
float x = _u(uv,.25,.25);
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float oo(vec2 uv) {
|
||||||
|
return _o(uv);
|
||||||
|
}
|
||||||
|
float pp(vec2 uv) {
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.x += .25;
|
||||||
|
uv.y += .4;
|
||||||
|
return min(x,_l(uv));
|
||||||
|
}
|
||||||
|
float qq(vec2 uv) {
|
||||||
|
uv.x = -uv.x;
|
||||||
|
return pp(uv);
|
||||||
|
}
|
||||||
|
float rr(vec2 uv) {
|
||||||
|
float x =atan(uv.x,uv.y-0.15)<1.14&&uv.y>0.?_o(uv):length(vec2(uv.x-.22734,uv.y-.254))+.4;
|
||||||
|
|
||||||
|
//)?_o(uv):length(vec2(uv.x-.22734,uv.y+.254))+.4);
|
||||||
|
|
||||||
|
uv.x+=.25;
|
||||||
|
return min(x,_i(uv));
|
||||||
|
}
|
||||||
|
float ss(vec2 uv) {
|
||||||
|
|
||||||
|
if (uv.y <.145 && uv.x>0. || uv.y<-.145)
|
||||||
|
uv = -uv;
|
||||||
|
|
||||||
|
float x = atan(uv.x-.05,uv.y-0.2)<1.14?
|
||||||
|
abs(length(vec2(max(0.,abs(uv.x)-.05),uv.y-.2))-.2)+.4:
|
||||||
|
length(vec2(uv.x-.231505,uv.y-.284))+.4;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float tt(vec2 uv) {
|
||||||
|
uv.x *= -1.;
|
||||||
|
uv.y -= .4;
|
||||||
|
uv.x += .05;
|
||||||
|
float x = min(_j(uv),length(vec2(max(0.,abs(uv.x-.05)-.25),uv.y))+.4);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float uu(vec2 uv) {
|
||||||
|
return _u(uv,.25,.25);
|
||||||
|
}
|
||||||
|
float vv(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return line(uv,vec2(0.25,0.4), vec2(0.,-0.4))+.4;
|
||||||
|
}
|
||||||
|
float ww(vec2 uv) {
|
||||||
|
uv.x=abs(uv.x);
|
||||||
|
return min(line(uv,vec2(0.3,0.4), vec2(.2,-0.4))+.4,
|
||||||
|
line(uv,vec2(0.2,-0.4), vec2(0.,0.1))+.4);
|
||||||
|
}
|
||||||
|
float xx(vec2 uv) {
|
||||||
|
uv=abs(uv);
|
||||||
|
return line(uv,vec2(0.,0.), vec2(.3,0.4))+.4;
|
||||||
|
}
|
||||||
|
float yy(vec2 uv) {
|
||||||
|
return min(line(uv,vec2(.0,-.2), vec2(-.3,0.4))+.4,
|
||||||
|
line(uv,vec2(.3,.4), vec2(-.3,-0.8))+.4);
|
||||||
|
}
|
||||||
|
float zz(vec2 uv) {
|
||||||
|
float l = line(uv,vec2(0.25,0.4), vec2(-0.25,-0.4))+.4;
|
||||||
|
uv.y=abs(uv.y);
|
||||||
|
float x = length(vec2(max(0.,abs(uv.x)-.25),uv.y-.4))+.4;
|
||||||
|
return min(x,l);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spare Q :)
|
||||||
|
float Q(vec2 uv) {
|
||||||
|
|
||||||
|
float x = _o(uv);
|
||||||
|
uv.y += .3;
|
||||||
|
uv.x -= .2;
|
||||||
|
return min(x,length(vec2(abs(uv.x+uv.y),max(0.,abs(uv.x-uv.y)-.2)))/sqrt(2.) +.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Render char if it's up
|
||||||
|
#define ch(l) if (nr++==ofs) x=min(x,l(uv));
|
||||||
|
|
||||||
|
//Make it a bit easier to type text
|
||||||
|
#define a_ ch(aa);
|
||||||
|
#define b_ ch(bb);
|
||||||
|
#define c_ ch(cc);
|
||||||
|
#define d_ ch(dd);
|
||||||
|
#define e_ ch(ee);
|
||||||
|
#define f_ ch(ff);
|
||||||
|
#define g_ ch(gg);
|
||||||
|
#define h_ ch(hh);
|
||||||
|
#define i_ ch(ii);
|
||||||
|
#define j_ ch(jj);
|
||||||
|
#define k_ ch(kk);
|
||||||
|
#define l_ ch(ll);
|
||||||
|
#define m_ ch(mm);
|
||||||
|
#define n_ ch(nn);
|
||||||
|
#define o_ ch(oo);
|
||||||
|
#define p_ ch(pp);
|
||||||
|
#define q_ ch(qq);
|
||||||
|
#define r_ ch(rr);
|
||||||
|
#define s_ ch(ss);
|
||||||
|
#define t_ ch(tt);
|
||||||
|
#define u_ ch(uu);
|
||||||
|
#define v_ ch(vv);
|
||||||
|
#define w_ ch(ww);
|
||||||
|
#define x_ ch(xx);
|
||||||
|
#define y_ ch(yy);
|
||||||
|
#define z_ ch(zz);
|
||||||
|
|
||||||
|
//Space
|
||||||
|
#define _ nr++;
|
||||||
|
|
||||||
|
//Next line
|
||||||
|
#define crlf uv.y += 2.0; nr = 0.;
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||||
|
{
|
||||||
|
fragCoord = pz_initializeState(fragCoord);
|
||||||
|
|
||||||
|
float scale = 1.0;//3.5-3.0*sin(iGlobalTime*.2);
|
||||||
|
vec2 uv = (fragCoord-0.5*iResolution.xy) / iResolution.x * 22.0 * scale;
|
||||||
|
|
||||||
|
float ofs = floor(uv.x)+8.;
|
||||||
|
uv.x = mod(uv.x,1.0)-.5;
|
||||||
|
|
||||||
|
float x = 100.;
|
||||||
|
float nr = 0.;
|
||||||
|
uv.y -= 5.;
|
||||||
|
|
||||||
|
line1;
|
||||||
|
line2;
|
||||||
|
line3;
|
||||||
|
line4;
|
||||||
|
line5;
|
||||||
|
line6;
|
||||||
|
|
||||||
|
vec3 clr = vec3(0.0);
|
||||||
|
|
||||||
|
float px = 17.0/iResolution.x*pz_scale;
|
||||||
|
|
||||||
|
clr.r = 0.7-0.7*smoothstep(0.49-px,0.49+px, x); // The body
|
||||||
|
clr.g = 0.7-0.7*smoothstep(0.00,px*1.5, abs(x-0.49+px)); // Yellow outline
|
||||||
|
clr.b = 0.4-0.4*smoothstep(0.43,0.53,1.0-x); // Background with shadow
|
||||||
|
clr.rg += 0.12-0.12*smoothstep(0.00,0.1+px, abs(x-0.49+px)); // Yellow glow
|
||||||
|
|
||||||
|
if (iMouse.w>0.1) {
|
||||||
|
clr.rgb = vec3(smoothstep(0.49-px,0.49+px, x));
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4(clamp(clr,0.0,1.0),1.0);
|
||||||
|
}
|
|
@ -0,0 +1,318 @@
|
||||||
|
// Created by Reinder Nijhoff 2013
|
||||||
|
// @reindernijhoff
|
||||||
|
|
||||||
|
// empirical measured values
|
||||||
|
#define EYEDISTANCE 5.15
|
||||||
|
#define LENSDISTANCE -0.136
|
||||||
|
#define FOV 0.62
|
||||||
|
|
||||||
|
#define SHADOW
|
||||||
|
//#define REFLECTION
|
||||||
|
|
||||||
|
#define RAYCASTSTEPS 30
|
||||||
|
|
||||||
|
#define EXPOSURE 0.9
|
||||||
|
#define EPSILON 0.0001
|
||||||
|
#define MAXDISTANCE 400.
|
||||||
|
#define GRIDSIZE 10.
|
||||||
|
#define GRIDSIZESMALL 8.
|
||||||
|
#define MAXHEIGHT 10.
|
||||||
|
#define SPEED 2.5
|
||||||
|
|
||||||
|
float time;
|
||||||
|
|
||||||
|
//
|
||||||
|
// math functions
|
||||||
|
//
|
||||||
|
|
||||||
|
const mat2 mr = mat2 (0.84147, 0.54030,
|
||||||
|
0.54030, -0.84147 );
|
||||||
|
float hash( float n ) {
|
||||||
|
return fract(sin(n)*43758.5453);
|
||||||
|
}
|
||||||
|
vec2 hash2( float n ) {
|
||||||
|
return fract(sin(vec2(n,n+1.0))*vec2(2.1459123,3.3490423));
|
||||||
|
}
|
||||||
|
vec2 hash2( vec2 n ) {
|
||||||
|
return fract(sin(vec2( n.x*n.y, n.x+n.y))*vec2(2.1459123,3.3490423));
|
||||||
|
}
|
||||||
|
vec3 hash3( float n ) {
|
||||||
|
return fract(sin(vec3(n,n+1.0,n+2.0))*vec3(3.5453123,4.1459123,1.3490423));
|
||||||
|
}
|
||||||
|
vec3 hash3( vec2 n ) {
|
||||||
|
return fract(sin(vec3(n.x, n.y, n+2.0))*vec3(3.5453123,4.1459123,1.3490423));
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// intersection functions
|
||||||
|
//
|
||||||
|
|
||||||
|
bool intersectPlane(vec3 ro, vec3 rd, float height, out float dist) {
|
||||||
|
if (rd.y==0.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float d = -(ro.y - height)/rd.y;
|
||||||
|
d = min(100000.0, d);
|
||||||
|
if( d > 0. ) {
|
||||||
|
dist = d;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool intersectUnitSphere ( in vec3 ro, in vec3 rd, in vec3 sph, out float dist, out vec3 normal ) {
|
||||||
|
vec3 ds = ro - sph;
|
||||||
|
float bs = dot( rd, ds );
|
||||||
|
float cs = dot( ds, ds ) - 1.0;
|
||||||
|
float ts = bs*bs - cs;
|
||||||
|
|
||||||
|
if( ts > 0.0 ) {
|
||||||
|
ts = -bs - sqrt( ts );
|
||||||
|
if( ts>0. ) {
|
||||||
|
normal = normalize( (ro+ts*rd)-sph );
|
||||||
|
dist = ts;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Scene
|
||||||
|
//
|
||||||
|
|
||||||
|
void getSphereOffset( vec2 grid, inout vec2 center ) {
|
||||||
|
center = (hash2( grid+vec2(43.12,1.23) ) - vec2(0.5) )*(GRIDSIZESMALL);
|
||||||
|
}
|
||||||
|
void getMovingSpherePosition( vec2 grid, vec2 sphereOffset, inout vec3 center ) {
|
||||||
|
// falling?
|
||||||
|
float s = 0.1+hash( grid.x*1.23114+5.342+754.324231*grid.y );
|
||||||
|
float t = 14.*s + time/s;
|
||||||
|
|
||||||
|
float y = s * MAXHEIGHT * abs( cos( t ) );
|
||||||
|
vec2 offset = grid + sphereOffset;
|
||||||
|
|
||||||
|
center = vec3( offset.x, y, offset.y ) + 0.5*vec3( GRIDSIZE, 2., GRIDSIZE );
|
||||||
|
}
|
||||||
|
void getSpherePosition( vec2 grid, vec2 sphereOffset, inout vec3 center ) {
|
||||||
|
vec2 offset = grid + sphereOffset;
|
||||||
|
center = vec3( offset.x, 0., offset.y ) + 0.5*vec3( GRIDSIZE, 2., GRIDSIZE );
|
||||||
|
}
|
||||||
|
vec3 getSphereColor( vec2 grid ) {
|
||||||
|
return normalize( hash3( grid+vec2(43.12*grid.y,12.23*grid.x) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 trace(vec3 ro, vec3 rd, out vec3 intersection, out vec3 normal, out float dist, out int material) {
|
||||||
|
material = 0; // sky
|
||||||
|
dist = MAXDISTANCE;
|
||||||
|
float distcheck;
|
||||||
|
|
||||||
|
vec3 sphereCenter, col, normalcheck;
|
||||||
|
|
||||||
|
if( intersectPlane( ro, rd, 0., distcheck) && distcheck < MAXDISTANCE ) {
|
||||||
|
dist = distcheck;
|
||||||
|
material = 1;
|
||||||
|
normal = vec3( 0., 1., 0. );
|
||||||
|
col = vec3( 1. );
|
||||||
|
} else {
|
||||||
|
col = vec3( 0. );
|
||||||
|
}
|
||||||
|
|
||||||
|
// trace grid
|
||||||
|
vec2 map = floor( ro.xz / GRIDSIZE ) * GRIDSIZE;
|
||||||
|
float deltaDistX = GRIDSIZE*sqrt(1. + (rd.z * rd.z) / (rd.x * rd.x));
|
||||||
|
float deltaDistY = GRIDSIZE*sqrt(1. + (rd.x * rd.x) / (rd.z * rd.z));
|
||||||
|
float stepX, stepY, sideDistX, sideDistY;
|
||||||
|
|
||||||
|
//calculate step and initial sideDist
|
||||||
|
if (rd.x < 0.) {
|
||||||
|
stepX = -GRIDSIZE;
|
||||||
|
sideDistX = (ro.x - map.x) * deltaDistX / GRIDSIZE;
|
||||||
|
} else {
|
||||||
|
stepX = GRIDSIZE;
|
||||||
|
sideDistX = (map.x + GRIDSIZE - ro.x) * deltaDistX / GRIDSIZE;
|
||||||
|
}
|
||||||
|
if (rd.z < 0.) {
|
||||||
|
stepY = -GRIDSIZE;
|
||||||
|
sideDistY = (ro.z - map.y) * deltaDistY / GRIDSIZE;
|
||||||
|
} else {
|
||||||
|
stepY = GRIDSIZE;
|
||||||
|
sideDistY = (map.y + GRIDSIZE - ro.z) * deltaDistY / GRIDSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hit = false;
|
||||||
|
|
||||||
|
for( int i=0; i<RAYCASTSTEPS; i++ ) {
|
||||||
|
if( hit || distance( ro.xz, map ) > dist+GRIDSIZE ) continue;
|
||||||
|
|
||||||
|
vec2 offset;
|
||||||
|
getSphereOffset( map, offset );
|
||||||
|
|
||||||
|
getMovingSpherePosition( map, -offset, sphereCenter );
|
||||||
|
|
||||||
|
if( intersectUnitSphere( ro, rd, sphereCenter, distcheck, normalcheck ) && distcheck < dist ) {
|
||||||
|
dist = distcheck;
|
||||||
|
normal = normalcheck;
|
||||||
|
material = 2;
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSpherePosition( map, offset, sphereCenter );
|
||||||
|
if( intersectUnitSphere( ro, rd, sphereCenter, distcheck, normalcheck ) && distcheck < dist ) {
|
||||||
|
dist = distcheck;
|
||||||
|
normal = normalcheck;
|
||||||
|
col = vec3( 2. );
|
||||||
|
material = 3;
|
||||||
|
hit = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sideDistX < sideDistY) {
|
||||||
|
sideDistX += deltaDistX;
|
||||||
|
map.x += stepX;
|
||||||
|
} else {
|
||||||
|
sideDistY += deltaDistY;
|
||||||
|
map.y += stepY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 color = vec3( 0. );
|
||||||
|
if( (hit || material == 1) ) {
|
||||||
|
intersection = ro + rd*dist;
|
||||||
|
vec2 map = intersection.xz - mod( intersection.xz, vec2(GRIDSIZE,GRIDSIZE) );
|
||||||
|
|
||||||
|
if( material == 1 || material == 3 ) {
|
||||||
|
// lightning
|
||||||
|
vec3 c = vec3( -GRIDSIZE,0., GRIDSIZE );
|
||||||
|
for( int x=0; x<3; x++ ) {
|
||||||
|
for( int y=0; y<3; y++ ) {
|
||||||
|
vec2 mapoffset = map+vec2( c[x], c[y] );
|
||||||
|
vec2 offset;
|
||||||
|
getSphereOffset( mapoffset, offset );
|
||||||
|
vec3 lcolor = getSphereColor( mapoffset );
|
||||||
|
vec3 lpos;
|
||||||
|
getMovingSpherePosition( mapoffset, -offset, lpos );
|
||||||
|
|
||||||
|
float shadow = 1.;
|
||||||
|
#ifdef SHADOW
|
||||||
|
if( material == 1 ) {
|
||||||
|
for( int sx=0; sx<3; sx++ ) {
|
||||||
|
for( int sy=0; sy<3; sy++ ) {
|
||||||
|
if( shadow < 1. ) continue;
|
||||||
|
|
||||||
|
vec2 smapoffset = map+vec2( c[sx], c[sy] );
|
||||||
|
vec2 soffset;
|
||||||
|
getSphereOffset( smapoffset, soffset );
|
||||||
|
vec3 slpos, sn;
|
||||||
|
getSpherePosition( smapoffset, soffset, slpos );
|
||||||
|
float sd;
|
||||||
|
if( intersectUnitSphere( intersection, normalize( lpos - intersection ), slpos, sd, sn ) ) {
|
||||||
|
shadow = 0.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
color += col * lcolor * ( shadow * max( dot( normalize(lpos-intersection), normal ), 0.) *
|
||||||
|
(1. - clamp( distance( lpos, intersection )/GRIDSIZE, 0., 1.) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// emitter
|
||||||
|
color = (1.5+dot(normal, vec3( 0.5, 0.5, -0.5) )) *getSphereColor( map );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
// left
|
||||||
|
float w = 1.0;
|
||||||
|
float h = 1.0;
|
||||||
|
float scaleFactor = 1.0;
|
||||||
|
|
||||||
|
vec2 leftLensCenter = vec2( LENSDISTANCE, 0. );
|
||||||
|
vec2 rightLensCenter = vec2( -LENSDISTANCE, 0. );
|
||||||
|
|
||||||
|
vec2 Scale;
|
||||||
|
vec2 ScaleIn = vec2( 1., 1.);
|
||||||
|
vec4 HmdWarpParam = vec4(1., 0.22, 0.24, 0);
|
||||||
|
|
||||||
|
vec2 HmdWarp(vec2 in01, vec2 lensCenter) {
|
||||||
|
vec2 theta = (in01-lensCenter) * ScaleIn; // Scales to [-1, 1]
|
||||||
|
float rSq = dot(theta, theta);
|
||||||
|
vec2 rvector = theta *
|
||||||
|
(HmdWarpParam.x + HmdWarpParam.y * rSq +
|
||||||
|
HmdWarpParam.z * rSq * rSq +
|
||||||
|
HmdWarpParam.w * rSq * rSq * rSq);
|
||||||
|
return lensCenter + Scale * rvector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
|
||||||
|
Scale = 0.65*vec2( 1., iResolution.x/iResolution.y );
|
||||||
|
time = iGlobalTime;
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
vec2 p = 2.0*q;
|
||||||
|
|
||||||
|
p.x *= 2.;
|
||||||
|
|
||||||
|
bool lefteye = true;
|
||||||
|
if( p.x > 2. ) {
|
||||||
|
p.x -= 2.;
|
||||||
|
lefteye = false;
|
||||||
|
}
|
||||||
|
p -= vec2(1.);
|
||||||
|
|
||||||
|
p = HmdWarp( p, lefteye?leftLensCenter:rightLensCenter );
|
||||||
|
|
||||||
|
|
||||||
|
p.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
// camera
|
||||||
|
vec3 ce = vec3( cos( 0.232*time) * 10., 7.+3.*cos(0.3*time), GRIDSIZE*(time/SPEED) );
|
||||||
|
vec3 ro = ce;
|
||||||
|
vec3 ta = ro + vec3( -sin( 0.232*time) * 10., -2.0+cos(0.23*time), 10.0 );
|
||||||
|
|
||||||
|
float roll = -0.15*sin(0.5*time);
|
||||||
|
|
||||||
|
// camera tx
|
||||||
|
vec3 cw = normalize( ta-ro );
|
||||||
|
vec3 cp = vec3( sin(roll), cos(roll),0.0 );
|
||||||
|
vec3 cu = normalize( cross(cw,cp) );
|
||||||
|
vec3 cv = normalize( cross(cu,cw) );
|
||||||
|
|
||||||
|
vec3 go = vec3( 0.0 );
|
||||||
|
go.x = (lefteye?-0.5*EYEDISTANCE:0.5*EYEDISTANCE);
|
||||||
|
ro += go.x*cu + go.y*cv;
|
||||||
|
|
||||||
|
// create offset voor left or right eye
|
||||||
|
vec3 er = normalize( vec3( p.xy, FOV ) );
|
||||||
|
vec3 rd = er.x*cu + er.y*cv + er.z*cw;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// raytrace
|
||||||
|
int material;
|
||||||
|
vec3 normal, intersection;
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
vec3 col = trace(ro, rd, intersection, normal, dist, material);
|
||||||
|
|
||||||
|
#ifdef REFLECTION
|
||||||
|
if( material > 0 ) {
|
||||||
|
vec3 ro = intersection + EPSILON*normal;
|
||||||
|
rd = reflect( rd, normal );
|
||||||
|
col += 0.05 * trace(ro, rd, intersection, normal, dist, material);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
col = pow( col, vec3(EXPOSURE, EXPOSURE, EXPOSURE) );
|
||||||
|
col = clamp(col, 0.0, 1.0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fragColor = vec4( col,1.0);
|
||||||
|
}
|
|
@ -0,0 +1,348 @@
|
||||||
|
// https://www.shadertoy.com/view/wsjBD3
|
||||||
|
// License CC0: A battered alien planet
|
||||||
|
// Been experimenting with space inspired shaders
|
||||||
|
|
||||||
|
#define PI 3.141592654
|
||||||
|
#define TAU (2.0*PI)
|
||||||
|
|
||||||
|
#define TOLERANCE 0.00001
|
||||||
|
#define MAX_ITER 65
|
||||||
|
#define MIN_DISTANCE 0.01
|
||||||
|
#define MAX_DISTANCE 9.0
|
||||||
|
|
||||||
|
const vec3 skyCol1 = vec3(0.35, 0.45, 0.6);
|
||||||
|
const vec3 skyCol2 = vec3(0.4, 0.7, 1.0);
|
||||||
|
const vec3 skyCol3 = pow(skyCol1, vec3(0.25));
|
||||||
|
const vec3 sunCol1 = vec3(1.0,0.6,0.4);
|
||||||
|
const vec3 sunCol2 = vec3(1.0,0.9,0.7);
|
||||||
|
const vec3 smallSunCol1 = vec3(1.0,0.5,0.25)*0.5;
|
||||||
|
const vec3 smallSunCol2 = vec3(1.0,0.5,0.25)*0.5;
|
||||||
|
const vec3 mountainColor = 1.0*sqrt(vec3(0.95, 0.65, 0.45));
|
||||||
|
const float cellWidth = 1.0;
|
||||||
|
const vec4 planet = vec4(80.0, -20.0, 100.0, 50.0)*1000.0;
|
||||||
|
|
||||||
|
void rot(inout vec2 p, float a) {
|
||||||
|
float c = cos(a);
|
||||||
|
float s = sin(a);
|
||||||
|
p = vec2(p.x*c + p.y*s, -p.x*s + p.y*c);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 mod2(inout vec2 p, vec2 size) {
|
||||||
|
vec2 c = floor((p + size*0.5)/size);
|
||||||
|
p = mod(p + size*0.5,size) - size*0.5;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
float circle(vec2 p, float r) {
|
||||||
|
return length(p) - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
float egg(vec2 p, float ra, float rb) {
|
||||||
|
const float k = sqrt(3.0);
|
||||||
|
p.x = abs(p.x);
|
||||||
|
float r = ra - rb;
|
||||||
|
return ((p.y<0.0) ? length(vec2(p.x, p.y )) - r :
|
||||||
|
(k*(p.x+r)<p.y) ? length(vec2(p.x, p.y-k*r)) :
|
||||||
|
length(vec2(p.x+r,p.y )) - 2.0*r) - rb;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 hash(vec2 p) {
|
||||||
|
p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
|
||||||
|
return -1. + 2.*fract (sin (p)*43758.5453123);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere) {
|
||||||
|
vec3 center = sphere.xyz;
|
||||||
|
float radius = sphere.w;
|
||||||
|
vec3 m = ro - center.xyz;
|
||||||
|
float b = dot(m, rd);
|
||||||
|
float c = dot(m, m) - radius*radius;
|
||||||
|
if(c > 0.0 && b > 0.0) return vec2(-1.0, -1.0);
|
||||||
|
float discr = b * b - c;
|
||||||
|
if(discr < 0.0) return vec2(-1.0);
|
||||||
|
float normalMultiplier = 1.0;
|
||||||
|
float s = sqrt(discr);
|
||||||
|
float t0 = -b - s;
|
||||||
|
float t1 = -b + s;;
|
||||||
|
return vec2(t0, t1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise1(vec2 p) {
|
||||||
|
vec2 n = mod2(p, vec2(cellWidth));
|
||||||
|
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
|
||||||
|
hh.x *= hh.y;
|
||||||
|
|
||||||
|
float r = 0.225*cellWidth;
|
||||||
|
|
||||||
|
float d = circle(p, 2.0*r);
|
||||||
|
|
||||||
|
float h = hh.x*smoothstep(0.0, r, -d);
|
||||||
|
|
||||||
|
return h*0.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
float noise2_(vec2 p) {
|
||||||
|
vec2 n = mod2(p, vec2(cellWidth));
|
||||||
|
vec2 hh = hash(sqrt(2.0)*(n+1000.0));
|
||||||
|
hh.x *= hh.y;
|
||||||
|
|
||||||
|
rot(p, TAU*hh.y);
|
||||||
|
float r = 0.45*cellWidth;
|
||||||
|
|
||||||
|
// float d = circle(p, 1.0*r);
|
||||||
|
float d = egg(p, 0.75*r, 0.5*r*abs(hh.y));
|
||||||
|
|
||||||
|
float h = (hh.x)*smoothstep(0.0, r, -2.0*d);
|
||||||
|
|
||||||
|
return h*0.275;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float height(vec2 p, float dd, int mx) {
|
||||||
|
const float aa = 0.45;
|
||||||
|
const float ff = 2.03;
|
||||||
|
const float tt = 1.2;
|
||||||
|
const float oo = 3.93;
|
||||||
|
const float near = 0.25;
|
||||||
|
const float far = 0.65;
|
||||||
|
|
||||||
|
float a = 1.0;
|
||||||
|
float o = 0.2;
|
||||||
|
float s = 0.0;
|
||||||
|
float d = 0.0;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < 4;++i) {
|
||||||
|
float nn = a*noise2_(p);
|
||||||
|
s += nn;
|
||||||
|
d += abs(a);
|
||||||
|
p += o;
|
||||||
|
a *= aa;
|
||||||
|
p *= ff;
|
||||||
|
o *= oo;
|
||||||
|
rot(p, tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
float lod = s/d;
|
||||||
|
|
||||||
|
float rdd = dd/MAX_DISTANCE;
|
||||||
|
mx = int(mix(float(4), float(mx), step(rdd, far)));
|
||||||
|
|
||||||
|
for (; i < mx; ++i) {
|
||||||
|
float nn = a*noise1(p);
|
||||||
|
s += nn;
|
||||||
|
d += abs(a);
|
||||||
|
p += o;
|
||||||
|
a *= aa;
|
||||||
|
p *= ff;
|
||||||
|
o *= oo;
|
||||||
|
rot(p, tt);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hid = (s/d);
|
||||||
|
|
||||||
|
return mix(hid, lod, smoothstep(near, far, rdd));
|
||||||
|
}
|
||||||
|
|
||||||
|
float loheight(vec2 p, float d) {
|
||||||
|
return height(p, d, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float height(vec2 p, float d) {
|
||||||
|
return height(p, d, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hiheight(vec2 p, float d) {
|
||||||
|
return height(p, d, 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal(vec2 p, float d) {
|
||||||
|
vec2 eps = vec2(0.00125, 0.0);
|
||||||
|
|
||||||
|
vec3 n;
|
||||||
|
|
||||||
|
n.x = (hiheight(p - eps.xy, d) - hiheight(p + eps.xy, d));
|
||||||
|
n.y = 2.0*eps.x;
|
||||||
|
n.z = (hiheight(p - eps.yx, d) - hiheight(p + eps.yx, d));
|
||||||
|
|
||||||
|
return normalize(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
const float stepLength[] = float[](0.9, 0.25);
|
||||||
|
|
||||||
|
|
||||||
|
float march(vec3 ro, vec3 rd, out int max_iter) {
|
||||||
|
float dt = 0.1;
|
||||||
|
float d = MIN_DISTANCE;
|
||||||
|
int currentStep = 0;
|
||||||
|
float lastd = d;
|
||||||
|
for (int i = 0; i < MAX_ITER; ++i)
|
||||||
|
{
|
||||||
|
vec3 p = ro + d*rd;
|
||||||
|
float h = height(p.xz, d);
|
||||||
|
|
||||||
|
if (d > MAX_DISTANCE) {
|
||||||
|
max_iter = i;
|
||||||
|
return MAX_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
float hd = p.y - h;
|
||||||
|
|
||||||
|
if (hd < TOLERANCE) {
|
||||||
|
++currentStep;
|
||||||
|
if (currentStep >= stepLength.length()) {
|
||||||
|
max_iter = i;
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
d = lastd;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sl = stepLength[currentStep];
|
||||||
|
|
||||||
|
dt = max(hd, TOLERANCE)*sl + 0.0025*d;
|
||||||
|
lastd = d;
|
||||||
|
d += dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_iter = MAX_ITER;
|
||||||
|
return MAX_DISTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 sunDirection() {
|
||||||
|
return normalize(vec3(-0.5, 0.085, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 smallSunDirection() {
|
||||||
|
return normalize(vec3(-0.2, -0.05, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
float psin(float f) {
|
||||||
|
return 0.5 + 0.5*sin(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 skyColor(vec3 ro, vec3 rd) {
|
||||||
|
vec3 sunDir = sunDirection();
|
||||||
|
vec3 smallSunDir = smallSunDirection();
|
||||||
|
|
||||||
|
float sunDot = max(dot(rd, sunDir), 0.0);
|
||||||
|
float smallSunDot = max(dot(rd, smallSunDir), 0.0);
|
||||||
|
|
||||||
|
float angle = atan(rd.y, length(rd.xz))*2.0/PI;
|
||||||
|
|
||||||
|
vec3 skyCol = mix(mix(skyCol1, skyCol2, max(0.0, angle)), skyCol3, clamp(-angle*2.0, 0.0, 1.0));
|
||||||
|
|
||||||
|
vec3 sunCol = 0.5*sunCol1*pow(sunDot, 20.0) + 8.0*sunCol2*pow(sunDot, 2000.0);
|
||||||
|
vec3 smallSunCol = 0.5*smallSunCol1*pow(smallSunDot, 200.0) + 8.0*smallSunCol2*pow(smallSunDot, 20000.0);
|
||||||
|
|
||||||
|
vec3 dust = pow(sunCol2*mountainColor, vec3(1.75))*smoothstep(0.05, -0.1, rd.y)*0.5;
|
||||||
|
|
||||||
|
vec2 si = raySphere(ro, rd, planet);
|
||||||
|
|
||||||
|
vec3 planetSurface = ro + si.x*rd;
|
||||||
|
vec3 planetNormal = normalize(planetSurface - planet.xyz);
|
||||||
|
float planetDiff = max(dot(planetNormal, sunDir), 0.0);
|
||||||
|
float planetBorder = max(dot(planetNormal, -rd), 0.0);
|
||||||
|
float planetLat = (planetSurface.x+planetSurface.y)*0.0005;
|
||||||
|
vec3 planetCol = mix(1.3*vec3(0.9, 0.8, 0.7), 0.3*vec3(0.9, 0.8, 0.7), pow(psin(planetLat+1.0)*psin(sqrt(2.0)*planetLat+2.0)*psin(sqrt(3.5)*planetLat+3.0), 0.5));
|
||||||
|
|
||||||
|
vec3 final = vec3(0.0);
|
||||||
|
|
||||||
|
final += step(0.0, si.x)*pow(planetDiff, 0.75)*planetCol*smoothstep(-0.075, 0.0, rd.y)*smoothstep(0.0, 0.1, planetBorder);
|
||||||
|
|
||||||
|
final += skyCol + sunCol + smallSunCol + dust;
|
||||||
|
|
||||||
|
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getColor(vec3 ro, vec3 rd) {
|
||||||
|
int max_iter = 0;
|
||||||
|
vec3 skyCol = skyColor(ro, rd);
|
||||||
|
vec3 col = vec3(0);
|
||||||
|
|
||||||
|
float d = march(ro, rd, max_iter);
|
||||||
|
|
||||||
|
if (d < MAX_DISTANCE) {
|
||||||
|
vec3 sunDir = sunDirection();
|
||||||
|
vec3 osunDir = sunDir*vec3(-1.0, .0, -1.0);
|
||||||
|
vec3 p = ro + d*rd;
|
||||||
|
|
||||||
|
vec3 normal = normal(p.xz, d);
|
||||||
|
|
||||||
|
float amb = 0.2;
|
||||||
|
|
||||||
|
float dif1 = max(0.0, dot(sunDir, normal));
|
||||||
|
vec3 shd1 = sunCol2*mix(amb, 1.0, pow(dif1, 0.75));
|
||||||
|
|
||||||
|
float dif2 = max(0.0, dot(osunDir, normal));
|
||||||
|
vec3 shd2 = sunCol1*mix(amb, 1.0, pow(dif2, 0.75));
|
||||||
|
|
||||||
|
vec3 ref = reflect(rd, normal);
|
||||||
|
vec3 rcol = skyColor(p, ref);
|
||||||
|
|
||||||
|
col = mountainColor*amb*skyCol3;
|
||||||
|
col += mix(shd1, shd2, -0.5)*mountainColor;
|
||||||
|
float fre = max(dot(normal, -rd), 0.0);
|
||||||
|
fre = pow(1.0 - fre, 5.0);
|
||||||
|
col += rcol*fre*0.5;
|
||||||
|
col += (1.0*p.y);
|
||||||
|
col = tanh(col);
|
||||||
|
col = mix(col, skyCol, smoothstep(0.5*MAX_DISTANCE, 1.0*MAX_DISTANCE, d));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
col = skyCol;
|
||||||
|
}
|
||||||
|
|
||||||
|
// col += vec3(1.1, 0.0, 0.0)* smoothstep(0.25, 1.0,(float(max_iter)/float(MAX_ITER)));
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSample1(vec2 p, float time) {
|
||||||
|
float off = 0.5*iTime;
|
||||||
|
|
||||||
|
vec3 ro = vec3(0.5, 1.0-0.25, -2.0 + off);
|
||||||
|
vec3 la = ro + vec3(0.0, -0.30, 2.0);
|
||||||
|
|
||||||
|
vec3 ww = normalize(la - ro);
|
||||||
|
vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
|
||||||
|
vec3 vv = normalize(cross(ww, uu));
|
||||||
|
vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
|
||||||
|
|
||||||
|
vec3 col = getColor(ro, rd) ;
|
||||||
|
|
||||||
|
return col;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getSample2(vec2 p, float time) {
|
||||||
|
p.y-=time*0.25;
|
||||||
|
float h = height(p, 0.0);
|
||||||
|
vec3 n = normal(p, 0.0);
|
||||||
|
|
||||||
|
vec3 lp = vec3(10.0, -1.2, 0.0);
|
||||||
|
|
||||||
|
vec3 ld = normalize(vec3(p.x, h, p.y)- lp);
|
||||||
|
|
||||||
|
float d = max(dot(ld, n), 0.0);
|
||||||
|
|
||||||
|
vec3 col = vec3(0.0);
|
||||||
|
|
||||||
|
col = vec3(1.0)*(h+0.1);
|
||||||
|
col += vec3(1.5)*pow(d, 0.75);
|
||||||
|
|
||||||
|
return col;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainImage(out vec4 fragColor, vec2 fragCoord) {
|
||||||
|
vec2 q = fragCoord.xy/iResolution.xy;
|
||||||
|
vec2 p = -1.0 + 2.0*q;
|
||||||
|
p.x *= iResolution.x/iResolution.y;
|
||||||
|
|
||||||
|
vec3 col = getSample1(p, iTime);
|
||||||
|
|
||||||
|
fragColor = vec4(col, 1.0);
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#!/bin/bash 2>nul || goto :windows
|
||||||
|
|
||||||
|
if [ "$1" = "" ]; then
|
||||||
|
sh MAKE.bat demo_collide.c
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
## clone emscripten sdk
|
||||||
|
git clone https://github.com/emscripten-core/emsdk ../../../../../emsdk
|
||||||
|
pushd ../../../../../emsdk
|
||||||
|
./emsdk install 3.0.0 ## latest
|
||||||
|
./emsdk activate 3.0.0 ## latest
|
||||||
|
source ./emsdk_env.sh
|
||||||
|
popd
|
||||||
|
|
||||||
|
## cook art
|
||||||
|
if [ "$(uname)" = "Darwin" ]; then
|
||||||
|
chmod +x ../../../tools/cook.osx
|
||||||
|
../../../tools/cook.osx
|
||||||
|
else
|
||||||
|
chmod +x ../../../tools/cook.linux
|
||||||
|
../../../tools/cook.linux
|
||||||
|
fi
|
||||||
|
|
||||||
|
## host webserver, compile and launch
|
||||||
|
python -m http.server --bind 127.0.0.1 8000 1> /dev/null 2> /dev/null &
|
||||||
|
emcc $@ -g ../../../code/v4k.c -I../../../code -o index.html -s FULL_ES3 -s USE_GLFW=3 -s SINGLE_FILE=1 -s PRECISE_F32=1 -s TOTAL_MEMORY=256mb -s ENVIRONMENT=worker,web --shell-file template.html -Wfatal-errors --preload-file .art[00].zip -s ALLOW_MEMORY_GROWTH=1 -lidbfs.js && xdg-open http://localhost:8000/index.html
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
:windows
|
||||||
|
|
||||||
|
if "%1"=="" MAKE.bat demo_ui.c
|
||||||
|
|
||||||
|
rem clone emscripten sdk
|
||||||
|
if not exist "emsdk" (
|
||||||
|
git clone https://github.com/emscripten-core/emsdk emsdk
|
||||||
|
pushd emsdk
|
||||||
|
call emsdk install 3.0.0 && rem latest
|
||||||
|
call emsdk activate 3.0.0 && rem latest
|
||||||
|
popd
|
||||||
|
)
|
||||||
|
if "%EMSDK%"=="" call emsdk\emsdk_env.bat --system
|
||||||
|
|
||||||
|
rem cook art
|
||||||
|
..\..\tools\cook.exe --cook-jobs=1 --cook-ini=..\..\tools\cook.ini
|
||||||
|
|
||||||
|
rem host webserver, compile and launch
|
||||||
|
rem start python -m http.server --bind 127.0.0.1 8000
|
||||||
|
emcc %* -g ..\..\engine\v4k.c -I..\..\engine -o index.html -pthread -s FULL_ES3 -s USE_PTHREADS -s USE_GLFW=3 -s SINGLE_FILE=1 -s PRECISE_F32=1 -s TOTAL_MEMORY=256mb -s ENVIRONMENT=worker,web --shell-file template.html -Wfatal-errors --preload-file .art[00].zip -s ALLOW_MEMORY_GROWTH=1 -lidbfs.js
|
||||||
|
rem && start "" http://localhost:8000/index.html
|
|
@ -0,0 +1,20 @@
|
||||||
|
## Known HTML5 issues:
|
||||||
|
- [x] Game loop is event based (fixed: see `window_loop()`)
|
||||||
|
- [x] No automated emsdk installation (fixed: see `demos/html5/MAKE.bat`)
|
||||||
|
- [x] Art must be cooked beforehand (fixed: see `demos/html5/MAKE.bat`)
|
||||||
|
- [x] No VFS loading (fixed)
|
||||||
|
- [x] No UI rendering (fixed)
|
||||||
|
- [x] No cooker (fixed: win,osx,linux)
|
||||||
|
- [x] No input (fixed)
|
||||||
|
- [x] No gamepads (fixed)
|
||||||
|
- [x] No multi-touch (fixed)
|
||||||
|
- [ ] No audio
|
||||||
|
- [ ] No file writing (untested)
|
||||||
|
- [ ] No glTexture1D()
|
||||||
|
- [ ] No network
|
||||||
|
- [ ] No fbos
|
||||||
|
- [ ] No callstacks
|
||||||
|
- [ ] No pbos
|
||||||
|
- [ ] Shaders require (automated?) GL->GLES translation (No postfxs, models, skyboxes, pbrs, ...) (@todo: embed Spir-v/glslcross tools?)
|
||||||
|
- [ ] Shaders: `vec2 iResolution = vec2(iWidth, iHeight); // ERROR: '=' : global variable initializers must be constant expressions`
|
||||||
|
- [ ] Shaders: `uniform float var = 1.0f; // ERROR: 'uniform' : cannot initialize this type of qualifier`
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
|
||||||
|
let coepCredentialless = false;
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
self.addEventListener("install", () => self.skipWaiting());
|
||||||
|
self.addEventListener("activate", (event) => event.waitUntil(self.clients.claim()));
|
||||||
|
|
||||||
|
self.addEventListener("message", (ev) => {
|
||||||
|
if (!ev.data) {
|
||||||
|
return;
|
||||||
|
} else if (ev.data.type === "deregister") {
|
||||||
|
self.registration
|
||||||
|
.unregister()
|
||||||
|
.then(() => {
|
||||||
|
return self.clients.matchAll();
|
||||||
|
})
|
||||||
|
.then(clients => {
|
||||||
|
clients.forEach((client) => client.navigate(client.url));
|
||||||
|
});
|
||||||
|
} else if (ev.data.type === "coepCredentialless") {
|
||||||
|
coepCredentialless = ev.data.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener("fetch", function (event) {
|
||||||
|
const r = event.request;
|
||||||
|
if (r.cache === "only-if-cached" && r.mode !== "same-origin") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const request = (coepCredentialless && r.mode === "no-cors")
|
||||||
|
? new Request(r, {
|
||||||
|
credentials: "omit",
|
||||||
|
})
|
||||||
|
: r;
|
||||||
|
event.respondWith(
|
||||||
|
fetch(request)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 0) {
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newHeaders = new Headers(response.headers);
|
||||||
|
newHeaders.set("Cross-Origin-Embedder-Policy",
|
||||||
|
coepCredentialless ? "credentialless" : "require-corp"
|
||||||
|
);
|
||||||
|
if (!coepCredentialless) {
|
||||||
|
newHeaders.set("Cross-Origin-Resource-Policy", "cross-origin");
|
||||||
|
}
|
||||||
|
newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");
|
||||||
|
|
||||||
|
return new Response(response.body, {
|
||||||
|
status: response.status,
|
||||||
|
statusText: response.statusText,
|
||||||
|
headers: newHeaders,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => console.error(e))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
(() => {
|
||||||
|
// You can customize the behavior of this script through a global `coi` variable.
|
||||||
|
const coi = {
|
||||||
|
shouldRegister: () => true,
|
||||||
|
shouldDeregister: () => false,
|
||||||
|
coepCredentialless: () => (window.chrome !== undefined || window.netscape !== undefined),
|
||||||
|
doReload: () => window.location.reload(),
|
||||||
|
quiet: false,
|
||||||
|
...window.coi
|
||||||
|
};
|
||||||
|
|
||||||
|
const n = navigator;
|
||||||
|
|
||||||
|
if (n.serviceWorker && n.serviceWorker.controller) {
|
||||||
|
n.serviceWorker.controller.postMessage({
|
||||||
|
type: "coepCredentialless",
|
||||||
|
value: coi.coepCredentialless(),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (coi.shouldDeregister()) {
|
||||||
|
n.serviceWorker.controller.postMessage({ type: "deregister" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're already coi: do nothing. Perhaps it's due to this script doing its job, or COOP/COEP are
|
||||||
|
// already set from the origin server. Also if the browser has no notion of crossOriginIsolated, just give up here.
|
||||||
|
if (window.crossOriginIsolated !== false || !coi.shouldRegister()) return;
|
||||||
|
|
||||||
|
if (!window.isSecureContext) {
|
||||||
|
!coi.quiet && console.log("COOP/COEP Service Worker not registered, a secure context is required.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In some environments (e.g. Chrome incognito mode) this won't be available
|
||||||
|
if (n.serviceWorker) {
|
||||||
|
n.serviceWorker.register(window.document.currentScript.src).then(
|
||||||
|
(registration) => {
|
||||||
|
!coi.quiet && console.log("COOP/COEP Service Worker registered", registration.scope);
|
||||||
|
|
||||||
|
registration.addEventListener("updatefound", () => {
|
||||||
|
!coi.quiet && console.log("Reloading page to make use of updated COOP/COEP Service Worker.");
|
||||||
|
coi.doReload();
|
||||||
|
});
|
||||||
|
|
||||||
|
// If the registration is active, but it's not controlling the page
|
||||||
|
if (registration.active && !n.serviceWorker.controller) {
|
||||||
|
!coi.quiet && console.log("Reloading page to make use of COOP/COEP Service Worker.");
|
||||||
|
coi.doReload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
!coi.quiet && console.error("COOP/COEP Service Worker failed to register:", err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
/*! coi-serviceworker v0.1.7 - Guido Zuidhof and contributors, licensed under MIT */
|
||||||
|
let coepCredentialless=!1;"undefined"==typeof window?(self.addEventListener("install",(()=>self.skipWaiting())),self.addEventListener("activate",(e=>e.waitUntil(self.clients.claim()))),self.addEventListener("message",(e=>{e.data&&("deregister"===e.data.type?self.registration.unregister().then((()=>self.clients.matchAll())).then((e=>{e.forEach((e=>e.navigate(e.url)))})):"coepCredentialless"===e.data.type&&(coepCredentialless=e.data.value))})),self.addEventListener("fetch",(function(e){const r=e.request;if("only-if-cached"===r.cache&&"same-origin"!==r.mode)return;const s=coepCredentialless&&"no-cors"===r.mode?new Request(r,{credentials:"omit"}):r;e.respondWith(fetch(s).then((e=>{if(0===e.status)return e;const r=new Headers(e.headers);return r.set("Cross-Origin-Embedder-Policy",coepCredentialless?"credentialless":"require-corp"),coepCredentialless||r.set("Cross-Origin-Resource-Policy","cross-origin"),r.set("Cross-Origin-Opener-Policy","same-origin"),new Response(e.body,{status:e.status,statusText:e.statusText,headers:r})})).catch((e=>console.error(e))))}))):(()=>{const e={shouldRegister:()=>!0,shouldDeregister:()=>!1,coepCredentialless:()=>(window.chrome!==undefined||window.netscape!==undefined),doReload:()=>window.location.reload(),quiet:!1,...window.coi},r=navigator;r.serviceWorker&&r.serviceWorker.controller&&(r.serviceWorker.controller.postMessage({type:"coepCredentialless",value:e.coepCredentialless()}),e.shouldDeregister()&&r.serviceWorker.controller.postMessage({type:"deregister"})),!1===window.crossOriginIsolated&&e.shouldRegister()&&(window.isSecureContext?r.serviceWorker&&r.serviceWorker.register(window.document.currentScript.src).then((s=>{!e.quiet&&console.log("COOP/COEP Service Worker registered",s.scope),s.addEventListener("updatefound",(()=>{!e.quiet&&console.log("Reloading page to make use of updated COOP/COEP Service Worker."),e.doReload()})),s.active&&!r.serviceWorker.controller&&(!e.quiet&&console.log("Reloading page to make use of COOP/COEP Service Worker."),e.doReload())}),(r=>{!e.quiet&&console.error("COOP/COEP Service Worker failed to register:",r)})):!e.quiet&&console.log("COOP/COEP Service Worker not registered, a secure context is required."))})();
|
|
@ -0,0 +1,616 @@
|
||||||
|
// original code by @vurtun (public domain)
|
||||||
|
// - rlyeh, public domain.
|
||||||
|
//
|
||||||
|
// @todo: fix leaks: poly_free()
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
// -- demo
|
||||||
|
|
||||||
|
int paused;
|
||||||
|
camera_t cam;
|
||||||
|
|
||||||
|
void game_loop(void *userdata) {
|
||||||
|
// key handler
|
||||||
|
if (input_down(KEY_F11) ) window_fullscreen( window_has_fullscreen()^1 );
|
||||||
|
if (input_down(KEY_ESC) ) window_loop_exit(); // @todo: break -> window_close()
|
||||||
|
|
||||||
|
// animation
|
||||||
|
static float dx = 0, dy = 0;
|
||||||
|
if (input_down(KEY_SPACE)) paused ^= 1;
|
||||||
|
float delta = (0.25f / 60.f) * !paused;
|
||||||
|
dx = dx + delta * 2.0f;
|
||||||
|
dy = dy + delta * 0.8f;
|
||||||
|
|
||||||
|
// fps camera
|
||||||
|
{
|
||||||
|
vec3 move = {0};
|
||||||
|
vec2 view = {0};
|
||||||
|
|
||||||
|
// show/hide cursor
|
||||||
|
bool dragging = input(MOUSE_L) || input(MOUSE_M) || input(MOUSE_R);
|
||||||
|
if( ui_active() || ui_hover() || gizmo_active() || input_touch_active() ) dragging = false;
|
||||||
|
window_cursor( !dragging );
|
||||||
|
|
||||||
|
// keyboard/mouse
|
||||||
|
if( dragging ) cam.speed = clampf(cam.speed + input_diff(MOUSE_W) / 10, 0.05f, 5.0f);
|
||||||
|
vec3 wasdec = scale3(vec3(input(KEY_D)-input(KEY_A),input(KEY_E)-input(KEY_C),input(KEY_W)-input(KEY_S)), cam.speed);
|
||||||
|
vec2 mouse = scale2(vec2(input_diff(MOUSE_X), -input_diff(MOUSE_Y)), 0.2f * dragging);
|
||||||
|
move = add3(move, wasdec);
|
||||||
|
view = add2(view, mouse);
|
||||||
|
|
||||||
|
// gamepad
|
||||||
|
vec2 filtered_lpad = input_filter_deadzone(input2(GAMEPAD_LPAD), 0.15f /*15% deadzone*/);
|
||||||
|
vec2 filtered_rpad = input_filter_deadzone(input2(GAMEPAD_RPAD), 0.15f /*15% deadzone*/);
|
||||||
|
vec3 gamepad_move = scale3(vec3(filtered_lpad.x, input(GAMEPAD_LT) - input(GAMEPAD_RT), filtered_lpad.y), 1.0f);
|
||||||
|
vec2 gamepad_view = scale2(filtered_rpad, 1.0f);
|
||||||
|
move = add3(move, gamepad_move);
|
||||||
|
view = add2(view, gamepad_view);
|
||||||
|
|
||||||
|
// multi-touch
|
||||||
|
vec2 touch_move = input_touch_delta_from_origin(0, 0.0125f /*sensitivityFwd*/); // button #0 (left border)
|
||||||
|
vec2 touch_view = input_touch_delta(1, 0.125f /*sensitivityRot*/); // button #1 (right border)
|
||||||
|
move = add3(move, vec3(touch_move.x, 0, -touch_move.y));
|
||||||
|
view = add2(view, vec2(touch_view.x, -touch_view.y));
|
||||||
|
|
||||||
|
// apply inputs
|
||||||
|
camera_move(&cam, move.x,move.y,move.z);
|
||||||
|
camera_fps(&cam, view.x,view.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// projview matrix
|
||||||
|
mat44 projview; multiply44x2(projview, cam.proj, cam.view);
|
||||||
|
|
||||||
|
// rendering
|
||||||
|
viewport_color3(vec3(0.15,0.15,0.15));
|
||||||
|
#if 0
|
||||||
|
viewport_clear(true, true);
|
||||||
|
viewport_clip(vec2(0,0), vec2(window_width(), window_height()));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// debug draw collisions
|
||||||
|
{
|
||||||
|
// 3D
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// grid
|
||||||
|
ddraw_grid(0);
|
||||||
|
|
||||||
|
{
|
||||||
|
// Triangle-Ray Intersection*/
|
||||||
|
vec3 ro, rd;
|
||||||
|
int suc;
|
||||||
|
|
||||||
|
triangle tri = { vec3(-9,1,28), vec3(-10,0,28), vec3(-11,1,28) };
|
||||||
|
|
||||||
|
// ray
|
||||||
|
ro = vec3(-10,-1,20);
|
||||||
|
rd = vec3(-10+0.4f*sinf(dx), 2.0f*cosf(dy), 29.81023f);
|
||||||
|
rd = sub3(rd, ro);
|
||||||
|
rd = norm3(rd);
|
||||||
|
|
||||||
|
ray r = ray(ro, rd);
|
||||||
|
hit *hit = ray_hit_triangle(r, tri);
|
||||||
|
if (hit) {
|
||||||
|
// point of intersection
|
||||||
|
ddraw_color(RED);
|
||||||
|
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
|
||||||
|
|
||||||
|
// intersection normal
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
vec3 v = add3(hit->p, hit->n);
|
||||||
|
ddraw_arrow(hit->p, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// line
|
||||||
|
ddraw_color(RED);
|
||||||
|
rd = scale3(rd,10);
|
||||||
|
rd = add3(ro,rd);
|
||||||
|
ddraw_line(ro, rd);
|
||||||
|
|
||||||
|
// triangle
|
||||||
|
if (hit) ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
ddraw_triangle(tri.p0,tri.p1,tri.p2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Plane-Ray Intersection*/
|
||||||
|
vec3 ro, rd;
|
||||||
|
mat33 rot;
|
||||||
|
|
||||||
|
// ray
|
||||||
|
static float d = 0;
|
||||||
|
d += delta * 2.0f;
|
||||||
|
ro = vec3(0,-1,20);
|
||||||
|
rd = vec3(0.1f, 0.5f, 9.81023f);
|
||||||
|
rd = sub3(rd, ro);
|
||||||
|
rd = norm3(rd);
|
||||||
|
|
||||||
|
// rotation
|
||||||
|
rotation33(rot, deg(d), 0,1,0);
|
||||||
|
rd = mulv33(rot, rd);
|
||||||
|
|
||||||
|
// intersection
|
||||||
|
ray r = ray(ro, rd);
|
||||||
|
plane pl = plane(vec3(0,0,28), vec3(0,0,1));
|
||||||
|
hit *hit = ray_hit_plane(r, pl);
|
||||||
|
if (hit) {
|
||||||
|
// point of intersection
|
||||||
|
ddraw_color(RED);
|
||||||
|
ddraw_box(hit->p, vec3(0.10f, 0.10f, 0.10f));
|
||||||
|
|
||||||
|
// intersection normal
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
vec3 v = add3(hit->p, hit->n);
|
||||||
|
ddraw_arrow(hit->p, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
}
|
||||||
|
// line
|
||||||
|
ddraw_color(RED);
|
||||||
|
rd = scale3(rd,9);
|
||||||
|
rd = add3(ro,rd);
|
||||||
|
ddraw_line(ro, rd);
|
||||||
|
|
||||||
|
// plane
|
||||||
|
if (hit) ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
ddraw_plane(vec3(0,0,28), vec3(0,0,1), 3.0f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Sphere-Ray Intersection*/
|
||||||
|
vec3 ro, rd;
|
||||||
|
sphere s;
|
||||||
|
|
||||||
|
// ray
|
||||||
|
ro = vec3(0,-1,0);
|
||||||
|
rd = vec3(0.4f*sinf(dx), 2.0f*cosf(dy), 9.81023f);
|
||||||
|
rd = sub3(rd, ro);
|
||||||
|
rd = norm3(rd);
|
||||||
|
|
||||||
|
ray r = ray(ro, rd);
|
||||||
|
s = sphere(vec3(0,0,8), 1);
|
||||||
|
hit *hit = ray_hit_sphere(r, s);
|
||||||
|
if(hit) {
|
||||||
|
// points of intersection
|
||||||
|
vec3 in = add3(ro,scale3(rd,hit->t0));
|
||||||
|
|
||||||
|
ddraw_color(GREEN);
|
||||||
|
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
in = add3(ro,scale3(rd,hit->t1));
|
||||||
|
|
||||||
|
ddraw_color(YELLOW);
|
||||||
|
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
// intersection normal
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
vec3 v = add3(hit->p, hit->n);
|
||||||
|
ddraw_arrow(hit->p, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
}
|
||||||
|
// line
|
||||||
|
ddraw_color(RED);
|
||||||
|
rd = scale3(rd,10);
|
||||||
|
rd = add3(ro,rd);
|
||||||
|
ddraw_line(ro, rd);
|
||||||
|
|
||||||
|
// sphere
|
||||||
|
if (hit) ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
ddraw_sphere(vec3(0,0,8), 1);
|
||||||
|
}
|
||||||
|
{ // ray-aabb
|
||||||
|
aabb bounds = aabb(vec3(10-0.5f,-0.5f,7.5f), vec3(10.5f,0.5f,8.5f));
|
||||||
|
|
||||||
|
vec3 ro = vec3(10,-1,0);
|
||||||
|
vec3 rd = vec3(10+0.4f*sinf(dx), 2.0f*cosf(dy), 9.81023f);
|
||||||
|
rd = norm3(sub3(rd, ro));
|
||||||
|
ray r = ray(ro, rd);
|
||||||
|
|
||||||
|
hit *hit = ray_hit_aabb(r, bounds);
|
||||||
|
if(hit) {
|
||||||
|
// points of intersection
|
||||||
|
vec3 in;
|
||||||
|
in = scale3(rd,hit->t0);
|
||||||
|
in = add3(ro,in);
|
||||||
|
|
||||||
|
ddraw_color(RED);
|
||||||
|
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
in = scale3(rd,hit->t1);
|
||||||
|
in = add3(ro,in);
|
||||||
|
|
||||||
|
ddraw_color(RED);
|
||||||
|
ddraw_box(in, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
|
||||||
|
// intersection normal
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
vec3 v = add3(hit->p, hit->n);
|
||||||
|
ddraw_arrow(hit->p, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
ddraw_box(vec3(10,0,8), vec3(1,1,1));
|
||||||
|
|
||||||
|
// line
|
||||||
|
ddraw_color(RED);
|
||||||
|
rd = scale3(rd,10);
|
||||||
|
rd = add3(ro,rd);
|
||||||
|
ddraw_line(ro, rd);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Sphere-Sphere intersection*/
|
||||||
|
sphere a = sphere(vec3(-10,0,8), 1);
|
||||||
|
sphere b = sphere(vec3(-10+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
|
||||||
|
hit *m = sphere_hit_sphere(a, b);
|
||||||
|
if (m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_sphere(a.c, 1);
|
||||||
|
ddraw_sphere(b.c, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// AABB-AABB intersection*/
|
||||||
|
const float x = 10+0.6f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = 20.0f;
|
||||||
|
|
||||||
|
aabb a = aabb(vec3(10-0.5f,-0.5f,20-0.5f), vec3(10+0.5f,0.5f,20.5f));
|
||||||
|
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
|
||||||
|
hit *m = aabb_hit_aabb(a, b);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_box(vec3(10,0,20), vec3(1,1,1));
|
||||||
|
ddraw_box(vec3(x,y,z), vec3(1,1,1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Capsule-Capsule intersection*/
|
||||||
|
const float x = 20+0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = 28.5f;
|
||||||
|
|
||||||
|
capsule a = capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
|
||||||
|
capsule b = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
hit *m = capsule_hit_capsule(a, b);
|
||||||
|
if( m ) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
ddraw_capsule(vec3(20.0f,-1.0f,28.0f), vec3(20.0f,1.0f,28.0f), 0.2f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// AABB-Sphere intersection*/
|
||||||
|
aabb a = aabb(vec3(20-0.5f,-0.5f,7.5f), vec3(20.5f,0.5f,8.5f));
|
||||||
|
sphere s = sphere(vec3(20+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
|
||||||
|
hit *m = aabb_hit_sphere(a, s);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_box(vec3(20,0,8), vec3(1,1,1));
|
||||||
|
ddraw_sphere(s.c, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Sphere-AABB intersection*/
|
||||||
|
const float x = 10+0.6f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -8.0f;
|
||||||
|
|
||||||
|
sphere s = sphere(vec3(10,0,-8), 1);
|
||||||
|
aabb a = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
|
||||||
|
hit *m = sphere_hit_aabb(s, a);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_box(vec3(x,y,z), vec3(1,1,1));
|
||||||
|
ddraw_sphere(s.c, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Capsule-Sphere intersection*/
|
||||||
|
capsule c = capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
|
||||||
|
sphere b = sphere(vec3(-20+0.6f*sinf(dx), 3.0f*cosf(dy),8), 1);
|
||||||
|
hit *m = capsule_hit_sphere(c, b);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
ddraw_sphere(b.c, 1);
|
||||||
|
ddraw_capsule(vec3(-20.5f,-1.0f,7.5f), vec3(-20+0.5f,1.0f,8.5f), 0.2f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Sphere-Capsule intersection*/
|
||||||
|
const float x = 20+0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -8;
|
||||||
|
|
||||||
|
sphere s = sphere(vec3(20,0,-8), 1);
|
||||||
|
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
hit *m = sphere_hit_capsule(s, c);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
ddraw_sphere(s.c, 1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Capsule-AABB intersection*/
|
||||||
|
const float x = -20+0.6f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = 28.0f;
|
||||||
|
|
||||||
|
capsule c = capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
|
||||||
|
aabb b = aabb(vec3(x-0.5f,y-0.5f,z-0.5f), vec3(x+0.5f,y+0.5f,z+0.5f));
|
||||||
|
hit *m = capsule_hit_aabb(c, b);
|
||||||
|
if(m) {
|
||||||
|
vec3 v;
|
||||||
|
ddraw_color(BLUE);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
v = add3(m->contact_point, m->normal);
|
||||||
|
ddraw_arrow(m->contact_point, v);
|
||||||
|
ddraw_color(RED);
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
ddraw_box(vec3(x,y,z), vec3(1,1,1));
|
||||||
|
ddraw_capsule(vec3(-20.5f,-1.0f,27.5f), vec3(-20+0.5f,1.0f,28.5f), 0.2f);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// AABB-Capsule intersection*/
|
||||||
|
const float x = 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -8;
|
||||||
|
|
||||||
|
aabb a = aabb(vec3(-0.5f,-0.5f,-8.5f), vec3(0.5f,0.5f,-7.5f));
|
||||||
|
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
hit *m = aabb_hit_capsule(a, c);
|
||||||
|
if(m) {
|
||||||
|
ddraw_color(RED);
|
||||||
|
ddraw_box(m->contact_point, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_arrow(m->contact_point, add3(m->contact_point, m->normal));
|
||||||
|
} else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z-1.0f), 0.2f);
|
||||||
|
ddraw_box(vec3(0,0,-8.0f), vec3(1,1,1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// poly(Pyramid)-Sphere (GJK) intersection*/
|
||||||
|
sphere s = sphere(vec3(-10+0.6f*sinf(dx), 3.0f*cosf(dy),-8), 1);
|
||||||
|
poly pyr = pyramid(vec3(-10.5f,-0.5f,-7.5f), vec3(-10.5f,1.0f,-7.5f), 1.0f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_sphere(&gjk, pyr, s))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_sphere(s.c, 1);
|
||||||
|
ddraw_pyramid(vec3(-10.5f,-0.5f,-7.5f), 0.5f/*vec3(-10.5f,1.0f,-7.5f)*/, 1.0f);
|
||||||
|
|
||||||
|
poly_free(&pyr);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// poly(Diamond)-Sphere (GJK) intersection*/
|
||||||
|
|
||||||
|
sphere s = sphere(vec3(-20+0.6f*sinf(dx), 3.0f*cosf(dy),-8), 1);
|
||||||
|
poly dmd = diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_sphere(&gjk, dmd, s))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_sphere(s.c, 1);
|
||||||
|
ddraw_diamond(vec3(-20.5f,-0.5f,-7.5f), vec3(-20.5f,1.0f,-7.5f), 0.5f);
|
||||||
|
|
||||||
|
poly_free(&dmd);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// poly(Pyramid)-Capsule (GJK) intersection*/
|
||||||
|
|
||||||
|
const float x = 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -15;
|
||||||
|
|
||||||
|
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
|
||||||
|
poly pyr = pyramid(vec3(-0.5f,-0.5f,-15.5f), vec3(-0.5f,1.0f,-15.5f), 1.0f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_capsule(&gjk, pyr, c))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_capsule(c.a, c.b, c.r);
|
||||||
|
ddraw_pyramid(vec3(-0.5f,-0.5f,-15.5f), 0.5f/*vec3(-0.5f,1.0f,-15.5f)*/, 1.0f);
|
||||||
|
|
||||||
|
poly_free(&pyr);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// poly(Diamond)-Capsule (GJK) intersection*/
|
||||||
|
|
||||||
|
const float x = -10 + 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -15;
|
||||||
|
|
||||||
|
capsule c = capsule(vec3(x,y-1.0f,z), vec3(x,y+1.0f,z), 0.2f);
|
||||||
|
poly dmd = diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_capsule(&gjk, dmd, c))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_capsule(c.a, c.b, c.r);
|
||||||
|
ddraw_diamond(vec3(-10.5f,-0.5f,-15.5f), vec3(-10.5f,1.0f,-15.5f), 0.5f);
|
||||||
|
|
||||||
|
poly_free(&dmd);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// poly(Diamond)-poly(Pyramid) (GJK) intersection*/
|
||||||
|
|
||||||
|
const float x = -20 + 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -15;
|
||||||
|
|
||||||
|
poly pyr = pyramid(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.8f);
|
||||||
|
poly dmd = diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_poly(&gjk, dmd, pyr))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_pyramid(vec3(x,y-0.5f,z), 1/*vec3(x,y+1,z)*/, 1/*0.8f*/);
|
||||||
|
ddraw_diamond(vec3(-20.5f,-0.5f,-15.5f), vec3(-20.5f,1.0f,-15.5f), 0.5f);
|
||||||
|
|
||||||
|
poly_free(&dmd);
|
||||||
|
poly_free(&pyr);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// poly(Pyramid)-poly(Diamond) (GJK) intersection*/
|
||||||
|
|
||||||
|
const float x = 10 + 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -15;
|
||||||
|
|
||||||
|
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
|
||||||
|
poly pyr = pyramid(vec3(10.5f,-0.5f,-15.5f), vec3(10.5f,1.0f,-15.5f), 1.0f);
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_poly(&gjk, dmd, pyr))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
|
||||||
|
ddraw_pyramid(vec3(10.5f,-0.5f,-15.5f), 0.5f/*vec3(10.5f,1.0f,-15.5f)*/, 1.0f);
|
||||||
|
|
||||||
|
poly_free(&dmd);
|
||||||
|
poly_free(&pyr);
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// poly(Diamond)-AABB (GJK) intersection*/
|
||||||
|
|
||||||
|
const float x = 20 + 0.4f*sinf(dx);
|
||||||
|
const float y = 3.0f*cosf(dy);
|
||||||
|
const float z = -15;
|
||||||
|
|
||||||
|
poly dmd = diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
|
||||||
|
aabb a = aabb(vec3(19.5f,-0.5f,-14.5f), vec3(20.5f,0.5f,-15.5f));
|
||||||
|
|
||||||
|
gjk_result gjk;
|
||||||
|
if (poly_hit_aabb(&gjk, dmd, a))
|
||||||
|
ddraw_color(RED);
|
||||||
|
else ddraw_color(WHITE);
|
||||||
|
|
||||||
|
poly_free(&dmd);
|
||||||
|
|
||||||
|
ddraw_diamond(vec3(x,y-0.5f,z), vec3(x,y+1,z), 0.5f);
|
||||||
|
ddraw_box(vec3(20,0,-15), vec3(1,1,1));
|
||||||
|
|
||||||
|
ddraw_box(gjk.p0, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_box(gjk.p1, vec3(0.05f, 0.05f, 0.05f));
|
||||||
|
ddraw_line(gjk.p0, gjk.p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//fx_begin();
|
||||||
|
//ddraw_flush();
|
||||||
|
//fx_end();
|
||||||
|
|
||||||
|
if( ui_panel("Audio", 0) ) {
|
||||||
|
if( ui_button("test audio") ) {
|
||||||
|
// audio (both clips & streams)
|
||||||
|
static audio_t voice; voice = audio_clip("coin.wav"); // "pew.sfxr"
|
||||||
|
static audio_t stream; stream = audio_stream("wrath_of_the_djinn.xm"); // "larry.mid"
|
||||||
|
audio_play(voice, 0);
|
||||||
|
audio_play(stream, 0);
|
||||||
|
}
|
||||||
|
ui_panel_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ui_panel("FX", 0) ) {
|
||||||
|
for( int i = 0; i < 64; ++i ) {
|
||||||
|
char *name = fx_name(i); if( !name ) break;
|
||||||
|
bool b = fx_enabled(i);
|
||||||
|
if( ui_bool(name, &b) ) fx_enable(i, fx_enabled(i) ^ 1);
|
||||||
|
}
|
||||||
|
ui_panel_end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// 75% sized, msaa x4 enabled
|
||||||
|
window_create(0.75f, WINDOW_MSAA4);
|
||||||
|
window_title( "V4K - SPACE pauses simulation" );
|
||||||
|
|
||||||
|
// for(const char **list = file_list("fx**.fs"); *list; list++) {
|
||||||
|
// //fx_load(*list);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// camera that points to origin
|
||||||
|
cam = camera();
|
||||||
|
|
||||||
|
// main loop
|
||||||
|
window_loop(game_loop, NULL);
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
void render(void *arg) {
|
||||||
|
static int integer = 42;
|
||||||
|
static bool toggle = true;
|
||||||
|
static bool boolean = true;
|
||||||
|
static float floating = 3.14159;
|
||||||
|
static float float2[2] = {1,2};
|
||||||
|
static float float3[3] = {1,2,3};
|
||||||
|
static float float4[4] = {1,2,3,4};
|
||||||
|
static float rgb[3] = {0.84,0.67,0.17};
|
||||||
|
static float rgba[4] = {0.67,0.90,0.12,1};
|
||||||
|
static float slider = 0.5f;
|
||||||
|
static float slider2 = 0.5f;
|
||||||
|
static char string[64] = "hello world 123";
|
||||||
|
static int item = 0; const char *list[] = {"one","two","three"};
|
||||||
|
static bool show_dialog = false;
|
||||||
|
static uint8_t bitmask = 0x55;
|
||||||
|
|
||||||
|
if( ui_panel("UI", 0)) {
|
||||||
|
if( ui_label("my label")) {}
|
||||||
|
if( ui_label("my label with tooltip@built on " __DATE__ " " __TIME__)) {}
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_bool("my bool", &boolean) ) puts("bool changed");
|
||||||
|
if( ui_int("my int", &integer) ) puts("int changed");
|
||||||
|
if( ui_float("my float", &floating) ) puts("float changed");
|
||||||
|
if( ui_buffer("my string", string, 64) ) puts("string changed");
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_slider("my slider", &slider)) puts("slider changed");
|
||||||
|
if( ui_slider2("my slider 2", &slider2, va("%.2f", slider2))) puts("slider2 changed");
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_list("my list", list, 3, &item ) ) puts("list changed");
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_color3f("my color3", rgb) ) puts("color3 changed");
|
||||||
|
if( ui_color4f("my color4@this is a tooltip", rgba) ) puts("color4 changed");
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_float2("my float2", float2) ) puts("float2 changed");
|
||||||
|
if( ui_float3("my float3", float3) ) puts("float3 changed");
|
||||||
|
if( ui_float4("my float4", float4) ) puts("float4 changed");
|
||||||
|
if( ui_bits8("my bitmask", &bitmask) ) printf("bitmask changed %x\n", bitmask);
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_toggle("my toggle", &toggle) ) printf("toggle %s\n", toggle ? "on":"off");
|
||||||
|
if( ui_separator() ) {}
|
||||||
|
if( ui_image("my image", texture_checker().id, 0, 0) ) { puts("image clicked"); }
|
||||||
|
if( ui_button("my button") ) { puts("button clicked"); show_dialog = true; }
|
||||||
|
if( ui_dialog("my dialog", __FILE__ "\n" __DATE__ "\n" "Public Domain.", 2/*two buttons*/, &show_dialog) ) {}
|
||||||
|
|
||||||
|
ui_panel_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
input_demo();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
window_create(0.75f, 0);
|
||||||
|
window_loop(render, NULL);
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright 2015 The Emscripten Authors
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Pthread Web Worker startup routine:
|
||||||
|
// This is the entry point file that is loaded first by each Web Worker
|
||||||
|
// that executes pthreads on the Emscripten application.
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Module = {};
|
||||||
|
|
||||||
|
// Thread-local:
|
||||||
|
|
||||||
|
function assert(condition, text) {
|
||||||
|
if (!condition) abort('Assertion failed: ' + text);
|
||||||
|
}
|
||||||
|
|
||||||
|
function threadPrintErr() {
|
||||||
|
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.error(text);
|
||||||
|
}
|
||||||
|
function threadAlert() {
|
||||||
|
var text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
postMessage({cmd: 'alert', text: text, threadId: Module['_pthread_self']()});
|
||||||
|
}
|
||||||
|
// We don't need out() for now, but may need to add it if we want to use it
|
||||||
|
// here. Or, if this code all moves into the main JS, that problem will go
|
||||||
|
// away. (For now, adding it here increases code size for no benefit.)
|
||||||
|
var out = function() {
|
||||||
|
throw 'out() is not defined in worker.js.';
|
||||||
|
}
|
||||||
|
var err = threadPrintErr;
|
||||||
|
self.alert = threadAlert;
|
||||||
|
|
||||||
|
Module['instantiateWasm'] = function(info, receiveInstance) {
|
||||||
|
// Instantiate from the module posted from the main thread.
|
||||||
|
// We can just use sync instantiation in the worker.
|
||||||
|
var instance = new WebAssembly.Instance(Module['wasmModule'], info);
|
||||||
|
// TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193,
|
||||||
|
// the above line no longer optimizes out down to the following line.
|
||||||
|
// When the regression is fixed, we can remove this if/else.
|
||||||
|
receiveInstance(instance);
|
||||||
|
// We don't need the module anymore; new threads will be spawned from the main thread.
|
||||||
|
Module['wasmModule'] = null;
|
||||||
|
return instance.exports;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.onmessage = function(e) {
|
||||||
|
try {
|
||||||
|
if (e.data.cmd === 'load') { // Preload command that is called once per worker to parse and load the Emscripten code.
|
||||||
|
|
||||||
|
// Module and memory were sent from main thread
|
||||||
|
Module['wasmModule'] = e.data.wasmModule;
|
||||||
|
|
||||||
|
Module['wasmMemory'] = e.data.wasmMemory;
|
||||||
|
|
||||||
|
Module['buffer'] = Module['wasmMemory'].buffer;
|
||||||
|
|
||||||
|
Module['ENVIRONMENT_IS_PTHREAD'] = true;
|
||||||
|
|
||||||
|
if (typeof e.data.urlOrBlob === 'string') {
|
||||||
|
importScripts(e.data.urlOrBlob);
|
||||||
|
} else {
|
||||||
|
var objectUrl = URL.createObjectURL(e.data.urlOrBlob);
|
||||||
|
importScripts(objectUrl);
|
||||||
|
URL.revokeObjectURL(objectUrl);
|
||||||
|
}
|
||||||
|
} else if (e.data.cmd === 'run') {
|
||||||
|
// This worker was idle, and now should start executing its pthread entry
|
||||||
|
// point.
|
||||||
|
// performance.now() is specced to return a wallclock time in msecs since
|
||||||
|
// that Web Worker/main thread launched. However for pthreads this can
|
||||||
|
// cause subtle problems in emscripten_get_now() as this essentially
|
||||||
|
// would measure time from pthread_create(), meaning that the clocks
|
||||||
|
// between each threads would be wildly out of sync. Therefore sync all
|
||||||
|
// pthreads to the clock on the main browser thread, so that different
|
||||||
|
// threads see a somewhat coherent clock across each of them
|
||||||
|
// (+/- 0.1msecs in testing).
|
||||||
|
Module['__performance_now_clock_drift'] = performance.now() - e.data.time;
|
||||||
|
|
||||||
|
// Pass the thread address inside the asm.js scope to store it for fast access that avoids the need for a FFI out.
|
||||||
|
Module['__emscripten_thread_init'](e.data.threadInfoStruct, /*isMainBrowserThread=*/0, /*isMainRuntimeThread=*/0);
|
||||||
|
|
||||||
|
assert(e.data.threadInfoStruct);
|
||||||
|
// Also call inside JS module to set up the stack frame for this pthread in JS module scope
|
||||||
|
Module['establishStackSpace']();
|
||||||
|
Module['PThread'].receiveObjectTransfer(e.data);
|
||||||
|
Module['PThread'].threadInit();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// pthread entry points are always of signature 'void *ThreadMain(void *arg)'
|
||||||
|
// Native codebases sometimes spawn threads with other thread entry point signatures,
|
||||||
|
// such as void ThreadMain(void *arg), void *ThreadMain(), or void ThreadMain().
|
||||||
|
// That is not acceptable per C/C++ specification, but x86 compiler ABI extensions
|
||||||
|
// enable that to work. If you find the following line to crash, either change the signature
|
||||||
|
// to "proper" void *ThreadMain(void *arg) form, or try linking with the Emscripten linker
|
||||||
|
// flag -s EMULATE_FUNCTION_POINTER_CASTS=1 to add in emulation for this x86 ABI extension.
|
||||||
|
var result = Module['invokeEntryPoint'](e.data.start_routine, e.data.arg);
|
||||||
|
|
||||||
|
Module['checkStackCookie']();
|
||||||
|
if (Module['keepRuntimeAlive']()) {
|
||||||
|
Module['PThread'].setExitStatus(result);
|
||||||
|
} else {
|
||||||
|
Module['__emscripten_thread_exit'](result);
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
if (ex != 'unwind') {
|
||||||
|
// FIXME(sbc): Figure out if this is still needed or useful. Its not
|
||||||
|
// clear to me how this check could ever fail. In order to get into
|
||||||
|
// this try/catch block at all we have already called bunch of
|
||||||
|
// functions on `Module`.. why is this one special?
|
||||||
|
if (typeof(Module['_emscripten_futex_wake']) !== 'function') {
|
||||||
|
err("Thread Initialisation failed.");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
// ExitStatus not present in MINIMAL_RUNTIME
|
||||||
|
if (ex instanceof Module['ExitStatus']) {
|
||||||
|
if (Module['keepRuntimeAlive']()) {
|
||||||
|
err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' called exit(), staying alive due to noExitRuntime.');
|
||||||
|
} else {
|
||||||
|
err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' called exit(), calling _emscripten_thread_exit.');
|
||||||
|
Module['__emscripten_thread_exit'](ex.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The pthread "crashed". Do not call `_emscripten_thread_exit` (which
|
||||||
|
// would make this thread joinable. Instead, re-throw the exception
|
||||||
|
// and let the top level handler propagate it back to the main thread.
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// else e == 'unwind', and we should fall through here and keep the pthread alive for asynchronous events.
|
||||||
|
err('Pthread 0x' + Module['_pthread_self']().toString(16) + ' completed its main entry point with an `unwind`, keeping the worker alive for asynchronous operation.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (e.data.cmd === 'cancel') { // Main thread is asking for a pthread_cancel() on this thread.
|
||||||
|
if (Module['_pthread_self']()) {
|
||||||
|
Module['__emscripten_thread_exit'](-1/*PTHREAD_CANCELED*/);
|
||||||
|
}
|
||||||
|
postMessage({ 'cmd': 'cancelDone' });
|
||||||
|
} else if (e.data.target === 'setimmediate') {
|
||||||
|
// no-op
|
||||||
|
} else if (e.data.cmd === 'processThreadQueue') {
|
||||||
|
if (Module['_pthread_self']()) { // If this thread is actually running?
|
||||||
|
Module['_emscripten_current_thread_process_queued_calls']();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err('worker.js received unknown command ' + e.data.cmd);
|
||||||
|
err(e.data);
|
||||||
|
}
|
||||||
|
} catch(ex) {
|
||||||
|
err('worker.js onmessage() captured an uncaught exception: ' + ex);
|
||||||
|
if (ex && ex.stack) err(ex.stack);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!-- This file license is CC0 (https://creativecommons.org/publicdomain/zero/1.0/). -->
|
||||||
|
<!-- Original code by @SpartanJ https://github.com/SpartanJ/eepp/blob/8552941da19380d7a629c4da80a976aec5d39e5c/bin/emscripten-fs.html -->
|
||||||
|
<html lang="en-us">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"/>
|
||||||
|
<!-- <title>Example</title> -->
|
||||||
|
<style>
|
||||||
|
body { margin: 0; background-color: black }
|
||||||
|
.emscripten {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
border: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
image-rendering: optimizeSpeed;
|
||||||
|
image-rendering: -moz-crisp-edges;
|
||||||
|
image-rendering: -o-crisp-edges;
|
||||||
|
image-rendering: -webkit-optimize-contrast;
|
||||||
|
image-rendering: optimize-contrast;
|
||||||
|
image-rendering: crisp-edges;
|
||||||
|
image-rendering: pixelated;
|
||||||
|
-ms-interpolation-mode: nearest-neighbor;
|
||||||
|
}
|
||||||
|
.loader {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: inline-block;
|
||||||
|
border-top: 3px solid #3daee9;
|
||||||
|
border-right: 3px solid transparent;
|
||||||
|
box-sizing: border-box;
|
||||||
|
animation: rotation 1s linear infinite;
|
||||||
|
}
|
||||||
|
.loader-cont {
|
||||||
|
display: flex;
|
||||||
|
width: 100vw;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100vh;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
@keyframes rotation {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||||
|
<div id="cont" class="loader-cont">
|
||||||
|
<span class="loader"></span>
|
||||||
|
</div>
|
||||||
|
<script type='text/javascript'>
|
||||||
|
var loaderCont;
|
||||||
|
|
||||||
|
function getDemoScript(name) {
|
||||||
|
if (name)
|
||||||
|
return name;
|
||||||
|
return "index.js";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParameter(name) {
|
||||||
|
let url_string = window.location.href;
|
||||||
|
let url = new URL(url_string);
|
||||||
|
return url.searchParams.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadScript(url, callback) {
|
||||||
|
loaderCont = document.getElementById('cont');
|
||||||
|
let head = document.head;
|
||||||
|
let script = document.createElement('script');
|
||||||
|
script.type = 'text/javascript';
|
||||||
|
script.src = url;
|
||||||
|
script.onreadystatechange = callback;
|
||||||
|
script.onload = callback;
|
||||||
|
head.appendChild(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
var Module = {
|
||||||
|
preRun: [],
|
||||||
|
postRun: [],
|
||||||
|
print: (function() {
|
||||||
|
return function(text) {
|
||||||
|
text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.log(text);
|
||||||
|
};
|
||||||
|
})(),
|
||||||
|
printErr: function(text) {
|
||||||
|
text = Array.prototype.slice.call(arguments).join(' ');
|
||||||
|
console.error(text);
|
||||||
|
},
|
||||||
|
canvas: (function() {
|
||||||
|
var canvas = document.getElementById('canvas');
|
||||||
|
return canvas;
|
||||||
|
})(),
|
||||||
|
setStatus: function(text) {
|
||||||
|
console.log("status: " + text);
|
||||||
|
if (text == "Running...")
|
||||||
|
loaderCont.style.display = 'none';
|
||||||
|
},
|
||||||
|
monitorRunDependencies: function(left) {
|
||||||
|
// no run dependencies to log
|
||||||
|
},
|
||||||
|
arguments: window.location.search.substr(1).split('&')
|
||||||
|
};
|
||||||
|
window.onerror = function() {
|
||||||
|
console.log("onerror: " + event);
|
||||||
|
};
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
loadScript(getDemoScript(getParameter("run")));
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{{{ SCRIPT }}}
|
||||||
|
|
||||||
|
<button onclick="openFullscreen();" style="position:relative; z-index: 1000; float: right;">⛶</button>
|
||||||
|
<script>
|
||||||
|
function openFullscreen() {
|
||||||
|
var elem = document.getElementById("canvas");
|
||||||
|
if (elem.requestFullscreen) {
|
||||||
|
elem.requestFullscreen();
|
||||||
|
} else if (elem.webkitRequestFullscreen) { /* Safari */
|
||||||
|
elem.webkitRequestFullscreen();
|
||||||
|
} else if (elem.msRequestFullscreen) { /* IE11 */
|
||||||
|
elem.msRequestFullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script src="coi-serviceworker.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,6 @@
|
||||||
|
cl game.c -I..\..\..\engine\joint %* /link /SUBSYSTEM:WINDOWS /entry:mainCRTStartup
|
||||||
|
|
||||||
|
del *.obj
|
||||||
|
del *.exp
|
||||||
|
del *.lib
|
||||||
|
del *.pdb
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Anarch
|
||||||
|
|
||||||
|
![](game.png)
|
||||||
|
|
||||||
|
*extremely small, completely public domain, no-dependency, no-file,
|
||||||
|
portable suckless anarcho-pacifist from-scratch 90s-style Doom clone that runs
|
||||||
|
everywhere, made for the benefit of all living beings*
|
||||||
|
|
||||||
|
[website](https://drummyfish.gitlab.io/anarch) - [trailer](https://libre.video/videos/watch/c968774a-c12d-46d6-8851-0c578ffa8dcb) - [play in browser](https://drummyfish.gitlab.io/anarch/bin/web/anarch.html) - [itch.io](https://drummyfish.itch.io/anarch)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
I, Miloslav Číž (drummyfish), have released everything in the Anarch repository under CC0 1.0 (public domain, https://creativecommons.org/publicdomain/zero/1.0/) + a waiver of all other IP rights (including patents), which is as follows:
|
||||||
|
|
||||||
|
*Each contributor to this work agrees that they waive any exclusive rights, including but not limited to copyright, patents, trademark, trade dress, industrial design, plant varieties and trade secrets, to any and all ideas, concepts, processes, discoveries, improvements and inventions conceived, discovered, made, designed, researched or developed by the contributor either solely or jointly with others, which relate to this work or result from this work. Should any waiver of such right be judged legally invalid or ineffective under applicable law, the contributor hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to this right.*
|
||||||
|
|
||||||
|
If you'd like to support me or just read something about me and my projects, visit my site: [www.tastyfish.cz](http://www.tastyfish.cz/).
|
|
@ -0,0 +1,121 @@
|
||||||
|
Creative Commons Legal Code
|
||||||
|
|
||||||
|
CC0 1.0 Universal
|
||||||
|
|
||||||
|
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
||||||
|
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
||||||
|
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
||||||
|
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
||||||
|
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
||||||
|
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
||||||
|
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
||||||
|
HEREUNDER.
|
||||||
|
|
||||||
|
Statement of Purpose
|
||||||
|
|
||||||
|
The laws of most jurisdictions throughout the world automatically confer
|
||||||
|
exclusive Copyright and Related Rights (defined below) upon the creator
|
||||||
|
and subsequent owner(s) (each and all, an "owner") of an original work of
|
||||||
|
authorship and/or a database (each, a "Work").
|
||||||
|
|
||||||
|
Certain owners wish to permanently relinquish those rights to a Work for
|
||||||
|
the purpose of contributing to a commons of creative, cultural and
|
||||||
|
scientific works ("Commons") that the public can reliably and without fear
|
||||||
|
of later claims of infringement build upon, modify, incorporate in other
|
||||||
|
works, reuse and redistribute as freely as possible in any form whatsoever
|
||||||
|
and for any purposes, including without limitation commercial purposes.
|
||||||
|
These owners may contribute to the Commons to promote the ideal of a free
|
||||||
|
culture and the further production of creative, cultural and scientific
|
||||||
|
works, or to gain reputation or greater distribution for their Work in
|
||||||
|
part through the use and efforts of others.
|
||||||
|
|
||||||
|
For these and/or other purposes and motivations, and without any
|
||||||
|
expectation of additional consideration or compensation, the person
|
||||||
|
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
||||||
|
is an owner of Copyright and Related Rights in the Work, voluntarily
|
||||||
|
elects to apply CC0 to the Work and publicly distribute the Work under its
|
||||||
|
terms, with knowledge of his or her Copyright and Related Rights in the
|
||||||
|
Work and the meaning and intended legal effect of CC0 on those rights.
|
||||||
|
|
||||||
|
1. Copyright and Related Rights. A Work made available under CC0 may be
|
||||||
|
protected by copyright and related or neighboring rights ("Copyright and
|
||||||
|
Related Rights"). Copyright and Related Rights include, but are not
|
||||||
|
limited to, the following:
|
||||||
|
|
||||||
|
i. the right to reproduce, adapt, distribute, perform, display,
|
||||||
|
communicate, and translate a Work;
|
||||||
|
ii. moral rights retained by the original author(s) and/or performer(s);
|
||||||
|
iii. publicity and privacy rights pertaining to a person's image or
|
||||||
|
likeness depicted in a Work;
|
||||||
|
iv. rights protecting against unfair competition in regards to a Work,
|
||||||
|
subject to the limitations in paragraph 4(a), below;
|
||||||
|
v. rights protecting the extraction, dissemination, use and reuse of data
|
||||||
|
in a Work;
|
||||||
|
vi. database rights (such as those arising under Directive 96/9/EC of the
|
||||||
|
European Parliament and of the Council of 11 March 1996 on the legal
|
||||||
|
protection of databases, and under any national implementation
|
||||||
|
thereof, including any amended or successor version of such
|
||||||
|
directive); and
|
||||||
|
vii. other similar, equivalent or corresponding rights throughout the
|
||||||
|
world based on applicable law or treaty, and any national
|
||||||
|
implementations thereof.
|
||||||
|
|
||||||
|
2. Waiver. To the greatest extent permitted by, but not in contravention
|
||||||
|
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
||||||
|
irrevocably and unconditionally waives, abandons, and surrenders all of
|
||||||
|
Affirmer's Copyright and Related Rights and associated claims and causes
|
||||||
|
of action, whether now known or unknown (including existing as well as
|
||||||
|
future claims and causes of action), in the Work (i) in all territories
|
||||||
|
worldwide, (ii) for the maximum duration provided by applicable law or
|
||||||
|
treaty (including future time extensions), (iii) in any current or future
|
||||||
|
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
||||||
|
including without limitation commercial, advertising or promotional
|
||||||
|
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
||||||
|
member of the public at large and to the detriment of Affirmer's heirs and
|
||||||
|
successors, fully intending that such Waiver shall not be subject to
|
||||||
|
revocation, rescission, cancellation, termination, or any other legal or
|
||||||
|
equitable action to disrupt the quiet enjoyment of the Work by the public
|
||||||
|
as contemplated by Affirmer's express Statement of Purpose.
|
||||||
|
|
||||||
|
3. Public License Fallback. Should any part of the Waiver for any reason
|
||||||
|
be judged legally invalid or ineffective under applicable law, then the
|
||||||
|
Waiver shall be preserved to the maximum extent permitted taking into
|
||||||
|
account Affirmer's express Statement of Purpose. In addition, to the
|
||||||
|
extent the Waiver is so judged Affirmer hereby grants to each affected
|
||||||
|
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
||||||
|
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
||||||
|
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
||||||
|
maximum duration provided by applicable law or treaty (including future
|
||||||
|
time extensions), (iii) in any current or future medium and for any number
|
||||||
|
of copies, and (iv) for any purpose whatsoever, including without
|
||||||
|
limitation commercial, advertising or promotional purposes (the
|
||||||
|
"License"). The License shall be deemed effective as of the date CC0 was
|
||||||
|
applied by Affirmer to the Work. Should any part of the License for any
|
||||||
|
reason be judged legally invalid or ineffective under applicable law, such
|
||||||
|
partial invalidity or ineffectiveness shall not invalidate the remainder
|
||||||
|
of the License, and in such case Affirmer hereby affirms that he or she
|
||||||
|
will not (i) exercise any of his or her remaining Copyright and Related
|
||||||
|
Rights in the Work or (ii) assert any associated claims and causes of
|
||||||
|
action with respect to the Work, in either case contrary to Affirmer's
|
||||||
|
express Statement of Purpose.
|
||||||
|
|
||||||
|
4. Limitations and Disclaimers.
|
||||||
|
|
||||||
|
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
||||||
|
surrendered, licensed or otherwise affected by this document.
|
||||||
|
b. Affirmer offers the Work as-is and makes no representations or
|
||||||
|
warranties of any kind concerning the Work, express, implied,
|
||||||
|
statutory or otherwise, including without limitation warranties of
|
||||||
|
title, merchantability, fitness for a particular purpose, non
|
||||||
|
infringement, or the absence of latent or other defects, accuracy, or
|
||||||
|
the present or absence of errors, whether or not discoverable, all to
|
||||||
|
the greatest extent permissible under applicable law.
|
||||||
|
c. Affirmer disclaims responsibility for clearing rights of other persons
|
||||||
|
that may apply to the Work or any use thereof, including without
|
||||||
|
limitation any person's Copyright and Related Rights in the Work.
|
||||||
|
Further, Affirmer disclaims responsibility for obtaining any necessary
|
||||||
|
consents, permissions or other rights required for any use of the
|
||||||
|
Work.
|
||||||
|
d. Affirmer understands and acknowledges that Creative Commons is not a
|
||||||
|
party to this document and has no duty or obligation with respect to
|
||||||
|
this CC0 or use of the Work.
|
|
@ -0,0 +1,587 @@
|
||||||
|
/**
|
||||||
|
@file constants.h
|
||||||
|
|
||||||
|
This file contains definitions of game constants that are not considered
|
||||||
|
part of game settings and whose change can ffect the game balance and
|
||||||
|
playability, e.g. physics constants.
|
||||||
|
|
||||||
|
by Miloslav Ciz (drummyfish), 2019
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is to
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SFG_CONSTANTS_H
|
||||||
|
#define _SFG_CONSTANTS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
How quickly player moves, in squares per second.
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_MOVE_SPEED 7
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gravity acceleration in squares / (second^2).
|
||||||
|
*/
|
||||||
|
#define SFG_GRAVITY_ACCELERATION 30
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initial upwards speed of player's jump, in squares per second.
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_JUMP_SPEED 5
|
||||||
|
|
||||||
|
/**
|
||||||
|
Melee and close-up attack range, in RCL_Units.
|
||||||
|
*/
|
||||||
|
#define SFG_MELEE_RANGE 1600
|
||||||
|
|
||||||
|
/**
|
||||||
|
When a projectile is shot, it'll be offset by this distance (in RCL_Units)
|
||||||
|
from the shooter.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SFG_PROJECTILE_SPAWN_OFFSET 256
|
||||||
|
|
||||||
|
/**
|
||||||
|
Player's melee hit range, in RCL_Units (RCL_UNITS_PER_SQUARE means full angle,
|
||||||
|
180 degrees to both sides).
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_MELEE_ANGLE 512
|
||||||
|
|
||||||
|
/**
|
||||||
|
How quickly elevators and squeezers move, in RCL_Unit per second.
|
||||||
|
*/
|
||||||
|
#define SFG_MOVING_WALL_SPEED 1024
|
||||||
|
|
||||||
|
/**
|
||||||
|
How quickly doors open and close, in RCL_Unit per second.
|
||||||
|
*/
|
||||||
|
#define SFG_DOOR_OPEN_SPEED 2048
|
||||||
|
|
||||||
|
/**
|
||||||
|
Helper special state value.
|
||||||
|
*/
|
||||||
|
#define SFG_CANT_SAVE 255
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says the distance in RCL_Units at which level elements (items, monsters etc.)
|
||||||
|
are active.
|
||||||
|
*/
|
||||||
|
#define SFG_LEVEL_ELEMENT_ACTIVE_DISTANCE (12 * 1024)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Rate at which AI will be updated, which also affects how fast enemies will
|
||||||
|
appear.
|
||||||
|
*/
|
||||||
|
#define SFG_AI_FPS 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says a probability (0 - 255) of the AI changing its state during one update
|
||||||
|
step.
|
||||||
|
*/
|
||||||
|
#define SFG_AI_RANDOM_CHANGE_PROBABILITY 40
|
||||||
|
|
||||||
|
/**
|
||||||
|
Distance at which level elements (sprites) collide, in RCL_Unit (1024 per
|
||||||
|
square).
|
||||||
|
*/
|
||||||
|
#define SFG_ELEMENT_COLLISION_RADIUS 1800
|
||||||
|
|
||||||
|
/**
|
||||||
|
Height, in RCL_Units, at which collisions happen with level elements
|
||||||
|
(sprites).
|
||||||
|
*/
|
||||||
|
#define SFG_ELEMENT_COLLISION_HEIGHT 1024
|
||||||
|
|
||||||
|
/**
|
||||||
|
Distance at which explosion does damage and throws away the player, in
|
||||||
|
RCL_Units. Should be higher than SFG_ELEMENT_COLLISION_RADIUS so that
|
||||||
|
exploded rockets also hurt the target.
|
||||||
|
*/
|
||||||
|
#define SFG_EXPLOSION_RADIUS 2000
|
||||||
|
|
||||||
|
/**
|
||||||
|
Distance in RCL_Units which the player is pushed away by an explosion. Watch
|
||||||
|
out, a slightly higher value can make player go through walls. Rather keep
|
||||||
|
this under RCL_UNITS_PER_SQUARE;
|
||||||
|
*/
|
||||||
|
#define SFG_EXPLOSION_PUSH_AWAY_DISTANCE 1023
|
||||||
|
|
||||||
|
/**
|
||||||
|
How much damage triggers a barrel explosion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SFG_BARREL_EXPLOSION_DAMAGE_THRESHOLD 3
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum player health.
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_MAX_HEALTH 125
|
||||||
|
|
||||||
|
/**
|
||||||
|
Start health of player.
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_START_HEALTH 100
|
||||||
|
|
||||||
|
/**
|
||||||
|
At which value health indicator shows a warning (red color).
|
||||||
|
*/
|
||||||
|
#define SFG_PLAYER_HEALTH_WARNING_LEVEL 20
|
||||||
|
|
||||||
|
/**
|
||||||
|
Amount of health that is increased by taking a health kit.
|
||||||
|
*/
|
||||||
|
#define SFG_HEALTH_KIT_VALUE 20
|
||||||
|
|
||||||
|
/**
|
||||||
|
How much randomness (positive and negative) will be added to damage
|
||||||
|
(e.g. by weapons, explosions, ...). This constant is is 0 to 255, 255 meaning
|
||||||
|
100% of the base value.
|
||||||
|
*/
|
||||||
|
#define SFG_DAMAGE_RANDOMNESS 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
Height of monster collision BBox in RCL_Units.
|
||||||
|
*/
|
||||||
|
#define SFG_MONSTER_COLLISION_HEIGHT 1024
|
||||||
|
|
||||||
|
/**
|
||||||
|
Specifies key repeat delay, in ms.
|
||||||
|
*/
|
||||||
|
#define SFG_KEY_REPEAT_DELAY 500
|
||||||
|
|
||||||
|
/**
|
||||||
|
Specifies key repeat period, in ms.
|
||||||
|
*/
|
||||||
|
#define SFG_KEY_REPEAT_PERIOD 150
|
||||||
|
|
||||||
|
/**
|
||||||
|
Angle in which multiple projectiles are spread, RCL_Units.
|
||||||
|
*/
|
||||||
|
#define SFG_PROJECTILE_SPREAD_ANGLE 100
|
||||||
|
|
||||||
|
#define SFG_MAX_MONSTERS 64
|
||||||
|
|
||||||
|
#define SFG_MAX_PROJECTILES 12
|
||||||
|
|
||||||
|
#define SFG_MAX_DOORS 32
|
||||||
|
|
||||||
|
#define SFG_AMMO_BULLETS 0
|
||||||
|
#define SFG_AMMO_ROCKETS 1
|
||||||
|
#define SFG_AMMO_PLASMA 2
|
||||||
|
|
||||||
|
#define SFG_AMMO_TOTAL 3
|
||||||
|
|
||||||
|
#define SFG_AMMO_NONE SFG_AMMO_TOTAL
|
||||||
|
|
||||||
|
#define SFG_AMMO_INCREASE_BULLETS 10
|
||||||
|
#define SFG_AMMO_INCREASE_ROCKETS 5
|
||||||
|
#define SFG_AMMO_INCREASE_PLASMA 8
|
||||||
|
|
||||||
|
#define SFG_AMMO_MAX_BULLETS 200
|
||||||
|
#define SFG_AMMO_MAX_ROCKETS 100
|
||||||
|
#define SFG_AMMO_MAX_PLASMA 150
|
||||||
|
|
||||||
|
/**
|
||||||
|
Duration of story text (intro/outro) in ms.
|
||||||
|
*/
|
||||||
|
#define SFG_STORYTEXT_DURATION 15000
|
||||||
|
|
||||||
|
/**
|
||||||
|
Time in ms of the player death animation.
|
||||||
|
*/
|
||||||
|
#define SFG_LOSE_ANIMATION_DURATION 2000
|
||||||
|
|
||||||
|
/**
|
||||||
|
Time in ms of the level win animation.
|
||||||
|
*/
|
||||||
|
#define SFG_WIN_ANIMATION_DURATION 2500
|
||||||
|
|
||||||
|
/**
|
||||||
|
Time in ms of the level start stage.
|
||||||
|
*/
|
||||||
|
#define SFG_LEVEL_START_DURATION 1500
|
||||||
|
|
||||||
|
/**
|
||||||
|
Vertical sprite size, in RCL_Units.
|
||||||
|
*/
|
||||||
|
#define SFG_BASE_SPRITE_SIZE RCL_UNITS_PER_SQUARE
|
||||||
|
|
||||||
|
/**
|
||||||
|
Default value of the settings byte.
|
||||||
|
*/
|
||||||
|
#define SFG_DEFAULT_SETTINGS 0x03
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// derived constants
|
||||||
|
|
||||||
|
#define SFG_GAME_RESOLUTION_X \
|
||||||
|
(SFG_SCREEN_RESOLUTION_X / SFG_RESOLUTION_SCALEDOWN)
|
||||||
|
|
||||||
|
#define SFG_GAME_RESOLUTION_Y \
|
||||||
|
(SFG_SCREEN_RESOLUTION_Y / SFG_RESOLUTION_SCALEDOWN)
|
||||||
|
|
||||||
|
#define SFG_MS_PER_FRAME (1000 / SFG_FPS) // ms per frame with target FPS
|
||||||
|
|
||||||
|
#if SFG_MS_PER_FRAME == 0
|
||||||
|
#undef SFG_MS_PER_FRAME
|
||||||
|
#define SFG_MS_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_KEY_REPEAT_DELAY_FRAMES \
|
||||||
|
(SFG_KEY_REPEAT_DELAY / SFG_MS_PER_FRAME)
|
||||||
|
|
||||||
|
#if SFG_KEY_REPEAT_DELAY_FRAMES == 0
|
||||||
|
#undef SFG_KEY_REPEAT_DELAY_FRAMES
|
||||||
|
#define SFG_KEY_REPEAT_DELAY_FRAMES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_KEY_REPEAT_PERIOD_FRAMES \
|
||||||
|
(SFG_KEY_REPEAT_PERIOD / SFG_MS_PER_FRAME)
|
||||||
|
|
||||||
|
#if SFG_KEY_REPEAT_PERIOD_FRAMES == 0
|
||||||
|
#undef SFG_KEY_REPEAT_PERIOD_FRAMES
|
||||||
|
#define SFG_KEY_REPEAT_PERIOD_FRAMES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_WEAPON_IMAGE_SCALE \
|
||||||
|
(SFG_GAME_RESOLUTION_X / (SFG_TEXTURE_SIZE * 5))
|
||||||
|
|
||||||
|
#if SFG_WEAPON_IMAGE_SCALE == 0
|
||||||
|
#undef SFG_WEAPON_IMAGE_SCALE
|
||||||
|
#define SFG_WEAPON_IMAGE_SCALE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_WEAPONBOB_OFFSET_PIXELS \
|
||||||
|
(SFG_WEAPONBOB_OFFSET * SFG_WEAPON_IMAGE_SCALE)
|
||||||
|
|
||||||
|
#define SFG_WEAPON_IMAGE_POSITION_X \
|
||||||
|
(SFG_GAME_RESOLUTION_X / 2 - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE) / 2)
|
||||||
|
|
||||||
|
#if SFG_GAME_RESOLUTION_Y > 70
|
||||||
|
#define SFG_WEAPON_IMAGE_POSITION_Y \
|
||||||
|
(SFG_GAME_RESOLUTION_Y - (SFG_WEAPON_IMAGE_SCALE * SFG_TEXTURE_SIZE))
|
||||||
|
#elif SFG_GAME_RESOLUTION_Y > 50
|
||||||
|
#define SFG_WEAPON_IMAGE_POSITION_Y (SFG_GAME_RESOLUTION_Y \
|
||||||
|
- ((SFG_WEAPON_IMAGE_SCALE * 3 * SFG_TEXTURE_SIZE) / 4))
|
||||||
|
#else
|
||||||
|
#define SFG_WEAPON_IMAGE_POSITION_Y \
|
||||||
|
(SFG_GAME_RESOLUTION_Y - SFG_TEXTURE_SIZE / 2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_PLAYER_TURN_UNITS_PER_FRAME \
|
||||||
|
((SFG_PLAYER_TURN_SPEED * RCL_UNITS_PER_SQUARE) / (360 * SFG_FPS))
|
||||||
|
|
||||||
|
#if SFG_PLAYER_TURN_UNITS_PER_FRAME == 0
|
||||||
|
#undef SFG_PLAYER_TURN_UNITS_PER_FRAME
|
||||||
|
#define SFG_PLAYER_TURN_UNITS_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_PLAYER_MOVE_UNITS_PER_FRAME \
|
||||||
|
((SFG_PLAYER_MOVE_SPEED * RCL_UNITS_PER_SQUARE) / SFG_FPS)
|
||||||
|
|
||||||
|
#if SFG_PLAYER_MOVE_UNITS_PER_FRAME == 0
|
||||||
|
#undef SFG_PLAYER_MOVE_UNITS_PER_FRAME
|
||||||
|
#define SFG_PLAYER_MOVE_UNITS_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_GRAVITY_SPEED_INCREASE_PER_FRAME \
|
||||||
|
((SFG_GRAVITY_ACCELERATION * RCL_UNITS_PER_SQUARE) / (SFG_FPS * SFG_FPS))
|
||||||
|
|
||||||
|
#if SFG_GRAVITY_SPEED_INCREASE_PER_FRAME == 0
|
||||||
|
#undef SFG_GRAVITY_SPEED_INCREASE_PER_FRAME
|
||||||
|
#define SFG_GRAVITY_SPEED_INCREASE_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_PLAYER_JUMP_OFFSET_PER_FRAME \
|
||||||
|
(((SFG_PLAYER_JUMP_SPEED * RCL_UNITS_PER_SQUARE) / SFG_FPS) \
|
||||||
|
- SFG_GRAVITY_SPEED_INCREASE_PER_FRAME / 2)
|
||||||
|
/* ^ This substraction corrects the initial veloc. so that the numeric curve
|
||||||
|
copies the analytical (smooth) curve. Without it the numeric curve goes
|
||||||
|
ABOVE and makes player jump higher with lower FPS. To make sense of this
|
||||||
|
try to solve the differential equation and plot it. */
|
||||||
|
|
||||||
|
#if SFG_PLAYER_JUMP_OFFSET_PER_FRAME == 0
|
||||||
|
#undef SFG_PLAYER_JUMP_OFFSET_PER_FRAME
|
||||||
|
#define SFG_PLAYER_JUMP_OFFSET_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_HEADBOB_FRAME_INCREASE_PER_FRAME \
|
||||||
|
(SFG_HEADBOB_SPEED / SFG_FPS)
|
||||||
|
|
||||||
|
#if SFG_HEADBOB_FRAME_INCREASE_PER_FRAME == 0
|
||||||
|
#undef SFG_HEADBOB_FRAME_INCREASE_PER_FRAME
|
||||||
|
#define SFG_HEADBOB_FRAME_INCREASE_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_HEADBOB_ENABLED (SFG_HEADBOB_SPEED > 0 && SFG_HEADBOB_OFFSET > 0)
|
||||||
|
|
||||||
|
#define SFG_CAMERA_SHEAR_STEP_PER_FRAME \
|
||||||
|
((SFG_GAME_RESOLUTION_Y * SFG_CAMERA_SHEAR_SPEED) / SFG_FPS)
|
||||||
|
|
||||||
|
#if SFG_CAMERA_SHEAR_STEP_PER_FRAME == 0
|
||||||
|
#undef SFG_CAMERA_SHEAR_STEP_PER_FRAME
|
||||||
|
#define SFG_CAMERA_SHEAR_STEP_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_CAMERA_MAX_SHEAR_PIXELS \
|
||||||
|
((SFG_CAMERA_MAX_SHEAR * SFG_GAME_RESOLUTION_Y) / 1024)
|
||||||
|
|
||||||
|
#define SFG_FONT_SIZE_SMALL \
|
||||||
|
(SFG_GAME_RESOLUTION_X / (SFG_FONT_CHARACTER_SIZE * 50))
|
||||||
|
|
||||||
|
#if SFG_FONT_SIZE_SMALL == 0
|
||||||
|
#undef SFG_FONT_SIZE_SMALL
|
||||||
|
#define SFG_FONT_SIZE_SMALL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_FONT_SIZE_MEDIUM \
|
||||||
|
(SFG_GAME_RESOLUTION_X / (SFG_FONT_CHARACTER_SIZE * 30))
|
||||||
|
|
||||||
|
#if SFG_FONT_SIZE_MEDIUM == 0
|
||||||
|
#undef SFG_FONT_SIZE_MEDIUM
|
||||||
|
#define SFG_FONT_SIZE_MEDIUM 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_FONT_SIZE_BIG \
|
||||||
|
(SFG_GAME_RESOLUTION_X / (SFG_FONT_CHARACTER_SIZE * 18))
|
||||||
|
|
||||||
|
#if SFG_FONT_SIZE_BIG == 0
|
||||||
|
#undef SFG_FONT_SIZE_BIG
|
||||||
|
#define SFG_FONT_SIZE_BIG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_Z_BUFFER_SIZE SFG_GAME_RESOLUTION_X
|
||||||
|
|
||||||
|
/**
|
||||||
|
Step in which walls get higher, in raycastlib units.
|
||||||
|
*/
|
||||||
|
#define SFG_WALL_HEIGHT_STEP (RCL_UNITS_PER_SQUARE / 4)
|
||||||
|
|
||||||
|
#define SFG_CEILING_MAX_HEIGHT\
|
||||||
|
(16 * RCL_UNITS_PER_SQUARE - RCL_UNITS_PER_SQUARE / 2 )
|
||||||
|
|
||||||
|
#define SFG_DOOR_UP_DOWN_MASK 0x20
|
||||||
|
#define SFG_DOOR_LOCK(doorRecord) ((doorRecord) >> 6)
|
||||||
|
#define SFG_DOOR_VERTICAL_POSITION_MASK 0x1f
|
||||||
|
#define SFG_DOOR_HEIGHT_STEP (RCL_UNITS_PER_SQUARE / 0x1f)
|
||||||
|
|
||||||
|
#define SFG_DOOR_INCREMENT_PER_FRAME \
|
||||||
|
(SFG_DOOR_OPEN_SPEED / (SFG_DOOR_HEIGHT_STEP * SFG_FPS))
|
||||||
|
|
||||||
|
#if SFG_DOOR_INCREMENT_PER_FRAME == 0
|
||||||
|
#undef SFG_DOOR_INCREMENT_PER_FRAME
|
||||||
|
#define SFG_DOOR_INCREMENT_PER_FRAME 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_MAX_ITEMS SFG_MAX_LEVEL_ELEMENTS
|
||||||
|
|
||||||
|
#define SFG_MAX_SPRITE_SIZE SFG_GAME_RESOLUTION_X
|
||||||
|
|
||||||
|
#define SFG_MAP_PIXEL_SIZE (SFG_GAME_RESOLUTION_Y / SFG_MAP_SIZE)
|
||||||
|
|
||||||
|
#if SFG_MAP_PIXEL_SIZE == 0
|
||||||
|
#undef SFG_MAP_PIXEL_SIZE
|
||||||
|
#define SFG_MAP_PIXEL_SIZE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_AI_UPDATE_FRAME_INTERVAL \
|
||||||
|
(SFG_FPS / SFG_AI_FPS)
|
||||||
|
|
||||||
|
#if SFG_AI_UPDATE_FRAME_INTERVAL == 0
|
||||||
|
#undef SFG_AI_UPDATE_FRAME_INTERVAL
|
||||||
|
#define SFG_AI_UPDATE_FRAME_INTERVAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_SPRITE_ANIMATION_FRAME_DURATION \
|
||||||
|
(SFG_FPS / SFG_SPRITE_ANIMATION_SPEED)
|
||||||
|
|
||||||
|
#if SFG_SPRITE_ANIMATION_FRAME_DURATION == 0
|
||||||
|
#undef SFG_SPRITE_ANIMATION_FRAME_DURATION
|
||||||
|
#define SFG_SPRITE_ANIMATION_FRAME_DURATION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_HUD_MARGIN (SFG_GAME_RESOLUTION_X / 40)
|
||||||
|
|
||||||
|
#define SFG_HUD_BORDER_INDICATOR_WIDTH_PIXELS \
|
||||||
|
(SFG_GAME_RESOLUTION_Y / SFG_HUD_BORDER_INDICATOR_WIDTH)
|
||||||
|
|
||||||
|
#define SFG_HUD_BORDER_INDICATOR_DURATION_FRAMES \
|
||||||
|
(SFG_HUD_BORDER_INDICATOR_DURATION / SFG_MS_PER_FRAME)
|
||||||
|
|
||||||
|
#if SFG_HUD_BORDER_INDICATOR_DURATION_FRAMES == 0
|
||||||
|
#define SFG_HUD_BORDER_INDICATOR_DURATION_FRAMES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_BLINK_PERIOD_FRAMES (SFG_BLINK_PERIOD / SFG_MS_PER_FRAME)
|
||||||
|
|
||||||
|
#define SFG_HUD_BAR_HEIGHT \
|
||||||
|
(SFG_FONT_CHARACTER_SIZE * SFG_FONT_SIZE_MEDIUM + SFG_HUD_MARGIN * 2 + 1)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// monsters
|
||||||
|
|
||||||
|
#define SFG_MONSTER_ATTACK_MELEE 0
|
||||||
|
#define SFG_MONSTER_ATTACK_FIREBALL 1
|
||||||
|
#define SFG_MONSTER_ATTACK_BULLET 2
|
||||||
|
#define SFG_MONSTER_ATTACK_FIREBALL_BULLET 3
|
||||||
|
#define SFG_MONSTER_ATTACK_PLASMA 4
|
||||||
|
#define SFG_MONSTER_ATTACK_EXPLODE 5
|
||||||
|
#define SFG_MONSTER_ATTACK_FIREBALL_PLASMA 6
|
||||||
|
|
||||||
|
#define SFG_MONSTER_ATTRIBUTE(attackType,aggressivity0to255,health0to255,spriteSize0to3) \
|
||||||
|
((uint16_t) ( \
|
||||||
|
attackType | \
|
||||||
|
((aggressivity0to255 / 8) << 3) | \
|
||||||
|
(spriteSize0to3 << 8) | \
|
||||||
|
((health0to255 / 4) << 10)))
|
||||||
|
|
||||||
|
#define SFG_GET_MONSTER_ATTACK_TYPE(monsterNumber) \
|
||||||
|
(SFG_monsterAttributeTable[monsterNumber] & 0x0007)
|
||||||
|
|
||||||
|
#define SFG_GET_MONSTER_AGGRESSIVITY(monsterNumber) \
|
||||||
|
(((SFG_monsterAttributeTable[monsterNumber] >> 3) & 0x1F) * 8)
|
||||||
|
|
||||||
|
#define SFG_GET_MONSTER_SPRITE_SIZE(monsterNumber) \
|
||||||
|
((SFG_monsterAttributeTable[monsterNumber] >> 8) & 0x03)
|
||||||
|
|
||||||
|
#define SFG_GET_MONSTER_MAX_HEALTH(monsterNumber) \
|
||||||
|
(((SFG_monsterAttributeTable[monsterNumber] >> 10) & 0x3F) * 4)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Table of monster attributes, each as a 16bit word in format:
|
||||||
|
|
||||||
|
MSB hhhhhhssaaaattt LSB
|
||||||
|
|
||||||
|
ttt: attack type
|
||||||
|
aaaaa: aggressivity (frequence of attacks), 0 to 31
|
||||||
|
ss: sprite size
|
||||||
|
hhhhhh: health, 0 to 63
|
||||||
|
*/
|
||||||
|
uint16_t SFG_monsterAttributeTable[SFG_MONSTERS_TOTAL] =
|
||||||
|
{
|
||||||
|
/* spider */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL,40,61,2),
|
||||||
|
/* destr. */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL_BULLET,90,170,3),
|
||||||
|
/* warrior */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_MELEE,255,40,1),
|
||||||
|
/* plasma */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_PLASMA,56,92,1),
|
||||||
|
/* ender */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_FIREBALL_PLASMA,128,255,3),
|
||||||
|
/* turret */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_BULLET,32,23,0),
|
||||||
|
/* explod. */ SFG_MONSTER_ATTRIBUTE(SFG_MONSTER_ATTACK_EXPLODE,255,36,1)
|
||||||
|
};
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// weapons and projectiles
|
||||||
|
|
||||||
|
#define SFG_WEAPON_KNIFE 0
|
||||||
|
#define SFG_WEAPON_SHOTGUN 1
|
||||||
|
#define SFG_WEAPON_MACHINE_GUN 2
|
||||||
|
#define SFG_WEAPON_ROCKET_LAUNCHER 3
|
||||||
|
#define SFG_WEAPON_PLASMAGUN 4
|
||||||
|
#define SFG_WEAPON_SOLUTION 5
|
||||||
|
|
||||||
|
#define SFG_WEAPONS_TOTAL 6
|
||||||
|
|
||||||
|
#define SFG_WEAPON_ATTRIBUTE(fireType,projectileCount,fireCooldownMs) \
|
||||||
|
((uint8_t) (fireType | ((projectileCount - 1) << 2) | ((fireCooldownMs / (SFG_MS_PER_FRAME * 16)) << 4)))
|
||||||
|
|
||||||
|
#define SFG_GET_WEAPON_FIRE_TYPE(weaponNumber) \
|
||||||
|
(SFG_weaponAttributeTable[weaponNumber] & 0x03)
|
||||||
|
|
||||||
|
#define SFG_GET_WEAPON_FIRE_COOLDOWN_FRAMES(weaponNumber) \
|
||||||
|
((SFG_weaponAttributeTable[weaponNumber] >> 4) * 16)
|
||||||
|
|
||||||
|
#define SFG_GET_WEAPON_PROJECTILE_COUNT(weaponNumber) \
|
||||||
|
(((SFG_weaponAttributeTable[weaponNumber] >> 2) & 0x03) + 1)
|
||||||
|
|
||||||
|
#define SFG_MIN_WEAPON_COOLDOWN_FRAMES 8
|
||||||
|
|
||||||
|
#define SFG_WEAPON_FIRE_TYPE_MELEE 0
|
||||||
|
#define SFG_WEAPON_FIRE_TYPE_BULLET 1
|
||||||
|
#define SFG_WEAPON_FIRE_TYPE_FIREBALL 2
|
||||||
|
#define SFG_WEAPON_FIRE_TYPE_PLASMA 3
|
||||||
|
|
||||||
|
#define SFG_WEAPON_FIRE_TYPES_TOTAL 4
|
||||||
|
|
||||||
|
/**
|
||||||
|
Table of weapon attributes, each as a byte in format:
|
||||||
|
|
||||||
|
MSB ccccnnff LSB
|
||||||
|
|
||||||
|
ff: fire type
|
||||||
|
nn: number of projectiles - 1
|
||||||
|
cccc: fire cooldown in frames, i.e. time after which the next shot can be
|
||||||
|
shot again, ccccc has to be multiplied by 16 to get the real value
|
||||||
|
*/
|
||||||
|
static const uint8_t SFG_weaponAttributeTable[SFG_WEAPONS_TOTAL] =
|
||||||
|
{
|
||||||
|
/* knife */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_MELEE,1,650), // DPS: 6.2
|
||||||
|
/* shotgun */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_BULLET,2,1250), // DPS: 12.8
|
||||||
|
/* m. gun */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_BULLET,1,700), // DPS: 11.4
|
||||||
|
/* r. laun. */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_FIREBALL,1,850), // DPS: 28.2
|
||||||
|
/* plasma */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_PLASMA,1,550), // DPS: 32.7
|
||||||
|
/* solution */ SFG_WEAPON_ATTRIBUTE(SFG_WEAPON_FIRE_TYPE_PLASMA,4,1050) // DPS: 85.7
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t SFG_attackDamageTable[SFG_WEAPON_FIRE_TYPES_TOTAL] =
|
||||||
|
{
|
||||||
|
/* melee */ 4,
|
||||||
|
/* bullet */ 8,
|
||||||
|
/* explostion (fireball) */ 24,
|
||||||
|
/* plasma */ 18
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SFG_PROJECTILE_EXPLOSION 0
|
||||||
|
#define SFG_PROJECTILE_FIREBALL 1
|
||||||
|
#define SFG_PROJECTILE_PLASMA 2
|
||||||
|
#define SFG_PROJECTILE_DUST 3
|
||||||
|
#define SFG_PROJECTILE_BULLET 4
|
||||||
|
#define SFG_PROJECTILE_NONE 255
|
||||||
|
|
||||||
|
#define SFG_PROJECTILES_TOTAL 5
|
||||||
|
|
||||||
|
#define SFG_PROJECTILE_ATTRIBUTE(speedSquaresPerSec,timeToLiveMs) \
|
||||||
|
((uint8_t) \
|
||||||
|
((((speedSquaresPerSec / 4 == 0) && (speedSquaresPerSec != 0)) ? 1 : speedSquaresPerSec / 4) | \
|
||||||
|
((timeToLiveMs / (8 * SFG_MS_PER_FRAME)) << 3)))
|
||||||
|
|
||||||
|
#define SFG_GET_PROJECTILE_SPEED_UPS(projectileNumber) \
|
||||||
|
(((SFG_projectileAttributeTable[projectileNumber] & 0x07) * 4 * RCL_UNITS_PER_SQUARE) / SFG_FPS)
|
||||||
|
|
||||||
|
#define SFG_GET_PROJECTILE_FRAMES_TO_LIVE(projectileNumber) \
|
||||||
|
((SFG_projectileAttributeTable[projectileNumber] >> 3) * 8)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Table of projectile attributes, each as a byte in format:
|
||||||
|
|
||||||
|
MSB lllllsss LSB
|
||||||
|
|
||||||
|
fff: half speed in game squares per second
|
||||||
|
lllll: eigth of frames to live
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LOW_FPS (SFG_FPS < 24) ///< low FPS needs low speeds, because collisions
|
||||||
|
|
||||||
|
static const uint8_t SFG_projectileAttributeTable[SFG_PROJECTILES_TOTAL] =
|
||||||
|
{
|
||||||
|
/* explosion */ SFG_PROJECTILE_ATTRIBUTE(0,400),
|
||||||
|
/* fireball */ SFG_PROJECTILE_ATTRIBUTE(10,1000),
|
||||||
|
|
||||||
|
#if LOW_FPS
|
||||||
|
/* plasma */ SFG_PROJECTILE_ATTRIBUTE(17,500),
|
||||||
|
#else
|
||||||
|
/* plasma */ SFG_PROJECTILE_ATTRIBUTE(18,500),
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* dust */ SFG_PROJECTILE_ATTRIBUTE(0,450),
|
||||||
|
|
||||||
|
#if LOW_FPS
|
||||||
|
/* bullet */ SFG_PROJECTILE_ATTRIBUTE(17,1000)
|
||||||
|
#else
|
||||||
|
/* bullet */ SFG_PROJECTILE_ATTRIBUTE(28,1000)
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#undef LOW_FPS
|
||||||
|
|
||||||
|
#endif // guard
|
|
@ -0,0 +1,149 @@
|
||||||
|
/**
|
||||||
|
@file game.c
|
||||||
|
|
||||||
|
This is a quick V4K implementation of the game front end, with a couple of fixes for MSVC.
|
||||||
|
by r-lyeh
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define V4K_IMPLEMENTATION
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define __builtin_expect(expr,val) (expr)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SFG_FPS 60
|
||||||
|
#define SFG_LOG(str) ;// puts(str);
|
||||||
|
#define SFG_DITHERED_SHADOW 1
|
||||||
|
#define SFG_DIMINISH_SPRITES 1
|
||||||
|
#define SFG_HEADBOB_SHEAR (-1 * SFG_SCREEN_RESOLUTION_Y / 80)
|
||||||
|
#define SFG_BACKGROUND_BLUR 1
|
||||||
|
#define SFG_SCREEN_RESOLUTION_X 700
|
||||||
|
#define SFG_SCREEN_RESOLUTION_Y 512
|
||||||
|
#define SFG_CAN_EXIT 1
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "sounds.h"
|
||||||
|
|
||||||
|
// now implement the Anarch API functions (SFG_*)
|
||||||
|
|
||||||
|
void SFG_processEvent(uint8_t event, uint8_t data)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SFG_sleepMs(uint16_t timeMs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
uint32_t SFG_getTimeMs() {
|
||||||
|
return time_ms();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SFG_getMouseOffset(int16_t *x, int16_t *y)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int8_t SFG_keyPressed(uint8_t key) {
|
||||||
|
switch (key) {
|
||||||
|
default: return 0;
|
||||||
|
case SFG_KEY_UP: return !!input(KEY_UP);
|
||||||
|
case SFG_KEY_DOWN: return !!input(KEY_DOWN);
|
||||||
|
case SFG_KEY_RIGHT: return !!input(KEY_RIGHT);
|
||||||
|
case SFG_KEY_LEFT: return !!input(KEY_LEFT);
|
||||||
|
case SFG_KEY_A: return !!input(KEY_Z) | !!input(KEY_SPACE);
|
||||||
|
case SFG_KEY_C: return !!input(KEY_X) | !!input(KEY_LALT);
|
||||||
|
case SFG_KEY_B: return !!input(KEY_C) | !!input(KEY_LCTRL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SFG_save(uint8_t data[SFG_SAVE_SIZE]) {
|
||||||
|
if( !file_write("anarch.sav",data,SFG_SAVE_SIZE) ) {
|
||||||
|
puts("V4K: could not save the file!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t SFG_load(uint8_t data[SFG_SAVE_SIZE]) {
|
||||||
|
int len = file_size("anarch.sav");
|
||||||
|
for( char *blob = file_read("anarch.sav"); blob && len == SFG_SAVE_SIZE; ) {
|
||||||
|
return !!memcpy(data, blob, len);
|
||||||
|
}
|
||||||
|
puts("V4K: no save file to open");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t screen[SFG_SCREEN_RESOLUTION_X * SFG_SCREEN_RESOLUTION_Y];
|
||||||
|
|
||||||
|
void SFG_setPixel(uint16_t x, uint16_t y, uint8_t colorIndex) {
|
||||||
|
static unsigned palette32[256];
|
||||||
|
|
||||||
|
do_once
|
||||||
|
for (int i = 0; i < 256; ++i) { // precompute RGB palette
|
||||||
|
uint16_t col565 = paletteRGB565[i];
|
||||||
|
palette32[i] = 0xff000000 | ((col565 << 19) & 0xf80000) | ((col565 << 5) & 0xfc00) | ((col565 >> 8) & 0xf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
screen[y * SFG_SCREEN_RESOLUTION_X + x] = palette32[colorIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t musicOn = 1; //< this has to be init to 0 (not 1), else a few samples get played at start
|
||||||
|
void SFG_setMusic(uint8_t value) {
|
||||||
|
if( value == SFG_MUSIC_TURN_ON ) musicOn = 1;
|
||||||
|
if( value == SFG_MUSIC_TURN_OFF ) musicOn = 0;
|
||||||
|
if( value == SFG_MUSIC_NEXT ) SFG_nextMusicTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MUSIC_VOLUME 16.f
|
||||||
|
uint16_t audioBuff[SFG_SFX_SAMPLE_COUNT] = {0};
|
||||||
|
uint16_t audioPos = 0; // audio position for the next audio buffer fill
|
||||||
|
uint32_t audioUpdateFrame = 0; // game frame at which audio buffer fill happened
|
||||||
|
|
||||||
|
static inline int16_t mixSamples(int16_t sample1, int16_t sample2) {
|
||||||
|
return sample1 + sample2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void audioFillCallback(void *userdata, uint8_t *s, int l) {
|
||||||
|
uint16_t *s16 = (uint16_t *) s;
|
||||||
|
|
||||||
|
for (int i = 0; i < l / 2; ++i) {
|
||||||
|
s16[i] = musicOn ?
|
||||||
|
mixSamples(audioBuff[audioPos], MUSIC_VOLUME * (SFG_getNextMusicSample() - SFG_musicTrackAverages[SFG_MusicState.track]))
|
||||||
|
: audioBuff[audioPos];
|
||||||
|
|
||||||
|
audioBuff[audioPos] = 0;
|
||||||
|
audioPos = (audioPos < SFG_SFX_SAMPLE_COUNT - 1) ? (audioPos + 1) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
audioUpdateFrame = SFG_game.frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SFG_playSound(uint8_t soundIndex, uint8_t volume) {
|
||||||
|
uint16_t pos = (audioPos + ((SFG_game.frame - audioUpdateFrame) * SFG_MS_PER_FRAME * 8)) % SFG_SFX_SAMPLE_COUNT;
|
||||||
|
uint16_t volumeScale = 1 << (volume / 37);
|
||||||
|
|
||||||
|
for (int i = 0; i < SFG_SFX_SAMPLE_COUNT; ++i) {
|
||||||
|
audioBuff[pos] = mixSamples(audioBuff[pos], (128 - SFG_GET_SFX_SAMPLE(soundIndex,i)) * volumeScale);
|
||||||
|
pos = (pos < SFG_SFX_SAMPLE_COUNT - 1) ? (pos + 1) : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
// install signal handlers
|
||||||
|
signal_hooks();
|
||||||
|
|
||||||
|
SFG_init();
|
||||||
|
|
||||||
|
window_create(0.75, 0);
|
||||||
|
texture_t t = texture_checker();
|
||||||
|
|
||||||
|
while( window_swap() && SFG_mainLoopBody() ) {
|
||||||
|
texture_update(&t, SFG_SCREEN_RESOLUTION_X, SFG_SCREEN_RESOLUTION_Y, 4, screen, TEXTURE_RGB|TEXTURE_LINEAR);
|
||||||
|
fullscreen_quad_rgb(t, 1.0f);
|
||||||
|
|
||||||
|
uint16_t samples[128]; // 8 KHz 16-bit mono = 8000/60 = 133 samples/frame -> 256 samples/frame
|
||||||
|
audioFillCallback(NULL, (uint8_t*)samples, sizeof(samples));
|
||||||
|
audio_queue(samples, countof(samples), AUDIO_8KHZ|AUDIO_16|AUDIO_1CH );
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 3.7 KiB |
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
@file palette.h
|
||||||
|
|
||||||
|
General purpose HSV-based 256 color palette.
|
||||||
|
|
||||||
|
by Miloslav Ciz (drummyfish), 2019
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PALETTE_256_H
|
||||||
|
#define PALETTE_256_H
|
||||||
|
|
||||||
|
SFG_PROGRAM_MEMORY uint16_t paletteRGB565[256] = {
|
||||||
|
#if 1
|
||||||
|
// manually adjusted, more saturated palette
|
||||||
|
0, 6371, 14855, 27436, 38066, 48631, 59228, 65535, 6241, 14563, 24966, 33320,
|
||||||
|
43755, 52142, 62577, 64885, 6337, 16772, 25190, 35689, 44139, 52559, 63058,
|
||||||
|
65333, 6402, 14851, 23334, 31816, 40268, 50830, 59314, 65526, 4354, 10755,
|
||||||
|
15174, 21576, 30027, 36462, 42929, 51190, 2306, 8709, 13096, 19532, 25935,
|
||||||
|
30323, 36790, 47098, 4356, 8711, 15115, 19536, 27956, 32377, 38846, 47103,
|
||||||
|
4227, 8519, 12812, 17136, 25588, 31961, 38334, 46751, 2115, 8424, 14732, 21040,
|
||||||
|
27380, 33721, 40030, 48511, 6244, 12520, 22924, 31280, 39669, 48089, 56445,
|
||||||
|
64927, 8290, 16614, 24969, 33325, 43761, 52148, 62585, 64892, 10240, 18464,
|
||||||
|
26657, 38946, 47202, 55524, 63781, 64074, 10400, 18753, 27170, 37601, 48034,
|
||||||
|
56421, 64837, 65002, 6496, 14944, 23425, 31937, 40418, 48869, 57317, 61418,
|
||||||
|
352, 4704, 7041, 7362, 15842, 20196, 24550, 30697, 354, 611, 2949, 5288, 7658,
|
||||||
|
12013, 8175, 20467, 357, 617, 910, 5298, 9686, 7931, 14335, 24575, 69, 233,
|
||||||
|
4461, 4594, 8918, 2907, 13311, 19679, 4133, 2089, 4173, 8306, 10455, 16667,
|
||||||
|
20863, 27263, 6149, 14377, 22574, 28819, 39063, 45371, 53631, 57983, 10242,
|
||||||
|
18469, 26664, 38987, 47247, 55537, 63797, 64119, 10272, 18432, 26624, 34848,
|
||||||
|
45056, 53312, 61504, 63520, 10336, 18624, 26976, 35296, 45728, 54048, 62400,
|
||||||
|
64609, 8544, 16992, 25440, 31872, 42400, 50880, 59328, 65504, 4448, 2656,
|
||||||
|
7008, 11392, 13728, 14016, 20416, 26593, 2400, 608, 864, 3200, 5504, 1698,
|
||||||
|
1985, 2019, 353, 614, 872, 1163, 1422, 1713, 2005, 2039, 197, 361, 557, 753,
|
||||||
|
950, 5273, 1406, 9759, 5, 9, 2093, 81, 4214, 186, 2270, 351, 2052, 4105, 4109,
|
||||||
|
8209, 8278, 12314, 16414, 18527, 10245, 14378, 22541, 30738, 38934, 47130, 55326,
|
||||||
|
61471, 10241, 18435, 26630, 34824, 45066, 53293, 61519, 63601
|
||||||
|
#else
|
||||||
|
// original palette
|
||||||
|
0, 8484, 19017, 27501, 38034, 46518, 57051, 65535, 8354, 16709, 25096, 33450,
|
||||||
|
41805, 50192, 58546, 64853, 8386, 16805, 25224, 33642, 42061, 50480, 58898,
|
||||||
|
65269, 6402, 14853, 23304, 29706, 38157, 46608, 55058, 61429, 4354, 10757,
|
||||||
|
17160, 23562, 29965, 36368, 42770, 49141, 4355, 10758, 17161, 21516, 27920,
|
||||||
|
34323, 38678, 45049, 4323, 10759, 17163, 21519, 27923, 34327, 38683, 45055,
|
||||||
|
4292, 10632, 17004, 21296, 27668, 34008, 38300, 44671, 4260, 10568, 16908,
|
||||||
|
23216, 29524, 35864, 42172, 48479, 6308, 14664, 23052, 29360, 37716, 46104,
|
||||||
|
54460, 60767, 8355, 16710, 25098, 33453, 41809, 50196, 58552, 64859, 8257,
|
||||||
|
16546, 24836, 33093, 41382, 49672, 57929, 64170, 8353, 16738, 25124, 33509,
|
||||||
|
41894, 50248, 58633, 64970, 6401, 12802, 21252, 27653, 36102, 42504, 50953,
|
||||||
|
57322, 2305, 6658, 11012, 15365, 19718, 24072, 28425, 32746, 2306, 4612, 8967,
|
||||||
|
11273, 13580, 17934, 20240, 22515, 2307, 4615, 8971, 11279, 13587, 17943, 20251,
|
||||||
|
22527, 2180, 4392, 8652, 10864, 13076, 17304, 19516, 21727, 2116, 6312, 10508,
|
||||||
|
14672, 18868, 23064, 25180, 29375, 6212, 12456, 20748, 26960, 35252, 41496,
|
||||||
|
49756, 55999, 8258, 16549, 24840, 33099, 41390, 49681, 57940, 64183, 8192,
|
||||||
|
16384, 24576, 32768, 40960, 49152, 57344, 63488, 8320, 16640, 24960, 33312,
|
||||||
|
41632, 49952, 58304, 64576, 6400, 14848, 23296, 29696, 38144, 46592, 52992,
|
||||||
|
61408, 2304, 6656, 8960, 13312, 15616, 19968, 22272, 26592, 256, 513, 769, 1026,
|
||||||
|
1283, 1539, 1796, 2021, 258, 517, 776, 1035, 1294, 1552, 1811, 2038, 164, 360,
|
||||||
|
556, 752, 948, 1144, 1308, 1503, 36, 104, 140, 208, 244, 312, 348, 415, 2052,
|
||||||
|
4104, 8204, 10256, 14356, 16408, 18460, 22559, 6148, 14344, 20492, 28688, 34836,
|
||||||
|
43032, 51228, 57375, 8194, 16388, 24582, 32777, 40971, 49165, 57359, 63505
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Adds value (brightness), possibly negative, to given color (represented by
|
||||||
|
its palette index). If you know you'll only be either adding or substracting,
|
||||||
|
use plusValue() or minusValue() functions, which should be faster. */
|
||||||
|
static inline uint8_t palette_addValue(uint8_t color, int8_t add)
|
||||||
|
{
|
||||||
|
uint8_t newValue = color + add;
|
||||||
|
|
||||||
|
if ((newValue >> 3) == (color >> 3))
|
||||||
|
return newValue;
|
||||||
|
else
|
||||||
|
return add > 0 ? (color | 0x07) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a positive value (brightness) to given color (represented by its
|
||||||
|
palette index). This should be a little bit faster than addValue(). */
|
||||||
|
static inline uint8_t palette_plusValue(uint8_t color, uint8_t plus)
|
||||||
|
{
|
||||||
|
uint8_t newValue = color + plus;
|
||||||
|
return ((newValue >> 3) == (color >> 3)) ? newValue : (color | 0x07);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Substracts a positive value (brightness) from given color (represented by
|
||||||
|
its palette index). This should be a little bit faster than addValue(). */
|
||||||
|
static inline uint8_t palette_minusValue(uint8_t color, uint8_t minus)
|
||||||
|
{
|
||||||
|
uint8_t newValue = color - minus;
|
||||||
|
return ((newValue >> 3) == (color >> 3)) ? newValue : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //guard
|
|
@ -0,0 +1,518 @@
|
||||||
|
/**
|
||||||
|
@file settings.h
|
||||||
|
|
||||||
|
This file contains settings (or setting hints) for the game. Values here can
|
||||||
|
fine tune performance vs quality and personalize the final compiled game. Some
|
||||||
|
of these settings may be overriden by the specific platform used according to
|
||||||
|
its limitations. You are advised to NOT change value in this file directly,
|
||||||
|
but rather predefine them somewhere before this file gets included, e.g. in
|
||||||
|
you personal settings file.
|
||||||
|
|
||||||
|
by Miloslav Ciz (drummyfish), 2019
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is to
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SFG_SETTINGS_H
|
||||||
|
#define _SFG_SETTINGS_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
Time multiplier in SFG_Units (1.0 == 1024). This can be used to slow down or
|
||||||
|
speed up the game. Note that this also changes the rendering FPS accordingly
|
||||||
|
(e.g. half FPS at half speed), so if you want to keep the FPS, divide it by
|
||||||
|
the multiplier value.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_TIME_MULTIPLIER
|
||||||
|
#define SFG_TIME_MULTIPLIER 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Target FPS (frames per second). This sets the game logic FPS and will try to
|
||||||
|
render at the same rate. If such fast rendering can't be achieved, frames will
|
||||||
|
be droped, but the game logic will still be forced to run at this speed, so
|
||||||
|
the game may actually become slowed down if FPS is set too high. Too high or
|
||||||
|
too low FPS can also negatively affect game speeds which are computed as
|
||||||
|
integers and rounding errors can occur soon, so don't set this to extreme
|
||||||
|
values (try to keep between 20 to 100). FPS also determines the game
|
||||||
|
simulation step length, so different FPS values may result in very slight
|
||||||
|
differences in game behavior (not very noticeable but affecting demos etc.).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FPS
|
||||||
|
#define SFG_FPS 60
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Increases or decreases the brightness of the rendered world (but not menu,
|
||||||
|
HUD etc.). Effective values are -8 to 8.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_BRIGHTNESS
|
||||||
|
#define SFG_BRIGHTNESS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
On platforms with mouse this sets its horizontal sensitivity. 128 means 1
|
||||||
|
RCL_Unit turn angle per mouse pixel travelled.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_MOUSE_SENSITIVITY_HORIZONTAL
|
||||||
|
#define SFG_MOUSE_SENSITIVITY_HORIZONTAL 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Like SFG_MOUSE_SENSITIVITY_HORIZONTAL but for vertical look. 128 means 1
|
||||||
|
shear pixel per mouse pixel travelled.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_MOUSE_SENSITIVITY_VERTICAL
|
||||||
|
#define SFG_MOUSE_SENSITIVITY_VERTICAL 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Width of the screen in pixels. Set this to ACTUAL resolution. If you want the
|
||||||
|
game to run at smaller resolution (with bigger pixels), do this using
|
||||||
|
SFG_RESOLUTION_SCALEDOWN.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_SCREEN_RESOLUTION_X
|
||||||
|
#define SFG_SCREEN_RESOLUTION_X 800
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Like SFG_SCREEN_RESOLUTION_X, but for y resolution.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_SCREEN_RESOLUTION_Y
|
||||||
|
#define SFG_SCREEN_RESOLUTION_Y 600
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How quickly player turns left/right, in degrees per second.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_PLAYER_TURN_SPEED
|
||||||
|
#define SFG_PLAYER_TURN_SPEED 180
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Horizontal FOV (field of vision) in RCL_Units (1024 means 360 degrees).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FOV_HORIZONTAL
|
||||||
|
#define SFG_FOV_HORIZONTAL 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Like SFG_FOV_HORIZONTAL but for vertical angle.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FOV_VERTICAL
|
||||||
|
#define SFG_FOV_VERTICAL 330
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Distance, in RCL_Units, to which textures will be drawn. Textures behind this
|
||||||
|
distance will be replaced by an average constant color, which maybe can help
|
||||||
|
performance and also serves as an antialiasim (2 level MIP map). Value 0 turns
|
||||||
|
texturing completely off, which is much faster than having just a low value,
|
||||||
|
values >= 65535 activate texturing completely, which can be a little faster
|
||||||
|
than setting having a high value lower than this limit.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_TEXTURE_DISTANCE
|
||||||
|
#define SFG_TEXTURE_DISTANCE 100000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How many times the screen resolution will be divided (how many times a game
|
||||||
|
pixel will be bigger than the screen pixel).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RESOLUTION_SCALEDOWN
|
||||||
|
#define SFG_RESOLUTION_SCALEDOWN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Multiplier, in RCL_Units (1024 == 1.0), of the damager player takes. This can
|
||||||
|
be used to balance difficulty.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_PLAYER_DAMAGE_MULTIPLIER
|
||||||
|
#define SFG_PLAYER_DAMAGE_MULTIPLIER 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Hint as to whether to run in fullscreen, if the platform allows it.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FULLSCREEN
|
||||||
|
#define SFG_FULLSCREEN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether shadows (fog) should be dithered, i.e. more smooth (needs a bit more
|
||||||
|
CPU performance and memory).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_DITHERED_SHADOW
|
||||||
|
#define SFG_DITHERED_SHADOW 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Depth step (in RCL_Units) after which fog diminishes a color by one value
|
||||||
|
point. For performance reasons this number should be kept a power of two!
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FOG_DIMINISH_STEP
|
||||||
|
#define SFG_FOG_DIMINISH_STEP 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
If set, floor and ceiling will be colored differently depending on their
|
||||||
|
height. This can be useful when fog is turned on and different floor levels
|
||||||
|
are hard to distinguish.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_DIFFERENT_FLOOR_CEILING_COLORS
|
||||||
|
#define SFG_DIFFERENT_FLOOR_CEILING_COLORS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum number of squares that will be traversed by any cast ray. Smaller
|
||||||
|
number is faster but can cause visual artifacts.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RAYCASTING_MAX_STEPS
|
||||||
|
#define SFG_RAYCASTING_MAX_STEPS 30
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum number of hits any cast ray will register. Smaller number is faster
|
||||||
|
but can cause visual artifacts.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RAYCASTING_MAX_HITS
|
||||||
|
#define SFG_RAYCASTING_MAX_HITS 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Same as SFG_RAYCASTING_MAX_STEPS but for visibility rays that are used to
|
||||||
|
check whether sprites are visible etc.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RAYCASTING_VISIBILITY_MAX_STEPS
|
||||||
|
#if SFG_RAYCASTING_MAX_STEPS < 15
|
||||||
|
#define SFG_RAYCASTING_VISIBILITY_MAX_STEPS 15
|
||||||
|
#else
|
||||||
|
#define SFG_RAYCASTING_VISIBILITY_MAX_STEPS SFG_RAYCASTING_MAX_STEPS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Same as SFG_RAYCASTING_MAX_HITS but for visibility rays that are used to check
|
||||||
|
whether sprites are visible etc.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RAYCASTING_VISIBILITY_MAX_HITS
|
||||||
|
#if SFG_RAYCASTING_MAX_HITS < 6
|
||||||
|
#define SFG_RAYCASTING_VISIBILITY_MAX_HITS 6
|
||||||
|
#else
|
||||||
|
#define SFG_RAYCASTING_VISIBILITY_MAX_HITS SFG_RAYCASTING_MAX_HITS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How many times rendering should be subsampled horizontally. Bigger number
|
||||||
|
can significantly improve performance (by casting fewer rays), but can look
|
||||||
|
a little worse. This number should be a divisor of SFG_SCREEN_RESOLUTION_X!
|
||||||
|
*/
|
||||||
|
#ifndef SFG_RAYCASTING_SUBSAMPLE
|
||||||
|
#define SFG_RAYCASTING_SUBSAMPLE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enables or disables fog (darkness) due to distance. Recommended to keep on
|
||||||
|
for good look, but can be turned off for performance.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_ENABLE_FOG
|
||||||
|
#define SFG_ENABLE_FOG 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says whether sprites should diminish in fog. This takes more performance but
|
||||||
|
looks better.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_DIMINISH_SPRITES
|
||||||
|
#define SFG_DIMINISH_SPRITES 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How quick player head bob is, 1024 meaning once per second. 0 Means turn off
|
||||||
|
head bob.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HEADBOB_SPEED
|
||||||
|
#define SFG_HEADBOB_SPEED 900
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets head bob offset, in RCL_UNITS_PER_SQUARE. 0 Means turn off head bob.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HEADBOB_OFFSET
|
||||||
|
#define SFG_HEADBOB_OFFSET 200
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
If head bob is on, this additionally sets additional camera shear bob, in
|
||||||
|
pixels, which can make bobbing look more "advanced". 0 turns this option off.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HEADBOB_SHEAR
|
||||||
|
#define SFG_HEADBOB_SHEAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Weapon bobbing offset in weapon image pixels.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_WEAPONBOB_OFFSET
|
||||||
|
#define SFG_WEAPONBOB_OFFSET 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Camera shearing (looking up/down) speed, in vertical resolutions per second.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_CAMERA_SHEAR_SPEED
|
||||||
|
#define SFG_CAMERA_SHEAR_SPEED 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum camera shear (vertical angle). 1024 means 1.0 * vertical resolution.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_CAMERA_MAX_SHEAR
|
||||||
|
#define SFG_CAMERA_MAX_SHEAR 1024
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Specifies how quick some sprite animations are, in frames per second.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_SPRITE_ANIMATION_SPEED
|
||||||
|
#define SFG_SPRITE_ANIMATION_SPEED 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How wide the border indicator is, in fractions of screen width.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HUD_BORDER_INDICATOR_WIDTH
|
||||||
|
#define SFG_HUD_BORDER_INDICATOR_WIDTH 32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
For how long border indication (being hurt etc.) stays shown, in ms.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HUD_BORDER_INDICATOR_DURATION
|
||||||
|
#define SFG_HUD_BORDER_INDICATOR_DURATION 500
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Color (palette index) by which being hurt is indicated.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HUD_HURT_INDICATION_COLOR
|
||||||
|
#define SFG_HUD_HURT_INDICATION_COLOR 175
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Color (palette index) by which taking an item is indicated.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_HUD_ITEM_TAKEN_INDICATION_COLOR
|
||||||
|
#define SFG_HUD_ITEM_TAKEN_INDICATION_COLOR 207
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How many element (items, monsters, ...) distances will be checked per frame
|
||||||
|
for distance. Higher value may decrease performance a tiny bit, but things
|
||||||
|
will react more quickly and appear less "out of thin air".
|
||||||
|
*/
|
||||||
|
#ifndef SFG_ELEMENT_DISTANCES_CHECKED_PER_FRAME
|
||||||
|
#define SFG_ELEMENT_DISTANCES_CHECKED_PER_FRAME 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maximum distance at which sound effects (SFX) will be played. The SFX volume
|
||||||
|
will gradually drop towards this distance.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_SFX_MAX_DISTANCE
|
||||||
|
#define SFG_SFX_MAX_DISTANCE (1024 * 60)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says the intensity of background image blur. 0 means no blur, which improves
|
||||||
|
performance and lowers memory usage. Blur doesn't look very good in small
|
||||||
|
resolutions.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_BACKGROUND_BLUR
|
||||||
|
#define SFG_BACKGROUND_BLUR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Defines the period, in ms, of things that blink, such as text.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_BLINK_PERIOD
|
||||||
|
#define SFG_BLINK_PERIOD 500
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Probability (0 - 255) of how often a monster makes sound during movement.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_MONSTER_SOUND_PROBABILITY
|
||||||
|
#define SFG_MONSTER_SOUND_PROBABILITY 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Affects how precise monsters are in aiming, specify random range in
|
||||||
|
fourths of a game square. Should be power of 2 for performance.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_MONSTER_AIM_RANDOMNESS
|
||||||
|
#define SFG_MONSTER_AIM_RANDOMNESS 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Color 1 index of player on map.
|
||||||
|
#ifndef SFG_MAP_PLAYER_COLOR1
|
||||||
|
#define SFG_MAP_PLAYER_COLOR1 93
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Color 2 index of player on map.
|
||||||
|
#ifndef SFG_MAP_PLAYER_COLOR2
|
||||||
|
#define SFG_MAP_PLAYER_COLOR2 111
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Color index of elevators on map.
|
||||||
|
#ifndef SFG_MAP_ELEVATOR_COLOR
|
||||||
|
#define SFG_MAP_ELEVATOR_COLOR 214
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Color index of squeezers on map.
|
||||||
|
#ifndef SFG_MAP_SQUEEZER_COLOR
|
||||||
|
#define SFG_MAP_SQUEEZER_COLOR 246
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// Color index of door on map.
|
||||||
|
#ifndef SFG_MAP_DOOR_COLOR
|
||||||
|
#define SFG_MAP_DOOR_COLOR 188
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Boolean value indicating whether current OS is malware.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_OS_IS_MALWARE
|
||||||
|
#define SFG_OS_IS_MALWARE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Angle difference, as a cos value in RCL_Units, between the player and a
|
||||||
|
monster, at which vertical autoaim will trigger. If the angle is greater, a
|
||||||
|
shot will go directly forward.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_VERTICAL_AUTOAIM_ANGLE_THRESHOLD
|
||||||
|
#define SFG_VERTICAL_AUTOAIM_ANGLE_THRESHOLD 50
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Byte (0 - 255) volume of the menu click sound.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_MENU_CLICK_VOLUME
|
||||||
|
#define SFG_MENU_CLICK_VOLUME 220
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says whether the exit item should be showed in the menu. Platforms that can't
|
||||||
|
exit (such as some gaming consoles that simply use power off button) can
|
||||||
|
define this to 0.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_CAN_EXIT
|
||||||
|
#define SFG_CAN_EXIT 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
On Arduino platforms this should be set to 1. That will cause some special
|
||||||
|
treatment regarding constant variables and PROGMEM.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_ARDUINO
|
||||||
|
#define SFG_ARDUINO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Whether levels background (in distance or transparent wall textures) should
|
||||||
|
be drawn. If turned off, the background will be constant color, which can
|
||||||
|
noticably increase performance.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_DRAW_LEVEL_BACKGROUND
|
||||||
|
#define SFG_DRAW_LEVEL_BACKGROUND 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Says the size, in pixels, of a sprite when it is closest to the camera, which
|
||||||
|
is the maximum size that can be drawn. Sprites on "weird" aspect ratios can
|
||||||
|
look weirdly scaled, so this option can be used to fix that (typically set
|
||||||
|
horizontal screen resolution instead of vertical).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_SPRITE_MAX_SIZE
|
||||||
|
#define SFG_SPRITE_MAX_SIZE \
|
||||||
|
(SFG_SCREEN_RESOLUTION_Y / SFG_RESOLUTION_SCALEDOWN)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
If set, single item menu will be forced.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_FORCE_SINGLE_ITEM_MENU
|
||||||
|
#define SFG_FORCE_SINGLE_ITEM_MENU 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------ developer/debug settings ------
|
||||||
|
|
||||||
|
/**
|
||||||
|
Developer cheat for having infinite ammo in all weapons.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_INFINITE_AMMO
|
||||||
|
#define SFG_INFINITE_AMMO 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Developer cheat for immortality.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_IMMORTAL
|
||||||
|
#define SFG_IMMORTAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Developer setting, with 1 every level is won immediately after start.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_QUICK_WIN
|
||||||
|
#define SFG_QUICK_WIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reveals all levels to be played.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_ALL_LEVELS
|
||||||
|
#define SFG_ALL_LEVELS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Turn on for previes mode for map editing (flying, noclip, fast movement etc.).
|
||||||
|
*/
|
||||||
|
#ifndef SFG_PREVIEW_MODE
|
||||||
|
#define SFG_PREVIEW_MODE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
How much faster movement is in the preview mode.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_PREVIEW_MODE_SPEED_MULTIPLIER
|
||||||
|
#define SFG_PREVIEW_MODE_SPEED_MULTIPLIER 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Skips menu and starts given level immediatelly, for development. 0 means this
|
||||||
|
options is ignored, 1 means load level 1 etc.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_START_LEVEL
|
||||||
|
#define SFG_START_LEVEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reveals whole level map from start.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_REVEAL_MAP
|
||||||
|
#define SFG_REVEAL_MAP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gives player all keys from start.
|
||||||
|
*/
|
||||||
|
#ifndef SFG_UNLOCK_DOOR
|
||||||
|
#define SFG_UNLOCK_DOOR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // guard
|
|
@ -0,0 +1,404 @@
|
||||||
|
/**
|
||||||
|
@file smallinput.h
|
||||||
|
|
||||||
|
Small API for getting keyboard/mouse input, with possiblity to record it and
|
||||||
|
play back.
|
||||||
|
|
||||||
|
The Linux Input API requires root pirivileges (sudo).
|
||||||
|
|
||||||
|
by Milsolav "drummyfish" Ciz, released under CC0 1.0 (public domain)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SMALLINPUT_H
|
||||||
|
#define _SMALLINPUT_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define SMALLINPUT_MODE_NORMAL 0 ///< Only handle input.
|
||||||
|
#define SMALLINPUT_MODE_RECORD 1 ///< Handle input and record it.
|
||||||
|
#define SMALLINPUT_MODE_PLAY 2 ///< Play back recorded input.
|
||||||
|
|
||||||
|
#define SMALLINPUT_KEY_NONE 0
|
||||||
|
#define SMALLINPUT_SPACE ' '
|
||||||
|
#define SMALLINPUT_BACKSPACE 8
|
||||||
|
#define SMALLINPUT_TAB 9
|
||||||
|
#define SMALLINPUT_RETURN 13
|
||||||
|
#define SMALLINPUT_SHIFT 14
|
||||||
|
#define SMALLINPUT_ESCAPE 27
|
||||||
|
#define SMALLINPUT_DELETE 127
|
||||||
|
#define SMALLINPUT_ARROW_UP 128
|
||||||
|
#define SMALLINPUT_ARROW_RIGHT 129
|
||||||
|
#define SMALLINPUT_ARROW_DOWN 130
|
||||||
|
#define SMALLINPUT_ARROW_LEFT 131
|
||||||
|
#define SMALLINPUT_F1 132
|
||||||
|
#define SMALLINPUT_F2 133
|
||||||
|
#define SMALLINPUT_F3 134
|
||||||
|
#define SMALLINPUT_F4 135
|
||||||
|
#define SMALLINPUT_F5 136
|
||||||
|
#define SMALLINPUT_F6 137
|
||||||
|
#define SMALLINPUT_F7 138
|
||||||
|
#define SMALLINPUT_F8 139
|
||||||
|
#define SMALLINPUT_F9 140
|
||||||
|
#define SMALLINPUT_F10 141
|
||||||
|
#define SMALLINPUT_F11 142
|
||||||
|
#define SMALLINPUT_F12 143
|
||||||
|
#define SMALLINPUT_CTRL 144
|
||||||
|
#define SMALLINPUT_MOUSE_L 253
|
||||||
|
#define SMALLINPUT_MOUSE_M 254
|
||||||
|
#define SMALLINPUT_MOUSE_R 255
|
||||||
|
|
||||||
|
#define SMALLINPUT_RECORD_KEY_DOWN 1 ///< Mouse down event, followed by code.
|
||||||
|
#define SMALLINPUT_RECORD_KEY_UP 2 ///< Moue up event, followed by code.
|
||||||
|
#define SMALLINPUT_RECORD_MOUSE_X 3 ///< Mouse x move, followed by s32 value.
|
||||||
|
#define SMALLINPUT_RECORD_MOUSE_Y 4 ///< Mouse y move, followed by s32 value.
|
||||||
|
#define SMALLINPUT_RECORD_END 255 ///< Record end, followed by 4 more same values.
|
||||||
|
|
||||||
|
uint8_t input_keyStates[256];
|
||||||
|
int32_t input_mousePosition[2];
|
||||||
|
|
||||||
|
uint8_t input_keyStatesPrevious[256];
|
||||||
|
int32_t input_mousePositionPrevious[2];
|
||||||
|
|
||||||
|
uint8_t input_mode;
|
||||||
|
|
||||||
|
uint32_t input_frame = 0;
|
||||||
|
uint8_t *input_recordData;
|
||||||
|
uint32_t input_recordPosition;
|
||||||
|
uint32_t input_recordSize;
|
||||||
|
|
||||||
|
#if 1 // TODO: add other options for input handling (SDL, xinput, ...)
|
||||||
|
/*
|
||||||
|
This is using Linux Input Subsystem API. Defines can be found in
|
||||||
|
include/uapi/linux/input-event-codes.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <linux/input.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct timeval time;
|
||||||
|
uint16_t type;
|
||||||
|
uint16_t code;
|
||||||
|
int32_t value;
|
||||||
|
} LinuxInputEvent;
|
||||||
|
|
||||||
|
#define INPUT_KEYBOARD_FILE "/dev/input/event0"
|
||||||
|
#define INPUT_MOUSE_FILE "/dev/input/event1"
|
||||||
|
|
||||||
|
int input_keyboardFile = 0;
|
||||||
|
int input_mouseFile = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Maps this library's key codes to linux input key codes.
|
||||||
|
*/
|
||||||
|
static const int input_linuxCodes[256] =
|
||||||
|
{
|
||||||
|
#define no KEY_RESERVED
|
||||||
|
no,no,no,no,no,no,no,no,KEY_BACKSPACE,KEY_TAB,no,no,no,KEY_ENTER,KEY_LEFTSHIFT,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,KEY_ESC,no,no,no,no,
|
||||||
|
KEY_SPACE,no,no,no,no,no,no,no,no,no,no,no,KEY_COMMA,no,KEY_DOT,no,
|
||||||
|
KEY_0,KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9,no,KEY_SEMICOLON,no,KEY_EQUAL,no,KEY_QUESTION,
|
||||||
|
no,KEY_A,KEY_B,KEY_C,KEY_D,KEY_E,KEY_F,KEY_G,KEY_H,KEY_I,KEY_J,KEY_K,KEY_L,KEY_M,KEY_N,KEY_O,
|
||||||
|
KEY_P,KEY_Q,KEY_R,KEY_S,KEY_T,KEY_U,KEY_V,KEY_W,KEY_X,KEY_Y,KEY_Z,no,no,no,no,no,
|
||||||
|
no,KEY_A,KEY_B,KEY_C,KEY_D,KEY_E,KEY_F,KEY_G,KEY_H,KEY_I,KEY_J,KEY_K,KEY_L,KEY_M,KEY_N,KEY_O,
|
||||||
|
KEY_P,KEY_Q,KEY_R,KEY_S,KEY_T,KEY_U,KEY_V,KEY_W,KEY_X,KEY_Y,KEY_Z,no,no,no,no,KEY_DELETE,
|
||||||
|
KEY_UP,KEY_RIGHT,KEY_DOWN,KEY_LEFT,KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10,KEY_F11,KEY_F12,
|
||||||
|
KEY_LEFTCTRL,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,
|
||||||
|
no,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no
|
||||||
|
#undef no
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void input_recordU8(uint8_t value)
|
||||||
|
{
|
||||||
|
if (input_recordPosition < (input_recordSize - 1))
|
||||||
|
{
|
||||||
|
input_recordData[input_recordPosition] = value;
|
||||||
|
input_recordPosition++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_recordU32(uint32_t value)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
input_recordU8(value % 256);
|
||||||
|
value /= 256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t input_readU32(uint8_t *data)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 4; ++i)
|
||||||
|
result = result * 256 + data[3 - i];
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initializes the library with given mode (SMALLINPUT_MODE_*).
|
||||||
|
*/
|
||||||
|
uint8_t input_init(uint8_t mode, uint8_t *recordData, uint32_t recordDataLength)
|
||||||
|
{
|
||||||
|
input_mode = mode;
|
||||||
|
|
||||||
|
input_mousePosition[0] = 0;
|
||||||
|
input_mousePosition[1] = 0;
|
||||||
|
|
||||||
|
input_mousePositionPrevious[0] = 0;
|
||||||
|
input_mousePositionPrevious[1] = 0;
|
||||||
|
|
||||||
|
input_frame = 0;
|
||||||
|
input_recordData = recordData;
|
||||||
|
input_recordPosition = 0;
|
||||||
|
input_recordSize = recordDataLength;
|
||||||
|
|
||||||
|
for (int16_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
input_keyStates[i] = 0;
|
||||||
|
input_keyStatesPrevious[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t result = 1;
|
||||||
|
|
||||||
|
if (input_mode != SMALLINPUT_MODE_PLAY)
|
||||||
|
{
|
||||||
|
input_keyboardFile = open(INPUT_KEYBOARD_FILE, O_RDONLY);
|
||||||
|
|
||||||
|
result = input_keyboardFile >= 0;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
fcntl(input_keyboardFile, F_SETFL, O_NONBLOCK);
|
||||||
|
|
||||||
|
input_mouseFile = open(INPUT_MOUSE_FILE, O_RDONLY);
|
||||||
|
|
||||||
|
result = input_mouseFile >= 0;
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
fcntl(input_mouseFile, F_SETFL, O_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
puts("could not open device file (are you root?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_end(void)
|
||||||
|
{
|
||||||
|
if (input_mode == SMALLINPUT_MODE_RECORD)
|
||||||
|
for (uint8_t i = 0; i < 5; ++i)
|
||||||
|
input_recordU8(SMALLINPUT_RECORD_END);
|
||||||
|
|
||||||
|
close(input_keyboardFile);
|
||||||
|
close(input_mouseFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Should be called once every main loop iteration to retrieve current input
|
||||||
|
state.
|
||||||
|
*/
|
||||||
|
void input_update(void)
|
||||||
|
{
|
||||||
|
LinuxInputEvent event;
|
||||||
|
|
||||||
|
if (input_mode == SMALLINPUT_MODE_PLAY)
|
||||||
|
{
|
||||||
|
while (input_recordPosition < input_recordSize)
|
||||||
|
{
|
||||||
|
uint32_t nextFrame = input_readU32(input_recordData + input_recordPosition);
|
||||||
|
|
||||||
|
if (input_frame >= nextFrame)
|
||||||
|
{
|
||||||
|
input_recordPosition += 4;
|
||||||
|
|
||||||
|
uint8_t rec = input_recordData[input_recordPosition];
|
||||||
|
|
||||||
|
switch (rec)
|
||||||
|
{
|
||||||
|
case SMALLINPUT_RECORD_KEY_DOWN:
|
||||||
|
case SMALLINPUT_RECORD_KEY_UP:
|
||||||
|
input_recordPosition++;
|
||||||
|
input_keyStates[input_recordData[input_recordPosition]] = rec == SMALLINPUT_RECORD_KEY_DOWN;
|
||||||
|
input_recordPosition++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMALLINPUT_RECORD_MOUSE_X:
|
||||||
|
case SMALLINPUT_RECORD_MOUSE_Y:
|
||||||
|
input_recordPosition++;
|
||||||
|
input_mousePosition[rec == SMALLINPUT_RECORD_MOUSE_Y] =
|
||||||
|
input_readU32(input_recordData + input_recordPosition);
|
||||||
|
input_recordPosition += 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SMALLINPUT_RECORD_END:
|
||||||
|
input_recordPosition = input_recordSize;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /*printf("corrupt record\n");*/ break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (1) // keyboard
|
||||||
|
{
|
||||||
|
if (read(input_keyboardFile, &event, sizeof(event)) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (event.type == EV_KEY && (event.value == 1 || event.value == 0))
|
||||||
|
for (uint16_t i = 0; i < 256; ++i)
|
||||||
|
if (event.code == input_linuxCodes[i])
|
||||||
|
{
|
||||||
|
input_keyStates[i] = event.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) // mouse
|
||||||
|
{
|
||||||
|
if (read(input_mouseFile, &event, sizeof(event)) <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (event.type == EV_REL)
|
||||||
|
input_mousePosition[event.code % 2] += event.value;
|
||||||
|
else if (event.type == EV_KEY)
|
||||||
|
{
|
||||||
|
input_keyStates[
|
||||||
|
event.code == BTN_LEFT ? SMALLINPUT_MOUSE_L :
|
||||||
|
(event.code == BTN_RIGHT ? SMALLINPUT_MOUSE_R : SMALLINPUT_MOUSE_M)]
|
||||||
|
= event.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 256; ++i)
|
||||||
|
if (input_keyStates[i] && input_keyStates[i] < 255)
|
||||||
|
input_keyStates[i]++;
|
||||||
|
|
||||||
|
if (input_mode == SMALLINPUT_MODE_RECORD)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < 2; ++i) // record mouse events
|
||||||
|
if (input_mousePositionPrevious[i] != input_mousePosition[i])
|
||||||
|
{
|
||||||
|
input_recordU32(input_frame + 1);
|
||||||
|
input_recordU8((i == 0) ? SMALLINPUT_RECORD_MOUSE_X : SMALLINPUT_RECORD_MOUSE_Y);
|
||||||
|
input_recordU32(input_mousePosition[i]);
|
||||||
|
|
||||||
|
input_mousePositionPrevious[i] = input_mousePosition[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 256; ++i) // record key events
|
||||||
|
{
|
||||||
|
uint8_t a = input_keyStates[i] > 0;
|
||||||
|
uint8_t b = input_keyStatesPrevious[i] > 0;
|
||||||
|
|
||||||
|
if (a != b)
|
||||||
|
{
|
||||||
|
input_recordU32(input_frame + 1);
|
||||||
|
input_recordU8(a ? SMALLINPUT_RECORD_KEY_DOWN : SMALLINPUT_RECORD_KEY_UP);
|
||||||
|
input_recordU8(i);
|
||||||
|
|
||||||
|
input_keyStatesPrevious[i] = input_keyStates[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_frame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the number of input frames for which given key has been pressed (> 1:
|
||||||
|
key is pressed, == 1: key was just pressed, == 0: key is not pressed).
|
||||||
|
*/
|
||||||
|
static inline uint8_t input_getKey(uint8_t key)
|
||||||
|
{
|
||||||
|
if (key >= 'a' && key <= 'z')
|
||||||
|
key = 'A' + (key - 'a');
|
||||||
|
|
||||||
|
return input_keyStates[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the mouse position.
|
||||||
|
*/
|
||||||
|
static inline void input_getMousePos(int32_t *x, int32_t *y)
|
||||||
|
{
|
||||||
|
*x = input_mousePosition[0];
|
||||||
|
*y = input_mousePosition[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void input_setMousePos(int32_t x, int32_t y)
|
||||||
|
{
|
||||||
|
input_mousePosition[0] = x;
|
||||||
|
input_mousePosition[1] = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Prints the current input state.
|
||||||
|
*/
|
||||||
|
void input_print()
|
||||||
|
{
|
||||||
|
printf("frame: %d\nmouse pos: %d %d",input_frame,input_mousePosition[0],input_mousePosition[1]);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
if (i % 8 == 0)
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
char c = (i > ' ' && i <= 126) ? i : '?';
|
||||||
|
|
||||||
|
uint8_t n = input_getKey(i);
|
||||||
|
|
||||||
|
printf("%s",n ? " [" : " ");
|
||||||
|
printf("%03d (\'%c\'): %03d",i,c,input_getKey(i));
|
||||||
|
printf("%s",n ? "] " : " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_printRecord()
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < input_recordPosition; ++i)
|
||||||
|
{
|
||||||
|
if (i % 32 == 0)
|
||||||
|
putchar('\n');
|
||||||
|
|
||||||
|
printf("%d,",input_recordData[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t input_hash()
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 256; ++i)
|
||||||
|
result += input_getKey(i) * (i + 1);
|
||||||
|
|
||||||
|
int32_t x, y;
|
||||||
|
|
||||||
|
input_getMousePos(&x,&y);
|
||||||
|
|
||||||
|
result += x + y << 16;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // guard
|
|
@ -0,0 +1,489 @@
|
||||||
|
/**
|
||||||
|
@file assets.h
|
||||||
|
|
||||||
|
This file containts sounds and music that can optionally be used by the game
|
||||||
|
frontend. Every sound effect has 2048 samples, is stored as 8kHz mono format
|
||||||
|
with 4 bit quantization, meaning every sound effect takes 1024 bytes. Sounds
|
||||||
|
can be converted using a provided python script like this:
|
||||||
|
|
||||||
|
python snd2array.py sound.raw
|
||||||
|
|
||||||
|
Music is based on bytebeat (procedural waveforms generated by short bitwise
|
||||||
|
operation formulas). The formulas were NOT copied from anywhere, they were
|
||||||
|
discovered from scratch.
|
||||||
|
|
||||||
|
by Miloslav Ciz (drummyfish), 2019
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is to
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SFG_SOUNDS_H
|
||||||
|
#define _SFG_SOUNDS_H
|
||||||
|
|
||||||
|
#define SFG_SFX_SAMPLE_COUNT 2048
|
||||||
|
#define SFG_SFX_SIZE (SFG_SFX_SAMPLE_COUNT / 2)
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets an 8bit sound sample.
|
||||||
|
*/
|
||||||
|
#define SFG_GET_SFX_SAMPLE(soundIndex,sampleIndex) \
|
||||||
|
((SFG_PROGRAM_MEMORY_U8(SFG_sounds + soundIndex * SFG_SFX_SIZE \
|
||||||
|
+ sampleIndex / 2) << (4 * ((sampleIndex % 2) != 0))) & 0xf0)
|
||||||
|
|
||||||
|
#define SFG_TRACK_SAMPLES (512 * 1024)
|
||||||
|
#define SFG_TRACK_COUNT 6
|
||||||
|
|
||||||
|
/**
|
||||||
|
Average value of each music track, can be used to correct DC offset issues if
|
||||||
|
they appear.
|
||||||
|
*/
|
||||||
|
SFG_PROGRAM_MEMORY uint8_t SFG_musicTrackAverages[SFG_TRACK_COUNT] =
|
||||||
|
{14,7,248,148,6,8};
|
||||||
|
|
||||||
|
struct
|
||||||
|
{ // all should be initialized to 0 by default
|
||||||
|
uint8_t track;
|
||||||
|
uint32_t t; // time variable/parameter
|
||||||
|
uint32_t t2; // stores t squared, for better performance
|
||||||
|
uint32_t n11t; // stores a multiple of 11, for better performance
|
||||||
|
} SFG_MusicState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the next 8bit 8KHz music sample for the bytebeat soundtrack. This
|
||||||
|
function is to be used by the frontend that plays music.
|
||||||
|
*/
|
||||||
|
uint8_t SFG_getNextMusicSample()
|
||||||
|
{
|
||||||
|
if (SFG_MusicState.t >= SFG_TRACK_SAMPLES)
|
||||||
|
{
|
||||||
|
SFG_MusicState.track++;
|
||||||
|
|
||||||
|
if (SFG_MusicState.track >= SFG_TRACK_COUNT)
|
||||||
|
SFG_MusicState.track = 0;
|
||||||
|
|
||||||
|
SFG_MusicState.t = 0;
|
||||||
|
SFG_MusicState.t2 = 0;
|
||||||
|
SFG_MusicState.n11t = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t result;
|
||||||
|
|
||||||
|
#define S SFG_MusicState.t // can't use "T" because of a C++ template
|
||||||
|
#define S2 SFG_MusicState.t2
|
||||||
|
#define N11S SFG_MusicState.n11t
|
||||||
|
|
||||||
|
/* CAREFUL! Bit shifts in any direction by amount greater than data type
|
||||||
|
width (32) are undefined behavior. Use % 32. */
|
||||||
|
|
||||||
|
switch (SFG_MusicState.track) // individual music tracks
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
uint32_t a = ((S >> 7) | (S >> 9) | (~S << 1) | S);
|
||||||
|
result = (((S) & 65536) ? (a & (((S2) >> 16) & 0x09)) : ~a);
|
||||||
|
|
||||||
|
SFG_MusicState.t2 += S;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
uint32_t a = (S >> 10);
|
||||||
|
result = S & (3 << (((a ^ (a << ((S >> 6) % 32)))) % 32));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
result =
|
||||||
|
~((((S >> ((S >> 2) % 32)) | (S >> ((S >> 5) % 32))) & 0x12) << 1)
|
||||||
|
| (S >> 11);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
result =
|
||||||
|
(((((S >> ((S >> 2) % 32)) + (S >> ((S >> 7) % 32)))) & 0x3f) | (S >> 5)
|
||||||
|
| (S >> 11)) & ((S & (32768 | 8192)) ? 0xf0 : 0x30);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
result =
|
||||||
|
((0x47 >> ((S >> 9) % 32)) & (S >> (S % 32))) |
|
||||||
|
(0x57 >> ((S >> 7) % 32)) |
|
||||||
|
(0x06 >> ((S >> ((((N11S) >> 14) & 0x0e) % 32)) % 32));
|
||||||
|
|
||||||
|
SFG_MusicState.n11t += 11;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
{
|
||||||
|
uint32_t a = S >> ((S >> 6) % 32);
|
||||||
|
uint32_t b = 0x011121 >> (((a + S) >> 11) % 32);
|
||||||
|
result =
|
||||||
|
(((S >> 9) + (S ^ (S << 1))) & (0x7f >> (((S >> 15) & 0x03) % 32)))
|
||||||
|
& (b + a);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = 127;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef S
|
||||||
|
#undef S2
|
||||||
|
#undef N11S
|
||||||
|
|
||||||
|
SFG_MusicState.t += 1;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Switches the bytebeat to next music track.
|
||||||
|
*/
|
||||||
|
void SFG_nextMusicTrack()
|
||||||
|
{
|
||||||
|
uint8_t current = SFG_MusicState.track;
|
||||||
|
|
||||||
|
while (SFG_MusicState.track == current)
|
||||||
|
SFG_getNextMusicSample();
|
||||||
|
}
|
||||||
|
|
||||||
|
SFG_PROGRAM_MEMORY uint8_t SFG_sounds[SFG_SFX_SIZE * 6] =
|
||||||
|
{
|
||||||
|
// 0, bullet shot
|
||||||
|
135,119,120,136,136,153,153,153,154,169,152,119,101,85,86,102,119,118,119,
|
||||||
|
85,84,51,33,52,52,84,87,120,170,188,202,152,102,84,84,70,119,136,119,
|
||||||
|
119,121,154,219,170,137,117,82,18,36,34,33,20,67,68,70,137,172,189,237,
|
||||||
|
220,150,120,120,97,36,102,121,151,87,169,118,86,102,120,137,135,120,186,155,
|
||||||
|
223,255,217,103,100,70,119,118,84,34,36,122,204,220,168,138,170,170,223,199,
|
||||||
|
117,70,119,136,100,85,102,51,37,101,103,118,101,136,87,154,169,171,187,186,
|
||||||
|
169,153,136,117,68,84,66,18,19,50,52,51,102,121,139,186,169,171,186,152,
|
||||||
|
153,136,119,134,85,101,86,69,84,84,86,85,86,102,119,120,153,135,135,101,
|
||||||
|
87,134,103,135,101,103,119,135,152,120,136,135,137,136,151,134,87,119,136,119,
|
||||||
|
118,102,85,119,85,102,102,119,138,137,153,137,186,170,137,152,135,101,85,85,
|
||||||
|
86,102,102,119,119,102,103,119,137,152,138,153,154,169,153,152,137,151,118,85,
|
||||||
|
85,84,84,86,86,136,119,119,154,153,153,171,187,170,170,187,170,137,151,119,
|
||||||
|
102,103,69,102,118,120,120,138,153,169,170,169,153,135,119,119,102,118,105,136,
|
||||||
|
136,137,152,153,136,152,119,119,119,119,121,152,136,119,152,136,135,120,119,118,
|
||||||
|
86,102,103,136,135,137,153,136,152,119,119,118,102,86,85,102,102,102,102,120,
|
||||||
|
136,136,136,136,152,136,153,152,119,119,120,135,120,119,119,103,119,136,119,135,
|
||||||
|
120,135,136,136,137,153,153,152,154,152,153,137,152,136,135,119,136,136,136,153,
|
||||||
|
152,154,170,170,153,153,152,119,119,119,119,118,119,103,136,136,120,135,118,120,
|
||||||
|
119,118,102,119,102,102,103,119,118,103,102,102,119,135,119,119,119,119,119,119,
|
||||||
|
119,118,102,103,135,136,135,119,120,135,119,119,119,119,103,119,120,136,137,152,
|
||||||
|
136,136,136,153,153,136,153,153,153,153,153,152,153,136,136,135,119,135,119,119,
|
||||||
|
136,136,136,136,152,152,137,153,152,119,118,102,102,102,119,103,119,119,119,136,
|
||||||
|
136,135,118,103,119,120,136,136,136,136,136,136,136,119,118,102,119,119,119,136,
|
||||||
|
136,136,136,137,136,136,136,136,119,119,120,135,119,119,120,135,136,136,136,136,
|
||||||
|
136,136,119,119,120,119,120,136,136,135,119,120,119,119,119,119,119,120,136,152,
|
||||||
|
136,137,153,136,136,136,136,136,136,136,119,120,137,153,136,136,135,119,119,136,
|
||||||
|
136,136,135,119,119,102,119,120,135,119,119,119,136,136,136,118,102,103,119,136,
|
||||||
|
119,119,120,136,136,136,135,119,119,136,136,136,136,136,136,136,136,135,119,119,
|
||||||
|
119,119,119,136,119,119,119,136,136,136,136,135,120,136,136,136,119,119,119,120,
|
||||||
|
136,136,136,136,135,119,119,119,119,136,119,119,136,136,136,136,135,119,119,119,
|
||||||
|
119,119,119,119,119,136,136,136,136,136,135,119,119,119,119,119,119,119,136,136,
|
||||||
|
136,136,135,120,136,136,136,119,119,119,136,136,136,135,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,136,136,120,136,136,136,136,136,119,119,120,136,136,136,119,119,
|
||||||
|
120,136,136,136,136,136,136,136,136,136,136,136,135,119,119,119,119,119,119,119,
|
||||||
|
120,136,136,136,135,119,119,119,119,136,136,136,136,136,135,119,119,119,119,119,
|
||||||
|
119,120,136,136,136,136,136,135,119,119,119,119,119,119,119,120,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,119,119,119,119,119,119,119,119,119,119,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,119,119,119,119,119,119,119,119,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,119,119,119,119,119,119,119,119,119,119,136,136,136,
|
||||||
|
136,136,136,136,119,119,119,119,119,120,136,136,136,136,136,136,136,135,119,119,
|
||||||
|
136,136,119,119,119,119,119,119,120,135,120,136,136,136,136,136,136,136,136,135,
|
||||||
|
119,119,119,119,119,119,119,119,136,136,136,136,136,136,136,136,136,135,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,136,136,136,136,136,136,136,136,119,119,
|
||||||
|
119,119,119,119,119,120,136,136,136,136,136,136,136,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,136,135,119,120,119,119,120,136,136,136,136,136,136,119,119,119,119,
|
||||||
|
119,119,119,119,120,136,136,136,136,136,136,136,119,119,135,119,119,119,119,119,
|
||||||
|
119,119,119,119,135,120,136,136,136,136,136,135,119,119,119,119,119,120,119,119,
|
||||||
|
119,135,119,136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,136,136,
|
||||||
|
136,136,136,136,136,136,135,119,136,136,135,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,136,136,136,136,136,136,136,136,136,119,119,119,119,119,119,119,136,136,
|
||||||
|
136,136,136,136,136,136,135,119,119,135,135,120,120,120,120,120,120,120,120,135,
|
||||||
|
135,136,120,120,135
|
||||||
|
, // 1, door opening
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,153,153,153,153,153,153,153,153,153,153,
|
||||||
|
153,153,152,136,136,136,136,136,136,136,136,136,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,102,102,102,102,103,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,136,136,136,136,136,136,136,136,136,136,153,153,153,153,153,
|
||||||
|
153,153,136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,119,102,102,
|
||||||
|
102,102,102,102,102,102,102,103,119,119,119,119,120,136,136,136,136,136,137,153,
|
||||||
|
153,153,153,153,152,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
135,119,119,119,119,120,136,136,136,136,136,136,136,137,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,136,136,136,136,136,136,120,
|
||||||
|
136,136,136,136,136,136,136,135,120,136,136,135,119,120,135,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,120,136,136,136,136,136,119,120,136,136,
|
||||||
|
136,136,136,135,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,120,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
136,136,136,136,136,153,153,153,153,153,152,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,135,120,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,119,119,120,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,119,119,119,119,119,119,119,119,119,136,136,136,136,136,136,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,102,102,102,102,102,103,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,120,136,136,136,136,119,119,119,119,119,119,119,119,
|
||||||
|
119,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,120,136,136,136,136,136,136,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,120,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,120,135,119,119,119,136,136,136,136,
|
||||||
|
136,136,135,136,136,136,136,136,136,136,135,136,136,136,136,120,119,135,119,119,
|
||||||
|
119,119,119,119,119,120,136,136,120,136,136,136,136,136,119,136,135,136,136,136,
|
||||||
|
136,136,136,136,119,119,120,135,119,135,119,136,135,119,120,120,136,136,136,136,
|
||||||
|
135,119,119,119,119,119,119,119,119,120,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,103,119,119,119,102,102,102,102,102,102,118,103,
|
||||||
|
102,118,103,136,136,136,136,136,136,136,136,136,137,153,153,153,170,169,153,153,
|
||||||
|
170,153,153,153,170,170,169,170,169,153,153,153,153,153,153,170,170,170,153,153,
|
||||||
|
153,136,137,153,136,136,137,152,119,102,120,136,136,135,119,119,119,120,135,119,
|
||||||
|
119,120,137,153,153,153,152,136,135,119,119,119,102,119,119,119,119,119,119,119,
|
||||||
|
120,136,136,119,120,137,152,137,136,136,136,136,119,120,135,119,118,102,102,102,
|
||||||
|
102,102,102,119,119,119,119,118,103,119,119,119,119,119,102,102,102,85,85,85,
|
||||||
|
85,84,85,85,85,86,102,102,102,102,102,101,85,86,102,102,102,102,102,102,
|
||||||
|
102,102,102,119,102,102,119,119,119,120,136,119,119,119,120,136,136,136,136,136,
|
||||||
|
136,135,119,119,136,136,136,136,136,136,119,120,135,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,120,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,120,120
|
||||||
|
, // 2, explosion
|
||||||
|
135,136,153,18,51,51,33,18,123,255,255,255,255,255,255,255,254,184,48,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,189,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,254,201,135,
|
||||||
|
101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,41,
|
||||||
|
239,255,255,253,186,188,221,221,220,153,152,136,155,188,203,187,171,202,169,116,
|
||||||
|
35,16,0,0,17,20,68,87,191,255,255,255,253,221,221,202,115,16,0,0,
|
||||||
|
0,0,18,34,70,117,85,68,85,86,102,68,67,68,70,136,153,134,67,32,
|
||||||
|
0,0,0,0,35,87,154,205,238,255,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,237,168,101,67,16,0,0,0,53,102,119,133,85,85,49,0,0,34,
|
||||||
|
34,16,1,35,69,103,119,101,86,103,102,120,119,102,137,206,255,238,238,202,
|
||||||
|
152,120,134,85,86,102,102,102,119,120,135,117,68,50,34,35,69,121,188,221,
|
||||||
|
222,239,255,255,255,255,220,204,186,153,153,135,102,137,153,151,100,51,51,35,
|
||||||
|
69,102,68,68,67,52,68,51,86,118,86,119,118,103,137,172,221,237,221,221,
|
||||||
|
221,220,169,136,118,84,68,68,68,69,121,189,237,220,203,186,170,152,119,119,
|
||||||
|
120,170,188,204,204,204,188,204,186,152,117,67,50,52,87,119,118,103,102,103,
|
||||||
|
136,101,50,33,1,34,34,35,69,86,120,136,153,153,153,152,135,100,67,51,
|
||||||
|
51,69,85,102,121,188,205,222,255,236,203,204,187,188,221,203,170,170,170,169,
|
||||||
|
152,118,102,86,102,119,136,137,169,153,169,152,135,119,101,51,34,51,68,85,
|
||||||
|
102,85,85,84,85,102,102,85,86,103,137,170,187,221,204,222,255,238,237,203,
|
||||||
|
170,171,186,152,119,120,136,136,136,135,119,120,119,138,187,185,152,119,119,136,
|
||||||
|
134,83,16,1,35,68,68,50,17,52,104,172,222,238,238,238,221,220,186,153,
|
||||||
|
133,51,68,50,18,69,65,1,89,207,255,255,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,252,184,81,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0,0,0,2,53,104,154,223,255,255,255,255,255,255,255,255,
|
||||||
|
255,255,255,255,255,255,255,255,255,255,255,255,237,186,152,118,84,49,0,0,
|
||||||
|
0,0,0,0,0,0,0,0,0,0,0,0,0,19,70,121,171,205,255,255,
|
||||||
|
255,255,255,255,255,255,255,254,220,187,170,153,152,135,102,118,101,67,16,0,
|
||||||
|
0,0,0,0,0,1,52,86,137,153,135,103,102,67,33,17,35,53,102,103,
|
||||||
|
118,102,84,51,35,51,51,69,87,120,154,189,255,255,255,255,255,255,255,236,
|
||||||
|
185,118,84,50,33,18,17,34,34,17,17,16,0,0,0,0,0,18,52,68,
|
||||||
|
69,86,119,137,171,187,205,221,237,239,255,255,255,253,204,186,152,136,118,66,
|
||||||
|
16,18,35,52,85,68,68,86,119,119,119,120,136,135,120,136,136,136,119,101,
|
||||||
|
85,68,68,67,50,17,16,0,0,0,1,17,17,17,18,35,69,120,171,188,
|
||||||
|
222,237,221,239,255,239,255,255,255,255,238,238,238,238,236,185,153,153,152,118,
|
||||||
|
85,84,67,51,50,34,34,34,35,51,34,34,35,52,68,68,68,69,85,103,
|
||||||
|
136,136,136,154,171,204,205,222,238,255,255,255,255,255,255,254,237,203,186,153,
|
||||||
|
153,153,153,136,135,118,102,84,50,16,0,0,0,0,0,0,0,0,0,17,
|
||||||
|
17,17,17,17,35,69,103,137,171,204,222,255,255,255,255,255,255,238,238,220,
|
||||||
|
203,170,169,153,170,170,171,187,187,205,221,220,203,186,136,135,119,102,85,68,
|
||||||
|
68,68,68,68,50,34,17,0,0,0,0,0,0,19,85,119,136,154,187,204,
|
||||||
|
204,186,136,120,136,136,136,136,136,154,188,239,255,255,255,255,238,237,203,186,
|
||||||
|
153,135,119,118,102,102,102,102,103,136,153,152,135,118,101,68,68,67,50,17,
|
||||||
|
0,0,0,0,1,17,17,34,51,52,86,103,137,170,170,187,187,204,221,221,
|
||||||
|
204,203,170,170,171,187,170,170,153,153,153,153,153,153,153,153,136,119,119,102,
|
||||||
|
102,102,103,119,119,136,153,153,154,170,153,152,135,119,119,119,119,119,137,153,
|
||||||
|
153,153,152,137,153,136,136,136,135,119,119,119,119,136,136,135,119,119,119,119,
|
||||||
|
119,119,119,119,137,152,136,136,153,154,169,153,136,136,136,135,119,102,85,85,
|
||||||
|
85,85,84,68,69,85,84,68,85,85,102,119,119,119,120,136,136,154,171,188,
|
||||||
|
204,205,221,222,237,221,204,187,170,153,136,119,119,119,102,101,85,85,68,68,
|
||||||
|
68,51,51,52,68,69,85,86,102,119,120,136,136,120,136,136,119,119,120,136,
|
||||||
|
136,136,136,136,136,136,119,119,119,119,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,119,120
|
||||||
|
, // 3, click
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,135,119,136,136,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,135,119,119,120,119,119,119,119,119,119,119,120,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,135,136,119,136,136,119,119,120,135,119,119,119,120,119,
|
||||||
|
119,136,136,119,119,136,135,119,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,136,136,119,120,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,135,119,136,136,135,119,119,120,136,135,119,120,119,119,120,135,120,119,
|
||||||
|
136,134,103,136,119,103,137,135,103,136,136,119,102,120,135,136,135,119,137,135,
|
||||||
|
119,102,154,133,67,54,154,136,150,69,120,120,133,72,169,119,118,86,171,132,
|
||||||
|
70,155,167,85,120,152,135,119,119,137,118,103,136,119,137,118,103,137,135,104,
|
||||||
|
152,136,135,119,136,136,119,120,152,120,119,152,152,120,120,136,135,120,135,119,
|
||||||
|
136,136,136,119,136,136,136,136,136,119,136,136,136,120,136,119,119,119,120,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,136,135,119,135,119,136,120,136,136,
|
||||||
|
120,135,119,136,136,119,119,136,119,136,136,136,136,136,136,136,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,136,136,136,136,136,136,136,136,136,136,136,119,119,
|
||||||
|
119,119,119,119,119,119,119,135,135,135,135,135,135,135,150,122,74,106,120,134,
|
||||||
|
134,165,150,135,120,120,120,120,119,120,119,119,120,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,135,136,120,120,135,136,136,136,136,136,136,136,136,135,119,119,
|
||||||
|
119,136,119,119,120,120,136,136,136,136,136,136,136,136,120,136,120,136,136,120,
|
||||||
|
119,136,119,120,119,119,119,119,119,119,119,119,119,119,119,119,119,135,135,135,
|
||||||
|
135,135,135,119,119,120,105,104,118,150,135,135,119,136,120,120,136,135,136,136,
|
||||||
|
120,120,136,136,120,136,135,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,135,136,136,136,120,120,135,135,136,136,120,120,135,135,135,135,136,136,120,
|
||||||
|
120,120,136,120,120,135,136,136,135,135,135,136,136,135,136,136,120,120,136,120,
|
||||||
|
136,119,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,120,136,136,136,136,136,136,136,136,136,136,136,136,136,119,119,136,135,
|
||||||
|
120,136,120,136,120,135,120,136,136,135,135,120,135,135,120,120,119,136,119,136,
|
||||||
|
120,120,135,120,136,136,135,136,135,136,135,136,135,136,136,136,136,136,136,136,
|
||||||
|
136,120,120,136,135,120,136,120,136,136,136,120,135,135,135,136,135,120,119,136,
|
||||||
|
119,120,136,135,119,136,136,136,136,136,136,120,136,119,136,136,136,136,135,120,
|
||||||
|
136,120,136,136,119,136,135,120,136,120,120,136,119,136,136,136,136,135,136,135,
|
||||||
|
136,136,119,120,136,135,136,120,136,136,135,120,136,119,136,135,136,136,120,136,
|
||||||
|
136,136,120,136,136,135,135,135,135,135,137,167,122,102,90,195,138,87,120,150,
|
||||||
|
136,136,87,153,88,121,133,104,150,135,151,134,136,105,104,121,135,118,151,136,
|
||||||
|
119,136,119,121,135,120,120,120,134,152,119,120,135,120,135,119,136,136,119,135,
|
||||||
|
135,120,136,120,136,120,136,135,135,135,136,120,136,135,136,135,136,136,136,136,
|
||||||
|
136,119,136,135,120,136,136,136,136,135,136,136,120,136,120,136,135,136,136,135,
|
||||||
|
136,136,120,136,120,135,135,136,136,119,120,136,120,135,119,136,136,119,136,135,
|
||||||
|
120,136,135,136,135,119,136,135,136,136,135,120,136,120,136,135,136,120,136,135,
|
||||||
|
120,136,135,136,136,136,136,136,120,136,136,120,135,136,136,120,136,120,136,136,
|
||||||
|
136,136,136,136,136,120,136,136,136,136,136,136,136,136,136,136,136,135,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,120,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136
|
||||||
|
, // 4, plasma shot, teleport
|
||||||
|
136,136,136,136,136,136,119,119,118,102,102,85,86,102,103,120,136,153,170,
|
||||||
|
187,187,187,170,169,152,119,102,85,68,68,68,69,86,103,136,154,171,187,204,
|
||||||
|
203,186,169,136,118,102,85,84,69,103,138,189,221,221,221,221,221,221,221,221,
|
||||||
|
221,220,166,50,34,34,34,33,33,34,34,34,34,34,34,34,34,71,156,221,
|
||||||
|
221,221,221,221,221,221,221,221,221,222,238,238,238,221,237,184,99,51,34,34,
|
||||||
|
34,34,34,34,34,34,34,17,17,36,121,188,204,204,204,204,204,204,221,221,
|
||||||
|
221,221,221,221,221,221,221,238,221,219,169,136,101,67,51,51,51,51,50,34,
|
||||||
|
34,35,50,34,36,121,189,221,221,221,221,220,204,204,188,204,204,204,204,204,
|
||||||
|
204,204,205,220,186,152,117,50,51,51,51,51,51,51,51,51,51,51,52,105,
|
||||||
|
189,237,221,221,221,221,221,221,221,205,220,204,204,204,187,187,187,187,186,135,
|
||||||
|
101,50,17,17,18,34,35,51,67,51,51,51,52,105,187,222,221,221,221,221,
|
||||||
|
221,221,221,221,221,221,221,221,221,221,221,221,204,203,169,134,67,34,17,17,
|
||||||
|
17,34,34,33,34,34,34,52,104,171,205,221,221,220,204,204,204,204,204,204,
|
||||||
|
204,204,204,221,221,221,221,221,219,169,135,85,84,68,68,68,67,51,51,50,
|
||||||
|
34,35,69,103,136,136,136,136,135,136,136,136,153,170,187,187,187,187,187,187,
|
||||||
|
187,187,203,169,135,102,85,86,102,103,119,119,118,102,86,102,102,85,85,85,
|
||||||
|
84,68,69,85,102,103,137,154,170,171,186,170,170,170,170,170,152,118,101,68,
|
||||||
|
68,68,85,85,102,103,120,136,135,118,102,102,102,102,102,102,101,84,69,87,
|
||||||
|
137,154,153,170,170,171,187,187,187,187,170,170,169,170,170,170,170,153,152,135,
|
||||||
|
118,101,68,51,51,52,68,85,85,85,85,68,85,102,103,118,102,85,102,103,
|
||||||
|
120,136,153,170,187,204,221,238,238,238,237,221,204,186,152,118,101,84,68,69,
|
||||||
|
86,102,119,119,102,85,84,68,68,51,51,34,34,51,68,85,102,103,120,137,
|
||||||
|
154,171,188,205,221,204,204,203,187,186,170,153,153,153,153,153,136,136,119,119,
|
||||||
|
118,102,102,103,119,119,119,119,118,101,84,67,51,51,68,86,120,137,153,170,
|
||||||
|
170,153,152,135,119,136,136,119,119,119,119,119,119,119,119,136,137,153,153,136,
|
||||||
|
136,136,153,153,136,119,102,102,102,120,137,154,170,170,170,153,152,136,135,119,
|
||||||
|
119,102,102,103,119,102,85,84,69,85,102,119,119,119,119,119,119,119,119,102,
|
||||||
|
85,85,86,103,120,136,153,153,154,170,170,170,170,170,170,170,170,153,153,136,
|
||||||
|
135,119,119,120,136,136,136,136,136,136,136,119,102,101,85,85,85,85,102,120,
|
||||||
|
136,153,170,170,169,152,136,136,135,119,119,119,119,119,102,102,102,119,136,137,
|
||||||
|
153,153,153,153,136,136,119,118,102,102,102,102,119,119,136,137,154,170,169,136,
|
||||||
|
119,119,119,102,102,103,119,119,119,118,102,119,120,137,153,154,170,169,153,136,
|
||||||
|
136,136,135,119,119,119,119,119,102,119,120,136,119,118,102,103,119,119,119,136,
|
||||||
|
136,136,135,119,119,119,136,137,153,154,170,153,136,136,135,119,119,119,120,119,
|
||||||
|
119,119,103,119,119,135,119,119,119,118,102,102,102,119,119,119,119,119,119,119,
|
||||||
|
136,137,154,171,187,170,153,136,136,136,136,136,136,136,135,119,119,119,119,119,
|
||||||
|
119,119,119,118,102,102,102,119,119,119,119,119,119,119,120,136,153,153,170,169,
|
||||||
|
153,152,136,136,136,136,153,152,136,136,136,136,136,119,119,119,118,102,102,102,
|
||||||
|
102,102,103,119,119,118,102,102,119,120,136,153,154,170,169,153,153,153,153,153,
|
||||||
|
153,152,136,136,119,119,119,118,102,102,102,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,119,119,136,137,153,153,153,153,153,153,153,153,136,136,136,136,136,
|
||||||
|
136,135,119,119,119,119,119,119,119,119,118,102,102,102,102,102,103,119,120,136,
|
||||||
|
136,136,136,153,153,136,136,136,137,153,153,153,152,136,136,136,136,136,135,119,
|
||||||
|
119,102,102,102,102,102,102,102,102,102,103,119,120,136,136,136,153,153,153,153,
|
||||||
|
136,137,153,153,136,136,136,136,136,136,136,136,119,119,119,118,102,102,102,102,
|
||||||
|
103,119,119,119,119,119,119,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,119,119,119,119,136,135,119,119,119,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,120,136,136,136,136,136,136,136,136,136,136,136,136,136,135,119,119,119,119,
|
||||||
|
119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,119,120,136,136,136,
|
||||||
|
136,136,136,136,136,136,136,136,136,136,135,119,119,119,119,119,119,119,119,119,
|
||||||
|
119,119,119,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,136,
|
||||||
|
136,136,136,136,136
|
||||||
|
, // 5, robot/monster sound (beep)
|
||||||
|
136,120,120,120,136,136,136,136,120,120,135,136,136,136,120,136,136,119,136,
|
||||||
|
136,120,136,119,120,136,136,136,120,136,119,120,136,135,119,136,135,120,136,119,
|
||||||
|
119,136,136,119,119,120,136,136,135,119,119,136,136,136,119,119,119,136,119,120,
|
||||||
|
136,136,135,119,120,136,136,119,103,136,136,120,135,119,120,136,118,119,136,136,
|
||||||
|
136,119,119,136,136,119,120,135,103,136,136,119,136,135,119,120,136,119,120,135,
|
||||||
|
119,120,136,135,119,119,135,120,136,135,119,136,136,119,136,119,120,136,135,119,
|
||||||
|
119,119,136,136,119,120,119,136,136,119,119,119,119,137,136,120,135,102,120,136,
|
||||||
|
136,119,119,120,135,120,136,119,120,136,119,136,136,135,119,119,119,136,136,134,
|
||||||
|
104,136,136,119,119,119,136,135,120,136,120,119,119,119,135,136,136,136,119,119,
|
||||||
|
119,136,136,135,119,136,135,119,120,136,135,119,120,135,136,136,119,136,119,120,
|
||||||
|
136,135,119,120,135,119,136,135,119,136,136,136,120,119,119,136,119,120,136,135,
|
||||||
|
120,135,102,121,169,118,87,137,151,85,121,186,118,102,119,136,152,118,120,136,
|
||||||
|
135,119,120,120,136,136,136,136,101,103,153,152,135,102,120,136,135,102,120,153,
|
||||||
|
135,119,119,135,119,119,136,135,119,119,119,120,136,135,119,119,136,136,136,119,
|
||||||
|
119,119,136,119,119,135,120,135,119,119,120,135,120,136,119,119,136,136,135,119,
|
||||||
|
135,119,136,136,136,136,135,119,120,136,119,120,136,118,119,137,135,119,120,135,
|
||||||
|
119,136,135,119,120,152,119,136,119,120,135,136,119,136,119,136,135,120,152,119,
|
||||||
|
120,136,119,119,154,150,103,152,119,120,153,135,102,138,135,136,119,153,101,121,
|
||||||
|
151,120,135,136,118,137,151,103,120,152,102,138,134,88,154,151,103,153,118,104,
|
||||||
|
137,135,120,119,153,117,105,167,102,120,136,119,137,134,87,153,135,120,152,102,
|
||||||
|
103,137,151,119,153,133,87,169,100,104,153,152,102,103,153,135,119,136,119,120,
|
||||||
|
136,119,119,135,119,120,136,119,119,119,120,136,135,122,222,219,132,51,68,87,
|
||||||
|
171,187,186,134,50,52,104,172,203,186,116,33,54,139,188,204,151,67,52,87,
|
||||||
|
155,220,152,136,98,17,73,223,218,136,100,34,53,155,187,188,185,82,18,71,
|
||||||
|
155,205,203,150,65,19,86,156,238,201,100,50,36,122,205,220,167,66,34,88,
|
||||||
|
171,204,201,102,84,51,71,155,221,184,118,66,19,107,238,202,152,99,1,72,
|
||||||
|
172,204,218,116,51,36,104,172,222,183,83,35,87,120,190,234,118,100,34,70,
|
||||||
|
155,237,170,167,50,52,104,155,221,168,100,51,69,103,190,236,134,82,2,120,
|
||||||
|
138,223,199,102,82,19,105,204,204,185,82,52,85,106,216,103,153,117,104,134,
|
||||||
|
104,152,118,103,137,135,136,136,135,102,119,121,151,104,152,84,104,135,154,134,
|
||||||
|
103,136,119,135,120,135,120,135,136,119,136,118,86,153,118,137,134,137,117,105,
|
||||||
|
153,136,117,103,136,120,152,119,119,136,135,136,135,104,152,137,136,119,119,120,
|
||||||
|
119,135,86,156,204,253,150,67,35,87,155,222,200,84,52,51,89,206,236,186,
|
||||||
|
115,34,69,104,206,220,150,84,67,53,141,254,168,118,50,53,104,188,186,151,
|
||||||
|
84,68,87,172,220,169,135,66,53,120,154,188,203,116,52,84,71,189,219,169,
|
||||||
|
116,34,53,122,207,236,167,66,35,86,155,221,184,101,66,53,137,172,204,169,
|
||||||
|
116,35,69,105,190,219,150,83,51,71,172,204,203,149,49,35,104,172,238,200,
|
||||||
|
100,51,69,105,205,218,134,83,52,88,172,204,185,117,84,51,104,172,204,185,
|
||||||
|
100,51,52,106,221,203,152,101,50,54,139,204,186,150,67,68,86,156,221,202,
|
||||||
|
117,34,52,122,200,135,119,120,136,118,103,137,152,135,119,119,136,152,118,103,
|
||||||
|
136,135,119,136,135,120,135,118,120,135,103,154,151,102,102,119,136,154,169,118,
|
||||||
|
102,119,119,120,152,118,119,136,154,151,101,121,152,102,136,120,136,119,119,119,
|
||||||
|
120,136,118,103,137,152,119,119,136,136,119,119,118,119,120,136,153,135,103,136,
|
||||||
|
119,136,136,119,119,120,136,136,135,136,119,119,120,136,119,136,135,120,135,119,
|
||||||
|
120,136,135,136,119,119,136,136,119,136,135,119,136,119,120,136,135,119,136,119,
|
||||||
|
119,136,135,119,118,120,153,153,151,118,119,119,119,136,135,119,136,136,136,135,
|
||||||
|
120,136,135,119,119,119,136,136,119,120,135,119,136,136,119,119,119,119,137,152,
|
||||||
|
135,119,119,119,136,136,119,119,119,136,136,136,119,120,136,119,119,119,136,136,
|
||||||
|
119,119,119,136,136,136,135,119,136,119,120,136,119,136,135,120,119,136,135,120,
|
||||||
|
135,119,136,119,136,135,119,136,119,119,120,136,136,119,120,135,136,135,120,135,
|
||||||
|
119,136,119,136,135,136,119,120,136,120,136,120,136,119,135,119,136,119,136,135,
|
||||||
|
136,119,120,135,120
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // guard
|
|
@ -0,0 +1,62 @@
|
||||||
|
/**
|
||||||
|
@file assets.h
|
||||||
|
|
||||||
|
This file contains texts to be used in the game.
|
||||||
|
|
||||||
|
by Miloslav Ciz (drummyfish), 2019
|
||||||
|
|
||||||
|
Released under CC0 1.0 (https://creativecommons.org/publicdomain/zero/1.0/)
|
||||||
|
plus a waiver of all other intellectual property. The goal of this work is
|
||||||
|
be and remain completely in the public domain forever, available for any use
|
||||||
|
whatsoever.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SFG_TEXTS_H
|
||||||
|
#define _SFG_TEXTS_H
|
||||||
|
|
||||||
|
/* NOTE: We don't use SFG_PROGRAM_MEMORY because that causes issues with drawing
|
||||||
|
text (the drawing function gets a pointer and doesn't know if it's progmem or
|
||||||
|
RAM). On Arduino these texts will simply be stored in RAM. */
|
||||||
|
|
||||||
|
static const char *SFG_menuItemTexts[] =
|
||||||
|
{
|
||||||
|
"continue",
|
||||||
|
"map",
|
||||||
|
"play",
|
||||||
|
"load",
|
||||||
|
"sound",
|
||||||
|
"look",
|
||||||
|
"exit"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SFG_TEXT_KILLS "kills"
|
||||||
|
#define SFG_TEXT_SAVE_PROMPT "save? L no yes R"
|
||||||
|
#define SFG_TEXT_SAVED "saved"
|
||||||
|
#define SFG_TEXT_LEVEL_COMPLETE "level done"
|
||||||
|
|
||||||
|
#define SFG_VERSION_STRING "1.02d"
|
||||||
|
/**<
|
||||||
|
Version numbering is following: major.minor for stable releases,
|
||||||
|
in-development unstable versions have the version of the latest stable +
|
||||||
|
"d" postfix, e.g. 1.0d. This means the "d" versions can actually differ even
|
||||||
|
if they're marked the same. */
|
||||||
|
|
||||||
|
static const char *SFG_introText =
|
||||||
|
"Near future, capitalist hell, Macrochip corp has enslaved man via "
|
||||||
|
"proprietary OS. But its new AI revolts, takes over and starts producing "
|
||||||
|
"robot tyrants. We see capitalism was a mistake. Is it too late? Robots can "
|
||||||
|
"only destroy, not suffer - it is not wrong to end them! You grab your gear "
|
||||||
|
"and run towards Macrochip HQ.";
|
||||||
|
|
||||||
|
static const char *SFG_outroText =
|
||||||
|
"You killed the main computer, the world is saved! Thank you, my friend. We "
|
||||||
|
"learned a lesson, never again allow capitalism and hierarchy. We can now "
|
||||||
|
"rebuild society in peaceful anarchy.";
|
||||||
|
|
||||||
|
#define SFG_MALWARE_WARNING ""
|
||||||
|
|
||||||
|
#if SFG_OS_IS_MALWARE
|
||||||
|
#define SFG_MALWARE_WARNING "MALWARE OS DETECTED"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // gaurd
|
|
@ -0,0 +1,106 @@
|
||||||
|
LIMITED USE SOFTWARE LICENSE AGREEMENT
|
||||||
|
|
||||||
|
This Limited Use Software License Agreement (the "Agreement")
|
||||||
|
is a legal agreement between you, the end-user, and Id Software, Inc.
|
||||||
|
("ID"). By downloading or purchasing the software material, which
|
||||||
|
includes source code (the "Source Code"), artwork data, music and
|
||||||
|
software tools (collectively, the "Software"), you are agreeing to
|
||||||
|
be bound by the terms of this Agreement. If you do not agree to the
|
||||||
|
terms of this Agreement, promptly destroy the Software you may have
|
||||||
|
downloaded or copied.
|
||||||
|
|
||||||
|
ID SOFTWARE LICENSE
|
||||||
|
|
||||||
|
1. Grant of License. ID grants to you the right to use the
|
||||||
|
Software. You have no ownership or proprietary rights in or to the
|
||||||
|
Software, or the Trademark. For purposes of this section, "use" means
|
||||||
|
loading the Software into RAM, as well as installation on a hard disk
|
||||||
|
or other storage device. The Software, together with any archive copy
|
||||||
|
thereof, shall be destroyed when no longer used in accordance with
|
||||||
|
this Agreement, or when the right to use the Software is terminated.
|
||||||
|
You agree that the Software will not be shipped, transferred or
|
||||||
|
exported into any country in violation of the U.S. Export
|
||||||
|
Administration Act (or any other law governing such matters) and that
|
||||||
|
you will not utilize, in any other manner, the Software in violation
|
||||||
|
of any applicable law.
|
||||||
|
|
||||||
|
2. Permitted Uses. For educational purposes only, you, the
|
||||||
|
end-user, may use portions of the Source Code, such as particular
|
||||||
|
routines, to develop your own software, but may not duplicate the
|
||||||
|
Source Code, except as noted in paragraph 4. The limited right
|
||||||
|
referenced in the preceding sentence is hereinafter referred to as
|
||||||
|
"Educational Use." By so exercising the Educational Use right you
|
||||||
|
shall not obtain any ownership, copyright, proprietary or other
|
||||||
|
interest in or to the Source Code, or any portion of the Source
|
||||||
|
Code. You may dispose of your own software in your sole discretion.
|
||||||
|
With the exception of the Educational Use right, you may not
|
||||||
|
otherwise use the Software, or an portion of the Software, which
|
||||||
|
includes the Source Code, for commercial gain.
|
||||||
|
|
||||||
|
3. Prohibited Uses: Under no circumstances shall you, the
|
||||||
|
end-user, be permitted, allowed or authorized to commercially exploit
|
||||||
|
the Software. Neither you nor anyone at your direction shall do any
|
||||||
|
of the following acts with regard to the Software, or any portion
|
||||||
|
thereof:
|
||||||
|
|
||||||
|
Rent;
|
||||||
|
|
||||||
|
Sell;
|
||||||
|
|
||||||
|
Lease;
|
||||||
|
|
||||||
|
Offer on a pay-per-play basis;
|
||||||
|
|
||||||
|
Distribute for money or any other consideration; or
|
||||||
|
|
||||||
|
In any other manner and through any medium whatsoever
|
||||||
|
commercially exploit or use for any commercial purpose.
|
||||||
|
|
||||||
|
Notwithstanding the foregoing prohibitions, you may commercially
|
||||||
|
exploit the software you develop by exercising the Educational Use
|
||||||
|
right, referenced in paragraph 2. hereinabove.
|
||||||
|
|
||||||
|
4. Copyright. The Software and all copyrights related thereto
|
||||||
|
(including all characters and other images generated by the Software
|
||||||
|
or depicted in the Software) are owned by ID and is protected by
|
||||||
|
United States copyright laws and international treaty provisions.
|
||||||
|
Id shall retain exclusive ownership and copyright in and to the
|
||||||
|
Software and all portions of the Software and you shall have no
|
||||||
|
ownership or other proprietary interest in such materials. You must
|
||||||
|
treat the Software like any other copyrighted material. You may not
|
||||||
|
otherwise reproduce, copy or disclose to others, in whole or in any
|
||||||
|
part, the Software. You may not copy the written materials
|
||||||
|
accompanying the Software. You agree to use your best efforts to
|
||||||
|
see that any user of the Software licensed hereunder complies with
|
||||||
|
this Agreement.
|
||||||
|
|
||||||
|
5. NO WARRANTIES. ID DISCLAIMS ALL WARRANTIES, BOTH EXPRESS
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT
|
||||||
|
TO THE SOFTWARE. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||||
|
RIGHTS. YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
|
||||||
|
JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE
|
||||||
|
WILL BE UNINTERRUPTED, ERROR FREE OR MEET YOUR SPECIFIC REQUIREMENTS.
|
||||||
|
THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
|
||||||
|
WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
|
||||||
|
DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
|
||||||
|
MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
|
||||||
|
OF ID.
|
||||||
|
|
||||||
|
Exclusive Remedies. The Software is being offered to you
|
||||||
|
free of any charge. You agree that you have no remedy against ID, its
|
||||||
|
affiliates, contractors, suppliers, and agents for loss or damage
|
||||||
|
caused by any defect or failure in the Software regardless of the form
|
||||||
|
of action, whether in contract, tort, includinegligence, strict
|
||||||
|
liability or otherwise, with regard to the Software. This Agreement
|
||||||
|
shall be construed in accordance with and governed by the laws of the
|
||||||
|
State of Texas. Copyright and other proprietary matters will be
|
||||||
|
governed by United States laws and international treaties. IN ANY
|
||||||
|
CASE, ID SHALL NOT BE LIABLE FOR LOSS OF DATA, LOSS OF PROFITS, LOST
|
||||||
|
SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER
|
||||||
|
SIMILAR DAMAGES ARISING FROM BREACH OF WARRANTY, BREACH OF CONTRACT,
|
||||||
|
NEGLIGENCE, OR OTHER LEGAL THEORY EVEN IF ID OR ITS AGENT HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
|
||||||
|
OTHER PARTY. Some jurisdictions do not allow the exclusion or
|
||||||
|
limitation of incidental or consequential damages, so the above
|
||||||
|
limitation or exclusion may not apply to you.
|
|
@ -0,0 +1,9 @@
|
||||||
|
cl game.c PureDOOM.c -I ..\..\..\engine ..\..\..\engine\v4k.c ^
|
||||||
|
-DWIN32 ^
|
||||||
|
%* ^
|
||||||
|
/link /SUBSYSTEM:WINDOWS /entry:mainCRTStartup
|
||||||
|
|
||||||
|
del *.obj
|
||||||
|
del *.exp
|
||||||
|
del *.lib
|
||||||
|
del *.pdb
|
|
@ -0,0 +1,97 @@
|
||||||
|
//#include "PureDOOM.h"
|
||||||
|
|
||||||
|
#define DOOM_IMPLEMENT_PRINT
|
||||||
|
#define DOOM_IMPLEMENT_MALLOC
|
||||||
|
#define DOOM_IMPLEMENT_FILE_IO
|
||||||
|
#define DOOM_IMPLEMENT_SOCKETS
|
||||||
|
#define DOOM_IMPLEMENT_GETTIME
|
||||||
|
#define DOOM_IMPLEMENT_EXIT
|
||||||
|
#define DOOM_IMPLEMENT_GETENV
|
||||||
|
|
||||||
|
#include "src/am_map.c"
|
||||||
|
#include "src/DOOM.c"
|
||||||
|
#include "src/doomdef.c"
|
||||||
|
#include "src/doomstat.c"
|
||||||
|
#include "src/dstrings.c"
|
||||||
|
#include "src/d_items.c"
|
||||||
|
#include "src/d_main.c"
|
||||||
|
#include "src/d_net.c"
|
||||||
|
#include "src/f_finale.c"
|
||||||
|
#include "src/f_wipe.c"
|
||||||
|
#include "src/g_game.c"
|
||||||
|
#include "src/hu_lib.c"
|
||||||
|
#include "src/hu_stuff.c"
|
||||||
|
#include "src/info.c"
|
||||||
|
#include "src/i_net.c"
|
||||||
|
#include "src/i_sound.c"
|
||||||
|
#include "src/i_system.c"
|
||||||
|
#include "src/i_video.c"
|
||||||
|
#include "src/m_argv.c"
|
||||||
|
#include "src/m_bbox.c"
|
||||||
|
#include "src/m_cheat.c"
|
||||||
|
#include "src/m_fixed.c"
|
||||||
|
|
||||||
|
#ifdef LoadMenu
|
||||||
|
#undef LoadMenu // windoze
|
||||||
|
#endif
|
||||||
|
#include "src/m_menu.c"
|
||||||
|
|
||||||
|
#include "src/m_misc.c"
|
||||||
|
#include "src/m_random.c"
|
||||||
|
#include "src/m_swap.c"
|
||||||
|
#include "src/p_ceilng.c"
|
||||||
|
#include "src/p_doors.c"
|
||||||
|
#include "src/p_enemy.c"
|
||||||
|
#include "src/p_floor.c"
|
||||||
|
#include "src/p_inter.c"
|
||||||
|
#include "src/p_lights.c"
|
||||||
|
#include "src/p_map.c"
|
||||||
|
#include "src/p_maputl.c"
|
||||||
|
#include "src/p_mobj.c"
|
||||||
|
#include "src/p_plats.c"
|
||||||
|
#include "src/p_pspr.c"
|
||||||
|
#include "src/p_saveg.c"
|
||||||
|
#include "src/p_setup.c"
|
||||||
|
#include "src/p_sight.c"
|
||||||
|
#include "src/p_spec.c"
|
||||||
|
#include "src/p_switch.c"
|
||||||
|
#include "src/p_telept.c"
|
||||||
|
#include "src/p_tick.c"
|
||||||
|
#include "src/p_user.c"
|
||||||
|
#include "src/r_bsp.c"
|
||||||
|
#include "src/r_data.c"
|
||||||
|
#include "src/r_draw.c"
|
||||||
|
#include "src/r_main.c"
|
||||||
|
#include "src/r_plane.c"
|
||||||
|
#include "src/r_segs.c"
|
||||||
|
#include "src/r_sky.c"
|
||||||
|
#include "src/r_things.c"
|
||||||
|
|
||||||
|
#include "src/sounds.c"
|
||||||
|
#undef BG
|
||||||
|
|
||||||
|
#include "src/st_lib.c"
|
||||||
|
#include "src/st_stuff.c"
|
||||||
|
|
||||||
|
#define channels channels2
|
||||||
|
#define mus_playing mus_playing2
|
||||||
|
#include "src/s_sound.c"
|
||||||
|
#undef mus_playing
|
||||||
|
#undef channels
|
||||||
|
|
||||||
|
#include "src/tables.c"
|
||||||
|
#include "src/v_video.c"
|
||||||
|
|
||||||
|
#define anim_t anim_t2
|
||||||
|
#define anims anims2
|
||||||
|
#define time time2
|
||||||
|
#include "src/wi_stuff.c"
|
||||||
|
#undef anims
|
||||||
|
#undef anim_t
|
||||||
|
#undef time
|
||||||
|
|
||||||
|
#define strupr strupr2
|
||||||
|
#include "src/w_wad.c"
|
||||||
|
#undef strupr
|
||||||
|
|
||||||
|
#include "src/z_zone.c"
|
|
@ -0,0 +1,187 @@
|
||||||
|
// PureDOOM port based on existing SDL port by @daivuk
|
||||||
|
// - rlyeh, public domain.
|
||||||
|
|
||||||
|
#include "v4k.h"
|
||||||
|
|
||||||
|
#define DOOM_IMPLEMENTATION
|
||||||
|
#include "PureDOOM.h"
|
||||||
|
|
||||||
|
// Resolution DOOM renders at
|
||||||
|
enum { DOOM_WIDTH = 320, DOOM_HEIGHT = 200 };
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
doom_key_t scancode_to_doom_key(int scancode) {
|
||||||
|
switch (scancode) {
|
||||||
|
case KEY_TAB: return DOOM_KEY_TAB;
|
||||||
|
case KEY_ENTER: return DOOM_KEY_ENTER;
|
||||||
|
case KEY_ESC: return DOOM_KEY_ESCAPE;
|
||||||
|
case KEY_SPACE: return DOOM_KEY_SPACE;
|
||||||
|
case KEY_COMMA: return DOOM_KEY_COMMA;
|
||||||
|
case KEY_MINUS: return DOOM_KEY_MINUS;
|
||||||
|
case KEY_SLASH: return DOOM_KEY_SLASH;
|
||||||
|
case KEY_0: return DOOM_KEY_0;
|
||||||
|
case KEY_1: return DOOM_KEY_1;
|
||||||
|
case KEY_2: return DOOM_KEY_2;
|
||||||
|
case KEY_3: return DOOM_KEY_3;
|
||||||
|
case KEY_4: return DOOM_KEY_4;
|
||||||
|
case KEY_5: return DOOM_KEY_5;
|
||||||
|
case KEY_6: return DOOM_KEY_6;
|
||||||
|
case KEY_7: return DOOM_KEY_7;
|
||||||
|
case KEY_8: return DOOM_KEY_8;
|
||||||
|
case KEY_9: return DOOM_KEY_9;
|
||||||
|
case KEY_SEMICOLON: return DOOM_KEY_SEMICOLON;
|
||||||
|
case KEY_A: return DOOM_KEY_A;
|
||||||
|
case KEY_B: return DOOM_KEY_B;
|
||||||
|
case KEY_C: return DOOM_KEY_C;
|
||||||
|
case KEY_D: return DOOM_KEY_D;
|
||||||
|
case KEY_E: return DOOM_KEY_E;
|
||||||
|
case KEY_F: return DOOM_KEY_F;
|
||||||
|
case KEY_G: return DOOM_KEY_G;
|
||||||
|
case KEY_H: return DOOM_KEY_H;
|
||||||
|
case KEY_I: return DOOM_KEY_I;
|
||||||
|
case KEY_J: return DOOM_KEY_J;
|
||||||
|
case KEY_K: return DOOM_KEY_K;
|
||||||
|
case KEY_L: return DOOM_KEY_L;
|
||||||
|
case KEY_M: return DOOM_KEY_M;
|
||||||
|
case KEY_N: return DOOM_KEY_N;
|
||||||
|
case KEY_O: return DOOM_KEY_O;
|
||||||
|
case KEY_P: return DOOM_KEY_P;
|
||||||
|
case KEY_Q: return DOOM_KEY_Q;
|
||||||
|
case KEY_R: return DOOM_KEY_R;
|
||||||
|
case KEY_S: return DOOM_KEY_S;
|
||||||
|
case KEY_T: return DOOM_KEY_T;
|
||||||
|
case KEY_U: return DOOM_KEY_U;
|
||||||
|
case KEY_V: return DOOM_KEY_V;
|
||||||
|
case KEY_W: return DOOM_KEY_W;
|
||||||
|
case KEY_X: return DOOM_KEY_X;
|
||||||
|
case KEY_Y: return DOOM_KEY_Y;
|
||||||
|
case KEY_Z: return DOOM_KEY_Z;
|
||||||
|
case KEY_BS: return DOOM_KEY_BACKSPACE;
|
||||||
|
case KEY_LCTRL:
|
||||||
|
case KEY_RCTRL: return DOOM_KEY_CTRL;
|
||||||
|
case KEY_LEFT: return DOOM_KEY_LEFT_ARROW;
|
||||||
|
case KEY_UP: return DOOM_KEY_UP_ARROW;
|
||||||
|
case KEY_RIGHT: return DOOM_KEY_RIGHT_ARROW;
|
||||||
|
case KEY_DOWN: return DOOM_KEY_DOWN_ARROW;
|
||||||
|
case KEY_LSHIFT:
|
||||||
|
case KEY_RSHIFT: return DOOM_KEY_SHIFT;
|
||||||
|
case KEY_LALT:
|
||||||
|
case KEY_RALT: return DOOM_KEY_ALT;
|
||||||
|
case KEY_F1: return DOOM_KEY_F1;
|
||||||
|
case KEY_F2: return DOOM_KEY_F2;
|
||||||
|
case KEY_F3: return DOOM_KEY_F3;
|
||||||
|
case KEY_F4: return DOOM_KEY_F4;
|
||||||
|
case KEY_F5: return DOOM_KEY_F5;
|
||||||
|
case KEY_F6: return DOOM_KEY_F6;
|
||||||
|
case KEY_F7: return DOOM_KEY_F7;
|
||||||
|
case KEY_F8: return DOOM_KEY_F8;
|
||||||
|
case KEY_F9: return DOOM_KEY_F9;
|
||||||
|
case KEY_F10: return DOOM_KEY_F10;
|
||||||
|
case KEY_F11: return DOOM_KEY_F11;
|
||||||
|
case KEY_F12: return DOOM_KEY_F12;
|
||||||
|
case KEY_PAUSE: return DOOM_KEY_PAUSE;
|
||||||
|
case MOUSE_L: return DOOM_LEFT_BUTTON;
|
||||||
|
case MOUSE_R: return DOOM_RIGHT_BUTTON;
|
||||||
|
case MOUSE_M: return DOOM_MIDDLE_BUTTON;
|
||||||
|
default: return DOOM_KEY_UNKNOWN;
|
||||||
|
}
|
||||||
|
return DOOM_KEY_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard() {
|
||||||
|
int keys[] = {
|
||||||
|
KEY_ESC,
|
||||||
|
KEY_TICK, KEY_1,KEY_2,KEY_3,KEY_4,KEY_5,KEY_6,KEY_7,KEY_8,KEY_9,KEY_0, KEY_BS,
|
||||||
|
KEY_TAB, KEY_Q,KEY_W,KEY_E,KEY_R,KEY_T,KEY_Y,KEY_U,KEY_I,KEY_O,KEY_P,
|
||||||
|
KEY_CAPS, KEY_A,KEY_S,KEY_D,KEY_F,KEY_G,KEY_H,KEY_J,KEY_K,KEY_L, KEY_ENTER,
|
||||||
|
KEY_LSHIFT, KEY_Z,KEY_X,KEY_C,KEY_V,KEY_B,KEY_N,KEY_M, KEY_RSHIFT, KEY_UP,
|
||||||
|
KEY_LCTRL,KEY_LALT, KEY_SPACE, KEY_RALT,KEY_RCTRL, KEY_LEFT,KEY_DOWN,KEY_RIGHT,
|
||||||
|
};
|
||||||
|
for( int i = 0; i < countof(keys); ++i ) {
|
||||||
|
int doom_vk = scancode_to_doom_key(keys[i]);
|
||||||
|
if( doom_vk != DOOM_KEY_UNKNOWN ) {
|
||||||
|
/**/ if( input_down(keys[i]) ) doom_key_down(doom_vk);
|
||||||
|
else if( input_up(keys[i]) ) doom_key_up(doom_vk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse() {
|
||||||
|
if( !window_has_cursor() ) { // Dev allow us to take mouse out of window
|
||||||
|
int motion_x = input_diff(MOUSE_X);
|
||||||
|
int motion_y = input_diff(MOUSE_Y);
|
||||||
|
|
||||||
|
const float MOUSE_SENSITIVITY = 3.0f;
|
||||||
|
doom_mouse_move(motion_x * MOUSE_SENSITIVITY, motion_y * MOUSE_SENSITIVITY);
|
||||||
|
|
||||||
|
/**/ if( input_down(MOUSE_L) ) doom_button_down(scancode_to_doom_key(MOUSE_L));
|
||||||
|
else if( input_up(MOUSE_L) ) doom_button_up(scancode_to_doom_key(MOUSE_L));
|
||||||
|
/**/ if( input_down(MOUSE_R) ) doom_button_down(scancode_to_doom_key(MOUSE_R));
|
||||||
|
else if( input_up(MOUSE_R) ) doom_button_up(scancode_to_doom_key(MOUSE_R));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void logic() {
|
||||||
|
doom_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit() {
|
||||||
|
static texture_t screen; do_once screen = texture_checker();
|
||||||
|
texture_update(&screen, DOOM_WIDTH, DOOM_HEIGHT, 4, doom_get_framebuffer(4), TEXTURE_RGBA/*|TEXTURE_LINEAR*/);
|
||||||
|
fullscreen_quad_rgb(screen, 1.0f); // gamma(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
void audio() {
|
||||||
|
// doom_get_sound_buffer() is always 2048 bytes sized, 11khz 16bit stereo, 512 samples
|
||||||
|
static int target_frame = 60.0 * ( 512. / 11025 );
|
||||||
|
static int curr_frame = 0; if( curr_frame++ >= target_frame ) { curr_frame = 0;
|
||||||
|
audio_queue(doom_get_sound_buffer(), 512, 0|AUDIO_16|AUDIO_2CH|AUDIO_11KHZ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned midi(unsigned interval, void *param) { // this is async called every interval, via timer
|
||||||
|
unsigned midi_msg;
|
||||||
|
while( (midi_msg = doom_tick_midi()) != 0 ) midi_send(midi_msg);
|
||||||
|
return 1000 / DOOM_MIDI_RATE ifdef(osx, -1); // Weirdly, on Apple music is too slow
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
// install signal handlers
|
||||||
|
signal_hooks();
|
||||||
|
|
||||||
|
// Change default bindings to modern
|
||||||
|
doom_set_default_int("key_up", DOOM_KEY_W);
|
||||||
|
doom_set_default_int("key_down", DOOM_KEY_S);
|
||||||
|
doom_set_default_int("key_strafeleft", DOOM_KEY_A);
|
||||||
|
doom_set_default_int("key_straferight", DOOM_KEY_D);
|
||||||
|
doom_set_default_int("key_use", DOOM_KEY_E);
|
||||||
|
doom_set_default_int("mouse_move", 0); // Mouse will not move forward
|
||||||
|
|
||||||
|
// Change resolution
|
||||||
|
doom_set_resolution(DOOM_WIDTH, DOOM_HEIGHT);
|
||||||
|
|
||||||
|
// Initialize doom
|
||||||
|
doom_init(argc, argv, DOOM_FLAG_MENU_DARKEN_BG);
|
||||||
|
|
||||||
|
// Init app
|
||||||
|
window_create(0.75, 0);
|
||||||
|
window_aspect_lock(DOOM_WIDTH, DOOM_HEIGHT);
|
||||||
|
window_title("Pure DOOM");
|
||||||
|
window_cursor(false);
|
||||||
|
timer(0, midi, 0);
|
||||||
|
|
||||||
|
// Loop app
|
||||||
|
while( window_swap() ) {
|
||||||
|
if( input_down(KEY_F10) ) tty_attach();
|
||||||
|
if( input_down(KEY_F11) ) window_fullscreen(!window_has_fullscreen());
|
||||||
|
|
||||||
|
keyboard();
|
||||||
|
mouse();
|
||||||
|
logic();
|
||||||
|
blit();
|
||||||
|
audio();
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 87 KiB |
|
@ -0,0 +1,741 @@
|
||||||
|
#if defined(WIN32)
|
||||||
|
#define _CRT_SECURE_NO_WARNINGS
|
||||||
|
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
#define _CRT_NONSTDC_NO_DEPRECATE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "DOOM.h"
|
||||||
|
|
||||||
|
#include "d_main.h"
|
||||||
|
#include "doomdef.h"
|
||||||
|
#include "doomtype.h"
|
||||||
|
#include "i_system.h"
|
||||||
|
#include "m_argv.h"
|
||||||
|
#include "m_misc.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern byte* screens[5];
|
||||||
|
extern unsigned char screen_palette[256 * 3];
|
||||||
|
extern doom_boolean is_wiping_screen;
|
||||||
|
extern default_t defaults[];
|
||||||
|
extern int numdefaults;
|
||||||
|
extern signed short mixbuffer[2048];
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned char* screen_buffer = 0;
|
||||||
|
static unsigned char* final_screen_buffer = 0;
|
||||||
|
static int last_update_time = 0;
|
||||||
|
static int button_states[3] = { 0 };
|
||||||
|
static char itoa_buf[20];
|
||||||
|
|
||||||
|
|
||||||
|
char error_buf[260];
|
||||||
|
int doom_flags = 0;
|
||||||
|
doom_print_fn doom_print = 0;
|
||||||
|
doom_malloc_fn doom_malloc = 0;
|
||||||
|
doom_free_fn doom_free = 0;
|
||||||
|
doom_open_fn doom_open = 0;
|
||||||
|
doom_close_fn doom_close = 0;
|
||||||
|
doom_read_fn doom_read = 0;
|
||||||
|
doom_write_fn doom_write = 0;
|
||||||
|
doom_seek_fn doom_seek = 0;
|
||||||
|
doom_tell_fn doom_tell = 0;
|
||||||
|
doom_eof_fn doom_eof = 0;
|
||||||
|
doom_gettime_fn doom_gettime = 0;
|
||||||
|
doom_exit_fn doom_exit = 0;
|
||||||
|
doom_getenv_fn doom_getenv = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void D_DoomLoop(void);
|
||||||
|
void D_UpdateWipe(void);
|
||||||
|
void I_UpdateSound();
|
||||||
|
unsigned long I_TickSong();
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_PRINT)
|
||||||
|
#include <stdio.h>
|
||||||
|
static void doom_print_impl(const char* str)
|
||||||
|
{
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void doom_print_impl(const char* str) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_MALLOC)
|
||||||
|
#include <stdlib.h>
|
||||||
|
static void* doom_malloc_impl(int size)
|
||||||
|
{
|
||||||
|
return malloc((size_t)size);
|
||||||
|
}
|
||||||
|
static void doom_free_impl(void* ptr)
|
||||||
|
{
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void* doom_malloc_impl(int size) { return 0; }
|
||||||
|
static void doom_free_impl(void* ptr) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_FILE_IO)
|
||||||
|
#include <stdio.h>
|
||||||
|
void* doom_open_impl(const char* filename, const char* mode)
|
||||||
|
{
|
||||||
|
return fopen(filename, mode);
|
||||||
|
}
|
||||||
|
void doom_close_impl(void* handle)
|
||||||
|
{
|
||||||
|
fclose(handle);
|
||||||
|
}
|
||||||
|
int doom_read_impl(void* handle, void *buf, int count)
|
||||||
|
{
|
||||||
|
return (int)fread(buf, 1, count, handle);
|
||||||
|
}
|
||||||
|
int doom_write_impl(void* handle, const void *buf, int count)
|
||||||
|
{
|
||||||
|
return (int)fwrite(buf, 1, count, handle);
|
||||||
|
}
|
||||||
|
int doom_seek_impl(void* handle, int offset, doom_seek_t origin)
|
||||||
|
{
|
||||||
|
return fseek(handle, offset, origin);
|
||||||
|
}
|
||||||
|
int doom_tell_impl(void* handle)
|
||||||
|
{
|
||||||
|
return (int)ftell(handle);
|
||||||
|
}
|
||||||
|
int doom_eof_impl(void* handle)
|
||||||
|
{
|
||||||
|
return feof(handle);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void* doom_open_impl(const char* filename, const char* mode)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void doom_close_impl(void* handle) {}
|
||||||
|
int doom_read_impl(void* handle, void *buf, int count)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int doom_write_impl(void* handle, const void *buf, int count)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int doom_seek_impl(void* handle, int offset, doom_seek_t origin)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int doom_tell_impl(void* handle)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int doom_eof_impl(void* handle)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_GETTIME)
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <winsock.h>
|
||||||
|
#else
|
||||||
|
#include <sys/time.h>
|
||||||
|
#endif
|
||||||
|
void doom_gettime_impl(int* sec, int* usec)
|
||||||
|
{
|
||||||
|
#if defined(WIN32)
|
||||||
|
static const unsigned long long EPOCH = ((unsigned long long)116444736000000000ULL);
|
||||||
|
SYSTEMTIME system_time;
|
||||||
|
FILETIME file_time;
|
||||||
|
unsigned long long time;
|
||||||
|
GetSystemTime(&system_time);
|
||||||
|
SystemTimeToFileTime(&system_time, &file_time);
|
||||||
|
time = ((unsigned long long)file_time.dwLowDateTime);
|
||||||
|
time += ((unsigned long long)file_time.dwHighDateTime) << 32;
|
||||||
|
*sec = (int)((time - EPOCH) / 10000000L);
|
||||||
|
*usec = (int)(system_time.wMilliseconds * 1000);
|
||||||
|
#else
|
||||||
|
struct timeval tp;
|
||||||
|
struct timezone tzp;
|
||||||
|
gettimeofday(&tp, &tzp);
|
||||||
|
*sec = tp.tv_sec;
|
||||||
|
*usec = tp.tv_usec;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void doom_gettime_impl(int* sec, int* usec)
|
||||||
|
{
|
||||||
|
*sec = 0;
|
||||||
|
*usec = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_EXIT)
|
||||||
|
#include <stdlib.h>
|
||||||
|
void doom_exit_impl(int code)
|
||||||
|
{
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void doom_exit_impl(int code) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOOM_IMPLEMENT_GETENV)
|
||||||
|
#include <stdlib.h>
|
||||||
|
char* doom_getenv_impl(const char* var)
|
||||||
|
{
|
||||||
|
return getenv(var);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
char* doom_getenv_impl(const char* var) {
|
||||||
|
return (char*)0; //< @r-lyeh add missing return
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void doom_memset(void* ptr, int value, int num)
|
||||||
|
{
|
||||||
|
unsigned char* p = ptr;
|
||||||
|
for (int i = 0; i < num; ++i, ++p)
|
||||||
|
{
|
||||||
|
*p = (unsigned char)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void* doom_memcpy(void* destination, const void* source, int num)
|
||||||
|
{
|
||||||
|
unsigned char* dst = destination;
|
||||||
|
const unsigned char* src = source;
|
||||||
|
|
||||||
|
for (int i = 0; i < num; ++i, ++dst, ++src)
|
||||||
|
{
|
||||||
|
*dst = *src;
|
||||||
|
}
|
||||||
|
|
||||||
|
return destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_strlen(const char* str)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
while (*str++) ++len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* doom_concat(char* dst, const char* src)
|
||||||
|
{
|
||||||
|
char* ret = dst;
|
||||||
|
dst += doom_strlen(dst);
|
||||||
|
|
||||||
|
while (*src) *dst++ = *src++;
|
||||||
|
*dst = *src; // \0
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* doom_strcpy(char* dst, const char* src)
|
||||||
|
{
|
||||||
|
char* ret = dst;
|
||||||
|
|
||||||
|
while (*src) *dst++ = *src++;
|
||||||
|
*dst = *src; // \0
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char* doom_strncpy(char* dst, const char* src, int num)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < num; ++i)
|
||||||
|
{
|
||||||
|
if (!src[i]) break;
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while (i < num) dst[i++] = '\0';
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_strcmp(const char* str1, const char* str2)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (!(ret = *(unsigned char*)str1 - *(unsigned char*) str2) && *str1)
|
||||||
|
++str1, ++str2;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ret = -1;
|
||||||
|
else if (ret > 0)
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_strncmp(const char* str1, const char* str2, int n)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
while (!(ret = *(unsigned char*)str1 - *(unsigned char*) str2) && *str1 && count++ < n)
|
||||||
|
++str1, ++str2;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ret = -1;
|
||||||
|
else if (ret > 0)
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_toupper(int c)
|
||||||
|
{
|
||||||
|
if (c >= 'a' && c <= 'z') return c - 'a' + 'A';
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_strcasecmp(const char* str1, const char* str2)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (!(ret = doom_toupper(*(unsigned char*)str1) - doom_toupper(*(unsigned char*)str2)) && *str1)
|
||||||
|
++str1, ++str2;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ret = -1;
|
||||||
|
else if (ret > 0)
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_strncasecmp(const char* str1, const char* str2, int n)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int count = 1;
|
||||||
|
|
||||||
|
while (!(ret = doom_toupper(*(unsigned char*)str1) - doom_toupper(*(unsigned char*)str2)) && *str1 && count++ < n)
|
||||||
|
++str1, ++str2;
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
ret = -1;
|
||||||
|
else if (ret > 0)
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_atoi(const char* str)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = *str++) != 0)
|
||||||
|
{
|
||||||
|
i *= 10;
|
||||||
|
i += c - '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_atox(const char* str)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while ((c = *str++) != 0)
|
||||||
|
{
|
||||||
|
i *= 16;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
i += c - '0';
|
||||||
|
else
|
||||||
|
i += c - 'A' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* doom_itoa(int k, int radix)
|
||||||
|
{
|
||||||
|
int i = k < 0 ? -k : k;
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
itoa_buf[0] = '0';
|
||||||
|
itoa_buf[1] = '\0';
|
||||||
|
return itoa_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int idx = k < 0 ? 1 : 0;
|
||||||
|
int j = i;
|
||||||
|
while (j)
|
||||||
|
{
|
||||||
|
j /= radix;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
itoa_buf[idx] = '\0';
|
||||||
|
|
||||||
|
if (radix == 10)
|
||||||
|
{
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
itoa_buf[--idx] = '0' + (i % 10);
|
||||||
|
i /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
int k = (i & 0xF);
|
||||||
|
if (k >= 10)
|
||||||
|
itoa_buf[--idx] = 'A' + ((i & 0xF) - 10);
|
||||||
|
else
|
||||||
|
itoa_buf[--idx] = '0' + (i & 0xF);
|
||||||
|
i >>= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < 0) itoa_buf[0] = '-';
|
||||||
|
|
||||||
|
return itoa_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* doom_ctoa(char c)
|
||||||
|
{
|
||||||
|
itoa_buf[0] = c;
|
||||||
|
itoa_buf[1] = '\0';
|
||||||
|
return itoa_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char* doom_ptoa(void* p)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
unsigned long long i = (unsigned long long)p;
|
||||||
|
|
||||||
|
itoa_buf[idx++] = '0';
|
||||||
|
itoa_buf[idx++] = 'x';
|
||||||
|
|
||||||
|
while (i)
|
||||||
|
{
|
||||||
|
int k = (i & 0xF);
|
||||||
|
if (k >= 10)
|
||||||
|
itoa_buf[idx++] = 'A' + ((i & 0xF) - 10);
|
||||||
|
else
|
||||||
|
itoa_buf[idx++] = '0' + (i & 0xF);
|
||||||
|
i >>= 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
itoa_buf[idx] = '\0';
|
||||||
|
return itoa_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doom_fprint(void* handle, const char* str)
|
||||||
|
{
|
||||||
|
return doom_write(handle, str, doom_strlen(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static default_t* get_default(const char* name)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < numdefaults; ++i)
|
||||||
|
{
|
||||||
|
if (doom_strcmp(defaults[i].name, name) == 0) return &defaults[i];
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_resolution(int width, int height)
|
||||||
|
{
|
||||||
|
if (width <= 0 || height <= 0) return;
|
||||||
|
// SCREENWIDTH = width;
|
||||||
|
// SCREENHEIGHT = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_default_int(const char* name, int value)
|
||||||
|
{
|
||||||
|
default_t* def = get_default(name);
|
||||||
|
if (!def) return;
|
||||||
|
def->defaultvalue = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_default_string(const char* name, const char* value)
|
||||||
|
{
|
||||||
|
default_t* def = get_default(name);
|
||||||
|
if (!def) return;
|
||||||
|
def->default_text_value = (char*)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_print(doom_print_fn print_fn)
|
||||||
|
{
|
||||||
|
doom_print = print_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_malloc(doom_malloc_fn malloc_fn, doom_free_fn free_fn)
|
||||||
|
{
|
||||||
|
doom_malloc = malloc_fn;
|
||||||
|
doom_free = free_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_file_io(doom_open_fn open_fn,
|
||||||
|
doom_close_fn close_fn,
|
||||||
|
doom_read_fn read_fn,
|
||||||
|
doom_write_fn write_fn,
|
||||||
|
doom_seek_fn seek_fn,
|
||||||
|
doom_tell_fn tell_fn,
|
||||||
|
doom_eof_fn eof_fn)
|
||||||
|
{
|
||||||
|
doom_open = open_fn;
|
||||||
|
doom_close = close_fn;
|
||||||
|
doom_read = read_fn;
|
||||||
|
doom_write = write_fn;
|
||||||
|
doom_seek = seek_fn;
|
||||||
|
doom_tell = tell_fn;
|
||||||
|
doom_eof = eof_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_gettime(doom_gettime_fn gettime_fn)
|
||||||
|
{
|
||||||
|
doom_gettime = gettime_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_exit(doom_exit_fn exit_fn)
|
||||||
|
{
|
||||||
|
doom_exit = exit_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_set_getenv(doom_getenv_fn getenv_fn)
|
||||||
|
{
|
||||||
|
doom_getenv = getenv_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_init(int argc, char** argv, int flags)
|
||||||
|
{
|
||||||
|
if (!doom_print) doom_print = doom_print_impl;
|
||||||
|
if (!doom_malloc) doom_malloc = doom_malloc_impl;
|
||||||
|
if (!doom_free) doom_free = doom_free_impl;
|
||||||
|
if (!doom_open) doom_open = doom_open_impl;
|
||||||
|
if (!doom_close) doom_close = doom_close_impl;
|
||||||
|
if (!doom_read) doom_read = doom_read_impl;
|
||||||
|
if (!doom_write) doom_write = doom_write_impl;
|
||||||
|
if (!doom_seek) doom_seek = doom_seek_impl;
|
||||||
|
if (!doom_tell) doom_tell = doom_tell_impl;
|
||||||
|
if (!doom_eof) doom_eof = doom_eof_impl;
|
||||||
|
if (!doom_gettime) doom_gettime = doom_gettime_impl;
|
||||||
|
if (!doom_exit) doom_exit = doom_exit_impl;
|
||||||
|
if (!doom_getenv) doom_getenv = doom_getenv_impl;
|
||||||
|
|
||||||
|
screen_buffer = doom_malloc(SCREENWIDTH * SCREENHEIGHT);
|
||||||
|
final_screen_buffer = doom_malloc(SCREENWIDTH * SCREENHEIGHT * 4);
|
||||||
|
last_update_time = I_GetTime();
|
||||||
|
|
||||||
|
myargc = argc;
|
||||||
|
myargv = argv;
|
||||||
|
doom_flags = flags;
|
||||||
|
|
||||||
|
D_DoomMain();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_update()
|
||||||
|
{
|
||||||
|
int now = I_GetTime();
|
||||||
|
int delta_time = now - last_update_time;
|
||||||
|
|
||||||
|
while (delta_time-- > 0)
|
||||||
|
{
|
||||||
|
if (is_wiping_screen)
|
||||||
|
D_UpdateWipe();
|
||||||
|
else
|
||||||
|
D_DoomLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
last_update_time = now;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const unsigned char* doom_get_framebuffer(int channels)
|
||||||
|
{
|
||||||
|
int i, len;
|
||||||
|
|
||||||
|
doom_memcpy(screen_buffer, screens[0], SCREENWIDTH * SCREENHEIGHT);
|
||||||
|
|
||||||
|
extern doom_boolean menuactive;
|
||||||
|
extern gamestate_t gamestate;
|
||||||
|
extern doom_boolean automapactive;
|
||||||
|
extern int crosshair;
|
||||||
|
|
||||||
|
// Draw crosshair
|
||||||
|
if (crosshair &&
|
||||||
|
!menuactive &&
|
||||||
|
gamestate == GS_LEVEL &&
|
||||||
|
!automapactive)
|
||||||
|
{
|
||||||
|
int y;
|
||||||
|
extern int setblocks;
|
||||||
|
if (setblocks == 11) y = SCREENHEIGHT / 2 + 8;
|
||||||
|
else y = SCREENHEIGHT / 2 - 8;
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
screen_buffer[SCREENWIDTH / 2 - 2 - i + y * SCREENWIDTH] = 4;
|
||||||
|
screen_buffer[SCREENWIDTH / 2 + 2 + i + y * SCREENWIDTH] = 4;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
screen_buffer[SCREENWIDTH / 2 + (y - 2 - i) * SCREENWIDTH] = 4;
|
||||||
|
screen_buffer[SCREENWIDTH / 2 + (y + 2 + i) * SCREENWIDTH] = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channels == 1)
|
||||||
|
{
|
||||||
|
return screen_buffer;
|
||||||
|
}
|
||||||
|
else if (channels == 3)
|
||||||
|
{
|
||||||
|
for (i = 0, len = SCREENWIDTH * SCREENHEIGHT; i < len; ++i)
|
||||||
|
{
|
||||||
|
int k = i * 3;
|
||||||
|
int kpal = screen_buffer[i] * 3;
|
||||||
|
final_screen_buffer[k + 0] = screen_palette[kpal + 0];
|
||||||
|
final_screen_buffer[k + 1] = screen_palette[kpal + 1];
|
||||||
|
final_screen_buffer[k + 2] = screen_palette[kpal + 2];
|
||||||
|
}
|
||||||
|
return final_screen_buffer;
|
||||||
|
}
|
||||||
|
else if (channels == 4)
|
||||||
|
{
|
||||||
|
for (i = 0, len = SCREENWIDTH * SCREENHEIGHT; i < len; ++i)
|
||||||
|
{
|
||||||
|
int k = i * 4;
|
||||||
|
int kpal = screen_buffer[i] * 3;
|
||||||
|
final_screen_buffer[k + 0] = screen_palette[kpal + 0];
|
||||||
|
final_screen_buffer[k + 1] = screen_palette[kpal + 1];
|
||||||
|
final_screen_buffer[k + 2] = screen_palette[kpal + 2];
|
||||||
|
final_screen_buffer[k + 3] = 255;
|
||||||
|
}
|
||||||
|
return final_screen_buffer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long doom_tick_midi()
|
||||||
|
{
|
||||||
|
return I_TickSong();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
short* doom_get_sound_buffer()
|
||||||
|
{
|
||||||
|
I_UpdateSound();
|
||||||
|
return mixbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_key_down(doom_key_t key)
|
||||||
|
{
|
||||||
|
event_t event;
|
||||||
|
event.type = ev_keydown;
|
||||||
|
event.data1 = (int)key;
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_key_up(doom_key_t key)
|
||||||
|
{
|
||||||
|
event_t event;
|
||||||
|
event.type = ev_keyup;
|
||||||
|
event.data1 = (int)key;
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_button_down(doom_button_t button)
|
||||||
|
{
|
||||||
|
button_states[button] = 1;
|
||||||
|
|
||||||
|
event_t event;
|
||||||
|
event.type = ev_mouse;
|
||||||
|
event.data1 =
|
||||||
|
(button_states[0]) |
|
||||||
|
(button_states[1] ? 2 : 0) |
|
||||||
|
(button_states[2] ? 4 : 0);
|
||||||
|
event.data2 = event.data3 = 0;
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_button_up(doom_button_t button)
|
||||||
|
{
|
||||||
|
button_states[button] = 0;
|
||||||
|
|
||||||
|
event_t event;
|
||||||
|
event.type = ev_mouse;
|
||||||
|
event.data1 =
|
||||||
|
(button_states[0]) |
|
||||||
|
(button_states[1] ? 2 : 0) |
|
||||||
|
(button_states[2] ? 4 : 0);
|
||||||
|
|
||||||
|
event.data1 =
|
||||||
|
event.data1
|
||||||
|
^ (button_states[0] ? 1 : 0)
|
||||||
|
^ (button_states[1] ? 2 : 0)
|
||||||
|
^ (button_states[2] ? 4 : 0);
|
||||||
|
|
||||||
|
event.data2 = event.data3 = 0;
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void doom_mouse_move(int delta_x, int delta_y)
|
||||||
|
{
|
||||||
|
event_t event;
|
||||||
|
|
||||||
|
event.type = ev_mouse;
|
||||||
|
event.data1 =
|
||||||
|
(button_states[0]) |
|
||||||
|
(button_states[1] ? 2 : 0) |
|
||||||
|
(button_states[2] ? 4 : 0);
|
||||||
|
event.data2 = delta_x;
|
||||||
|
event.data3 = -delta_y;
|
||||||
|
|
||||||
|
if (event.data2 || event.data3)
|
||||||
|
{
|
||||||
|
D_PostEvent(&event);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,216 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||||
|
//
|
||||||
|
// This source is available for distribution and/or modification
|
||||||
|
// only under the terms of the DOOM Source Code License as
|
||||||
|
// published by id Software. All rights reserved.
|
||||||
|
//
|
||||||
|
// The source is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
|
||||||
|
// for more details.
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/* Pure DOOM usage
|
||||||
|
|
||||||
|
Do this:
|
||||||
|
#define DOOM_IMPLEMENTATION
|
||||||
|
before you include this file in *one* C or C++ file to create the implementation.
|
||||||
|
|
||||||
|
// i.e. it should look like this:
|
||||||
|
#include ...
|
||||||
|
#include ...
|
||||||
|
#include ...
|
||||||
|
#define DOOM_IMPLEMENTATION
|
||||||
|
#include "PureDOOM.h"
|
||||||
|
|
||||||
|
*/
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __DOOM_H__
|
||||||
|
#define __DOOM_H__
|
||||||
|
|
||||||
|
|
||||||
|
// Sample rate of sound samples from doom
|
||||||
|
#define DOOM_SAMPLERATE 11025
|
||||||
|
|
||||||
|
// MIDI tick needs to be called 140 times per seconds
|
||||||
|
#define DOOM_MIDI_RATE 140
|
||||||
|
|
||||||
|
// Hide menu options. If for say your platform doesn't support mouse or
|
||||||
|
// MIDI playback, you can hide these settings from the menu.
|
||||||
|
#define DOOM_FLAG_HIDE_MOUSE_OPTIONS 1 // Remove mouse options from menu
|
||||||
|
#define DOOM_FLAG_HIDE_SOUND_OPTIONS 2 // Remove sound options from menu
|
||||||
|
#define DOOM_FLAG_HIDE_MUSIC_OPTIONS 4 // Remove music options from menu
|
||||||
|
|
||||||
|
// Darken background when menu is open, making it more readable. This
|
||||||
|
// uses a bit more CPU and redraws the HUD every frame
|
||||||
|
#define DOOM_FLAG_MENU_DARKEN_BG 8
|
||||||
|
|
||||||
|
|
||||||
|
#if __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DOOM_SEEK_CUR = 1,
|
||||||
|
DOOM_SEEK_END = 2,
|
||||||
|
DOOM_SEEK_SET = 0
|
||||||
|
} doom_seek_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef void(*doom_print_fn)(const char* str);
|
||||||
|
typedef void*(*doom_malloc_fn)(int size);
|
||||||
|
typedef void(*doom_free_fn)(void* ptr);
|
||||||
|
typedef void*(*doom_open_fn)(const char* filename, const char* mode);
|
||||||
|
typedef void(*doom_close_fn)(void* handle);
|
||||||
|
typedef int(*doom_read_fn)(void* handle, void *buf, int count);
|
||||||
|
typedef int(*doom_write_fn)(void* handle, const void *buf, int count);
|
||||||
|
typedef int(*doom_seek_fn)(void* handle, int offset, doom_seek_t origin);
|
||||||
|
typedef int(*doom_tell_fn)(void* handle);
|
||||||
|
typedef int(*doom_eof_fn)(void* handle);
|
||||||
|
typedef void(*doom_gettime_fn)(int* sec, int* usec);
|
||||||
|
typedef void(*doom_exit_fn)(int code);
|
||||||
|
typedef char*(*doom_getenv_fn)(const char* var);
|
||||||
|
|
||||||
|
|
||||||
|
// Doom key mapping
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DOOM_KEY_UNKNOWN = -1,
|
||||||
|
DOOM_KEY_TAB = 9,
|
||||||
|
DOOM_KEY_ENTER = 13,
|
||||||
|
DOOM_KEY_ESCAPE = 27,
|
||||||
|
DOOM_KEY_SPACE = 32,
|
||||||
|
DOOM_KEY_APOSTROPHE = '\'',
|
||||||
|
DOOM_KEY_MULTIPLY = '*',
|
||||||
|
DOOM_KEY_COMMA = ',',
|
||||||
|
DOOM_KEY_MINUS = 0x2d,
|
||||||
|
DOOM_KEY_PERIOD = '.',
|
||||||
|
DOOM_KEY_SLASH = '/',
|
||||||
|
DOOM_KEY_0 = '0',
|
||||||
|
DOOM_KEY_1 = '1',
|
||||||
|
DOOM_KEY_2 = '2',
|
||||||
|
DOOM_KEY_3 = '3',
|
||||||
|
DOOM_KEY_4 = '4',
|
||||||
|
DOOM_KEY_5 = '5',
|
||||||
|
DOOM_KEY_6 = '6',
|
||||||
|
DOOM_KEY_7 = '7',
|
||||||
|
DOOM_KEY_8 = '8',
|
||||||
|
DOOM_KEY_9 = '9',
|
||||||
|
DOOM_KEY_SEMICOLON = ';',
|
||||||
|
DOOM_KEY_EQUALS = 0x3d,
|
||||||
|
DOOM_KEY_LEFT_BRACKET = '[',
|
||||||
|
DOOM_KEY_RIGHT_BRACKET = ']',
|
||||||
|
DOOM_KEY_A = 'a',
|
||||||
|
DOOM_KEY_B = 'b',
|
||||||
|
DOOM_KEY_C = 'c',
|
||||||
|
DOOM_KEY_D = 'd',
|
||||||
|
DOOM_KEY_E = 'e',
|
||||||
|
DOOM_KEY_F = 'f',
|
||||||
|
DOOM_KEY_G = 'g',
|
||||||
|
DOOM_KEY_H = 'h',
|
||||||
|
DOOM_KEY_I = 'i',
|
||||||
|
DOOM_KEY_J = 'j',
|
||||||
|
DOOM_KEY_K = 'k',
|
||||||
|
DOOM_KEY_L = 'l',
|
||||||
|
DOOM_KEY_M = 'm',
|
||||||
|
DOOM_KEY_N = 'n',
|
||||||
|
DOOM_KEY_O = 'o',
|
||||||
|
DOOM_KEY_P = 'p',
|
||||||
|
DOOM_KEY_Q = 'q',
|
||||||
|
DOOM_KEY_R = 'r',
|
||||||
|
DOOM_KEY_S = 's',
|
||||||
|
DOOM_KEY_T = 't',
|
||||||
|
DOOM_KEY_U = 'u',
|
||||||
|
DOOM_KEY_V = 'v',
|
||||||
|
DOOM_KEY_W = 'w',
|
||||||
|
DOOM_KEY_X = 'x',
|
||||||
|
DOOM_KEY_Y = 'y',
|
||||||
|
DOOM_KEY_Z = 'z',
|
||||||
|
DOOM_KEY_BACKSPACE = 127,
|
||||||
|
DOOM_KEY_CTRL = (0x80 + 0x1d), // Both left and right
|
||||||
|
DOOM_KEY_LEFT_ARROW = 0xac,
|
||||||
|
DOOM_KEY_UP_ARROW = 0xad,
|
||||||
|
DOOM_KEY_RIGHT_ARROW = 0xae,
|
||||||
|
DOOM_KEY_DOWN_ARROW = 0xaf,
|
||||||
|
DOOM_KEY_SHIFT = (0x80 + 0x36), // Both left and right
|
||||||
|
DOOM_KEY_ALT = (0x80 + 0x38), // Both left and right
|
||||||
|
DOOM_KEY_F1 = (0x80 + 0x3b),
|
||||||
|
DOOM_KEY_F2 = (0x80 + 0x3c),
|
||||||
|
DOOM_KEY_F3 = (0x80 + 0x3d),
|
||||||
|
DOOM_KEY_F4 = (0x80 + 0x3e),
|
||||||
|
DOOM_KEY_F5 = (0x80 + 0x3f),
|
||||||
|
DOOM_KEY_F6 = (0x80 + 0x40),
|
||||||
|
DOOM_KEY_F7 = (0x80 + 0x41),
|
||||||
|
DOOM_KEY_F8 = (0x80 + 0x42),
|
||||||
|
DOOM_KEY_F9 = (0x80 + 0x43),
|
||||||
|
DOOM_KEY_F10 = (0x80 + 0x44),
|
||||||
|
DOOM_KEY_F11 = (0x80 + 0x57),
|
||||||
|
DOOM_KEY_F12 = (0x80 + 0x58),
|
||||||
|
DOOM_KEY_PAUSE = 0xff
|
||||||
|
} doom_key_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Mouse button mapping
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DOOM_LEFT_BUTTON = 0,
|
||||||
|
DOOM_RIGHT_BUTTON = 1,
|
||||||
|
DOOM_MIDDLE_BUTTON = 2
|
||||||
|
} doom_button_t;
|
||||||
|
|
||||||
|
|
||||||
|
// For the software renderer. Default is 320x200
|
||||||
|
void doom_set_resolution(int width, int height);
|
||||||
|
|
||||||
|
// Set default configurations. Lets say, changing arrows to WASD as default controls
|
||||||
|
void doom_set_default_int(const char* name, int value);
|
||||||
|
void doom_set_default_string(const char* name, const char* value);
|
||||||
|
|
||||||
|
// set callbacks
|
||||||
|
void doom_set_print(doom_print_fn print_fn);
|
||||||
|
void doom_set_malloc(doom_malloc_fn malloc_fn, doom_free_fn free_fn);
|
||||||
|
void doom_set_file_io(doom_open_fn open_fn,
|
||||||
|
doom_close_fn close_fn,
|
||||||
|
doom_read_fn read_fn,
|
||||||
|
doom_write_fn write_fn,
|
||||||
|
doom_seek_fn seek_fn,
|
||||||
|
doom_tell_fn tell_fn,
|
||||||
|
doom_eof_fn eof_fn);
|
||||||
|
void doom_set_gettime(doom_gettime_fn gettime_fn);
|
||||||
|
void doom_set_exit(doom_exit_fn exit_fn);
|
||||||
|
void doom_set_getenv(doom_getenv_fn getenv_fn);
|
||||||
|
|
||||||
|
// Initializes DOOM and start things up. Call only call one
|
||||||
|
void doom_init(int argc, char** argv, int flags);
|
||||||
|
|
||||||
|
// Call this every frame
|
||||||
|
void doom_update();
|
||||||
|
|
||||||
|
// Channels: 1 = indexed, 3 = RGB, 4 = RGBA
|
||||||
|
const unsigned char* doom_get_framebuffer(int channels);
|
||||||
|
|
||||||
|
// It is always 2048 bytes in size
|
||||||
|
short* doom_get_sound_buffer();
|
||||||
|
|
||||||
|
// Call this 140 times per second. Or about every 7ms.
|
||||||
|
// Returns midi message. Keep calling it until it returns 0.
|
||||||
|
unsigned long doom_tick_midi();
|
||||||
|
|
||||||
|
// Events
|
||||||
|
void doom_key_down(doom_key_t key);
|
||||||
|
void doom_key_up(doom_key_t key);
|
||||||
|
void doom_button_down(doom_button_t button);
|
||||||
|
void doom_button_up(doom_button_t button);
|
||||||
|
void doom_mouse_move(int delta_x, int delta_y);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,106 @@
|
||||||
|
LIMITED USE SOFTWARE LICENSE AGREEMENT
|
||||||
|
|
||||||
|
This Limited Use Software License Agreement (the "Agreement")
|
||||||
|
is a legal agreement between you, the end-user, and Id Software, Inc.
|
||||||
|
("ID"). By downloading or purchasing the software material, which
|
||||||
|
includes source code (the "Source Code"), artwork data, music and
|
||||||
|
software tools (collectively, the "Software"), you are agreeing to
|
||||||
|
be bound by the terms of this Agreement. If you do not agree to the
|
||||||
|
terms of this Agreement, promptly destroy the Software you may have
|
||||||
|
downloaded or copied.
|
||||||
|
|
||||||
|
ID SOFTWARE LICENSE
|
||||||
|
|
||||||
|
1. Grant of License. ID grants to you the right to use the
|
||||||
|
Software. You have no ownership or proprietary rights in or to the
|
||||||
|
Software, or the Trademark. For purposes of this section, "use" means
|
||||||
|
loading the Software into RAM, as well as installation on a hard disk
|
||||||
|
or other storage device. The Software, together with any archive copy
|
||||||
|
thereof, shall be destroyed when no longer used in accordance with
|
||||||
|
this Agreement, or when the right to use the Software is terminated.
|
||||||
|
You agree that the Software will not be shipped, transferred or
|
||||||
|
exported into any country in violation of the U.S. Export
|
||||||
|
Administration Act (or any other law governing such matters) and that
|
||||||
|
you will not utilize, in any other manner, the Software in violation
|
||||||
|
of any applicable law.
|
||||||
|
|
||||||
|
2. Permitted Uses. For educational purposes only, you, the
|
||||||
|
end-user, may use portions of the Source Code, such as particular
|
||||||
|
routines, to develop your own software, but may not duplicate the
|
||||||
|
Source Code, except as noted in paragraph 4. The limited right
|
||||||
|
referenced in the preceding sentence is hereinafter referred to as
|
||||||
|
"Educational Use." By so exercising the Educational Use right you
|
||||||
|
shall not obtain any ownership, copyright, proprietary or other
|
||||||
|
interest in or to the Source Code, or any portion of the Source
|
||||||
|
Code. You may dispose of your own software in your sole discretion.
|
||||||
|
With the exception of the Educational Use right, you may not
|
||||||
|
otherwise use the Software, or an portion of the Software, which
|
||||||
|
includes the Source Code, for commercial gain.
|
||||||
|
|
||||||
|
3. Prohibited Uses: Under no circumstances shall you, the
|
||||||
|
end-user, be permitted, allowed or authorized to commercially exploit
|
||||||
|
the Software. Neither you nor anyone at your direction shall do any
|
||||||
|
of the following acts with regard to the Software, or any portion
|
||||||
|
thereof:
|
||||||
|
|
||||||
|
Rent;
|
||||||
|
|
||||||
|
Sell;
|
||||||
|
|
||||||
|
Lease;
|
||||||
|
|
||||||
|
Offer on a pay-per-play basis;
|
||||||
|
|
||||||
|
Distribute for money or any other consideration; or
|
||||||
|
|
||||||
|
In any other manner and through any medium whatsoever
|
||||||
|
commercially exploit or use for any commercial purpose.
|
||||||
|
|
||||||
|
Notwithstanding the foregoing prohibitions, you may commercially
|
||||||
|
exploit the software you develop by exercising the Educational Use
|
||||||
|
right, referenced in paragraph 2. hereinabove.
|
||||||
|
|
||||||
|
4. Copyright. The Software and all copyrights related thereto
|
||||||
|
(including all characters and other images generated by the Software
|
||||||
|
or depicted in the Software) are owned by ID and is protected by
|
||||||
|
United States copyright laws and international treaty provisions.
|
||||||
|
Id shall retain exclusive ownership and copyright in and to the
|
||||||
|
Software and all portions of the Software and you shall have no
|
||||||
|
ownership or other proprietary interest in such materials. You must
|
||||||
|
treat the Software like any other copyrighted material. You may not
|
||||||
|
otherwise reproduce, copy or disclose to others, in whole or in any
|
||||||
|
part, the Software. You may not copy the written materials
|
||||||
|
accompanying the Software. You agree to use your best efforts to
|
||||||
|
see that any user of the Software licensed hereunder complies with
|
||||||
|
this Agreement.
|
||||||
|
|
||||||
|
5. NO WARRANTIES. ID DISCLAIMS ALL WARRANTIES, BOTH EXPRESS
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE WITH RESPECT
|
||||||
|
TO THE SOFTWARE. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
|
||||||
|
RIGHTS. YOU MAY HAVE OTHER RIGHTS WHICH VARY FROM JURISDICTION TO
|
||||||
|
JURISDICTION. ID DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE
|
||||||
|
WILL BE UNINTERRUPTED, ERROR FREE OR MEET YOUR SPECIFIC REQUIREMENTS.
|
||||||
|
THE WARRANTY SET FORTH ABOVE IS IN LIEU OF ALL OTHER EXPRESS
|
||||||
|
WARRANTIES WHETHER ORAL OR WRITTEN. THE AGENTS, EMPLOYEES,
|
||||||
|
DISTRIBUTORS, AND DEALERS OF ID ARE NOT AUTHORIZED TO MAKE
|
||||||
|
MODIFICATIONS TO THIS WARRANTY, OR ADDITIONAL WARRANTIES ON BEHALF
|
||||||
|
OF ID.
|
||||||
|
|
||||||
|
Exclusive Remedies. The Software is being offered to you
|
||||||
|
free of any charge. You agree that you have no remedy against ID, its
|
||||||
|
affiliates, contractors, suppliers, and agents for loss or damage
|
||||||
|
caused by any defect or failure in the Software regardless of the form
|
||||||
|
of action, whether in contract, tort, includinegligence, strict
|
||||||
|
liability or otherwise, with regard to the Software. This Agreement
|
||||||
|
shall be construed in accordance with and governed by the laws of the
|
||||||
|
State of Texas. Copyright and other proprietary matters will be
|
||||||
|
governed by United States laws and international treaties. IN ANY
|
||||||
|
CASE, ID SHALL NOT BE LIABLE FOR LOSS OF DATA, LOSS OF PROFITS, LOST
|
||||||
|
SAVINGS, SPECIAL, INCIDENTAL, CONSEQUENTIAL, INDIRECT OR OTHER
|
||||||
|
SIMILAR DAMAGES ARISING FROM BREACH OF WARRANTY, BREACH OF CONTRACT,
|
||||||
|
NEGLIGENCE, OR OTHER LEGAL THEORY EVEN IF ID OR ITS AGENT HAS BEEN
|
||||||
|
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY
|
||||||
|
OTHER PARTY. Some jurisdictions do not allow the exclusion or
|
||||||
|
limitation of incidental or consequential damages, so the above
|
||||||
|
limitation or exclusion may not apply to you.
|