├── .gitattributes ├── .github └── workflows │ ├── linux.yml │ └── windows.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── binary ├── ThreadPool │ ├── COPYING │ ├── README.md │ ├── ThreadPool.h │ └── example.cpp ├── gwater2_install.bat ├── premake5.lua └── src │ ├── cuda │ └── libcudart_static.a │ ├── flex_mesh.cpp │ ├── flex_mesh.h │ ├── flex_renderer.cpp │ ├── flex_renderer.h │ ├── flex_solver.cpp │ ├── flex_solver.h │ ├── main.cpp │ ├── shader_inject.h │ ├── shaders │ ├── GWaterFinalpass.h │ ├── GWaterNormals.h │ ├── GWaterSmooth.h │ ├── GWaterVolumetric.h │ ├── hlsl │ │ ├── GWaterFinalpass_ps30.hlsl │ │ ├── GWaterFinalpass_vs30.hlsl │ │ ├── GWaterNormals_ps30.hlsl │ │ ├── GWaterNormals_vs30.hlsl │ │ ├── GWaterSmooth_ps30.hlsl │ │ ├── GWaterVolumetric_ps30.hlsl │ │ └── GWaterVolumetric_vs30.hlsl │ ├── inc │ │ ├── GWaterFinalpass_ps30.inc │ │ ├── GWaterFinalpass_vs30.inc │ │ ├── GWaterNormals_ps30.inc │ │ ├── GWaterNormals_vs30.inc │ │ ├── GWaterSmooth_ps30.inc │ │ ├── GWaterVolumetric_ps30.inc │ │ └── GWaterVolumetric_vs30.inc │ └── vcs │ │ ├── GWaterFinalpass_ps30.vcs │ │ ├── GWaterFinalpass_vs30.vcs │ │ ├── GWaterNormals_ps30.vcs │ │ ├── GWaterNormals_vs30.vcs │ │ ├── GWaterSmooth_ps30.vcs │ │ ├── GWaterVolumetric_ps30.vcs │ │ └── GWaterVolumetric_vs30.vcs │ └── sourceengine │ ├── BaseShader.cpp │ ├── BaseVSShader.h │ ├── IShaderSystem.h │ ├── cpp_shader_constant_register_map.h │ ├── imaterialsysteminternal.h │ ├── materialsystem_global.cpp │ ├── materialsystem_global.h │ ├── meshutils.cpp │ ├── meshutils.h │ ├── shaderDLL_Global.h │ ├── shader_constant_register_map.h │ └── shadersystem.h ├── data_static └── gwater2 │ ├── locale │ ├── gwater2_bg.txt │ ├── gwater2_en.txt │ ├── gwater2_es-ES.txt │ ├── gwater2_fr.txt │ ├── gwater2_hu.txt │ ├── gwater2_pl.txt │ ├── gwater2_pt-BR.txt │ ├── gwater2_ru.txt │ ├── gwater2_tr.txt │ ├── gwater2_uk.txt │ ├── gwater2_zh-CN.txt │ └── gwater2_zh-TW.txt │ └── patrons.txt ├── lua ├── autorun │ ├── gwater2_init.lua │ └── gwater2_menufix.lua ├── entities │ ├── gwater2_blackhole.lua │ ├── gwater2_bluetooth_hose.lua │ ├── gwater2_cleanup.lua │ ├── gwater2_cloth.lua │ ├── gwater2_cube.lua │ ├── gwater2_drain.lua │ ├── gwater2_emitter.lua │ ├── gwater2_forcefield.lua │ ├── gwater2_mentoscola.lua │ ├── gwater2_pickup.lua │ ├── gwater2_rain_emitter.lua │ ├── gwater2_showerhead.lua │ ├── gwater2_sphere.lua │ ├── gwater2_transmuter.lua │ ├── gwater2_transporter_recv.lua │ └── gwater2_transporter_send.lua ├── gwater2_interactions.lua ├── gwater2_menu.lua ├── gwater2_net.lua ├── gwater2_shaders.lua ├── menu │ ├── gwater2_params.lua │ ├── gwater2_paramstabs.lua │ ├── gwater2_presets.lua │ ├── gwater2_styling.lua │ └── gwater2_util.lua ├── starfall │ └── libs_cl │ │ └── gwater2module.lua └── weapons │ ├── gmod_tool │ └── stools │ │ └── gwater2_transmuter.lua │ ├── weapon_gw2_advwatergun.lua │ ├── weapon_gw2_partseas.lua │ └── weapon_gw2_watergun.lua ├── materials ├── entities │ ├── gwater2_blackhole.png │ ├── gwater2_bluetooth_hose.png │ ├── gwater2_cleanup.png │ ├── gwater2_cloth_200.png │ ├── gwater2_cloth_50.png │ ├── gwater2_cube_10.png │ ├── gwater2_cube_20.png │ ├── gwater2_cube_5.png │ ├── gwater2_drain.png │ ├── gwater2_emitter.png │ ├── gwater2_forcefield.png │ ├── gwater2_mentoscola.png │ ├── gwater2_rain_emitter.png │ ├── gwater2_showerhead.png │ ├── gwater2_sphere_10.png │ ├── gwater2_sphere_20.png │ ├── gwater2_sphere_5.png │ ├── gwater2_transmuter.png │ ├── gwater2_transporter_recv.png │ ├── weapon_gw2_advwatergun.png │ ├── weapon_gw2_partseas.png │ ├── weapon_gw2_watergun.png │ ├── weapon_gw2_watergun_icon.vmt │ └── weapon_gw2_watergun_icon.vtf └── gwater2 │ ├── black.vmt │ ├── blackhole.vmt │ ├── bubble.vmt │ ├── bubble.vtf │ ├── cloth.vmt │ ├── clouds.vmt │ ├── clouds.vtf │ ├── finalpass.vmt │ ├── mist.vmt │ ├── normals.vmt │ ├── smooth.vmt │ ├── sphere.vtf │ ├── splash.vtf │ ├── volumetric.vmt │ ├── water_gun │ ├── base.vmt │ ├── handle.vmt │ ├── nozzle.vmt │ ├── pipe.vmt │ ├── screw.vmt │ ├── strut.vmt │ └── tank.vmt │ └── whitehole.vmt ├── models └── gwater2 │ ├── water_gun.dx80.vtx │ ├── water_gun.dx90.vtx │ ├── water_gun.mdl │ └── water_gun.vvd ├── resource └── fonts │ ├── RobotoMonoVariable.ttf │ ├── RobotoVariable.ttf │ ├── SpaceMonoRegular.ttf │ ├── TitilliumWeb-Regular.ttf │ └── coolvetica.ttf └── sound └── gwater2 ├── menu ├── confirm.wav ├── reset.wav ├── rollover.wav ├── select.wav ├── select_deny.wav ├── select_ok.wav └── toggle.wav ├── paint_loop.wav ├── soda_launch.wav └── water_loop.wav /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: linux 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | submodules: recursive 18 | 19 | - name: compile or somthing idk 20 | run: | 21 | cd binary 22 | curl https://github.com/premake/premake-core/releases/download/v5.0.0-beta3/premake-5.0.0-beta3-linux.tar.gz -O -J -L 23 | tar -xvzf premake-5.0.0-beta3-linux.tar.gz 24 | sudo chmod +x ./premake5 25 | ./premake5 gmake 26 | make config=release_x86_64 27 | 28 | - name: Upload artifact 29 | uses: actions/upload-artifact@v4.3.1 30 | with: 31 | name: gmcl_gwater2_linux64.dll 32 | path: binary/x86_64/Release/gmcl_gwater2_linux64.dll 33 | if-no-files-found: error 34 | 35 | -------------------------------------------------------------------------------- /.github/workflows/windows.yml: -------------------------------------------------------------------------------- 1 | name: windows 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | pull_request: 7 | branches: [ "main" ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: windows-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | submodules: recursive 18 | 19 | - name: Get premake5 20 | run: | 21 | cd binary 22 | curl https://github.com/premake/premake-core/releases/download/v5.0.0-beta2/premake-5.0.0-beta2-windows.zip -O -J -L 23 | 7z x premake-5.0.0-beta2-windows.zip 24 | dir 25 | ./premake5.exe vs2019 26 | 27 | - name: Add msbuild to PATH 28 | uses: microsoft/setup-msbuild@v2 29 | with: 30 | msbuild-architecture: 'x64' 31 | 32 | - name: Build app for release 33 | run: msbuild D:\a\gwater2\gwater2\binary\gmcl_gwater2.vcxproj -t:rebuild -verbosity:diag -property:Configuration=Release -p:platform=x64 34 | 35 | - name: Check if it compiled successfully 36 | run: | 37 | cd D:\a\gwater2\gwater2\binary\ 38 | dir 39 | - name: Upload artifact 40 | uses: actions/upload-artifact@v4.3.1 41 | with: 42 | name: gmcl_gwater2_win64.dll 43 | path: D:\a\gwater2\gwater2\binary\x86_64\Release\gmcl_gwater2_win64.dll 44 | if-no-files-found: error 45 | 46 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | /binary/x86 3 | /binary/x86_64 4 | *.vcxproj* 5 | *.sln 6 | /binary/openssl 7 | 8 | # premake stuff (WINDOWS) 9 | /binary/premake5.exe 10 | /binary/premake5.pdb 11 | /binary/luasocket.dll 12 | /binary/luasocket.lib 13 | /binary/luasocket.exp 14 | /binary/luasocket.pdb 15 | /binary/example.dll 16 | /binary/example.lib 17 | /binary/example.exp 18 | /binary/example.pdb 19 | 20 | # premake stuff (LINUX) 21 | /binary/Makefile 22 | /binary/premake5 23 | /binary/gmcl_gwater2.make 24 | /binary/garrysmod_common/projects/linux/gmake/helpers.make 25 | /binary/garrysmod_common/projects/linux/gmake/lua_shared.make 26 | /binary/garrysmod_common/scanning/projects/linux/gmake/Makefile 27 | /binary/garrysmod_common/sourcesdk-minimal/projects/linux/gmake/tier1.make 28 | /binary/garrysmod_common/sourcesdk-minimal/projects/linux/gmake/LZMA.make 29 | /binary/garrysmod_common/sourcesdk-minimal/projects/linux/gmake/mathlib.make 30 | 31 | # gmod_require require module 32 | /lua/includes/modules/require.lua 33 | .vscode/settings.json 34 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "binary/FleX"] 2 | path = binary/FleX 3 | url = https://github.com/NVIDIAGameWorks/FleX 4 | [submodule "binary/GMFS"] 5 | path = binary/GMFS 6 | url = https://github.com/Derpius/GMFS 7 | [submodule "binary/garrysmod_common"] 8 | path = binary/garrysmod_common 9 | url = https://github.com/danielga/garrysmod_common 10 | [submodule "binary/BSPParser"] 11 | path = binary/BSPParser 12 | url = https://github.com/Derpius/BSPParser 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GWater2 [![made with - mee++](https://img.shields.io/badge/made_with-mee%2B%2B-2ea44f)](https://github.com/meetric1/gwater2) 2 | ![waterflowing](https://github.com/user-attachments/assets/80888b54-62a9-47fa-9ca1-fae9a6ae453f) 3 | 4 | **GWater2** Is a fluid simulation mod for Garry's Mod. It adds the ability to spawn and create a multitude of different liquids that flow in real time.\ 5 | Due to the complex nature of simulating and rendering fluid dynamics, the backend of this mod requires a binary module. 6 | 7 | # Table of Contents 8 | - [Overview](#gwater2) 9 | - [Features](#features) 10 | - [Requirements](#requirements) 11 | - [Installation](#installation) 12 | - [Compilation](#compilation) 13 | - [Credits](#credits) 14 | - [Translating](#translating) 15 | - [Extras](#extras) 16 | 17 | # Features 18 | **GWater2** comes with a bunch of SWEPs and Entities to mess with, and a menu to change fluid behavior.\ 19 | Multiplayer is supported, and menu options (fluid parameters) are synced. 20 | 21 | Features include: 22 | - The fastest fluid rendering achieved inside sourceengine 23 | - Reaction Forces (Water can force objects around) 24 | - Swimming / player interactions with liquids 25 | - Liquid sounds 26 | - Foam & bubble particles 27 | - Multiplayer support 28 | - Spawnable dynamic cloth 29 | - Custom menu (default key = G), with: 30 | - Multiplayer syncing 31 | - Lots of options and settings to mess with 32 | - Preset saving 33 | - Language localization support 34 | - Custom SWEPs, including: 35 | - Water gun, modeled by me 36 | - Part the seas, now you can roleplay as moses! 37 | - Advanced water gun (courtesy of googer_) 38 | - Custom SENTs, including: 39 | - Black hole (forcefield variant) 40 | - Bluetooth hose 41 | - Spawnable liquid cubes, spheres and cloth 42 | - Drain (removes water) 43 | - Emitter (creates water) 44 | - Forcefield (forces water around) 45 | - Mentos with cola (from GWater1) 46 | - Rain Emitter (minature rainclouds) 47 | - Shower head (smaller emitter) 48 | - Transmuter (turns entities into water) 49 | - Transporter (linked drain and emitter) 50 | 51 | # Requirements 52 | > [!IMPORTANT] 53 | > In order to run **GWater2** you MUST have a DirectX11 capable graphics card 54 | 55 | A capable card must have:\ 56 | `Nvidia Driver version 396.45` (or higher)\ 57 | OR\ 58 | `AMD Software version 16.9.1` (or higher)\ 59 | OR\ 60 | `Intel® Graphics version 15.33.43.4425` (or higher) 61 | 62 | If this is all gibberish to you, essentially any graphics card manufactured later than 2012 will work just fine. 63 | 64 | ### Supported systems 65 | ✅ = Fully Supported\ 66 | ⚠️ = Half Supported (Must be ran under proton)\ 67 | ❌ = Not supported\ 68 | ❔ = Untested 69 | 70 | | OS | GMod Branch | GPU | Supported | 71 | | --- | --- | --- | --- | 72 | | Windows | Any | Nvidia | ✅ | 73 | | Windows | Any | AMD | ✅ | 74 | | Windows | Any | Intel | ✅ | 75 | | Linux | Any | Nvidia | ⚠️ | 76 | | Linux | Any | AMD | ⚠️ | 77 | | Linux | Any | Intel | ❔ | 78 | | MacOS | Any | Mac | ❔ | 79 | 80 | # Installation 81 | 82 | ### For Normal Users: 83 | 1. Go to the [releases tab](https://github.com/meetric1/gwater2/releases) and read the instructions 84 | 85 | ### For Developers: 86 | 1. cd to `GarrysMod/garrysmod/addons/` 87 | 2. run `git clone https://github.com/meetric1/gwater2` in a terminal. 88 | 3. Unsubscribe to the workshop version if you have it installed 89 | 4. If you wish to work on the C++, make sure to clone recursively. See [Compilation](#compilation) for more info 90 | 91 | 99 | 100 | # Compilation 101 | 102 | ### Module compilation 103 | This repository is set up with a [github actions](https://github.com/meetric1/gwater2/actions), which automatically compiles new modules for you.\ 104 | Feel free to download new module versions from there. 105 | 106 | Compiled modules should go in `GarrysMod/garrysmod/lua/bin`. 107 | 108 | > [!WARNING] 109 | > This repo is quite large (upwards of 1 gb), as it includes some submodules needed for compilation 110 | 111 | > [!WARNING] 112 | > Extremely new versions of visual studio may cause errors during compilation. This can be fixed by manually altering the gmcommon source code or by using vs2019 113 | 114 | If you wish to compile it yourself, simply follow these steps. 115 | 1. *Recursively* clone this repository into your desired folder. 116 | - Example command: `git clone https://github.com/meetric1/gwater2 --recursive` 117 | 2. Download [premake5](https://premake.github.io/download) 118 | - If you are on Windows, add the executable to PATH or copy it into this repositories `binary` directory 119 | - If copied correctly, premake5.exe should be in the same folder as premake5.lua 120 | - On Linux, you should just be able to install it via your package manager. If that doesn't work, just download it directly, chmod the executable, and place it into `binary` 121 | 3. CD into the repositories `binary` directory and run `premake5` with your desired build system. 122 | - I use Visual Studio 2022, so I would do `premake5 vs2022` 123 | - Linux users would do `./premake5 gmake` 124 | - [List of supported build systems](https://premake.github.io/docs/Using-Premake#using-premake-to-generate-project-files) 125 | - I am honestly unsure how new your build system needs to be. I'd personally just make sure to use vs2015 or later 126 | 4. Now, build the project like normal. 127 | - On Windows, open the .sln file, go to the top taskbar, Build -> Build Solution 128 | - On Linux, run `make config=release_x86_64` 129 | 130 | > [!TIP] 131 | > If you need help with compiling, feel free to look at the github workflow source code 132 | 133 | > [!NOTE] 134 | > By default, this repo builds for the x86-64 branch of GMod. If you wish to compile for the main branch, you will need to remove the gmcommon submodule and *recursively* re-clone the main branch version, found [here](https://github.com/danielga/garrysmod_common).\ 135 | > After that, you will need to add a preprocessor definition, `GMOD_MAIN`. This can be done in visual studio by going to the project properties -> Preprocessor -> Preprocessor Definitions 136 | 137 | >[!NOTE] 138 | > Linux builds end in `.dll` __THIS IS INTENTIONAL!__ Blame Garry for the weird syntax 139 | 140 | > [!CAUTION] 141 | > Although Linux builds successfully, it throws errors during runtime, which I do not know how to fix. (pls help)\ 142 | > See https://github.com/meetric1/gwater2/issues/1 for more information 143 | 144 | ### Shader compilation 145 | Custom shaders were created in HLSL, and compiled using [ShaderCompile](https://github.com/SCell555/ShaderCompile).\ 146 | Documentation on how to compile them can be found here: https://developer.valvesoftware.com/wiki/Shader_Authoring 147 | 148 | You could also potentially compile them via this repo: https://github.com/ficool2/sdk_screenspace_shaders 149 | 150 | # Credits 151 | ``` 152 | Meetric | Main Developer 153 | googer | Menu rewrite, adv water gun, Wiremod support, Transporter 154 | jn | Water-player interactions, Forcefield entity 155 | Xenthio | Diffuse and lighting improvements, VVIS culling 156 | MyUsername | Linux help 157 | Kegan | Github actions / Linux help 158 | Stickrpg | Reaction force sigs 159 | Mikey | StarfallEx API 160 | Joka | Water gun icon 161 | Spanky | Particle stretching code 162 | PotatoOS | Quaternion math 163 | AndrewEathan | GWater1 entities 164 | Kodya | Swimming code 165 | Patrons | Generously supporting my work :) 166 | Nvidia | FleX Particle Library 167 | ``` 168 | 169 | # Translating 170 | The **GWater2** menu supports language localization.\ 171 | If you wish to translate the menu into your native language, clone (or download) this repo, and go to `data_static/gwater2/locale/`\ 172 | Find out your language id by going [here](https://wiki.facepunch.com/gmod/Addon_Localization#supportedlanguages)\ 173 | Then, copy `gwater2_en.txt`, and rename it (for example, Spanish would be `gwater2_es-ES.txt`) and start translating.\ 174 | Once done, make a PR here, or make a discussion on the steam page, or DM me on [discord](https://discord.gg/xWvhfargMY) 175 | 176 | **Please refrain from using ChatGPT for translations, as it usually messes up sentence inflection** 177 | 178 | Thanks to these people for translating the menu into their native language. 179 | ``` 180 | Gandzhalex | Russian 181 | Zeetric | Russian 182 | googer_ | Russian 183 | pigeondriver45 | Turkish 184 | Cast_E | Brazilian Portuguese 185 | SCRENG R | Spanish 186 | DarkSM | Hungarian 187 | ErickMaksimets | Ukrainian 188 | Hexak12 | Polish 189 | TheOnly8Z | Simplified Chinese 190 | GoranRayman | French 191 | Limule | French 192 | dvdvideo | Bulgarian 193 | FengHo | Traditional Chinese 194 | ``` 195 | 196 | # Extras 197 | Please consider checking out [Gelly](https://github.com/gelly-gmod/gelly), another GMod fluid addon made in parallel alongside **GWater2** 198 | -------------------------------------------------------------------------------- /binary/ThreadPool/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jakob Progsch, Václav Zeman 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source 20 | distribution. 21 | -------------------------------------------------------------------------------- /binary/ThreadPool/README.md: -------------------------------------------------------------------------------- 1 | ThreadPool 2 | ========== 3 | 4 | A simple C++11 Thread Pool implementation. 5 | 6 | Basic usage: 7 | ```c++ 8 | // create thread pool with 4 worker threads 9 | ThreadPool pool(4); 10 | 11 | // enqueue and store future 12 | auto result = pool.enqueue([](int answer) { return answer; }, 42); 13 | 14 | // get result from future 15 | std::cout << result.get() << std::endl; 16 | 17 | ``` 18 | -------------------------------------------------------------------------------- /binary/ThreadPool/ThreadPool.h: -------------------------------------------------------------------------------- 1 | #ifndef THREAD_POOL_H 2 | #define THREAD_POOL_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | class ThreadPool { 15 | public: 16 | ThreadPool(size_t); 17 | template 18 | auto enqueue(F&& f, Args&&... args) 19 | -> std::future::type>; 20 | ~ThreadPool(); 21 | private: 22 | // need to keep track of threads so we can join them 23 | std::vector< std::thread > workers; 24 | // the task queue 25 | std::queue< std::function > tasks; 26 | 27 | // synchronization 28 | std::mutex queue_mutex; 29 | std::condition_variable condition; 30 | bool stop; 31 | }; 32 | 33 | // the constructor just launches some amount of workers 34 | inline ThreadPool::ThreadPool(size_t threads) 35 | : stop(false) 36 | { 37 | for(size_t i = 0;i task; 44 | 45 | { 46 | std::unique_lock lock(this->queue_mutex); 47 | this->condition.wait(lock, 48 | [this]{ return this->stop || !this->tasks.empty(); }); 49 | if(this->stop && this->tasks.empty()) 50 | return; 51 | task = std::move(this->tasks.front()); 52 | this->tasks.pop(); 53 | } 54 | 55 | task(); 56 | } 57 | } 58 | ); 59 | } 60 | 61 | // add new work item to the pool 62 | template 63 | auto ThreadPool::enqueue(F&& f, Args&&... args) 64 | -> std::future::type> 65 | { 66 | using return_type = typename std::result_of::type; 67 | 68 | auto task = std::make_shared< std::packaged_task >( 69 | std::bind(std::forward(f), std::forward(args)...) 70 | ); 71 | 72 | std::future res = task->get_future(); 73 | { 74 | std::unique_lock lock(queue_mutex); 75 | 76 | // don't allow enqueueing after stopping the pool 77 | if(stop) 78 | throw std::runtime_error("enqueue on stopped ThreadPool"); 79 | 80 | tasks.emplace([task](){ (*task)(); }); 81 | } 82 | condition.notify_one(); 83 | return res; 84 | } 85 | 86 | // the destructor joins all threads 87 | inline ThreadPool::~ThreadPool() 88 | { 89 | { 90 | std::unique_lock lock(queue_mutex); 91 | stop = true; 92 | } 93 | condition.notify_all(); 94 | for(std::thread &worker: workers) 95 | worker.join(); 96 | } 97 | 98 | #endif 99 | -------------------------------------------------------------------------------- /binary/ThreadPool/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "ThreadPool.h" 6 | 7 | int main() 8 | { 9 | 10 | ThreadPool pool(4); 11 | std::vector< std::future > results; 12 | 13 | for(int i = 0; i < 8; ++i) { 14 | results.emplace_back( 15 | pool.enqueue([i] { 16 | std::cout << "hello " << i << std::endl; 17 | std::this_thread::sleep_for(std::chrono::seconds(1)); 18 | std::cout << "world " << i << std::endl; 19 | return i*i; 20 | }) 21 | ); 22 | } 23 | 24 | for(auto && result: results) 25 | std::cout << result.get() << ' '; 26 | std::cout << std::endl; 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /binary/gwater2_install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | SETLOCAL EnableDelayedExpansion 3 | title GWater2 Installer 4 | 5 | FOR /F "tokens=*" %%a in ('powershell -command $PSVersionTable.PSVersion.Major 2^>nul') do set powershell_version=%%a 6 | if defined powershell_version if !powershell_version! geq 4 GOTO prompt 7 | echo This script requires Windows PowerShell 4.0+ (included in Windows 8.1 and later) 8 | pause & exit 9 | 10 | :prompt 11 | cls 12 | FOR /F "tokens=2* skip=2" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Valve\Steam" /v "InstallPath" 2^>nul') do set steam_dir=%%b 13 | FOR /F "tokens=2* skip=2" %%a in ('reg query "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Valve\Steam" /v "InstallPath" 2^>nul') do set steam_dir=%%b 14 | if not defined steam_dir ( 15 | echo "Steam installation path not found. Please get gwater2 manually by downloading the .zip" 16 | pause 17 | exit 18 | ) 19 | if exist "%steam_dir%\steamapps\appmanifest_4000.acf" set "gmod_dir=%steam_dir%\steamapps\common\GarrysMod" 20 | for /f "usebackq tokens=2 skip=4" %%A in ("%steam_dir%\steamapps\libraryfolders.vdf") do ( 21 | if exist "%%~A\steamapps\appmanifest_4000.acf" set "gmod_dir=%%~A\steamapps\common\GarrysMod" 22 | ) 23 | if not defined gmod_dir ( 24 | echo "GMod installation path not found. Please get gwater2 manually by downloading the .zip" 25 | pause 26 | exit 27 | ) 28 | 29 | echo Detected Directory: %gmod_dir% 30 | echo Make sure to close GMod before running the installer. 31 | echo. 32 | 33 | echo Select an option (Type 1 or 2 and hit enter): 34 | echo 1) install 35 | echo 2) uninstall 36 | set /p choice="> " 37 | 38 | cls 39 | if %choice%==1 GOTO install 40 | if %choice%==2 GOTO uninstall 41 | echo Invalid option. Valid options are: 1, 2 42 | pause 43 | goto prompt 44 | 45 | :install 46 | pushd %gmod_dir% 47 | echo Downloading gwater2... 48 | powershell -command [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest 'https://github.com/meetric1/gwater2/releases/download/v1.0/gwater2_1.0.zip' -Out gwater2.zip 49 | 50 | if not exist gwater2.zip ( 51 | echo Download failed, Invalid Link 52 | pause 53 | exit 54 | ) 55 | 56 | echo Decompressing... 57 | powershell -command Expand-Archive gwater2.zip -Force 58 | echo Installing... 59 | rmdir ".\garrysmod\addons\gwater2" /s /q 60 | xcopy /e /y /q gwater2 . 61 | rmdir /s /q gwater2 62 | del gwater2.zip 63 | echo. 64 | echo Finished Install 65 | echo. 66 | pause 67 | exit 68 | 69 | :uninstall 70 | pushd %gmod_dir% 71 | echo Uninstalling... 72 | del ".\garrysmod\lua\bin\gmcl_gwater2_win32.dll" 73 | del ".\garrysmod\lua\bin\gmcl_gwater2_win64.dll" 74 | del ".\garrysmod\lua\bin\gmcl_gwater2_main_win32.dll" 75 | rmdir ".\garrysmod\addons\gwater2" /s /q 76 | del ".\garrysmod\shaders\fxc\GWaterFinalpass_ps30.vcs" 77 | del ".\garrysmod\shaders\fxc\GWaterFinalpass_vs30.vcs" 78 | del ".\garrysmod\shaders\fxc\GWaterNormals_ps30.vcs" 79 | del ".\garrysmod\shaders\fxc\GWaterNormals_vs30.vcs" 80 | del ".\garrysmod\shaders\fxc\GWaterSmooth_ps30.vcs" 81 | del ".\garrysmod\shaders\fxc\GWaterVolumetric_ps30.vcs" 82 | del ".\garrysmod\shaders\fxc\GWaterVolumetric_vs30.vcs" 83 | del ".\amd_ags_x64.dll" 84 | del ".\amd_ags_x86.dll" 85 | del ".\GFSDK_Aftermath_Lib.x64.dll" 86 | del ".\GFSDK_Aftermath_Lib.x86.dll" 87 | del ".\NvFlexExtReleaseD3D_x64.dll" 88 | del ".\NvFlexExtReleaseD3D_x86.dll" 89 | del ".\NvFlexReleaseD3D_x64.dll" 90 | del ".\NvFlexReleaseD3D_x86.dll" 91 | del ".\nvToolsExt32_1.dll" 92 | del ".\nvToolsExt64_1.dll" 93 | 94 | echo Finished Uninstall 95 | pause 96 | -------------------------------------------------------------------------------- /binary/premake5.lua: -------------------------------------------------------------------------------- 1 | PROJECT_GENERATOR_VERSION = 3 -- 3 = 64 bit support 2 | 3 | newoption({ 4 | trigger = "gmcommon", 5 | description = "Sets the path to the garrysmod_common (https://github.com/danielga/garrysmod_common) directory", 6 | value = "./garrysmod_common", 7 | default = "./garrysmod_common" 8 | }) 9 | 10 | local gmcommon = assert(_OPTIONS.gmcommon or os.getenv("GARRYSMOD_COMMON"), 11 | "you didn't provide a path to your garrysmod_common (https://github.com/danielga/garrysmod_common) directory") 12 | 13 | include(gmcommon) 14 | 15 | CreateWorkspace({name = "gwater2", abi_compatible = true, path = ""}) 16 | --CreateProject({serverside = true, source_path = "source", manual_files = false}) 17 | -- IncludeLuaShared() 18 | -- IncludeScanning() 19 | -- IncludeDetouring() 20 | -- IncludeSDKCommon() 21 | -- IncludeSDKTier0() 22 | -- IncludeSDKTier1() 23 | 24 | CreateProject({serverside = false, source_path = "src"}) 25 | IncludeLuaShared() 26 | IncludeScanning() 27 | --IncludeDetouring() 28 | --IncludeSteamAPI() 29 | IncludeSDKCommon() 30 | IncludeSDKTier0() 31 | IncludeSDKTier1() 32 | IncludeSDKMathlib() 33 | 34 | includedirs { 35 | "FleX/include", 36 | "BSPParser", 37 | "GMFS", 38 | "src/sourceengine", 39 | "ThreadPool" 40 | } 41 | 42 | files { 43 | "BSPParser/**", 44 | "GMFS/**", 45 | "src/sourceengine/*", 46 | "src/shaders/*" 47 | } 48 | 49 | filter({"system:windows", "platforms:x86"}) 50 | targetsuffix("_win32") 51 | 52 | libdirs { 53 | "FleX/lib/win32", 54 | } 55 | 56 | links { 57 | "NvFlexReleaseD3D_x86", 58 | "NvFlexExtReleaseD3D_x86", 59 | } 60 | 61 | filter({"system:windows", "platforms:x86_64"}) 62 | targetsuffix("_win64") 63 | 64 | libdirs { 65 | "FleX/lib/win64", 66 | } 67 | 68 | links { 69 | "NvFlexReleaseD3D_x64", 70 | "NvFlexExtReleaseD3D_x64", 71 | } 72 | 73 | filter({"system:linux", "platforms:x86_64"}) 74 | targetsuffix("_linux64") 75 | 76 | includedirs { 77 | --"/usr/local/cuda-9.2/include", 78 | --"/usr/local/cuda-9.2/extras/cupti/include", 79 | } 80 | 81 | libdirs { 82 | "FleX/lib/linux64", 83 | --"/usr/local/cuda-9.2/lib64" 84 | "src/cuda" 85 | } 86 | 87 | links { 88 | ":NvFlexReleaseCUDA_x64.a", 89 | ":NvFlexExtReleaseCUDA_x64.a", 90 | --":NvFlexDebugCUDA_x64.a", 91 | --":NvFlexDeviceDebug_x64.a", 92 | --":NvFlexExtDebugCUDA_x64.a", 93 | "cudart_static", 94 | } 95 | 96 | defines { 97 | "DX_TO_GL_ABSTRACTION", 98 | "IsPlatformOpenGL()" 99 | } 100 | -------------------------------------------------------------------------------- /binary/src/cuda/libcudart_static.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/cuda/libcudart_static.a -------------------------------------------------------------------------------- /binary/src/flex_mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "flex_mesh.h" 2 | 3 | float rad(float degree) { 4 | return (degree * (M_PI / 180)); 5 | } 6 | 7 | // provided by PotatoOS 8 | inline Vector4D unfuckQuat(Vector4D q) { 9 | return Vector4D(q.y, q.z, q.w, q.x); 10 | } 11 | 12 | // Angle to Quat conversion provided by Wikipidia (https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles) 13 | Vector4D angle_to_quat(QAngle ang) { 14 | float p = rad(ang.x) / 2.0; 15 | float y = rad(ang.y) / 2.0; 16 | float r = rad(ang.z) / 2.0; 17 | float cr = cos(r); 18 | float sr = sin(r); 19 | float cp = cos(p); 20 | float sp = sin(p); 21 | float cy = cos(y); 22 | float sy = sin(y); 23 | 24 | return unfuckQuat(Vector4D( 25 | cr * cp * cy + sr * sp * sy, 26 | sr * cp * cy - cr * sp * sy, 27 | cr * sp * cy + sr * cp * sy, 28 | cr * cp * sy - sr * sp * cy 29 | )); 30 | } 31 | 32 | void FlexMesh::destroy() { 33 | if (vertices != nullptr) { 34 | NvFlexFreeBuffer(vertices); 35 | if (indices == nullptr) { 36 | NvFlexDestroyConvexMesh(library, id); 37 | } else { // Convex meshes dont have an indices buffer, so the mesh must be concave 38 | NvFlexFreeBuffer(indices); 39 | NvFlexDestroyTriangleMesh(library, id); 40 | } 41 | } 42 | } 43 | 44 | 45 | bool FlexMesh::init_convex(std::vector verts, bool dynamic) { 46 | if (library == nullptr) return false; 47 | 48 | destroy(); 49 | 50 | // Is Mesh invalid? 51 | if (verts.size() == 0 || verts.size() % 3 != 0) { 52 | return false; 53 | } 54 | 55 | // Allocate buffers 56 | vertices = NvFlexAllocBuffer(library, verts.size() / 3, sizeof(Vector4D), eNvFlexBufferHost); 57 | Vector4D* host_verts = (Vector4D*)NvFlexMap(vertices, eNvFlexMapWait); 58 | 59 | // Find OBB Bounding box automatically during parsing 60 | Vector min = verts[0]; 61 | Vector max = verts[0]; 62 | for (int i = 0; i < verts.size(); i += 3) { 63 | Vector tri[3] = { verts[i], verts[i + 1], verts[i + 2] }; 64 | 65 | // Turn triangle into normalized plane & add to vertex buffer 66 | Vector plane_dir = (tri[1] - tri[0]).Cross(tri[0] - tri[2]).Normalized(); 67 | float plane_height = -plane_dir.Dot(tri[0]); // Negative because our triangle winding is reversed 68 | host_verts[i / 3] = Vector4D(plane_dir.x, plane_dir.y, plane_dir.z, plane_height); 69 | 70 | min = min.Min(tri[0]); 71 | min = min.Min(tri[1]); 72 | min = min.Min(tri[2]); 73 | 74 | max = max.Max(tri[0]); 75 | max = max.Max(tri[1]); 76 | max = max.Max(tri[2]); 77 | } 78 | 79 | NvFlexUnmap(vertices); 80 | 81 | float lower[3] = { min.x, min.y, min.z }; 82 | float upper[3] = { max.x, max.y, max.z }; 83 | 84 | id = NvFlexCreateConvexMesh(library); 85 | flags = NvFlexMakeShapeFlags(eNvFlexShapeConvexMesh, dynamic); 86 | NvFlexUpdateConvexMesh(library, id, vertices, verts.size() / 3, lower, upper); 87 | 88 | return true; 89 | } 90 | 91 | bool FlexMesh::init_concave(std::vector verts, bool dynamic) { 92 | if (library == nullptr) return false; 93 | 94 | destroy(); 95 | 96 | // Is Mesh invalid? 97 | if (verts.size() == 0 || verts.size() % 3 != 0) { 98 | return false; 99 | } 100 | 101 | // Allocate buffers 102 | vertices = NvFlexAllocBuffer(library, verts.size(), sizeof(Vector4D), eNvFlexBufferHost); 103 | indices = NvFlexAllocBuffer(library, verts.size(), sizeof(int), eNvFlexBufferHost); 104 | Vector4D* host_verts = (Vector4D*)NvFlexMap(vertices, eNvFlexMapWait); 105 | int* host_indices = (int*)NvFlexMap(indices, eNvFlexMapWait); 106 | 107 | // Find OBB Bounding box automatically during parsing 108 | Vector min = verts[0]; 109 | Vector max = verts[0]; 110 | for (int i = 0; i < verts.size(); i++) { 111 | host_verts[i] = Vector4D(verts[i].x, verts[i].y, verts[i].z, 0); 112 | 113 | // Flip triangle winding (xyz -> yxz) 114 | switch (i % 3) { 115 | case 0: 116 | host_indices[i] = i + 1; 117 | break; 118 | case 1: 119 | host_indices[i] = i - 1; 120 | break; 121 | case 2: 122 | host_indices[i] = i; 123 | break; 124 | } 125 | 126 | min = min.Min(verts[i]); 127 | max = max.Max(verts[i]); 128 | } 129 | NvFlexUnmap(vertices); 130 | NvFlexUnmap(indices); 131 | 132 | float lower[3] = { min.x, min.y, min.z }; 133 | float upper[3] = { max.x, max.y, max.z }; 134 | 135 | id = NvFlexCreateTriangleMesh(library); 136 | flags = NvFlexMakeShapeFlags(eNvFlexShapeTriangleMesh, dynamic); 137 | NvFlexUpdateTriangleMesh(library, id, vertices, indices, verts.size(), verts.size() / 3, lower, upper); 138 | 139 | return true; 140 | } 141 | 142 | // this overload is only used for map collision, as the BSP Parser returns an array instead of a vector 143 | bool FlexMesh::init_concave(Vector* verts, int num_verts, bool dynamic) { 144 | if (library == nullptr) return false; 145 | 146 | destroy(); 147 | 148 | // Is Mesh invalid? 149 | if (num_verts == 0 || num_verts % 3 != 0) { 150 | return false; 151 | } 152 | 153 | // Allocate buffers 154 | vertices = NvFlexAllocBuffer(library, num_verts, sizeof(Vector4D), eNvFlexBufferHost); 155 | indices = NvFlexAllocBuffer(library, num_verts, sizeof(int), eNvFlexBufferHost); 156 | Vector4D* host_verts = (Vector4D*)NvFlexMap(vertices, eNvFlexMapWait); 157 | int* host_indices = (int*)NvFlexMap(indices, eNvFlexMapWait); 158 | 159 | // Find OBB Bounding box automatically during parsing 160 | Vector min = verts[0]; 161 | Vector max = verts[0]; 162 | for (int i = 0; i < num_verts; i++) { 163 | host_verts[i] = Vector4D(verts[i].x, verts[i].y, verts[i].z, 0); 164 | host_indices[i] = i; 165 | 166 | min = min.Min(verts[i]); 167 | max = max.Max(verts[i]); 168 | } 169 | NvFlexUnmap(vertices); 170 | NvFlexUnmap(indices); 171 | 172 | float lower[3] = { min.x, min.y, min.z }; 173 | float upper[3] = { max.x, max.y, max.z }; 174 | 175 | id = NvFlexCreateTriangleMesh(library); 176 | flags = NvFlexMakeShapeFlags(eNvFlexShapeTriangleMesh, dynamic); 177 | NvFlexUpdateTriangleMesh(library, id, vertices, indices, num_verts, num_verts / 3, lower, upper); 178 | 179 | return true; 180 | } 181 | 182 | // sets the previous position/angle to current position/angle (previous_pos = pos; previous_ang = ang) 183 | void FlexMesh::update() { 184 | ppos = pos; 185 | pang = ang; 186 | } 187 | 188 | Vector4D FlexMesh::get_pos() { 189 | return pos; 190 | } 191 | 192 | void FlexMesh::set_pos(Vector p) { 193 | pos = Vector4D(p.x, p.y, p.z, 0); // unsure what the last number is for. FleX requires it to exist 194 | } 195 | 196 | void FlexMesh::set_pos(Vector4D p) { 197 | pos = p; 198 | } 199 | 200 | Vector4D FlexMesh::get_ang() { 201 | return ang; 202 | } 203 | 204 | Vector4D FlexMesh::get_ppos() { 205 | return ppos; 206 | } 207 | 208 | Vector4D FlexMesh::get_pang() { 209 | return pang; 210 | } 211 | 212 | void FlexMesh::set_ang(QAngle a) { 213 | ang = angle_to_quat(a); 214 | } 215 | 216 | void FlexMesh::set_ang(Vector4D a) { 217 | ang = a; 218 | } 219 | 220 | void FlexMesh::set_collide(bool collide) { 221 | if (collide) { 222 | flags |= eNvFlexPhaseShapeChannelMask; 223 | } else { 224 | flags &= ~eNvFlexPhaseShapeChannelMask; 225 | } 226 | } 227 | 228 | NvFlexTriangleMeshId FlexMesh::get_id() { 229 | return id; 230 | } 231 | 232 | int FlexMesh::get_entity_id() { 233 | return entity_id; 234 | } 235 | 236 | int FlexMesh::get_flags() { 237 | return flags; 238 | } 239 | 240 | FlexMesh::FlexMesh() { 241 | 242 | } 243 | 244 | FlexMesh::FlexMesh(NvFlexLibrary* lib, int id) { 245 | library = lib; 246 | entity_id = id; 247 | } 248 | 249 | -------------------------------------------------------------------------------- /binary/src/flex_mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "mathlib/vector.h" 4 | #include "mathlib/vector4d.h" 5 | #include "mathlib/vmatrix.h" 6 | #include 7 | 8 | // Data wrapper for FleX collisions 9 | class FlexMesh { 10 | private: 11 | NvFlexLibrary* library = nullptr; 12 | NvFlexBuffer* vertices = nullptr; 13 | NvFlexBuffer* indices = nullptr; 14 | NvFlexTriangleMeshId id = 0; 15 | int entity_id = 0; // id associated with the entity its attached to in source, as some physmeshes have multiple colliders (eg. ragdolls) 16 | int flags = 0; 17 | 18 | Vector4D pos = Vector4D(0, 0, 0, 0); 19 | Vector4D ang = Vector4D(0, 0, 0, 1); // Quaternion 20 | 21 | Vector4D ppos = Vector4D(0, 0, 0, 0); // Previous pos 22 | Vector4D pang = Vector4D(0, 0, 0, 1); // Previous ang 23 | 24 | public: 25 | bool init_concave(std::vector verts, bool dynamic); 26 | bool init_concave(Vector* verts, int num_verts, bool dynamic); // Used only for maps 27 | bool init_convex(std::vector verts, bool dynamic); 28 | void destroy(); 29 | 30 | void set_pos(Vector pos); 31 | void set_pos(Vector4D pos); 32 | void set_ang(QAngle ang); 33 | void set_ang(Vector4D ang); 34 | void set_collide(bool collide); 35 | 36 | Vector4D get_pos(); // Returns a Vector4D for convenience 37 | Vector4D get_ang(); 38 | 39 | Vector4D get_ppos(); 40 | Vector4D get_pang(); 41 | 42 | NvFlexTriangleMeshId get_id(); 43 | int get_entity_id(); 44 | int get_flags(); 45 | 46 | void update(); // sets the previous position/angle to current position/angle (previous_pos = pos; previous_ang = ang) 47 | 48 | FlexMesh(); 49 | FlexMesh(NvFlexLibrary* lib, int mesh_id); 50 | }; -------------------------------------------------------------------------------- /binary/src/flex_renderer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include "meshutils.h" // Fixes linker errors 6 | #include "flex_solver.h" 7 | #include 8 | #include "ThreadPool.h" 9 | 10 | #define MAX_PRIMATIVES 21845 11 | #define SQRT3 1.73205081 12 | #define VERTEX_GWATER2 VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D 13 | 14 | struct FlexRendererThreadData { 15 | VMatrix view_projection_matrix; 16 | Vector4D* particle_positions; 17 | Vector4D* particle_ani0 = nullptr; // also used as triangle normals 18 | Vector4D* particle_ani1 = nullptr; 19 | Vector4D* particle_ani2 = nullptr; 20 | int* particle_phases; // also used as triangle indices 21 | int* particle_active; 22 | Vector eye_pos; 23 | //int* render_buffer; 24 | int max_particles; 25 | float radius; 26 | bool cull; // should we do vvis culling? 27 | }; 28 | 29 | class FlexRenderer { 30 | private: 31 | ThreadPool* threads = nullptr; 32 | //int* water_buffer = nullptr; // which particles should be rendered? 33 | //int* diffuse_buffer = nullptr; // ^ 34 | std::vector> water_queue; 35 | std::vector water_meshes; 36 | 37 | std::vector> diffuse_queue; 38 | std::vector diffuse_meshes; 39 | 40 | std::vector> triangle_queue; 41 | std::vector triangle_meshes; 42 | 43 | void destroy_meshes(); 44 | void update_water(); 45 | void update_diffuse(); 46 | void update_cloth(); 47 | public: 48 | void draw_water(); 49 | void draw_diffuse(); 50 | void draw_cloth(); 51 | 52 | void build_meshes(FlexSolver* flex, float diffuse_radius, bool cull); 53 | 54 | FlexRenderer(); 55 | ~FlexRenderer(); 56 | }; -------------------------------------------------------------------------------- /binary/src/flex_solver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | //#include 5 | #include 6 | #include 7 | #include 8 | #include "flex_mesh.h" 9 | 10 | #define MAX_COLLIDERS 8192 // source can't go over this number of props so.. might as well just have it as the limit 11 | 12 | enum FlexPhase { 13 | WATER = (0 & eNvFlexPhaseGroupMask) | ((eNvFlexPhaseSelfCollide | eNvFlexPhaseFluid) & eNvFlexPhaseFlagsMask) | (eNvFlexPhaseShapeChannelMask & eNvFlexPhaseShapeChannelMask), 14 | CLOTH = (0 & eNvFlexPhaseGroupMask) | ((eNvFlexPhaseSelfCollide ) & eNvFlexPhaseFlagsMask) | (eNvFlexPhaseShapeChannelMask & eNvFlexPhaseShapeChannelMask), 15 | }; 16 | 17 | struct Particle { 18 | Vector4D pos = Vector4D(0, 0, 0, 1); 19 | Vector vel = Vector(0, 0, 0); 20 | int phase = FlexPhase::WATER; 21 | float lifetime = FLT_MAX; 22 | }; 23 | 24 | // Holds flex buffer information 25 | // TODO(?): Should this be defined as an std::pair, so the host and FleX buffers are always together? 26 | struct FlexBuffers { 27 | NvFlexBuffer* particle_pos; 28 | NvFlexBuffer* particle_vel; 29 | NvFlexBuffer* particle_phase; 30 | NvFlexBuffer* particle_active; 31 | NvFlexBuffer* particle_smooth; 32 | 33 | NvFlexBuffer* particle_ani0; 34 | NvFlexBuffer* particle_ani1; 35 | NvFlexBuffer* particle_ani2; 36 | 37 | NvFlexBuffer* geometry; 38 | NvFlexBuffer* geometry_pos; 39 | NvFlexBuffer* geometry_prevpos; 40 | NvFlexBuffer* geometry_quat; 41 | NvFlexBuffer* geometry_prevquat; 42 | NvFlexBuffer* geometry_flags; 43 | 44 | NvFlexBuffer* contact_planes; 45 | NvFlexBuffer* contact_vel; 46 | NvFlexBuffer* contact_count; 47 | NvFlexBuffer* contact_indices; 48 | 49 | NvFlexBuffer* diffuse_pos; 50 | NvFlexBuffer* diffuse_vel; 51 | NvFlexBuffer* diffuse_count; 52 | 53 | NvFlexBuffer* triangle_indices; 54 | NvFlexBuffer* triangle_normals; 55 | 56 | NvFlexBuffer* spring_indices; 57 | NvFlexBuffer* spring_restlengths; 58 | NvFlexBuffer* spring_stiffness; 59 | 60 | std::vector buffers; 61 | 62 | template NvFlexBuffer* init(NvFlexLibrary* library, T** host, int count); 63 | void destroy(); 64 | }; 65 | 66 | // Holds CPU mapped NvFlexBuffer* data 67 | struct FlexHosts { 68 | Vector4D* particle_pos; 69 | Vector* particle_vel; 70 | int* particle_phase; 71 | int* particle_active; 72 | Vector4D* particle_smooth; 73 | float* particle_lifetime; 74 | 75 | Vector4D* particle_ani0; 76 | Vector4D* particle_ani1; 77 | Vector4D* particle_ani2; 78 | 79 | NvFlexCollisionGeometry* geometry; 80 | Vector4D* geometry_pos; 81 | Vector4D* geometry_prevpos; 82 | Vector4D* geometry_ang; 83 | Vector4D* geometry_prevang; 84 | int* geometry_flags; 85 | 86 | Vector4D* contact_planes; 87 | Vector4D* contact_vel; 88 | int* contact_count; 89 | int* contact_indices; 90 | 91 | Vector4D* diffuse_pos; 92 | Vector4D* diffuse_vel; 93 | int* diffuse_count; 94 | 95 | int* triangle_indices; 96 | Vector4D* triangle_normals; 97 | 98 | int* spring_indices; 99 | float* spring_restlengths; 100 | float* spring_stiffness; 101 | }; 102 | 103 | // Struct that holds FleX solver data 104 | class FlexSolver { 105 | private: 106 | NvFlexLibrary* library = nullptr; 107 | NvFlexSolver* solver = nullptr; 108 | NvFlexExtForceFieldCallback* force_field_callback = nullptr; // unsure why this is required. crashes without it 109 | NvFlexParams parameters = NvFlexParams(); 110 | NvFlexCopyDesc copy_active = NvFlexCopyDesc(); 111 | NvFlexCopyDesc copy_triangles = NvFlexCopyDesc(); 112 | NvFlexCopyDesc copy_springs = NvFlexCopyDesc(); 113 | NvFlexSolverDesc solver_description = NvFlexSolverDesc(); // stores stuff such as max particles 114 | std::map param_map; // TODO: figure out if this is the best way to do this... Would a set/get switch statement be better..? 115 | 116 | std::map particle_queue; 117 | int particle_queue_index = 0; 118 | std::vector force_field_queue; 119 | bool diffuse_enabled = true; 120 | 121 | void set_particle(int particle_index, int active_index, Particle particle); 122 | void next_particle(); 123 | 124 | public: 125 | std::vector meshes; // physics meshes.. not visual! 126 | FlexBuffers buffers; 127 | FlexHosts hosts; 128 | 129 | void reset(); 130 | void reset_cloth(); 131 | void reset_diffuse(); 132 | int get_active_particles(); 133 | int get_active_diffuse(); 134 | int get_active_triangles(); 135 | int get_max_particles(); 136 | int get_max_diffuse_particles(); 137 | int get_max_contacts(); 138 | 139 | bool add_particle(Particle particle); // true = success, false otherwise 140 | void add_cloth(VMatrix translation, Vector2D size, Particle particle); 141 | void add_force_field(NvFlexExtForceField force_field); 142 | 143 | bool tick(float dt, NvFlexMapFlags wait); 144 | 145 | void add_mesh(FlexMesh mesh); 146 | bool update_meshes(NvFlexMapFlags wait); 147 | void remove_mesh(int id); 148 | 149 | bool set_parameter(std::string param, float number); // Returns true on success, false otherwise 150 | float get_parameter(std::string param); // returns NaN on invalid parameter 151 | void enable_bounds(Vector mins, Vector maxs); 152 | void disable_bounds(); 153 | void enable_diffuse(bool enabled); 154 | 155 | FlexSolver(NvFlexLibrary* library, int particles, int diffuse_particles); 156 | ~FlexSolver(); 157 | }; -------------------------------------------------------------------------------- /binary/src/shader_inject.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shaders/GWaterNormals.h" 3 | #include "shaders/GWaterSmooth.h" 4 | #include "shaders/GWaterVolumetric.h" 5 | #include "shaders/GWaterFinalpass.h" 6 | 7 | // This file is intentionally overcommented because of how undocumented source shaders are 8 | // Note that this is *my* understanding of how this works. I very well could be butchering what this actually is doing 9 | 10 | #include "shadersystem.h" // A conglomeration of valve structs shoved into a file. 11 | // ^ This file gives us access to CShaderSystem.. 12 | // CShaderSystem has privated variables (which we edit and make public) to get access to the internal shader DLLs (directories) 13 | // With these 'DLLs' made public, we can add our own shaders into the materialsystem without having to go through valves fucked up API 14 | 15 | // these externals MUST be defined (NOT NULL) BEFORE inserting shaders into the materialsystem or you WILL crash! 16 | extern IMaterialSystemHardwareConfig* g_pHardwareConfig = NULL; 17 | extern const MaterialSystem_Config_t* g_pConfig = NULL; 18 | IShaderSystem* g_pSLShaderSystem; // I literally have no idea where this is defined in the source sdk. Fails to compile without it 19 | 20 | CShaderSystem::ShaderDLLInfo_t* shaderlibdll = NULL; // our shader "directory" 21 | //int m_ShaderDLLs_index; 22 | 23 | // returns true if successful, false otherwise 24 | bool inject_shaders() { 25 | // Load source interfaces for personal use 26 | if (!Sys_LoadInterface("materialsystem", MATERIALSYSTEM_HARDWARECONFIG_INTERFACE_VERSION, NULL, (void**)&g_pHardwareConfig)) return false; 27 | if (!Sys_LoadInterface("materialsystem", MATERIALSYSTEM_CONFIG_VERSION, NULL, (void**)&g_pConfig)) return false; 28 | if (!Sys_LoadInterface("materialsystem", SHADERSYSTEM_INTERFACE_VERSION, NULL, (void**)&g_pSLShaderSystem)) return false; 29 | 30 | // imagine not being able to run dx9 31 | if (g_pHardwareConfig->GetDXSupportLevel() < 90) return false; 32 | // ^this check isnt technically required, but I only compiled my shaders for dx9 and above 33 | 34 | // this will cast the memory given by the valve interfaces to an edited CShaderSystem class which allows us to use privated variables which otherwise would be hidden 35 | CShaderSystem* s_ShaderSystem = (CShaderSystem*)g_pSLShaderSystem; 36 | 37 | // Create new shader directory (dll) 38 | //m_ShaderDLLs_index = s_ShaderSystem->m_ShaderDLLs.AddToTail(); // adding more than 8 TOTAL shader dlls crashes the game!!! 39 | //shaderlibdll = &s_ShaderSystem->m_ShaderDLLs[m_ShaderDLLs_index]; 40 | 41 | // if the above code is uncommented, m_ShaderDLLs_index ends up being equal to 7 (I think the maximum allowed number of shader directories) 42 | // im not sure what indexes 0-6 actually mean in terms of the gmod source code but ive found injecting into 0 tends to be the most stable 43 | // in theory you could have an unlimited amount of shaders on this index, you just need to make sure to remove them on module unload 44 | shaderlibdll = &s_ShaderSystem->m_ShaderDLLs[0]; 45 | 46 | //shaderlibdll->m_pFileName = strdup("gwater_shaders.dll"); // name likely doesnt matter 47 | //shaderlibdll->m_bModShaderDLL = true; 48 | 49 | // Insert our shaders into the shader directory 50 | // you need the COMPILED .vcs shaders in GarrysMod/garrysmod/shaders/fxc for the shaders to appear ingame! 51 | shaderlibdll->m_ShaderDict.Insert(GWaterNormals::s_Name, &GWaterNormals::s_ShaderInstance); 52 | shaderlibdll->m_ShaderDict.Insert(GWaterSmooth::s_Name, &GWaterSmooth::s_ShaderInstance); 53 | shaderlibdll->m_ShaderDict.Insert(GWaterVolumetric::s_Name, &GWaterVolumetric::s_ShaderInstance); 54 | shaderlibdll->m_ShaderDict.Insert(GWaterFinalpass::s_Name, &GWaterFinalpass::s_ShaderInstance); 55 | 56 | return true; 57 | } 58 | 59 | bool eject_shaders() { 60 | // Dont forget to free shaders or you crash on reload! 61 | if (shaderlibdll) { 62 | // Remove inserted shader(s) 63 | shaderlibdll->m_ShaderDict.Remove(GWaterNormals::s_Name); 64 | shaderlibdll->m_ShaderDict.Remove(GWaterSmooth::s_Name); 65 | shaderlibdll->m_ShaderDict.Remove(GWaterVolumetric::s_Name); 66 | shaderlibdll->m_ShaderDict.Remove(GWaterFinalpass::s_Name); 67 | //shaderlibdll->m_ShaderDict.PurgeAndDeleteElements(); 68 | 69 | // Remove our added shader directory (dll?) in material system 70 | //s_ShaderSystem->m_ShaderDLLs.Remove(m_ShaderDLLs_index); 71 | 72 | return true; 73 | } 74 | 75 | return false; 76 | } 77 | -------------------------------------------------------------------------------- /binary/src/shaders/GWaterFinalpass.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "shaders/inc/GWaterFinalpass_vs30.inc" 4 | #include "shaders/inc/GWaterFinalpass_ps30.inc" 5 | #include "cpp_shader_constant_register_map.h" 6 | 7 | ConVar* gwater2_hdr_fix; 8 | 9 | BEGIN_VS_SHADER(GWaterFinalpass, "gwater2 helper") 10 | 11 | // Shader parameters 12 | BEGIN_SHADER_PARAMS 13 | SHADER_PARAM(RADIUS, SHADER_PARAM_TYPE_FLOAT, "1", "Radius of particles") 14 | SHADER_PARAM(NORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Texture of smoothed normals") 15 | SHADER_PARAM(SCREENTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Texture of screen") 16 | SHADER_PARAM(DEPTHTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Depth texture") 17 | SHADER_PARAM(IOR, SHADER_PARAM_TYPE_FLOAT, "1.333", "Ior of water") 18 | SHADER_PARAM(COLOR2, SHADER_PARAM_TYPE_COLOR, "[1.0 1.0 1.0 1.0]", "Color of water. Alpha channel represents absorption amount") 19 | //SHADER_PARAM(ABSORPTIONMULTIPLIER, SHADER_PARAM_TYPE_FLOAT, "1", "Absorbsion multiplier") 20 | SHADER_PARAM(REFLECTANCE, SHADER_PARAM_TYPE_FLOAT, "0.0", "Reflectance of water") 21 | SHADER_PARAM(ENVMAP, SHADER_PARAM_TYPE_TEXTURE, "env_cubemap", "envmap") 22 | SHADER_PARAM(FLASHLIGHTTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "effects/flashlight001", "Flashlight") 23 | END_SHADER_PARAMS 24 | 25 | SHADER_INIT_PARAMS() { 26 | if (g_pHardwareConfig->SupportsBorderColor()) { 27 | params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight_border"); 28 | } else { 29 | params[FLASHLIGHTTEXTURE]->SetStringValue("effects/flashlight001"); 30 | } 31 | 32 | // This shader can be used with hw skinning 33 | SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_HW_SKINNING); 34 | SET_FLAGS2(MATERIAL_VAR2_LIGHTING_VERTEX_LIT); 35 | SET_FLAGS2(MATERIAL_VAR2_SUPPORTS_FLASHLIGHT); 36 | } 37 | 38 | SHADER_INIT { 39 | if (params[ENVMAP]->IsDefined()) { 40 | LoadCubeMap(ENVMAP, TEXTUREFLAGS_SRGB); 41 | } 42 | if (params[SCREENTEXTURE]->IsDefined()) { 43 | LoadTexture(SCREENTEXTURE); 44 | } 45 | if (params[NORMALTEXTURE]->IsDefined()) { 46 | LoadTexture(NORMALTEXTURE); 47 | } 48 | if (params[DEPTHTEXTURE]->IsDefined()) { 49 | LoadTexture(DEPTHTEXTURE); 50 | } 51 | if (FLASHLIGHTTEXTURE != -1) { 52 | LoadTexture(FLASHLIGHTTEXTURE, TEXTUREFLAGS_SRGB); 53 | } 54 | } 55 | 56 | SHADER_FALLBACK{ 57 | return NULL; 58 | } 59 | 60 | SHADER_DRAW { 61 | bool bHasFlashlight = UsingFlashlight(params); 62 | SHADOW_STATE { 63 | // Note: Removing VERTEX_COLOR makes the shader work on all objects (Like props) 64 | pShaderShadow->VertexShaderVertexFormat(VERTEX_GWATER2, 1, 0, 0); 65 | pShaderShadow->EnableTexture(SHADER_SAMPLER0, true); // Smoothed normals texture 66 | pShaderShadow->EnableTexture(SHADER_SAMPLER1, true); // Screen texture 67 | pShaderShadow->EnableTexture(SHADER_SAMPLER2, true); // Cubemap 68 | pShaderShadow->EnableTexture(SHADER_SAMPLER3, true); // Depth 69 | 70 | int nShadowFilterMode = 0; 71 | 72 | if (bHasFlashlight) { 73 | if (SCREENTEXTURE != -1) { 74 | SetAdditiveBlendingShadowState(SCREENTEXTURE, true); 75 | } 76 | pShaderShadow->EnableBlending(true); 77 | pShaderShadow->EnableDepthWrites(false); 78 | 79 | // Be sure not to write to dest alpha 80 | pShaderShadow->EnableAlphaWrites(false); 81 | 82 | nShadowFilterMode = g_pHardwareConfig->GetShadowFilterMode(); // Based upon vendor and device dependent formats 83 | 84 | pShaderShadow->EnableTexture(SHADER_SAMPLER4, true); // Shadow depth map 85 | pShaderShadow->SetShadowDepthFiltering(SHADER_SAMPLER4); 86 | pShaderShadow->EnableSRGBRead(SHADER_SAMPLER4, false); 87 | pShaderShadow->EnableTexture(SHADER_SAMPLER5, true); // Noise map 88 | pShaderShadow->EnableTexture(SHADER_SAMPLER6, true); // Flashlight cookie 89 | pShaderShadow->EnableSRGBRead(SHADER_SAMPLER6, true); 90 | } else { 91 | if (SCREENTEXTURE != -1) { 92 | SetDefaultBlendingShadowState(SCREENTEXTURE, true); 93 | } 94 | } 95 | 96 | DECLARE_STATIC_VERTEX_SHADER(GWaterFinalpass_vs30); 97 | SET_STATIC_VERTEX_SHADER(GWaterFinalpass_vs30); 98 | 99 | DECLARE_STATIC_PIXEL_SHADER(GWaterFinalpass_ps30); 100 | SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHT, bHasFlashlight); 101 | SET_STATIC_PIXEL_SHADER_COMBO(FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode); 102 | SET_STATIC_PIXEL_SHADER(GWaterFinalpass_ps30); 103 | } 104 | 105 | DYNAMIC_STATE { 106 | // constants 107 | int scr_x, scr_y; pShaderAPI->GetBackBufferDimensions(scr_x, scr_y); 108 | const float scr_s[2] = { 1.0 / scr_x, 1.0 / scr_y }; 109 | float radius = params[RADIUS]->GetFloatValue(); 110 | float ior = params[IOR]->GetFloatValue(); 111 | float reflectance = params[REFLECTANCE]->GetFloatValue(); 112 | const float* color2 = params[COLOR2]->GetVecValue(); 113 | const float color2_normalized[4] = { color2[0] / 255.0, color2[1] / 255.0, color2[2] / 255.0, color2[3] / 255.0 }; 114 | 115 | pShaderAPI->SetPixelShaderConstant(0, scr_s); 116 | pShaderAPI->SetPixelShaderConstant(1, &radius); 117 | pShaderAPI->SetPixelShaderConstant(2, &ior); 118 | pShaderAPI->SetPixelShaderConstant(3, &reflectance); 119 | pShaderAPI->SetPixelShaderConstant(4, color2_normalized); 120 | pShaderAPI->SetPixelShaderStateAmbientLightCube(5, false); 121 | 122 | /* 123 | CMatRenderContextPtr pRenderContext(materials); 124 | 125 | // Yoinked from viewrender.cpp (in a water detection function of all things, ironic..) 126 | VMatrix viewMatrix, projectionMatrix, viewProjectionMatrix, inverseViewProjectionMatrix; 127 | pRenderContext->GetMatrix(MATERIAL_VIEW, &viewMatrix); 128 | pRenderContext->GetMatrix(MATERIAL_PROJECTION, &projectionMatrix); 129 | MatrixMultiply(projectionMatrix, viewMatrix, viewProjectionMatrix); 130 | MatrixInverseGeneral(viewProjectionMatrix, inverseViewProjectionMatrix); 131 | 132 | float matrix[16]; 133 | for (int i = 0; i < 16; i++) { 134 | int x = i % 4; 135 | int y = i / 4; 136 | matrix[i] = inverseViewProjectionMatrix[y][x]; 137 | }*/ 138 | BindTexture(SHADER_SAMPLER0, NORMALTEXTURE); 139 | BindTexture(SHADER_SAMPLER1, SCREENTEXTURE); 140 | BindTexture(SHADER_SAMPLER2, ENVMAP); 141 | BindTexture(SHADER_SAMPLER3, DEPTHTEXTURE); 142 | 143 | // Flashlight (lamp) shit 144 | 145 | pShaderAPI->CommitPixelShaderLighting(PSREG_LIGHT_INFO_ARRAY); 146 | LightState_t lightState = { 0, false, false }; 147 | bool bFlashlightShadows = false; 148 | if (bHasFlashlight) { 149 | //Assert(info.m_nFlashlightTexture >= 0 && info.m_nFlashlightTextureFrame >= 0); 150 | BindTexture(SHADER_SAMPLER6, FLASHLIGHTTEXTURE, FLASHLIGHTTEXTUREFRAME); 151 | VMatrix worldToTexture; 152 | ITexture* pFlashlightDepthTexture; 153 | FlashlightState_t state = pShaderAPI->GetFlashlightStateEx(worldToTexture, &pFlashlightDepthTexture); 154 | bFlashlightShadows = state.m_bEnableShadows && (pFlashlightDepthTexture != NULL); 155 | 156 | SetFlashLightColorFromState(state, pShaderAPI, PSREG_FLASHLIGHT_COLOR); 157 | 158 | if (pFlashlightDepthTexture && g_pConfig->ShadowDepthTexture() && state.m_bEnableShadows) 159 | { 160 | BindTexture(SHADER_SAMPLER4, pFlashlightDepthTexture, 0); 161 | pShaderAPI->BindStandardTexture(SHADER_SAMPLER5, TEXTURE_SHADOW_NOISE_2D); 162 | } 163 | 164 | float atten[4], pos[4], tweaks[4]; 165 | 166 | const FlashlightState_t& flashlightState = pShaderAPI->GetFlashlightState(worldToTexture); 167 | SetFlashLightColorFromState(flashlightState, pShaderAPI, PSREG_FLASHLIGHT_COLOR); 168 | 169 | BindTexture(SHADER_SAMPLER6, flashlightState.m_pSpotlightTexture, flashlightState.m_nSpotlightTextureFrame); 170 | 171 | atten[0] = flashlightState.m_fConstantAtten; // Set the flashlight attenuation factors 172 | atten[1] = flashlightState.m_fLinearAtten; 173 | atten[2] = flashlightState.m_fQuadraticAtten; 174 | atten[3] = flashlightState.m_FarZ; 175 | pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_ATTENUATION, atten, 1); 176 | 177 | pos[0] = flashlightState.m_vecLightOrigin[0]; // Set the flashlight origin 178 | pos[1] = flashlightState.m_vecLightOrigin[1]; 179 | pos[2] = flashlightState.m_vecLightOrigin[2]; 180 | pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_POSITION_RIM_BOOST, pos, 1); 181 | 182 | pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE, worldToTexture.Base(), 4); 183 | 184 | // Tweaks associated with a given flashlight 185 | tweaks[0] = ShadowFilterFromState(flashlightState); 186 | tweaks[1] = ShadowAttenFromState(flashlightState); 187 | HashShadow2DJitter(flashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3]); 188 | pShaderAPI->SetPixelShaderConstant(26, tweaks, 1); // PSREG_ENVMAP_TINT__SHADOW_TWEAKS is c2, we're using that already for the cubemap, so use c26 instead. 189 | 190 | // Dimensions of screen, used for screen-space noise map sampling 191 | float vScreenScale[4] = { 1280.0f / 32.0f, 720.0f / 32.0f, 0, 0 }; 192 | int nWidth, nHeight; 193 | pShaderAPI->GetBackBufferDimensions(nWidth, nHeight); 194 | vScreenScale[0] = (float)nWidth / 32.0f; 195 | vScreenScale[1] = (float)nHeight / 32.0f; 196 | pShaderAPI->SetPixelShaderConstant(PSREG_FLASHLIGHT_SCREEN_SCALE, vScreenScale, 1); 197 | } else { 198 | pShaderAPI->GetDX9LightState(&lightState); 199 | } 200 | 201 | DECLARE_DYNAMIC_VERTEX_SHADER(GWaterFinalpass_vs30); 202 | SET_DYNAMIC_VERTEX_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); 203 | SET_DYNAMIC_VERTEX_SHADER(GWaterFinalpass_vs30); 204 | 205 | DECLARE_DYNAMIC_PIXEL_SHADER(GWaterFinalpass_ps30); 206 | SET_DYNAMIC_PIXEL_SHADER_COMBO(NUM_LIGHTS, lightState.m_nNumLights); 207 | SET_DYNAMIC_PIXEL_SHADER_COMBO(FLASHLIGHTSHADOWS, bFlashlightShadows); 208 | SET_DYNAMIC_PIXEL_SHADER_COMBO(OPAQUE, color2[3] > 254); 209 | SET_DYNAMIC_PIXEL_SHADER_COMBO(HDR, gwater2_hdr_fix->GetInt()); 210 | SET_DYNAMIC_PIXEL_SHADER(GWaterFinalpass_ps30); 211 | 212 | //pShaderAPI->SetVertexShaderConstant(4, matrix, 4, true); // FORCE into cModelViewProj! 213 | } 214 | 215 | Draw(); 216 | } 217 | 218 | END_SHADER -------------------------------------------------------------------------------- /binary/src/shaders/GWaterNormals.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "shaders/inc/GWaterNormals_vs30.inc" 4 | #include "shaders/inc/GWaterNormals_ps30.inc" 5 | 6 | BEGIN_VS_SHADER(GWaterNormals, "gwater2 helper") 7 | 8 | // Shader parameters 9 | BEGIN_SHADER_PARAMS 10 | SHADER_PARAM(DEPTHFIX, SHADER_PARAM_TYPE_BOOL, "0", "Depth fix enabled/disabled") 11 | SHADER_PARAM(RADIUS, SHADER_PARAM_TYPE_FLOAT, "1", "Radius of particles") 12 | END_SHADER_PARAMS 13 | 14 | SHADER_INIT_PARAMS() { 15 | 16 | } 17 | 18 | SHADER_INIT { 19 | 20 | } 21 | 22 | SHADER_FALLBACK{ 23 | return NULL; 24 | } 25 | 26 | SHADER_DRAW { 27 | SHADOW_STATE { 28 | pShaderShadow->VertexShaderVertexFormat(VERTEX_GWATER2, 1, 0, 0); 29 | pShaderShadow->EnableAlphaWrites(true); // we write to the alpha channel 30 | 31 | DECLARE_STATIC_VERTEX_SHADER(GWaterNormals_vs30); 32 | SET_STATIC_VERTEX_SHADER(GWaterNormals_vs30); 33 | 34 | DECLARE_STATIC_PIXEL_SHADER(GWaterNormals_ps30); 35 | SET_STATIC_PIXEL_SHADER(GWaterNormals_ps30); 36 | } 37 | 38 | DYNAMIC_STATE { 39 | 40 | // constants 41 | const float radius = params[RADIUS]->GetFloatValue(); 42 | const bool depthfix = params[DEPTHFIX]->GetIntValue(); 43 | 44 | pShaderAPI->SetPixelShaderConstant(0, &radius); 45 | 46 | DECLARE_DYNAMIC_VERTEX_SHADER(GWaterNormals_vs30); 47 | SET_DYNAMIC_VERTEX_SHADER(GWaterNormals_vs30); 48 | 49 | DECLARE_DYNAMIC_PIXEL_SHADER(GWaterNormals_ps30); 50 | SET_DYNAMIC_PIXEL_SHADER_COMBO(DEPTH, depthfix); 51 | SET_DYNAMIC_PIXEL_SHADER(GWaterNormals_ps30); 52 | 53 | } 54 | 55 | Draw(); 56 | 57 | } 58 | 59 | END_SHADER -------------------------------------------------------------------------------- /binary/src/shaders/GWaterSmooth.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "shaders/inc/GWaterVolumetric_vs30.inc" // vertex shader is reused because I don't feel like recompiling another one 4 | #include "shaders/inc/GWaterSmooth_ps30.inc" 5 | 6 | BEGIN_VS_SHADER(GWaterSmooth, "gwater2 helper") 7 | 8 | // Shader parameters 9 | BEGIN_SHADER_PARAMS 10 | SHADER_PARAM(RADIUS, SHADER_PARAM_TYPE_FLOAT, "1", "Radius of particles") 11 | SHADER_PARAM(SCRS, SHADER_PARAM_TYPE_VEC2, "[1 1]", "Screen Size") 12 | SHADER_PARAM(NORMALTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Texture of normals") 13 | SHADER_PARAM(DEPTHTEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Texture of depth") 14 | END_SHADER_PARAMS 15 | 16 | SHADER_INIT_PARAMS() { 17 | 18 | } 19 | 20 | SHADER_INIT { 21 | LoadTexture(NORMALTEXTURE); 22 | LoadTexture(DEPTHTEXTURE); 23 | } 24 | 25 | SHADER_FALLBACK{ 26 | return NULL; 27 | } 28 | 29 | SHADER_DRAW { 30 | SHADOW_STATE { 31 | 32 | // Note: Removing VERTEX_COLOR makes the shader work on all objects (Like props) 33 | unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL | VERTEX_TEXCOORD0_2D; 34 | pShaderShadow->VertexShaderVertexFormat(flags, 1, 0, 0); 35 | pShaderShadow->EnableTexture(SHADER_SAMPLER0, true); 36 | pShaderShadow->EnableTexture(SHADER_SAMPLER1, true); 37 | pShaderShadow->EnableAlphaWrites(true); // We use and update the alpha channel 38 | 39 | DECLARE_STATIC_VERTEX_SHADER(GWaterVolumetric_vs30); 40 | SET_STATIC_VERTEX_SHADER(GWaterVolumetric_vs30); 41 | 42 | DECLARE_STATIC_PIXEL_SHADER(GWaterSmooth_ps30); 43 | SET_STATIC_PIXEL_SHADER(GWaterSmooth_ps30); 44 | } 45 | 46 | DYNAMIC_STATE { 47 | // constants 48 | const float* scr_s = params[SCRS]->GetVecValue(); 49 | const float radius = params[RADIUS]->GetFloatValue(); 50 | 51 | pShaderAPI->SetPixelShaderConstant(0, scr_s); 52 | pShaderAPI->SetPixelShaderConstant(1, &radius); 53 | 54 | BindTexture(SHADER_SAMPLER0, NORMALTEXTURE); 55 | BindTexture(SHADER_SAMPLER1, DEPTHTEXTURE); 56 | 57 | DECLARE_DYNAMIC_VERTEX_SHADER(GWaterVolumetric_vs30); 58 | SET_DYNAMIC_VERTEX_SHADER(GWaterVolumetric_vs30); 59 | 60 | DECLARE_DYNAMIC_PIXEL_SHADER(GWaterSmooth_ps30); 61 | SET_DYNAMIC_PIXEL_SHADER(GWaterSmooth_ps30); 62 | } 63 | 64 | Draw(); 65 | 66 | } 67 | 68 | END_SHADER -------------------------------------------------------------------------------- /binary/src/shaders/GWaterVolumetric.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "shaders/inc/GWaterVolumetric_vs30.inc" 4 | #include "shaders/inc/GWaterVolumetric_ps30.inc" 5 | 6 | BEGIN_VS_SHADER(GWaterVolumetric, "gwater2 helper") 7 | 8 | // Shader parameters 9 | BEGIN_SHADER_PARAMS 10 | SHADER_PARAM(ALPHA, SHADER_PARAM_TYPE_FLOAT, "0.025", "Amount of transparency") 11 | SHADER_PARAM(BASETEXTURE, SHADER_PARAM_TYPE_TEXTURE, "lights/white", "Base texture") 12 | END_SHADER_PARAMS 13 | 14 | SHADER_INIT_PARAMS() { 15 | 16 | } 17 | 18 | SHADER_INIT{ 19 | LoadTexture(BASETEXTURE); 20 | } 21 | 22 | SHADER_FALLBACK{ 23 | return NULL; 24 | } 25 | 26 | SHADER_DRAW { 27 | 28 | 29 | SHADOW_STATE { 30 | pShaderShadow->VertexShaderVertexFormat(VERTEX_GWATER2, 1, 0, 0); 31 | 32 | // Transparent things (alpha 0 <= x <= 1) 33 | if (IS_FLAG_SET(MATERIAL_VAR_TRANSLUCENT)) { 34 | pShaderShadow->EnableDepthWrites(false); 35 | pShaderShadow->EnableBlending(true); 36 | 37 | // Additive vs multiplicitive 38 | if (IS_FLAG_SET(MATERIAL_VAR_ADDITIVE)) { 39 | pShaderShadow->BlendFunc(SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE); 40 | } else { 41 | pShaderShadow->BlendFunc(SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA); 42 | //pShaderShadow->BlendFunc(SHADER_BLEND_ONE, SHADER_BLEND_ONE); 43 | } 44 | } 45 | 46 | // Transparent things (alpha = 0 or alpha = 1) 47 | pShaderShadow->EnableAlphaTest(IS_FLAG_SET(MATERIAL_VAR_ALPHATEST)); 48 | pShaderShadow->EnableTexture(SHADER_SAMPLER0, true); 49 | 50 | DECLARE_STATIC_VERTEX_SHADER(GWaterVolumetric_vs30); 51 | SET_STATIC_VERTEX_SHADER(GWaterVolumetric_vs30); 52 | 53 | DECLARE_STATIC_PIXEL_SHADER(GWaterVolumetric_ps30); 54 | SET_STATIC_PIXEL_SHADER(GWaterVolumetric_ps30); 55 | } 56 | 57 | DYNAMIC_STATE { 58 | // constants 59 | const float alpha = params[ALPHA]->GetFloatValue(); 60 | 61 | pShaderAPI->SetPixelShaderConstant(0, &alpha); 62 | BindTexture(SHADER_SAMPLER0, BASETEXTURE); 63 | 64 | DECLARE_DYNAMIC_VERTEX_SHADER(GWaterVolumetric_vs30); 65 | SET_DYNAMIC_VERTEX_SHADER(GWaterVolumetric_vs30); 66 | 67 | DECLARE_DYNAMIC_PIXEL_SHADER(GWaterVolumetric_ps30); 68 | SET_DYNAMIC_PIXEL_SHADER(GWaterVolumetric_ps30); 69 | } 70 | 71 | Draw(); 72 | 73 | } 74 | 75 | END_SHADER -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterFinalpass_ps30.hlsl: -------------------------------------------------------------------------------- 1 | // DYNAMIC: "OPAQUE" "0..1" 2 | // DYNAMIC: "NUM_LIGHTS" "0..4" 3 | // DYNAMIC: "HDR" "0..1" 4 | // STATIC: "FLASHLIGHT" "0..1" 5 | // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" 6 | 7 | // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" 8 | 9 | /* 10 | I am very new to GPU archetecture and shader optimization. 11 | 12 | Please for your own sake, do not copy or reference any of this file. 13 | This is genuinely the most garbage piece of code I've ever written 14 | */ 15 | 16 | #include "common_flashlight_fxc.h" 17 | #include "shader_constant_register_map.h" 18 | //#include "common_vertexlitgeneric_dx9.h" 19 | 20 | float2 SCR_S : register(c0); 21 | float RADIUS : register(c1); 22 | float IOR : register(c2); 23 | float REFLECTANCE : register(c3); 24 | float4 COLOR2 : register(c4); 25 | float3 cAmbientCube[6] : register(c5); 26 | 27 | PixelShaderLightInfo cLightInfo[3] : register(PSREG_LIGHT_INFO_ARRAY); // c20 - c25, 2 registers each - 6 registers total (4th light spread across w's) 28 | const float4 g_ShadowTweaks : register(c26); // PSREG_ENVMAP_TINT__SHADOW_TWEAKS is supposed to be c2, we're using that already, so use c26 instead 29 | const float4 g_FlashlightAttenuationFactors : register(PSREG_FLASHLIGHT_ATTENUATION); // c13, On non-flashlight pass 30 | const float4 g_FlashlightPos_RimBoost : register(PSREG_FLASHLIGHT_POSITION_RIM_BOOST); // c14 31 | const float4x4 g_FlashlightWorldToTexture : register(PSREG_FLASHLIGHT_TO_WORLD_TEXTURE); // c15 32 | 33 | sampler NORMALS : register(s0); 34 | sampler FRAMEBUFFER : register(s1); 35 | samplerCUBE CUBEMAP : register(s2); 36 | sampler DEPTH : register(s3); 37 | sampler ShadowDepthSampler : register(s4); // Flashlight shadow depth map sampler 38 | sampler NormalizeRandRotSampler : register(s5); // Normalization / RandomRotation samplers 39 | sampler FlashlightSampler : register(s6); // Flashlight cookie 40 | 41 | struct PS_INPUT { 42 | float2 P : VPOS; 43 | float2 coord : TEXCOORD0; 44 | float3 view_dir : TEXCOORD1; 45 | float3 pos : TEXCOORD2; 46 | float4x4 proj : TEXCOORD3; 47 | float4 lightAtten : TEXCOORD8; // Scalar light attenuation factors for FOUR lights 48 | }; 49 | 50 | #define SUN_DIR float3(-0.377821, 0.520026, 0.766044) // TODO: get from map OR get lighting data 51 | 52 | #define SpecularExponent 200 53 | #define g_FlashlightPos g_FlashlightPos_RimBoost.xyz 54 | 55 | bool is_zero(float3 i) { 56 | return i.x == 0 && i.y == 0 && i.z == 0; 57 | } 58 | 59 | // Assumes that incoming IOR is 1 60 | float fresnel_schlicks(float cos_theta, float ior) { 61 | float r0 = (1.0 - ior) / (1.0 + ior); 62 | r0 = r0 * r0; 63 | return r0 + (1.0 - r0) * pow(1.0 - cos_theta, 5.0); 64 | } 65 | 66 | float4 final_output(float3 final) { 67 | return FinalOutput(float4(final, 1), 0, 0, TONEMAP_SCALE_LINEAR); 68 | } 69 | 70 | float3 do_flashlight(PS_INPUT i, float3 normal) { 71 | float3 reflected = float3(0, 0, 0); 72 | float3 diffuse = float3(0, 0, 0); 73 | float4 flashlightSpacePosition = mul(float4(i.pos, 1.0f), g_FlashlightWorldToTexture); 74 | if (flashlightSpacePosition.z > 0) { 75 | DoSpecularFlashlight( 76 | g_FlashlightPos, 77 | i.pos, 78 | flashlightSpacePosition, 79 | normal, 80 | g_FlashlightAttenuationFactors.xyz, 81 | g_FlashlightAttenuationFactors.w, 82 | FlashlightSampler, 83 | ShadowDepthSampler, 84 | NormalizeRandRotSampler, 85 | FLASHLIGHTDEPTHFILTERMODE, 86 | FLASHLIGHTSHADOWS, 87 | true, 88 | i.P * SCR_S, 89 | SpecularExponent, 90 | -i.view_dir, 91 | false, 92 | FRAMEBUFFER, 93 | 0, 94 | g_ShadowTweaks, 95 | 96 | // These two values are output 97 | diffuse, 98 | reflected 99 | ); 100 | } 101 | 102 | #if OPAQUE 103 | return COLOR2.xyz * diffuse + reflected; 104 | #else 105 | return reflected; 106 | #endif 107 | } 108 | 109 | float3 do_absorption(PS_INPUT i) { 110 | float absorption_distance = tex2D(DEPTH, i.P * SCR_S).x * 100 * COLOR2.w; 111 | return exp((COLOR2.xyz - float3(1, 1, 1)) * absorption_distance); // Beers law 112 | } 113 | 114 | // despite saying "do specular", this actually only calculates radiance from local area lights 115 | // (also: does fresnel internally) 116 | float3 do_specular(PS_INPUT i, float3 normal) { 117 | float3 specular_lighting; 118 | float3 rim_lighting; // Unused 119 | 120 | PixelShaderDoSpecularLighting( 121 | i.pos, 122 | normal, 123 | SpecularExponent, 124 | -i.view_dir, 125 | i.lightAtten, 126 | NUM_LIGHTS, 127 | cLightInfo, 128 | false, 129 | 0, 130 | false, 131 | FRAMEBUFFER, 132 | 0, 133 | false, 134 | 1, 135 | specular_lighting, 136 | rim_lighting 137 | ); 138 | 139 | return specular_lighting; 140 | } 141 | 142 | float3 do_cubemap(PS_INPUT i, float3 normal) { 143 | #if HDR 144 | return pow(texCUBE(CUBEMAP, reflect(i.view_dir, normal)).xyz * ENV_MAP_SCALE, 1 / 2.2); 145 | #else 146 | return texCUBE(CUBEMAP, reflect(i.view_dir, normal)).xyz * ENV_MAP_SCALE; 147 | #endif 148 | } 149 | 150 | float3 do_diffuse(PS_INPUT i, float3 normal) { 151 | return COLOR2.xyz * (dot(normal, SUN_DIR) * 0.4 + 0.6); // not accurate! 152 | 153 | // include "common_vertexlitgeneric_dx9.h" to use 154 | // may cause seizures 155 | /*return COLOR2.xyz * pow(PixelShaderDoLighting( 156 | i.pos, 157 | normal, 158 | float3( 0.0f, 0.0f, 0.0f ), 159 | false, 160 | true, 161 | i.lightAtten, 162 | cAmbientCube, 163 | NormalizeRandRotSampler, 164 | NUM_LIGHTS, 165 | cLightInfo, 166 | true, 167 | 168 | // These are dummy parameters: 169 | false, 170 | 1.0f, 171 | false, 172 | NormalizeRandRotSampler //supposed to be BaseTextureSampler? 173 | ), 1 / 2.2);*/ 174 | } 175 | 176 | float3 do_refraction(PS_INPUT i, float3 normal) { 177 | // Calculate refraction vector in 3d space and project it to screen 178 | float3 offset = refract(i.view_dir, normal, 1.0 / IOR) * RADIUS * 2; //normal * -RADIUS;// 179 | float4 uv = mul(float4(i.pos + offset, 1), i.proj); uv.xy /= uv.w; 180 | 181 | float2 refract_pos = float2(uv.x / 2.0 + 0.5, 0.5 - uv.y / 2.0); //-1,1 -> 0,1 182 | return tex2D(FRAMEBUFFER, refract_pos).xyz / LINEAR_LIGHT_SCALE; 183 | } 184 | 185 | float4 main(PS_INPUT i) : COLOR { 186 | // kill pixels outside of sphere 187 | float2 offset = (i.coord - 0.5) * 2.0; 188 | float radius2 = dot(offset, offset); 189 | if (radius2 > 1) discard; 190 | 191 | //i.view_dir = normalize(i.pos - i.view_dir); 192 | float3 smoothed_normal = tex2D(NORMALS, i.P * SCR_S).xyz; 193 | 194 | // Weight the normals forward, as the only visible part is facing the player 195 | smoothed_normal = normalize(smoothed_normal + i.view_dir * REFLECTANCE * clamp(-dot(i.view_dir, smoothed_normal), 0.5, 1)); 196 | 197 | // Flashlight lighting (eg. a lamp is casting shadow) 198 | #if FLASHLIGHT 199 | return final_output(do_flashlight(i, smoothed_normal)); 200 | #endif 201 | 202 | // Final lighting calculations 203 | #if OPAQUE 204 | return final_output(do_diffuse(i, smoothed_normal) + do_specular(i, smoothed_normal)); 205 | 206 | #else // Translucent 207 | // incorrect fresnel calculation, but looks better 208 | float fresnel = min(fresnel_schlicks(max(dot(smoothed_normal, -i.view_dir), 0.0), IOR) + 0.05, 1); 209 | 210 | // Chat is this accurate?? 211 | return final_output((1.0 - fresnel) * do_refraction(i, smoothed_normal) * do_absorption(i) + do_cubemap(i, smoothed_normal) * fresnel + do_specular(i, smoothed_normal)); 212 | #endif 213 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterFinalpass_vs30.hlsl: -------------------------------------------------------------------------------- 1 | #include "common_vs_fxc.h" 2 | 3 | // DYNAMIC: "NUM_LIGHTS" "0..4" 4 | 5 | struct VS_INPUT { 6 | float4 vPos : POSITION; // Position 7 | float4 vTexCoord : TEXCOORD0; // Texture coordinates 8 | }; 9 | 10 | struct VS_OUTPUT { 11 | float4 projPosSetup : POSITION; 12 | float2 coord : TEXCOORD0; 13 | float3 view_dir : TEXCOORD1; 14 | float3 pos : TEXCOORD2; 15 | float4x4 proj : TEXCOORD3; // Used in refraction 16 | float4 lightAtten : TEXCOORD8; // Scalar light attenuation factors for FOUR lights 17 | //float psize : PSIZE; 18 | }; 19 | 20 | VS_OUTPUT main(const VS_INPUT v) { 21 | VS_OUTPUT o = (VS_OUTPUT)0; 22 | 23 | // Extract real position 24 | float3 world_pos; 25 | SkinPosition(0, v.vPos, 0, 0, world_pos); 26 | 27 | float4 vProjPos = mul(float4(world_pos, 1), cViewProj); 28 | //vProjPos.z = dot(float4(extruded_world_pos, 1), cViewProjZ); // wtf does this even do? 29 | 30 | o.projPosSetup = vProjPos; 31 | o.coord = v.vTexCoord; 32 | o.view_dir = normalize(world_pos - cEyePos); 33 | o.proj = cViewProj; 34 | o.pos = world_pos; 35 | 36 | // Scalar attenuations for four lights 37 | o.lightAtten.xyz = float4(0,0,0,0); 38 | #if (NUM_LIGHTS > 0) 39 | o.lightAtten.x = GetVertexAttenForLight(world_pos, 0, false); 40 | #endif 41 | #if (NUM_LIGHTS > 1) 42 | o.lightAtten.y = GetVertexAttenForLight(world_pos, 1, false); 43 | #endif 44 | #if (NUM_LIGHTS > 2) 45 | o.lightAtten.z = GetVertexAttenForLight(world_pos, 2, false); 46 | #endif 47 | #if (NUM_LIGHTS > 3) 48 | o.lightAtten.w = GetVertexAttenForLight(world_pos, 3, false); 49 | #endif 50 | 51 | return o; 52 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterNormals_ps30.hlsl: -------------------------------------------------------------------------------- 1 | // DYNAMIC: "DEPTH" "0..1" 2 | 3 | float RADIUS : register(c0); 4 | 5 | struct PS_INPUT { 6 | float2 P : VPOS; 7 | float2 coord : TEXCOORD0; 8 | float3 pos : TEXCOORD1; 9 | float4x4 proj : TEXCOORD2; 10 | float3x3 normal : NORMAL0; 11 | }; 12 | 13 | struct PS_OUTPUT { 14 | float4 rt0 : COLOR0; 15 | float4 rt1 : COLOR1; 16 | #if DEPTH 17 | float depth : DEPTH0; 18 | #endif 19 | }; 20 | 21 | PS_OUTPUT main(const PS_INPUT i) { 22 | 23 | // kill pixels outside of sphere 24 | float2 offset = (i.coord - 0.5) * 2.0; 25 | float radius2 = dot(offset, offset); 26 | if (radius2 > 1) discard; 27 | 28 | // Calculate world normal from texture coords 29 | float bulge = sqrt(1 - radius2); 30 | float3 world_normal = normalize(mul(float3(offset.x, bulge, -offset.y), i.normal)); 31 | 32 | // Standard mipmap calculation 33 | float2 uvdx = ddx(i.coord); 34 | float2 uvdy = ddy(i.coord); 35 | float uvdmax = 1.0 / sqrt(max(dot(uvdx, uvdx), dot(uvdy, uvdy))); 36 | 37 | // Depth calculations 38 | float4 bulge_pos = mul(float4(i.pos.xyz + i.normal[1] * bulge * RADIUS, 1), i.proj); 39 | 40 | // Output colors to rendertargets 41 | PS_OUTPUT o = (PS_OUTPUT)0; 42 | o.rt0 = float4(world_normal, bulge_pos.z); 43 | //o.rt0 = float4(i.coord.x, i.coord.y, 0, bulge_pos.z); 44 | o.rt1 = float4(uvdmax, 0, 0, 1); 45 | #if DEPTH 46 | o.depth = bulge_pos.z / bulge_pos.w; 47 | #endif 48 | 49 | return o; 50 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterNormals_vs30.hlsl: -------------------------------------------------------------------------------- 1 | #include "common_vs_fxc.h" 2 | 3 | struct VS_INPUT { 4 | float4 vPos : POSITION; 5 | float4 vTexCoord : TEXCOORD0; // Texture coordinates 6 | float3 vNormal : NORMAL0; 7 | }; 8 | 9 | struct VS_OUTPUT { 10 | float4 projPosSetup : POSITION; // Register 0 11 | float4 coord : TEXCOORD0; // Register 1 12 | float3 pos : TEXCOORD1; // Register 2 13 | float4x4 proj : TEXCOORD2; // Registers 3 4 5 6 14 | float3x3 normal : NORMAL0; // Registers 7 8 9 15 | }; 16 | 17 | VS_OUTPUT main(const VS_INPUT v) { 18 | VS_OUTPUT o = (VS_OUTPUT)0; 19 | 20 | // Extract real position 21 | float3 world_normal, world_pos; 22 | SkinPositionAndNormal(0, v.vPos, v.vNormal, 0, 0, world_pos, world_normal); 23 | 24 | float4 vProjPos = mul(float4(world_pos, 1), cViewProj); 25 | //vProjPos.z = dot(float4(extruded_world_pos, 1), cViewProjZ); // wtf does this even do? 26 | 27 | o.projPosSetup = vProjPos; 28 | o.coord = v.vTexCoord; 29 | o.pos = world_pos; 30 | o.proj = cViewProj; // Used in spherical depth 31 | 32 | float3 right = normalize(cross(world_normal, float3(0, 0, 1))); 33 | float3 up = cross(world_normal, right); 34 | o.normal = float3x3( 35 | -right.x, -right.y, -right.z, 36 | world_normal.x, world_normal.y, world_normal.z, 37 | -up.x, -up.y, -up.z 38 | ); 39 | 40 | return o; 41 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterSmooth_ps30.hlsl: -------------------------------------------------------------------------------- 1 | sampler NORMALS : register(s0); 2 | sampler DEPTH : register(s1); 3 | float2 SCR_S : register(c0); 4 | float RADIUS : register(c1); 5 | 6 | #define RESOLUTION 4 7 | #define THRESHOLD 0 8 | 9 | struct PS_INPUT { 10 | float2 P : VPOS; 11 | float2 coord : TEXCOORD0; 12 | }; 13 | 14 | // Algorithm smooths normals of particle (uses my own method) (separated into X and Y passes) 15 | // Worked on this algorithm for multiple months, so it may be a little messy. Smoothing particle information is not easy.. 16 | float4 main(PS_INPUT i) : COLOR { 17 | float4 og_normal = tex2D(NORMALS, i.coord); 18 | //if (og_normal.w <= RADIUS) return float4(0, 0, 0, 0); // Dont blur if too close. 19 | 20 | float mipmap = tex2D(DEPTH, i.coord).x; 21 | float3 final_normal = og_normal.xyz; 22 | 23 | // Blurring right 24 | [unroll] 25 | for (int x = 1; x <= RESOLUTION; x++) { 26 | float2 texcoord_pos = i.coord + float2(x * SCR_S.x, x * SCR_S.y) * mipmap; // Grabs adjacent pixel based on how much screen space the particle takes up 27 | 28 | // Is particle close enough to be blended? 29 | float4 neighbor_normal = tex2D(NORMALS, texcoord_pos); 30 | if (neighbor_normal.w - og_normal.w > RADIUS || neighbor_normal.w == 0) return og_normal; 31 | 32 | // Weigh smooth amount based on angle 33 | float cosTheta = dot(og_normal.xyz, neighbor_normal.xyz); 34 | if (cosTheta < THRESHOLD) break; 35 | //cosTheta = max(cosTheta, THRESHOLD); 36 | 37 | final_normal += neighbor_normal.xyz * cosTheta * cosTheta; 38 | } 39 | 40 | // Blurring left 41 | // (Identical to above loop^) 42 | [unroll] 43 | for (int x = -1; x >= -RESOLUTION; x--) { 44 | float2 texcoord_pos = i.coord + float2(x * SCR_S.x, x * SCR_S.y) * mipmap; 45 | float4 neighbor_normal = tex2D(NORMALS, texcoord_pos); 46 | if (neighbor_normal.w - og_normal.w > RADIUS || neighbor_normal.w == 0) return og_normal; 47 | float cosTheta = dot(og_normal.xyz, neighbor_normal.xyz); 48 | if (cosTheta < THRESHOLD) break; 49 | final_normal += neighbor_normal.xyz * cosTheta * cosTheta; 50 | } 51 | 52 | return float4(normalize(final_normal), og_normal.w); 53 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterVolumetric_ps30.hlsl: -------------------------------------------------------------------------------- 1 | float ALPHA : register(c0); 2 | sampler BASETEXTURE : register(s0); 3 | 4 | struct PS_INPUT { 5 | float4 P : VPOS; 6 | float2 coord : TEXCOORD0; 7 | }; 8 | 9 | float4 main(PS_INPUT i) : COLOR { 10 | return tex2D(BASETEXTURE, i.coord) * ALPHA; 11 | }; -------------------------------------------------------------------------------- /binary/src/shaders/hlsl/GWaterVolumetric_vs30.hlsl: -------------------------------------------------------------------------------- 1 | #include "common_vs_fxc.h" 2 | 3 | struct VS_INPUT { 4 | float4 vPos : POSITION; // Position 5 | float4 vTexCoord : TEXCOORD0; // Texture coordinates 6 | }; 7 | 8 | struct VS_OUTPUT { 9 | float4 projPosSetup : POSITION; 10 | float4 world_coord : TEXCOORD0; 11 | }; 12 | 13 | VS_OUTPUT main(const VS_INPUT v) { 14 | VS_OUTPUT o = (VS_OUTPUT)0; 15 | 16 | // Extract real position 17 | float3 world_pos; 18 | SkinPosition(0, v.vPos, 0, 0, world_pos); 19 | 20 | float4 vProjPos = mul(float4(world_pos, 1), cViewProj); 21 | //vProjPos.z = dot(float4(world_pos, 1), cViewProjZ); // wtf does this even do? 22 | o.projPosSetup = vProjPos; 23 | o.world_coord = v.vTexCoord; 24 | return o; 25 | }; -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterFinalpass_ps30.inc: -------------------------------------------------------------------------------- 1 | // ALL SKIP STATEMENTS THAT AFFECT THIS SHADER!!! 2 | // defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED 3 | // defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA 4 | // defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0 5 | // defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT 6 | // defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST 7 | // defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH 8 | // ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW 9 | // defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED 10 | // defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA 11 | // defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0 12 | // defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT 13 | // defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST 14 | // defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH 15 | // ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW 16 | 17 | #pragma once 18 | #include "shaderlib/cshader.h" 19 | class GWaterFinalpass_ps30_Static_Index 20 | { 21 | unsigned int m_nFLASHLIGHT : 2; 22 | unsigned int m_nFLASHLIGHTDEPTHFILTERMODE : 2; 23 | #ifdef _DEBUG 24 | bool m_bFLASHLIGHT : 1; 25 | bool m_bFLASHLIGHTDEPTHFILTERMODE : 1; 26 | #endif // _DEBUG 27 | public: 28 | void SetFLASHLIGHT( int i ) 29 | { 30 | Assert( i >= 0 && i <= 1 ); 31 | m_nFLASHLIGHT = i; 32 | #ifdef _DEBUG 33 | m_bFLASHLIGHT = true; 34 | #endif // _DEBUG 35 | } 36 | 37 | void SetFLASHLIGHTDEPTHFILTERMODE( int i ) 38 | { 39 | Assert( i >= 0 && i <= 2 ); 40 | m_nFLASHLIGHTDEPTHFILTERMODE = i; 41 | #ifdef _DEBUG 42 | m_bFLASHLIGHTDEPTHFILTERMODE = true; 43 | #endif // _DEBUG 44 | } 45 | 46 | GWaterFinalpass_ps30_Static_Index( ) 47 | { 48 | m_nFLASHLIGHT = 0; 49 | m_nFLASHLIGHTDEPTHFILTERMODE = 0; 50 | #ifdef _DEBUG 51 | m_bFLASHLIGHT = false; 52 | m_bFLASHLIGHTDEPTHFILTERMODE = false; 53 | #endif // _DEBUG 54 | } 55 | 56 | int GetIndex() const 57 | { 58 | Assert( m_bFLASHLIGHT && m_bFLASHLIGHTDEPTHFILTERMODE ); 59 | return ( 40 * m_nFLASHLIGHT ) + ( 80 * m_nFLASHLIGHTDEPTHFILTERMODE ) + 0; 60 | } 61 | }; 62 | 63 | #define shaderStaticTest_GWaterFinalpass_ps30 psh_forgot_to_set_static_FLASHLIGHT + psh_forgot_to_set_static_FLASHLIGHTDEPTHFILTERMODE 64 | 65 | 66 | class GWaterFinalpass_ps30_Dynamic_Index 67 | { 68 | unsigned int m_nOPAQUE : 2; 69 | unsigned int m_nNUM_LIGHTS : 3; 70 | unsigned int m_nHDR : 2; 71 | unsigned int m_nFLASHLIGHTSHADOWS : 2; 72 | #ifdef _DEBUG 73 | bool m_bOPAQUE : 1; 74 | bool m_bNUM_LIGHTS : 1; 75 | bool m_bHDR : 1; 76 | bool m_bFLASHLIGHTSHADOWS : 1; 77 | #endif // _DEBUG 78 | public: 79 | void SetOPAQUE( int i ) 80 | { 81 | Assert( i >= 0 && i <= 1 ); 82 | m_nOPAQUE = i; 83 | #ifdef _DEBUG 84 | m_bOPAQUE = true; 85 | #endif // _DEBUG 86 | } 87 | 88 | void SetNUM_LIGHTS( int i ) 89 | { 90 | Assert( i >= 0 && i <= 4 ); 91 | m_nNUM_LIGHTS = i; 92 | #ifdef _DEBUG 93 | m_bNUM_LIGHTS = true; 94 | #endif // _DEBUG 95 | } 96 | 97 | void SetHDR( int i ) 98 | { 99 | Assert( i >= 0 && i <= 1 ); 100 | m_nHDR = i; 101 | #ifdef _DEBUG 102 | m_bHDR = true; 103 | #endif // _DEBUG 104 | } 105 | 106 | void SetFLASHLIGHTSHADOWS( int i ) 107 | { 108 | Assert( i >= 0 && i <= 1 ); 109 | m_nFLASHLIGHTSHADOWS = i; 110 | #ifdef _DEBUG 111 | m_bFLASHLIGHTSHADOWS = true; 112 | #endif // _DEBUG 113 | } 114 | 115 | GWaterFinalpass_ps30_Dynamic_Index( ) 116 | { 117 | m_nOPAQUE = 0; 118 | m_nNUM_LIGHTS = 0; 119 | m_nHDR = 0; 120 | m_nFLASHLIGHTSHADOWS = 0; 121 | #ifdef _DEBUG 122 | m_bOPAQUE = false; 123 | m_bNUM_LIGHTS = false; 124 | m_bHDR = false; 125 | m_bFLASHLIGHTSHADOWS = false; 126 | #endif // _DEBUG 127 | } 128 | 129 | int GetIndex() const 130 | { 131 | Assert( m_bOPAQUE && m_bNUM_LIGHTS && m_bHDR && m_bFLASHLIGHTSHADOWS ); 132 | return ( 1 * m_nOPAQUE ) + ( 2 * m_nNUM_LIGHTS ) + ( 10 * m_nHDR ) + ( 20 * m_nFLASHLIGHTSHADOWS ) + 0; 133 | } 134 | }; 135 | 136 | #define shaderDynamicTest_GWaterFinalpass_ps30 psh_forgot_to_set_dynamic_OPAQUE + psh_forgot_to_set_dynamic_NUM_LIGHTS + psh_forgot_to_set_dynamic_HDR + psh_forgot_to_set_dynamic_FLASHLIGHTSHADOWS 137 | 138 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterFinalpass_vs30.inc: -------------------------------------------------------------------------------- 1 | // ALL SKIP STATEMENTS THAT AFFECT THIS SHADER!!! 2 | // defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH 3 | 4 | #pragma once 5 | #include "shaderlib/cshader.h" 6 | class GWaterFinalpass_vs30_Static_Index 7 | { 8 | public: 9 | GWaterFinalpass_vs30_Static_Index() 10 | { 11 | } 12 | 13 | int GetIndex() const 14 | { 15 | return 0; 16 | } 17 | }; 18 | 19 | #define shaderStaticTest_GWaterFinalpass_vs30 1 20 | 21 | 22 | class GWaterFinalpass_vs30_Dynamic_Index 23 | { 24 | unsigned int m_nNUM_LIGHTS : 3; 25 | #ifdef _DEBUG 26 | bool m_bNUM_LIGHTS : 1; 27 | #endif // _DEBUG 28 | public: 29 | void SetNUM_LIGHTS( int i ) 30 | { 31 | Assert( i >= 0 && i <= 4 ); 32 | m_nNUM_LIGHTS = i; 33 | #ifdef _DEBUG 34 | m_bNUM_LIGHTS = true; 35 | #endif // _DEBUG 36 | } 37 | 38 | GWaterFinalpass_vs30_Dynamic_Index() 39 | { 40 | m_nNUM_LIGHTS = 0; 41 | #ifdef _DEBUG 42 | m_bNUM_LIGHTS = false; 43 | #endif // _DEBUG 44 | } 45 | 46 | int GetIndex() const 47 | { 48 | Assert( m_bNUM_LIGHTS ); 49 | return ( 1 * m_nNUM_LIGHTS ) + 0; 50 | } 51 | }; 52 | 53 | #define shaderDynamicTest_GWaterFinalpass_vs30 vsh_forgot_to_set_dynamic_NUM_LIGHTS 54 | 55 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterNormals_ps30.inc: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shaderlib/cshader.h" 3 | class GWaterNormals_ps30_Static_Index 4 | { 5 | public: 6 | GWaterNormals_ps30_Static_Index( ) 7 | { 8 | } 9 | 10 | int GetIndex() const 11 | { 12 | return 0; 13 | } 14 | }; 15 | 16 | #define shaderStaticTest_GWaterNormals_ps30 1 17 | 18 | 19 | class GWaterNormals_ps30_Dynamic_Index 20 | { 21 | unsigned int m_nDEPTH : 2; 22 | #ifdef _DEBUG 23 | bool m_bDEPTH : 1; 24 | #endif // _DEBUG 25 | public: 26 | void SetDEPTH( int i ) 27 | { 28 | Assert( i >= 0 && i <= 1 ); 29 | m_nDEPTH = i; 30 | #ifdef _DEBUG 31 | m_bDEPTH = true; 32 | #endif // _DEBUG 33 | } 34 | 35 | GWaterNormals_ps30_Dynamic_Index( ) 36 | { 37 | m_nDEPTH = 0; 38 | #ifdef _DEBUG 39 | m_bDEPTH = false; 40 | #endif // _DEBUG 41 | } 42 | 43 | int GetIndex() const 44 | { 45 | Assert( m_bDEPTH ); 46 | return ( 1 * m_nDEPTH ) + 0; 47 | } 48 | }; 49 | 50 | #define shaderDynamicTest_GWaterNormals_ps30 psh_forgot_to_set_dynamic_DEPTH 51 | 52 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterNormals_vs30.inc: -------------------------------------------------------------------------------- 1 | // ALL SKIP STATEMENTS THAT AFFECT THIS SHADER!!! 2 | // defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH 3 | 4 | #pragma once 5 | #include "shaderlib/cshader.h" 6 | class GWaterNormals_vs30_Static_Index 7 | { 8 | public: 9 | GWaterNormals_vs30_Static_Index( ) 10 | { 11 | } 12 | 13 | int GetIndex() const 14 | { 15 | return 0; 16 | } 17 | }; 18 | 19 | #define shaderStaticTest_GWaterNormals_vs30 1 20 | 21 | 22 | class GWaterNormals_vs30_Dynamic_Index 23 | { 24 | public: 25 | GWaterNormals_vs30_Dynamic_Index( ) 26 | { 27 | } 28 | 29 | int GetIndex() const 30 | { 31 | return 0; 32 | } 33 | }; 34 | 35 | #define shaderDynamicTest_GWaterNormals_vs30 1 36 | 37 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterSmooth_ps30.inc: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shaderlib/cshader.h" 3 | class GWaterSmooth_ps30_Static_Index 4 | { 5 | public: 6 | GWaterSmooth_ps30_Static_Index( ) 7 | { 8 | } 9 | 10 | int GetIndex() const 11 | { 12 | return 0; 13 | } 14 | }; 15 | 16 | #define shaderStaticTest_GWaterSmooth_ps30 1 17 | 18 | 19 | class GWaterSmooth_ps30_Dynamic_Index 20 | { 21 | public: 22 | GWaterSmooth_ps30_Dynamic_Index( ) 23 | { 24 | } 25 | 26 | int GetIndex() const 27 | { 28 | return 0; 29 | } 30 | }; 31 | 32 | #define shaderDynamicTest_GWaterSmooth_ps30 1 33 | 34 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterVolumetric_ps30.inc: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "shaderlib/cshader.h" 3 | class GWaterVolumetric_ps30_Static_Index 4 | { 5 | public: 6 | GWaterVolumetric_ps30_Static_Index( ) 7 | { 8 | } 9 | 10 | int GetIndex() const 11 | { 12 | return 0; 13 | } 14 | }; 15 | 16 | #define shaderStaticTest_GWaterVolumetric_ps30 1 17 | 18 | 19 | class GWaterVolumetric_ps30_Dynamic_Index 20 | { 21 | public: 22 | GWaterVolumetric_ps30_Dynamic_Index( ) 23 | { 24 | } 25 | 26 | int GetIndex() const 27 | { 28 | return 0; 29 | } 30 | }; 31 | 32 | #define shaderDynamicTest_GWaterVolumetric_ps30 1 33 | 34 | -------------------------------------------------------------------------------- /binary/src/shaders/inc/GWaterVolumetric_vs30.inc: -------------------------------------------------------------------------------- 1 | // ALL SKIP STATEMENTS THAT AFFECT THIS SHADER!!! 2 | // defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH 3 | 4 | #pragma once 5 | #include "shaderlib/cshader.h" 6 | class GWaterVolumetric_vs30_Static_Index 7 | { 8 | public: 9 | GWaterVolumetric_vs30_Static_Index( ) 10 | { 11 | } 12 | 13 | int GetIndex() const 14 | { 15 | return 0; 16 | } 17 | }; 18 | 19 | #define shaderStaticTest_GWaterVolumetric_vs30 1 20 | 21 | 22 | class GWaterVolumetric_vs30_Dynamic_Index 23 | { 24 | public: 25 | GWaterVolumetric_vs30_Dynamic_Index( ) 26 | { 27 | } 28 | 29 | int GetIndex() const 30 | { 31 | return 0; 32 | } 33 | }; 34 | 35 | #define shaderDynamicTest_GWaterVolumetric_vs30 1 36 | 37 | -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterFinalpass_ps30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterFinalpass_ps30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterFinalpass_vs30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterFinalpass_vs30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterNormals_ps30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterNormals_ps30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterNormals_vs30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterNormals_vs30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterSmooth_ps30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterSmooth_ps30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterVolumetric_ps30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterVolumetric_ps30.vcs -------------------------------------------------------------------------------- /binary/src/shaders/vcs/GWaterVolumetric_vs30.vcs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/shaders/vcs/GWaterVolumetric_vs30.vcs -------------------------------------------------------------------------------- /binary/src/sourceengine/IShaderSystem.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/sourceengine/IShaderSystem.h -------------------------------------------------------------------------------- /binary/src/sourceengine/cpp_shader_constant_register_map.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: Provide convenient mapping for shader constants 4 | // 5 | // $NoKeywords: $ 6 | //============================================================================= 7 | 8 | #define C_CODE_HACK 9 | #include "shader_constant_register_map.h" 10 | #undef C_CODE_HACK 11 | 12 | // For the C code, map the above file's defines back to integers... 13 | #define PSREG_CONSTANT_00 0 14 | #define PSREG_CONSTANT_01 1 15 | #define PSREG_CONSTANT_02 2 16 | #define PSREG_CONSTANT_03 3 17 | #define PSREG_CONSTANT_04 4 18 | #define PSREG_CONSTANT_05 5 19 | #define PSREG_CONSTANT_06 6 20 | #define PSREG_CONSTANT_07 7 21 | #define PSREG_CONSTANT_08 8 22 | #define PSREG_CONSTANT_09 9 23 | #define PSREG_CONSTANT_10 10 24 | #define PSREG_CONSTANT_11 11 25 | #define PSREG_CONSTANT_12 12 26 | #define PSREG_CONSTANT_13 13 27 | #define PSREG_CONSTANT_14 14 28 | #define PSREG_CONSTANT_15 15 29 | #define PSREG_CONSTANT_16 16 30 | #define PSREG_CONSTANT_17 17 31 | #define PSREG_CONSTANT_18 18 32 | #define PSREG_CONSTANT_19 19 33 | #define PSREG_CONSTANT_20 20 34 | #define PSREG_CONSTANT_21 21 35 | #define PSREG_CONSTANT_22 22 36 | #define PSREG_CONSTANT_23 23 37 | #define PSREG_CONSTANT_24 24 38 | #define PSREG_CONSTANT_25 25 39 | #define PSREG_CONSTANT_26 26 40 | #define PSREG_CONSTANT_27 27 41 | #define PSREG_CONSTANT_28 28 42 | #define PSREG_CONSTANT_29 29 43 | #define PSREG_CONSTANT_30 30 44 | #define PSREG_CONSTANT_31 31 45 | 46 | -------------------------------------------------------------------------------- /binary/src/sourceengine/imaterialsysteminternal.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | // $NoKeywords: $ 6 | // 7 | //=============================================================================// 8 | 9 | #ifndef IMATERIALSYSTEMINTERNAL_H 10 | #define IMATERIALSYSTEMINTERNAL_H 11 | 12 | #ifdef _WIN32 13 | #pragma once 14 | #endif 15 | 16 | #include "materialsystem/imaterialsystem.h" 17 | #include "tier1/callqueue.h" 18 | #include "tier1/memstack.h" 19 | 20 | class IMaterialInternal; 21 | 22 | //----------------------------------------------------------------------------- 23 | // Special call queue that knows (a) single threaded access, and (b) all 24 | // functions called after last function added 25 | //----------------------------------------------------------------------------- 26 | 27 | class CMatCallQueue 28 | { 29 | public: 30 | CMatCallQueue() 31 | { 32 | MEM_ALLOC_CREDIT_( "CMatCallQueue.m_Allocator" ); 33 | #ifdef SWDS 34 | m_Allocator.Init( NULL, 0, 0, 4 ); 35 | #else 36 | #ifdef GMOD_MAIN 37 | m_Allocator.Init(IsX360() ? 2 * 1024 * 1024 : 8 * 1024 * 1024, 64 * 1024, 256 * 1024, 4); 38 | #else 39 | m_Allocator.Init(NULL, IsX360() ? 2 * 1024 * 1024 : 8 * 1024 * 1024, 64 * 1024, 256 * 1024, 4); // needed to edit this function so it is compatable with the 2013 sdk 40 | #endif 41 | #endif 42 | m_FunctorFactory.SetAllocator( &m_Allocator ); 43 | m_pHead = m_pTail = NULL; 44 | } 45 | 46 | size_t GetMemoryUsed() 47 | { 48 | return m_Allocator.GetUsed(); 49 | } 50 | 51 | int Count() 52 | { 53 | int i = 0; 54 | Elem_t *pCurrent = m_pHead; 55 | while ( pCurrent ) 56 | { 57 | i++; 58 | pCurrent = pCurrent->pNext; 59 | } 60 | return i; 61 | } 62 | 63 | void CallQueued() 64 | { 65 | if ( !m_pHead ) 66 | { 67 | return; 68 | } 69 | 70 | CFunctor *pFunctor; 71 | 72 | Elem_t *pCurrent = m_pHead; 73 | while ( pCurrent ) 74 | { 75 | pFunctor = pCurrent->pFunctor; 76 | #ifdef _DEBUG 77 | if ( pFunctor->m_nUserID == m_nBreakSerialNumber) 78 | { 79 | m_nBreakSerialNumber = (unsigned)-1; 80 | } 81 | #endif 82 | (*pFunctor)(); 83 | pFunctor->Release(); 84 | pCurrent = pCurrent->pNext; 85 | } 86 | m_Allocator.FreeAll( false ); 87 | m_pHead = m_pTail = NULL; 88 | } 89 | 90 | void QueueFunctor( CFunctor *pFunctor ) 91 | { 92 | Assert( pFunctor ); 93 | QueueFunctorInternal( RetAddRef( pFunctor ) ); 94 | } 95 | 96 | void Flush() 97 | { 98 | if ( !m_pHead ) 99 | { 100 | return; 101 | } 102 | 103 | CFunctor *pFunctor; 104 | 105 | Elem_t *pCurrent = m_pHead; 106 | while ( pCurrent ) 107 | { 108 | pFunctor = pCurrent->pFunctor; 109 | pFunctor->Release(); 110 | pCurrent = pCurrent->pNext; 111 | } 112 | 113 | m_Allocator.FreeAll( false ); 114 | m_pHead = m_pTail = NULL; 115 | } 116 | 117 | #define DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL(N) \ 118 | template \ 119 | void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ 120 | { \ 121 | QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ 122 | } 123 | 124 | //------------------------------------- 125 | 126 | #define DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL(N) \ 127 | template \ 128 | void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ 129 | { \ 130 | QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ 131 | } 132 | 133 | //------------------------------------- 134 | 135 | #define DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \ 136 | template \ 137 | void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ 138 | { \ 139 | QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \ 140 | } 141 | 142 | //------------------------------------- 143 | 144 | FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL ); 145 | FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL ); 146 | FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL ); 147 | 148 | private: 149 | void QueueFunctorInternal( CFunctor *pFunctor ) 150 | { 151 | #ifdef _DEBUG 152 | pFunctor->m_nUserID = m_nCurSerialNumber++; 153 | #endif 154 | MEM_ALLOC_CREDIT_( "CMatCallQueue.m_Allocator" ); 155 | Elem_t *pNew = (Elem_t *)m_Allocator.Alloc( sizeof(Elem_t) ); 156 | if ( m_pTail ) 157 | { 158 | m_pTail->pNext = pNew; 159 | m_pTail = pNew; 160 | } 161 | else 162 | { 163 | m_pHead = m_pTail = pNew; 164 | } 165 | pNew->pNext = NULL; 166 | pNew->pFunctor = pFunctor; 167 | } 168 | 169 | struct Elem_t 170 | { 171 | Elem_t *pNext; 172 | CFunctor *pFunctor; 173 | }; 174 | 175 | Elem_t *m_pHead; 176 | Elem_t *m_pTail; 177 | 178 | CMemoryStack m_Allocator; 179 | CCustomizedFunctorFactory > > m_FunctorFactory; 180 | unsigned m_nCurSerialNumber; 181 | unsigned m_nBreakSerialNumber; 182 | }; 183 | 184 | 185 | class IMaterialProxy; 186 | 187 | 188 | //----------------------------------------------------------------------------- 189 | // Additional interfaces used internally to the library 190 | //----------------------------------------------------------------------------- 191 | abstract_class IMaterialSystemInternal : public IMaterialSystem 192 | { 193 | public: 194 | // Returns the current material 195 | virtual IMaterial* GetCurrentMaterial() = 0; 196 | 197 | virtual int GetLightmapPage( void ) = 0; 198 | 199 | // Gets the maximum lightmap page size... 200 | virtual int GetLightmapWidth( int lightmap ) const = 0; 201 | virtual int GetLightmapHeight( int lightmap ) const = 0; 202 | 203 | virtual ITexture *GetLocalCubemap( void ) = 0; 204 | 205 | // virtual bool RenderZOnlyWithHeightClipEnabled( void ) = 0; 206 | virtual void ForceDepthFuncEquals( bool bEnable ) = 0; 207 | virtual enum MaterialHeightClipMode_t GetHeightClipMode( void ) = 0; 208 | 209 | // FIXME: Remove? Here for debugging shaders in CShaderSystem 210 | virtual void AddMaterialToMaterialList( IMaterialInternal *pMaterial ) = 0; 211 | virtual void RemoveMaterial( IMaterialInternal *pMaterial ) = 0; 212 | virtual void RemoveMaterialSubRect( IMaterialInternal *pMaterial ) = 0; 213 | virtual bool InFlashlightMode() const = 0; 214 | 215 | // Can we use editor materials? 216 | virtual bool CanUseEditorMaterials() const = 0; 217 | virtual const char *GetForcedTextureLoadPathID() = 0; 218 | 219 | virtual CMatCallQueue *GetRenderCallQueue() = 0; 220 | 221 | virtual void UnbindMaterial( IMaterial *pMaterial ) = 0; 222 | virtual uint GetRenderThreadId() const = 0 ; 223 | 224 | virtual IMaterialProxy *DetermineProxyReplacements( IMaterial *pMaterial, KeyValues *pFallbackKeyValues ) = 0; 225 | }; 226 | 227 | 228 | #endif // IMATERIALSYSTEMINTERNAL_H 229 | -------------------------------------------------------------------------------- /binary/src/sourceengine/materialsystem_global.cpp: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | //=====================================================================================// 6 | 7 | #include "materialsystem_global.h" 8 | #include "shaderapi/ishaderapi.h" 9 | #include "shadersystem.h" 10 | #include 11 | #include "filesystem.h" 12 | 13 | // memdbgon must be the last include file in a .cpp file!!! 14 | #include "tier0/memdbgon.h" 15 | 16 | int g_FrameNum; 17 | IShaderAPI *g_pShaderAPI = 0; 18 | IShaderDeviceMgr* g_pShaderDeviceMgr = 0; 19 | IShaderDevice *g_pShaderDevice = 0; 20 | IShaderShadow* g_pShaderShadow = 0; 21 | -------------------------------------------------------------------------------- /binary/src/sourceengine/materialsystem_global.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: 4 | // 5 | // $Header: $ 6 | // $NoKeywords: $ 7 | // 8 | //=============================================================================// 9 | 10 | #ifndef MATERIALSYSTEM_GLOBAL_H 11 | #define MATERIALSYSTEM_GLOBAL_H 12 | 13 | #ifdef _WIN32 14 | #pragma once 15 | #endif 16 | 17 | #include "imaterialsysteminternal.h" 18 | #include "tier0/dbg.h" 19 | #include "tier2/tier2.h" 20 | 21 | 22 | //----------------------------------------------------------------------------- 23 | // Forward declarations 24 | //----------------------------------------------------------------------------- 25 | class ITextureInternal; 26 | class IShaderAPI; 27 | class IHardwareConfigInternal; 28 | class IShaderUtil; 29 | class IShaderShadow; 30 | class IShaderDeviceMgr; 31 | class IShaderDevice; 32 | class IShaderSystemInternal; 33 | class IMaterialInternal; 34 | class IColorCorrectionSystem; 35 | class IMaterialVar; 36 | 37 | 38 | //----------------------------------------------------------------------------- 39 | // Constants used by the system 40 | //----------------------------------------------------------------------------- 41 | 42 | #define MATERIAL_MAX_PATH 256 43 | 44 | // GR - limits for blured image (HDR stuff) 45 | #define MAX_BLUR_IMAGE_WIDTH 256 46 | #define MAX_BLUR_IMAGE_HEIGHT 192 47 | 48 | #define CLAMP_BLUR_IMAGE_WIDTH( _w ) ( ( _w < MAX_BLUR_IMAGE_WIDTH ) ? _w : MAX_BLUR_IMAGE_WIDTH ) 49 | #define CLAMP_BLUR_IMAGE_HEIGHT( _h ) ( ( _h < MAX_BLUR_IMAGE_HEIGHT ) ? _h : MAX_BLUR_IMAGE_HEIGHT ) 50 | 51 | //----------------------------------------------------------------------------- 52 | // Global structures 53 | //----------------------------------------------------------------------------- 54 | extern MaterialSystem_Config_t g_config; 55 | extern uint32 g_nDebugVarsSignature; 56 | 57 | //extern MaterialSystem_ErrorFunc_t Error; 58 | //extern MaterialSystem_WarningFunc_t Warning; 59 | 60 | extern int g_FrameNum; 61 | 62 | extern IShaderAPI* g_pShaderAPI; 63 | extern IShaderDeviceMgr* g_pShaderDeviceMgr; 64 | extern IShaderDevice* g_pShaderDevice; 65 | extern IShaderShadow* g_pShaderShadow; 66 | 67 | extern IMaterialInternal *g_pErrorMaterial; 68 | 69 | IShaderSystemInternal* ShaderSystem(); 70 | inline IShaderSystemInternal* ShaderSystem() 71 | { 72 | extern IShaderSystemInternal *g_pShaderSystem; 73 | return g_pShaderSystem; 74 | } 75 | 76 | inline IHardwareConfigInternal *HardwareConfig() 77 | { 78 | extern IHardwareConfigInternal* g_pHWConfig; 79 | return g_pHWConfig; 80 | } 81 | 82 | //----------------------------------------------------------------------------- 83 | // Accessor to get at the material system 84 | //----------------------------------------------------------------------------- 85 | inline IMaterialSystemInternal* MaterialSystem() 86 | { 87 | extern IMaterialSystemInternal *g_pInternalMaterialSystem; 88 | return g_pInternalMaterialSystem; 89 | } 90 | 91 | inline IShaderUtil* ShaderUtil() 92 | { 93 | extern IShaderUtil *g_pShaderUtil; 94 | return g_pShaderUtil; 95 | } 96 | 97 | extern IColorCorrectionSystem *g_pColorCorrectionSystem; 98 | inline IColorCorrectionSystem *ColorCorrectionSystem() 99 | { 100 | return g_pColorCorrectionSystem; 101 | } 102 | 103 | 104 | //----------------------------------------------------------------------------- 105 | // Global methods related to material vars 106 | //----------------------------------------------------------------------------- 107 | void EnableThreadedMaterialVarAccess( bool bEnable, IMaterialVar **ppParams, int nVarCount ); 108 | 109 | 110 | #endif // MATERIALSYSTEM_GLOBAL_H 111 | -------------------------------------------------------------------------------- /binary/src/sourceengine/meshutils.cpp: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: A set of utilities to render standard shapes 4 | // 5 | //===========================================================================// 6 | 7 | #include "tier2/meshutils.h" 8 | 9 | 10 | //----------------------------------------------------------------------------- 11 | // Helper methods to create various standard index buffer types 12 | //----------------------------------------------------------------------------- 13 | void GenerateSequentialIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex ) 14 | { 15 | if ( !pIndices ) 16 | return; 17 | 18 | // Format the sequential buffer 19 | for ( int i = 0; i < nIndexCount; ++i ) 20 | { 21 | pIndices[i] = (unsigned short)( i + nFirstVertex ); 22 | } 23 | } 24 | 25 | void GenerateQuadIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex ) 26 | { 27 | if ( !pIndices ) 28 | return; 29 | 30 | // Format the quad buffer 31 | int i; 32 | int numQuads = nIndexCount / 6; 33 | int baseVertex = nFirstVertex; 34 | for ( i = 0; i < numQuads; ++i) 35 | { 36 | // Triangle 1 37 | pIndices[0] = (unsigned short)( baseVertex ); 38 | pIndices[1] = (unsigned short)( baseVertex + 1 ); 39 | pIndices[2] = (unsigned short)( baseVertex + 2 ); 40 | 41 | // Triangle 2 42 | pIndices[3] = (unsigned short)( baseVertex ); 43 | pIndices[4] = (unsigned short)( baseVertex + 2 ); 44 | pIndices[5] = (unsigned short)( baseVertex + 3 ); 45 | 46 | baseVertex += 4; 47 | pIndices += 6; 48 | } 49 | } 50 | 51 | void GeneratePolygonIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex ) 52 | { 53 | if ( !pIndices ) 54 | return; 55 | 56 | int i; 57 | int numPolygons = nIndexCount / 3; 58 | for ( i = 0; i < numPolygons; ++i) 59 | { 60 | // Triangle 1 61 | pIndices[0] = (unsigned short)( nFirstVertex ); 62 | pIndices[1] = (unsigned short)( nFirstVertex + i + 1 ); 63 | pIndices[2] = (unsigned short)( nFirstVertex + i + 2 ); 64 | pIndices += 3; 65 | } 66 | } 67 | 68 | 69 | void GenerateLineStripIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex ) 70 | { 71 | if ( !pIndices ) 72 | return; 73 | 74 | int i; 75 | int numLines = nIndexCount / 2; 76 | for ( i = 0; i < numLines; ++i) 77 | { 78 | pIndices[0] = (unsigned short)( nFirstVertex + i ); 79 | pIndices[1] = (unsigned short)( nFirstVertex + i + 1 ); 80 | pIndices += 2; 81 | } 82 | } 83 | 84 | void GenerateLineLoopIndexBuffer( unsigned short* pIndices, int nIndexCount, int nFirstVertex ) 85 | { 86 | if ( !pIndices ) 87 | { 88 | return; 89 | } 90 | 91 | int i; 92 | int numLines = nIndexCount / 2; 93 | 94 | pIndices[0] = (unsigned short)( nFirstVertex + numLines - 1 ); 95 | pIndices[1] = (unsigned short)( nFirstVertex ); 96 | pIndices += 2; 97 | 98 | for ( i = 1; i < numLines; ++i) 99 | { 100 | pIndices[0] = (unsigned short)( nFirstVertex + i - 1 ); 101 | pIndices[1] = (unsigned short)( nFirstVertex + i ); 102 | pIndices += 2; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /binary/src/sourceengine/meshutils.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: A set of utilities to help with generating meshes 4 | // 5 | //===========================================================================// 6 | 7 | #ifndef MESHUTILS_H 8 | #define MESHUTILS_H 9 | 10 | #ifdef _WIN32 11 | #pragma once 12 | #endif 13 | 14 | 15 | //----------------------------------------------------------------------------- 16 | // Helper methods to create various standard index buffer types 17 | //----------------------------------------------------------------------------- 18 | void GenerateSequentialIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); 19 | void GenerateQuadIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); 20 | void GeneratePolygonIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); 21 | void GenerateLineStripIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); 22 | void GenerateLineLoopIndexBuffer( unsigned short* pIndexMemory, int nIndexCount, int nFirstVertex ); 23 | 24 | 25 | #endif // MESHUTILS_H 26 | 27 | -------------------------------------------------------------------------------- /binary/src/sourceengine/shaderDLL_Global.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/binary/src/sourceengine/shaderDLL_Global.h -------------------------------------------------------------------------------- /binary/src/sourceengine/shader_constant_register_map.h: -------------------------------------------------------------------------------- 1 | //========= Copyright Valve Corporation, All rights reserved. ============// 2 | // 3 | // Purpose: Provide convenient mapping for shader constants 4 | // 5 | // $NoKeywords: $ 6 | //============================================================================= 7 | 8 | #ifndef C_CODE_HACK 9 | #include "common_vertexlitgeneric_dx9.h" 10 | #endif 11 | 12 | #define PSREG_SELFILLUMTINT PSREG_CONSTANT_00 13 | #define PSREG_DIFFUSE_MODULATION PSREG_CONSTANT_01 14 | #define PSREG_ENVMAP_TINT__SHADOW_TWEAKS PSREG_CONSTANT_02 15 | #define PSREG_SELFILLUM_SCALE_BIAS_EXP PSREG_CONSTANT_03 16 | #define PSREG_AMBIENT_CUBE PSREG_CONSTANT_04 17 | // PSREG_AMBIENT_CUBE PSREG_CONSTANT_05 18 | // PSREG_AMBIENT_CUBE PSREG_CONSTANT_06 19 | // PSREG_AMBIENT_CUBE PSREG_CONSTANT_07 20 | // PSREG_AMBIENT_CUBE PSREG_CONSTANT_08 21 | // PSREG_AMBIENT_CUBE PSREG_CONSTANT_09 22 | #define PSREG_ENVMAP_FRESNEL__SELFILLUMMASK PSREG_CONSTANT_10 23 | #define PSREG_EYEPOS_SPEC_EXPONENT PSREG_CONSTANT_11 24 | #define PSREG_FOG_PARAMS PSREG_CONSTANT_12 25 | #define PSREG_FLASHLIGHT_ATTENUATION PSREG_CONSTANT_13 26 | #define PSREG_FLASHLIGHT_POSITION_RIM_BOOST PSREG_CONSTANT_14 27 | #define PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_15 28 | // PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_16 29 | // PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_17 30 | // PSREG_FLASHLIGHT_TO_WORLD_TEXTURE PSREG_CONSTANT_18 31 | #define PSREG_FRESNEL_SPEC_PARAMS PSREG_CONSTANT_19 32 | #define PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_20 33 | // PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_21 34 | // PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_22 35 | // PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_23 36 | // PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_24 37 | // PSREG_LIGHT_INFO_ARRAY PSREG_CONSTANT_25 38 | #define PSREG_SPEC_RIM_PARAMS PSREG_CONSTANT_26 39 | // #define **free** PSREG_CONSTANT_27 //actually using this often blows constant limits, since literals have to get stuffed somewhere... 40 | #define PSREG_FLASHLIGHT_COLOR PSREG_CONSTANT_28 41 | #define PSREG_LINEAR_FOG_COLOR PSREG_CONSTANT_29 42 | #define PSREG_LIGHT_SCALE PSREG_CONSTANT_30 43 | #define PSREG_FLASHLIGHT_SCREEN_SCALE PSREG_CONSTANT_31 44 | // --- End of ps_2_0 and ps_2_b constants --- 45 | 46 | 47 | #ifndef C_CODE_HACK 48 | //for fxc code, map the constants to register names. 49 | #define PSREG_CONSTANT_00 c0 50 | #define PSREG_CONSTANT_01 c1 51 | #define PSREG_CONSTANT_02 c2 52 | #define PSREG_CONSTANT_03 c3 53 | #define PSREG_CONSTANT_04 c4 54 | #define PSREG_CONSTANT_05 c5 55 | #define PSREG_CONSTANT_06 c6 56 | #define PSREG_CONSTANT_07 c7 57 | #define PSREG_CONSTANT_08 c8 58 | #define PSREG_CONSTANT_09 c9 59 | #define PSREG_CONSTANT_10 c10 60 | #define PSREG_CONSTANT_11 c11 61 | #define PSREG_CONSTANT_12 c12 62 | #define PSREG_CONSTANT_13 c13 63 | #define PSREG_CONSTANT_14 c14 64 | #define PSREG_CONSTANT_15 c15 65 | #define PSREG_CONSTANT_16 c16 66 | #define PSREG_CONSTANT_17 c17 67 | #define PSREG_CONSTANT_18 c18 68 | #define PSREG_CONSTANT_19 c19 69 | #define PSREG_CONSTANT_20 c20 70 | #define PSREG_CONSTANT_21 c21 71 | #define PSREG_CONSTANT_22 c22 72 | #define PSREG_CONSTANT_23 c23 73 | #define PSREG_CONSTANT_24 c24 74 | #define PSREG_CONSTANT_25 c25 75 | #define PSREG_CONSTANT_26 c26 76 | #define PSREG_CONSTANT_27 c27 77 | #define PSREG_CONSTANT_28 c28 78 | #define PSREG_CONSTANT_29 c29 79 | #define PSREG_CONSTANT_30 c30 80 | #define PSREG_CONSTANT_31 c31 81 | #endif 82 | -------------------------------------------------------------------------------- /lua/autorun/gwater2_menufix.lua: -------------------------------------------------------------------------------- 1 | -- fixes menu not working in singleplayer because of predicted hooks. Fuck this shit hack 2 | if !game.SinglePlayer() or CLIENT then return end 3 | 4 | hook.Add("PlayerButtonDown", "gwater2_menu", function(ply, key) 5 | ply:SendLua("pcall(function() gwater2.open_menu(LocalPlayer(), " .. key .. ") end)") 6 | end) 7 | hook.Add("PlayerButtonUp", "gwater2_menu", function(ply, key) 8 | ply:SendLua("pcall(function() gwater2.close_menu(LocalPlayer(), " .. key .. ") end)") 9 | end) -------------------------------------------------------------------------------- /lua/entities/gwater2_blackhole.lua: -------------------------------------------------------------------------------- 1 | -- subject for removal? maybe add a bool in forcefield to make it look like a black hole? 2 | 3 | AddCSLuaFile() 4 | 5 | ENT.Type = "anim" 6 | ENT.Base = "base_anim" 7 | 8 | ENT.Category = "GWater2" 9 | ENT.PrintName = "Black Hole" 10 | ENT.Author = "Meetric" 11 | ENT.Purpose = "" 12 | ENT.Instructions = "" 13 | ENT.Spawnable = true 14 | ENT.Editable = true 15 | 16 | function ENT:SetupDataTables() 17 | self:NetworkVar("Float", 0, "Radius", {KeyName = "Radius", Edit = {type = "Float", order = 0, min = 0, max = 2000}}) 18 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 1, min = -200, max = 200}}) 19 | self:NetworkVar("Bool", 0, "Linear", {KeyName = "Linear", Edit = {type = "Bool", order = 2}}) 20 | self:NetworkVar("Int", 0, "Mode", {KeyName = "Force Mode", Edit = {type = "Int", order = 3, min = 0, max = 2}}) 21 | 22 | if SERVER then return end 23 | 24 | self.PARTICLE_EMITTER = ParticleEmitter(self:GetPos(), false) 25 | hook.Add("gwater2_tick_drains", self, function() 26 | gwater2.solver:AddForceField(self:GetPos(), self:GetRadius(), -self:GetStrength(), self:GetMode(), self:GetLinear()) 27 | end) 28 | end 29 | 30 | if SERVER then 31 | function ENT:Initialize() 32 | self:SetModel("models/hunter/misc/sphere075x075.mdl") 33 | self:SetMaterial("lights/white") 34 | 35 | self:SetColor(color_black) 36 | self:PhysicsInit(SOLID_VPHYSICS) 37 | self:SetMoveType(MOVETYPE_VPHYSICS) 38 | self:SetSolid(SOLID_VPHYSICS) 39 | 40 | -- celestial body, no wiremod integration >:( 41 | end 42 | 43 | function ENT:SpawnFunction(ply, tr, class) 44 | if not tr.Hit then return end 45 | local ent = ents.Create(class) 46 | ent:SetPos(tr.HitPos + tr.HitNormal * 50) 47 | ent:Spawn() 48 | ent:Activate() 49 | 50 | ent:SetRadius(1000) 51 | ent:SetStrength(50) 52 | ent:SetMode(0) 53 | ent:SetLinear(1) 54 | 55 | return ent 56 | end 57 | elseif CLIENT then 58 | function ENT:Draw() 59 | if halo.RenderedEntity() == self then self:DrawModel() end 60 | 61 | -- VERY old code for blackhole visuals, reused from a script I made 3 years ago 62 | if !self.PARTICLE_EMITTER then return end 63 | 64 | local part = self.PARTICLE_EMITTER:Add("particle/warp_ripple", self:GetPos()) 65 | part:SetVelocity(Vector()) 66 | part:SetGravity(Vector()) 67 | part:SetDieTime(FrameTime() * 10) 68 | part:SetStartSize(50) 69 | part:SetEndSize(50) 70 | part:SetLighting(false) 71 | part:SetStartAlpha(50) 72 | part:SetEndAlpha(50) 73 | 74 | -- particle/warp1_warp 75 | local part 76 | if self:GetStrength() >= 0 then 77 | part = self.PARTICLE_EMITTER:Add("gwater2/blackhole", self:GetPos()) 78 | self:SetColor(Color(0, 0, 0, 255)) 79 | else 80 | part = self.PARTICLE_EMITTER:Add("gwater2/whitehole", self:GetPos()) 81 | self:SetColor(color_white) 82 | end 83 | part:SetVelocity(Vector()) 84 | part:SetGravity(Vector()) 85 | part:SetDieTime(FrameTime() * 15) 86 | part:SetStartSize(25 + (math.sin(CurTime() * 2) * 3)) 87 | part:SetEndSize(22) 88 | part:SetStartAlpha(255) 89 | part:SetEndAlpha(255) 90 | --self:SetNextClientThink(CurTime() + 0.001) 91 | self:RemoveAllDecals() 92 | end 93 | 94 | function ENT:OnRemove() 95 | if self.PARTICLE_EMITTER then 96 | self.PARTICLE_EMITTER:Finish() 97 | end 98 | end 99 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_bluetooth_hose.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_gmodentity" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Bluetooth Hose" 8 | ENT.Author = "AndrewEathan" 9 | ENT.Purpose = "Use it to turn it on" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | 13 | function ENT:SetupDataTables() 14 | self:NetworkVar("Bool", 0, "Enabled") 15 | end 16 | 17 | function ENT:Initialize() 18 | if CLIENT then return end 19 | 20 | self:SetModel("models/props_c17/GasPipes006a.mdl") 21 | self:PhysicsInit(SOLID_VPHYSICS) 22 | self:SetMoveType(MOVETYPE_VPHYSICS) 23 | self:SetSolid(SOLID_VPHYSICS) 24 | self:SetUseType(SIMPLE_USE) 25 | self:SetCollisionGroup(COLLISION_GROUP_WORLD) 26 | end 27 | 28 | function ENT:Use() 29 | self:EmitSound("buttons/lever1.wav") 30 | self:SetEnabled(!self:GetEnabled()) 31 | end 32 | 33 | if SERVER then return end 34 | 35 | function ENT:Think() 36 | if !gwater2 then return end 37 | 38 | if self:GetEnabled() then 39 | local pos = self:LocalToWorld(Vector(-7, 0, 25)) 40 | local ang = self:LocalToWorldAngles(Angle(180, 0, 0)) 41 | local vel = self:GetVelocity() 42 | 43 | gwater2.solver:AddParticle(pos + VectorRand(-2, 2), {vel = ang:Forward() * 3 + self:GetVelocity() * FrameTime()}) 44 | end 45 | 46 | self:SetNextClientThink(CurTime() + 0.05) 47 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_cleanup.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "point" 4 | ENT.Base = "base_point" 5 | ENT.AdminOnly = false 6 | ENT.PrintName = "Clean Up" 7 | ENT.Category = "GWater2" 8 | ENT.Author = "AndrewEathan" 9 | ENT.Spawnable = true 10 | 11 | function ENT:SpawnFunction(ply, tr, ClassName) 12 | gwater2.ResetSolver() 13 | 14 | for k, v in ipairs(ents.FindByClass("gwater2_cloth_*")) do -- die 15 | SafeRemoveEntity(v) 16 | end 17 | 18 | return nil 19 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_cloth.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | -- "Refusing to load gwater2_cube because it is missing Type and Base keys!" 4 | ENT.Type = "point" 5 | ENT.Base = "base_point" 6 | -- 7 | 8 | local xyz = { 9 | Vector(50, 50), 10 | Vector(200, 200) 11 | } 12 | 13 | for k, v in ipairs(xyz) do 14 | local ENT = scripted_ents.Get("base_point") 15 | ENT.Type = "point" 16 | ENT.Base = "base_point" 17 | ENT.AdminOnly = false 18 | ENT.PrintName = "Cloth (" .. v.x .. ")" 19 | ENT.Category = "GWater2" 20 | ENT.Author = "AndrewEathan" 21 | ENT.Spawnable = true 22 | 23 | function ENT:SpawnFunction(ply, tr, ClassName) 24 | gwater2.AddCloth(gwater2.quick_matrix(tr.HitPos + Vector(0, 0, 50)), v) 25 | 26 | gwater2.cloth_exists = true 27 | 28 | undo.Create("Cloth (all)") 29 | undo.AddFunction(function(undo, vararg) 30 | if not gwater2.cloth_exists then return false end 31 | gwater2.cloth_exists = false 32 | gwater2.RemoveCloth() 33 | return true 34 | end) 35 | undo.SetPlayer(ply) 36 | undo.Finish() 37 | return nil 38 | end 39 | 40 | scripted_ents.Register(ENT, "gwater2_cloth_" .. v.x) 41 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_cube.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | -- "Refusing to load gwater2_cube because it is missing Type and Base keys!" 4 | ENT.Type = "point" 5 | ENT.Base = "base_point" 6 | -- 7 | 8 | local xyz = { 9 | Vector(5, 5, 5), 10 | Vector(10, 10, 10), 11 | Vector(20, 20, 20), 12 | } 13 | 14 | for k, v in ipairs(xyz) do 15 | local ENT = scripted_ents.Get("base_point") 16 | ENT.Type = "point" 17 | ENT.Base = "base_point" 18 | ENT.AdminOnly = false 19 | ENT.PrintName = "Cube (" .. v.x .. ")" 20 | ENT.Category = "GWater2" 21 | ENT.Author = "AndrewEathan" 22 | ENT.Spawnable = true 23 | 24 | function ENT:SpawnFunction(ply, tr, ClassName) 25 | gwater2.AddCube(gwater2.quick_matrix(tr.HitPos + tr.HitNormal * v.x * (gwater2.parameters.radius or 10) / 2), v) 26 | 27 | return nil 28 | end 29 | 30 | scripted_ents.Register(ENT, "gwater2_cube_" .. v.x) 31 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_drain.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Drain" 8 | ENT.Author = "Meetric" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | 14 | function ENT:SetupDataTables() 15 | self:NetworkVar("Float", 0, "Radius", {KeyName = "Radius", Edit = {type = "Float", order = 0, min = 0, max = 100}}) 16 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 1, min = 0, max = 200}}) 17 | 18 | if SERVER then return end 19 | 20 | hook.Add("gwater2_tick_drains", self, function() 21 | gwater2.solver:AddForceField(self:GetPos(), self:GetRadius(), -self:GetStrength(), 0, true) 22 | 23 | local removed = gwater2.solver:RemoveSphere(gwater2.quick_matrix(self:GetPos(), nil, self:GetRadius())) 24 | if removed > 0 then 25 | self:EmitSound("player/footsteps/slosh" .. math.random(1,4) .. ".wav", 60) 26 | end 27 | end) 28 | end 29 | 30 | function ENT:Initialize() 31 | if CLIENT then return end 32 | self:SetModel("models/xqm/button3.mdl") 33 | self:SetMaterial("phoenix_storms/dome") 34 | 35 | self:PhysicsInit(SOLID_VPHYSICS) 36 | self:SetMoveType(MOVETYPE_VPHYSICS) 37 | self:SetSolid(SOLID_VPHYSICS) 38 | 39 | -- wiremod integration 40 | if WireLib ~= nil then 41 | WireLib.CreateInputs(self, { 42 | "Radius", 43 | "Strength" 44 | }) 45 | end 46 | end 47 | 48 | -- wiremod integration 49 | function ENT:TriggerInput(name, val) 50 | if name == "Radius" then 51 | return self:SetRadius(math.max(0, math.min(100, val))) 52 | end 53 | if name == "Strength" then 54 | return self:SetStrength(math.max(0, math.min(200, val))) 55 | end 56 | end 57 | 58 | function ENT:SpawnFunction(ply, tr, class) 59 | if not tr.Hit then return end 60 | local ent = ents.Create(class) 61 | ent:SetPos(tr.HitPos) 62 | ent:Spawn() 63 | ent:Activate() 64 | 65 | ent:SetRadius(20) 66 | ent:SetStrength(100) 67 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 68 | 69 | return ent 70 | end 71 | 72 | function ENT:Draw() 73 | self:DrawModel() 74 | local pos, ang = self:GetPos(), self:GetAngles() 75 | ang:RotateAroundAxis(ang:Right(), 180) 76 | pos = pos + ang:Up()*0.25 77 | cam.Start3D2D(pos, ang, 0.05) 78 | draw.DrawText("Drain", "DermaDefault", 0, -72, color_white, TEXT_ALIGN_CENTER) 79 | draw.DrawText(language.GetPhrase("gwater2.ent.drain.side"), "DermaLarge", 0, -24, color_white, TEXT_ALIGN_CENTER) 80 | draw.DrawText(string.format( 81 | language.GetPhrase("gwater2.ent.strength").." ".. 82 | language.GetPhrase("gwater2.ent.radius"), self:GetStrength() or "?", self:GetRadius() or "?" 83 | ), "DermaDefault", 0, 96, color_white, TEXT_ALIGN_CENTER) 84 | cam.End3D2D() 85 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_emitter.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_gmodentity" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Emitter" 8 | ENT.Author = "Meetric" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | 14 | function ENT:Initialize() 15 | if CLIENT then return end 16 | 17 | self:SetModel("models/mechanics/wheels/wheel_speed_72.mdl") 18 | self:PhysicsInit(SOLID_VPHYSICS) 19 | self:SetMoveType(MOVETYPE_VPHYSICS) 20 | self:SetSolid(SOLID_VPHYSICS) 21 | self:SetUseType(SIMPLE_USE) 22 | 23 | -- wiremod integration 24 | if WireLib ~= nil then 25 | WireLib.CreateInputs(self, { 26 | "Active", 27 | "Radius", 28 | "Strength", 29 | "Spread", 30 | "Lifetime" 31 | }) 32 | end 33 | end 34 | 35 | -- wiremod integration 36 | function ENT:TriggerInput(name, val) 37 | if name == "Active" then 38 | return self:SetOn(val > 0) 39 | end 40 | if name == "Radius" then 41 | return self:SetRadius(math.max(1, math.min(20, val))) 42 | end 43 | if name == "Strength" then 44 | return self:SetStrength(math.max(1, math.min(100, val))) 45 | end 46 | if name == "Spread" then 47 | return self:SetSpread(math.max(1, math.min(2, val))) 48 | end 49 | if name == "Lifetime" then 50 | return self:SetLifetime(math.max(0, math.min(100, val))) 51 | end 52 | end 53 | 54 | function ENT:SpawnFunction(ply, tr, class) 55 | if not tr.Hit then return end 56 | local ent = ents.Create(class) 57 | ent:SetPos(tr.HitPos) 58 | ent:Spawn() 59 | ent:Activate() 60 | 61 | ent:SetRadius(6) 62 | ent:SetStrength(10) 63 | ent:SetSpread(1) 64 | ent:SetLifetime(0) 65 | ent:SetOn(false) 66 | --ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 67 | ent:SetMaterial("phoenix_storms/gear") 68 | 69 | return ent 70 | end 71 | 72 | function ENT:Use(_, _, type) 73 | self:EmitSound("buttons/lever1.wav") 74 | self:SetOn(not self:GetOn()) 75 | end 76 | 77 | function ENT:SetupDataTables() 78 | self:NetworkVar("Int", 0, "Radius", {KeyName = "Radius", Edit = {type = "Int", order = 0, min = 1, max = 20}}) 79 | self:NetworkVar("Float", 0, "Spread", {KeyName = "Spread", Edit = {type = "Float", order = 2, min = 1, max = 2}}) 80 | self:NetworkVar("Float", 1, "Lifetime", {KeyName = "Lifetime", Edit = {type = "Float", order = 3, min = 0, max = 100}}) 81 | self:NetworkVar("Float", 2, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 4, min = 1, max = 100}}) 82 | self:NetworkVar("Bool", 0, "On", {KeyName = "On", Edit = {type = "Bool", order = 5}}) 83 | 84 | if SERVER then return end 85 | 86 | -- runs per client FleX frame, this may be different per client. 87 | -- more particles might be spawned depending on the client, but this setup allows for laminar flow, which I think looks better 88 | -- The alternative is running a gwater2.AddCylinder in a serverside Think hook, however with that setup different clients may see different results 89 | hook.Add("gwater2_tick_particles", self, function() 90 | if !self:GetOn() then return end 91 | 92 | local particle_radius = gwater2.solver:GetParameter("radius") 93 | local radius = self:GetRadius() 94 | local spread = self:GetSpread() 95 | local strength = self:GetStrength() 96 | 97 | local mat = Matrix() 98 | mat:SetScale(Vector(spread, spread, spread)) 99 | mat:SetAngles(self:GetAngles()) 100 | --mat:SetAngles(self:LocalToWorldAngles(Angle(0, CurTime() * 200, 0))) 101 | mat:SetTranslation(self:GetPos() + self:GetUp() * (6 + particle_radius) * math.Rand(0.999, 1)) 102 | 103 | local lifetime = self:GetLifetime() 104 | if lifetime <= 0 then lifetime = nil end 105 | 106 | gwater2.solver:AddCylinder(mat, Vector(radius, radius, 1), {vel = self:GetUp() * strength, lifetime = lifetime}) 107 | end) 108 | end 109 | 110 | function ENT:Draw() 111 | self:DrawModel() 112 | 113 | local pos, ang = self:GetPos(), self:GetAngles() 114 | ang:RotateAroundAxis(ang:Up(), 180) 115 | pos = pos + ang:Up()*7 116 | 117 | cam.Start3D2D(pos, ang, 0.1) 118 | draw.DrawText("Emitter", "DermaDefault", 0, -72, color_white, TEXT_ALIGN_CENTER) 119 | 120 | draw.DrawText(language.GetPhrase("gwater2.ent.emitter.side"), "DermaLarge", 0, -24, color_white, TEXT_ALIGN_CENTER) 121 | 122 | draw.DrawText(string.format( 123 | language.GetPhrase("gwater2.ent."..(self:GetOn() and "on" or "off")).." ".. 124 | language.GetPhrase("gwater2.ent.strength").." ".. 125 | language.GetPhrase("gwater2.ent.radius").." ".. 126 | language.GetPhrase("gwater2.ent.spread").." ".. 127 | language.GetPhrase("gwater2.ent.lifetime"), 128 | self:GetStrength() or "?", self:GetRadius() or "?", self:GetSpread() or "?", self:GetLifetime() or "?" 129 | ), "DermaDefault", 0, 96, color_white, TEXT_ALIGN_CENTER) 130 | cam.End3D2D() 131 | end 132 | -------------------------------------------------------------------------------- /lua/entities/gwater2_forcefield.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_gmodentity" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Forcefield" 8 | ENT.Author = "Meetric / Jn" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | 14 | function ENT:Initialize() 15 | if CLIENT then return end 16 | 17 | self:SetModel("models/hunter/blocks/cube05x05x05.mdl") 18 | self:PhysicsInit(SOLID_VPHYSICS) 19 | self:SetMoveType(MOVETYPE_VPHYSICS) 20 | self:SetSolid(SOLID_VPHYSICS) 21 | end 22 | 23 | if CLIENT then 24 | function ENT:Draw() 25 | render.DrawWireframeBox(self:GetPos(), Angle(), -Vector(12,12,12), Vector(12,12,12), Color(0, 255, 0), true) 26 | 27 | render.DrawWireframeSphere(self:GetPos(), self:GetRadius(), 15, 15, Color(0, 255, 0), true) 28 | end 29 | end 30 | 31 | function ENT:SpawnFunction(ply, tr, class) 32 | if not tr.Hit then return end 33 | local ent = ents.Create(class) 34 | ent:SetPos(tr.HitPos + Vector(0, 5, 0)) 35 | ent:Spawn() 36 | ent:Activate() 37 | 38 | ent:SetRadius(1000) 39 | ent:SetStrength(50) 40 | ent:SetMode(0) 41 | ent:SetLinear(1) 42 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 43 | 44 | return ent 45 | end 46 | 47 | function ENT:SetupDataTables() 48 | self:NetworkVar("Float", 0, "Radius", {KeyName = "Radius", Edit = {type = "Float", order = 0, min = 0, max = 2000}}) 49 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 1, min = -200, max = 200}}) 50 | self:NetworkVar("Bool", 0, "Linear", {KeyName = "Linear", Edit = {type = "Bool", order = 2}}) 51 | self:NetworkVar("Int", 0, "Mode", {KeyName = "Force Mode", Edit = {type = "Int", order = 3, min = 0, max = 2}}) 52 | 53 | if SERVER then 54 | -- wiremod integration 55 | if WireLib ~= nil then 56 | WireLib.CreateInputs(self, { 57 | "Radius", 58 | "Strength", 59 | "Linear", 60 | "Mode"}) 61 | end 62 | return 63 | end 64 | 65 | hook.Add("gwater2_tick_drains", self, function() 66 | gwater2.solver:AddForceField(self:GetPos(), self:GetRadius(), -self:GetStrength(), self:GetMode(), self:GetLinear()) 67 | end) 68 | end 69 | -- wiremod integration 70 | function ENT:TriggerInput(name, val) 71 | if name == "Radius" then 72 | return self:SetRadius(math.max(0, math.min(2000, val))) 73 | end 74 | if name == "Strength" then 75 | return self:SetStrength(math.max(-200, math.min(200, val))) 76 | end 77 | if name == "Linear" then 78 | return self:SetLinear(val > 0) 79 | end 80 | if name == "Mode" then 81 | return self:SetMode(math.max(0, math.min(2, val))) 82 | end 83 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_mentoscola.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | 5 | ENT.Category = "GWater2" 6 | ENT.PrintName = "Mentos with Cola" 7 | ENT.Author = "AndrewEathan" 8 | ENT.Purpose = "OH NO" 9 | ENT.AdminOnly = false 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | 14 | function ENT:SetupDataTables() 15 | self:NetworkVar("Float", 0, "Strength", { KeyName = "Strength", Edit = {type = "Float", order = 1, min = 0, max = 60}}) 16 | self:NetworkVar("Float", 1, "DieTime", { KeyName = "DieTime", Edit = {type = "Float", order = 2, min = 1, max = 20}}) 17 | end 18 | 19 | if CLIENT then return end 20 | -- SERVER 21 | 22 | function ENT:Initialize() 23 | if WireLib then 24 | WireLib.CreateOutputs(self, {"Active"}) 25 | end 26 | 27 | self.ACTIVATED = false 28 | self.FLOW_SOUND = CreateSound(self, "PhysicsCannister.ThrusterLoop") 29 | self:SetModel("models/props_junk/garbage_glassbottle003a.mdl") 30 | 31 | self:PhysicsInit(SOLID_VPHYSICS) 32 | self:SetMoveType(MOVETYPE_VPHYSICS) 33 | self:SetSolid(SOLID_VPHYSICS) 34 | self:SetUseType(SIMPLE_USE) 35 | end 36 | 37 | function ENT:SpawnFunction(ply, tr, class) 38 | if not tr.Hit then return end 39 | 40 | local ent = ents.Create(class) 41 | ent:SetPos(tr.HitPos + tr.HitNormal * 10) 42 | ent:Spawn() 43 | ent:Activate() 44 | 45 | ent:SetStrength(1) 46 | ent:SetDieTime(6) 47 | 48 | return ent 49 | end 50 | 51 | function ENT:Use() 52 | if self.ACTIVATED or self.START_TIME then return end 53 | 54 | self.ACTIVATED = true 55 | self:EmitSound("gwater2/soda_launch.wav") 56 | 57 | timer.Simple(1, function() 58 | if !IsValid(self) then return end 59 | 60 | self.START_TIME = CurTime() 61 | 62 | self.FLOW_SOUND:Play() 63 | self.FLOW_SOUND:ChangeVolume(1) 64 | end) 65 | end 66 | 67 | function ENT:TriggerInput(name, value) 68 | if name == "Active" and value > 0 then 69 | self:Use(self) 70 | end 71 | end 72 | 73 | 74 | function ENT:OnRemove() 75 | self.FLOW_SOUND:Stop() 76 | end 77 | 78 | function ENT:Think() 79 | self:NextThink(CurTime() + 0.03) 80 | 81 | if !self.ACTIVATED or !self.START_TIME then return end 82 | 83 | if self.START_TIME and CurTime() > self.START_TIME + self:GetDieTime() then 84 | self.START_TIME = nil 85 | self.ACTIVATED = false 86 | self.FLOW_SOUND:Stop() 87 | return true 88 | end 89 | 90 | local phys = self:GetPhysicsObject() 91 | if !IsValid(phys) then return end 92 | 93 | local pos = self:LocalToWorld(Vector(0, 0, 5)) 94 | local ang = self:GetUp() 95 | local percent = 1 - (CurTime() - self.START_TIME) / self:GetDieTime() 96 | 97 | self.FLOW_SOUND:ChangeVolume(percent) 98 | util.ScreenShake(self:GetPos(), percent, 20, 1, 1000) 99 | phys:ApplyForceCenter(-self:GetUp() * percent * phys:GetMass() * 200 * self:GetStrength()) 100 | 101 | --for i = 0, 20 * percent do 102 | -- gwater2.AddParticle(pos + VectorRand(-10, 10), {vel = VectorRand(-1, 1) * 25 * percent}) 103 | --end 104 | 105 | for i = 0, 10 * percent do 106 | gwater2.AddParticle( 107 | self:LocalToWorld(Vector(0, 0, math.random(7, 40))), 108 | {vel = ang * 10 * percent + VectorRand(-1, 1)} 109 | ) 110 | end 111 | 112 | return true 113 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_pickup.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "gravgun_pickup" 8 | ENT.Author = "Meetric" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = false 12 | 13 | -- This file includes multiplayer gravgun support for gwater2 14 | -- this is done via a black hole esque entity which is teleported in front of the players eyes 15 | 16 | function ENT:SetupDataTables() 17 | 18 | if SERVER then return end 19 | 20 | hook.Add("gwater2_tick_drains", self, function() 21 | gwater2.solver:AddForceField(self:GetPos(), 150, -150, 0, true) 22 | end) 23 | end 24 | 25 | if CLIENT then 26 | function ENT:Draw() 27 | self:SetNoDraw(true) 28 | end 29 | 30 | return 31 | end 32 | 33 | --- SERVER --- 34 | 35 | local function is_valid_pickup(ply, key) 36 | if !IsValid(ply) then 37 | return false 38 | end 39 | 40 | if !ply:KeyDown(key or IN_ATTACK2) then 41 | return false 42 | end 43 | 44 | local weapon = ply:GetActiveWeapon() 45 | return IsValid(weapon) and weapon:GetClass() == "weapon_physcannon" 46 | end 47 | 48 | function ENT:UpdatePosition() 49 | local owner = self.GWATER2_PARENT 50 | self:SetPos(owner:EyePos() + owner:GetAimVector() * 170) 51 | end 52 | 53 | function ENT:Initialize() 54 | self:SetModel("models/maxofs2d/hover_basic.mdl") 55 | self:SetNotSolid(true) 56 | self:SetMoveType(MOVETYPE_NONE) 57 | end 58 | 59 | function ENT:Think() 60 | local owner = self.GWATER2_PARENT 61 | if !is_valid_pickup(owner) then 62 | self:Remove() 63 | return 64 | end 65 | 66 | self:UpdatePosition() 67 | self:NextThink(CurTime()) 68 | return true 69 | end 70 | 71 | hook.Add("KeyPress", "gwater2_gravgun", function(ply, key) 72 | if !IsValid(ply.GWATER2_PARENT) and is_valid_pickup(ply) then 73 | local force_field = ents.Create("gwater2_pickup") 74 | force_field.GWATER2_PARENT = ply 75 | ply.GWATER2_PARENT = force_field 76 | force_field:UpdatePosition() 77 | force_field:DrawShadow(false) 78 | force_field:Spawn() 79 | end 80 | end) 81 | 82 | hook.Add("Tick", "gwater2_gravgun", function() 83 | for _, ply in player.Iterator() do 84 | if is_valid_pickup(ply, IN_ATTACK) and (ply.GWATER2_PUNT or 0) < ply:GetActiveWeapon():GetNextPrimaryFire() then 85 | ply.GWATER2_PUNT = ply:GetActiveWeapon():GetNextPrimaryFire() 86 | gwater2.AddForceField(ply:EyePos(), 320, 200, 1, false) 87 | end 88 | end 89 | end) -------------------------------------------------------------------------------- /lua/entities/gwater2_rain_emitter.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_gmodentity" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Rain Emitter" 8 | ENT.Author = "Meetric / googer_" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | ENT.RenderGroup = RENDERGROUP_TRANSLUCENT 14 | 15 | function ENT:Initialize() 16 | if CLIENT then return end 17 | 18 | self:SetModel("models/hunter/plates/plate16x16.mdl") 19 | self:PhysicsInit(SOLID_VPHYSICS) 20 | self:SetMoveType(MOVETYPE_VPHYSICS) 21 | self:SetSolid(SOLID_VPHYSICS) 22 | self:SetUseType(SIMPLE_USE) 23 | 24 | -- wiremod integration 25 | if WireLib ~= nil then 26 | WireLib.CreateInputs(self, { 27 | "Active", 28 | "Density", 29 | "Strength", 30 | "Spread", 31 | "Lifetime" 32 | }) 33 | end 34 | end 35 | 36 | -- wiremod integration 37 | function ENT:TriggerInput(name, val) 38 | if name == "Active" then 39 | return self:SetOn(val > 0) 40 | end 41 | if name == "Density" then 42 | return self:SetDensity(math.max(1, math.min(200, val))) 43 | end 44 | if name == "Strength" then 45 | return self:SetStrength(math.max(1, math.min(100, val))) 46 | end 47 | if name == "Lifetime" then 48 | return self:SetLifetime(math.max(0, math.min(100, val))) 49 | end 50 | end 51 | 52 | function ENT:SpawnFunction(ply, tr, class) 53 | if not tr.Hit then return end 54 | local ent = ents.Create(class) 55 | ent:SetPos(tr.HitPos + tr.HitNormal * 300) 56 | ent:Spawn() 57 | ent:Activate() 58 | 59 | ent:SetDensity(10) 60 | ent:SetStrength(1) 61 | ent:SetLifetime(0) 62 | ent:SetOn(true) 63 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 64 | ent:DrawShadow(false) 65 | 66 | return ent 67 | end 68 | 69 | function ENT:Use(_, _, type) 70 | self:EmitSound("buttons/lever1.wav") 71 | self:SetOn(not self:GetOn()) 72 | end 73 | 74 | function ENT:SetupDataTables() 75 | self:NetworkVar("Int", 1, "Density", {KeyName = "Density", Edit = {type = "Int", order = 1, min = 1, max = 200}}) 76 | self:NetworkVar("Float", 0, "Lifetime", {KeyName = "Lifetime", Edit = {type = "Float", order = 2, min = 0, max = 100}}) 77 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 3, min = 1, max = 100}}) 78 | self:NetworkVar("Bool", 0, "On", {KeyName = "On", Edit = {type = "Bool", order = 4}}) 79 | 80 | if SERVER then return end 81 | 82 | local function vector_rand_range(v1, v2) 83 | return Vector(math.Rand(v1[1], v2[1]), math.Rand(v1[2], v2[2]), math.Rand(v1[3], v2[3])) 84 | end 85 | 86 | hook.Add("gwater2_tick_particles", self, function() 87 | if !self:GetOn() then return end 88 | 89 | local lifetime = self:GetLifetime() 90 | if lifetime <= 0 then lifetime = nil end 91 | 92 | for i = 1, self:GetDensity() do 93 | gwater2.solver:AddParticle( 94 | self:LocalToWorld(self:OBBCenter() + vector_rand_range(self:OBBMins(), self:OBBMaxs())), 95 | {vel = -self:GetUp() * self:GetStrength(), lifetime = lifetime} 96 | ) 97 | end 98 | end) 99 | end 100 | 101 | local function render_easyquad(pos, ang, sizex, sizey, winding) 102 | local p0 = ang:Forward() * sizex 103 | local p1 = ang:Forward() * -sizex 104 | local p2 = ang:Right() * sizey 105 | local p3 = ang:Right() * -sizey 106 | 107 | if winding then 108 | render.DrawQuad( 109 | pos + p0 + p2, 110 | pos + p0 + p3, 111 | pos + p1 + p3, 112 | pos + p1 + p2 113 | ) 114 | else 115 | render.DrawQuad( 116 | pos + p1 + p3, 117 | pos + p0 + p3, 118 | pos + p0 + p2, 119 | pos + p1 + p2 120 | ) 121 | end 122 | end 123 | 124 | -- 3d parallax effect 125 | local function unfuck_lighting(pos0, pos1) 126 | render.OverrideColorWriteEnable(true, false) 127 | render.OverrideDepthEnable(true, false) 128 | render.Model({model = "models/shadertest/vertexlit.mdl",pos = pos0, angle = EyeAngles()}) -- lighting 129 | render.OverrideDepthEnable(false, false) 130 | render.OverrideColorWriteEnable(false, false) 131 | end 132 | 133 | local cloud = Material("gwater2/clouds") 134 | function ENT:Draw() 135 | if halo.RenderedEntity() == self then 136 | self:DrawModel() 137 | return 138 | end 139 | 140 | unfuck_lighting(self:GetPos()) 141 | render.SetMaterial(cloud) 142 | 143 | local color = self:GetColor() 144 | cloud:SetVector4D("$color2", color.r / 255, color.g / 255, color.b / 255, 255) 145 | 146 | local obb = self:OBBMaxs() 147 | local width = obb[1] 148 | local length = obb[2] 149 | local height = obb[3] 150 | 151 | -- top 152 | for i = 0, 9 do 153 | cloud:SetInt("$frame", i) -- slice of volume texture 154 | render_easyquad(self:GetPos() + self:GetUp() * i * height, self:GetAngles(), width, length) 155 | end 156 | 157 | -- bottom 158 | 159 | for i = 0, 9 do 160 | cloud:SetInt("$frame", 9 - i) 161 | render_easyquad(self:GetPos() + self:GetUp() * (9 - i) * height, self:GetAngles(), width, length, true) 162 | end 163 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_showerhead.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Base = "base_gmodentity" 4 | ENT.Type = "anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Shower Head" 8 | ENT.Author = "AndrewEathan" 9 | ENT.Purpose = "Functional GWater showerhead!" 10 | ENT.Instructions = "" 11 | ENT.Editable = true 12 | ENT.Spawnable = true 13 | 14 | function ENT:SetupDataTables() 15 | self:NetworkVar("Int", 0, "Density", {KeyName = "Density", Edit = {type = "Int", order = 0, min = 1, max = 20}}) 16 | self:NetworkVar("Float", 0, "Lifetime", {KeyName = "Lifetime", Edit = {type = "Float", order = 1, min = 0, max = 100}}) 17 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 2, min = 1, max = 10}}) 18 | self:NetworkVar("Bool", 0, "On", {KeyName = "On", Edit = {type = "Bool", order = 3}}) 19 | end 20 | 21 | function ENT:Initialize() 22 | if CLIENT then return end 23 | 24 | -- wiremod integration 25 | if WireLib ~= nil then 26 | WireLib.CreateInputs(self, { 27 | "Active", 28 | "Density", 29 | "Strength", 30 | "Lifetime" 31 | }) 32 | end 33 | 34 | self:PhysicsInit(SOLID_VPHYSICS) 35 | self:SetMoveType(MOVETYPE_VPHYSICS) 36 | self:SetSolid(SOLID_VPHYSICS) 37 | self:SetUseType(SIMPLE_USE) 38 | end 39 | 40 | function ENT:SpawnFunction(ply, tr, class) 41 | if not tr.Hit then return end 42 | 43 | local ent = ents.Create(class) 44 | ent:SetModel("models/props_wasteland/prison_lamp001a.mdl") 45 | ent:SetSkin(1) 46 | ent:PhysicsInit(SOLID_VPHYSICS) 47 | ent:SetMoveType(MOVETYPE_VPHYSICS) 48 | ent:SetSolid(SOLID_VPHYSICS) 49 | ent:SetUseType(SIMPLE_USE) 50 | ent:SetPos(tr.HitPos + tr.HitNormal * 10) 51 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 52 | ent:Spawn() 53 | ent:SetOn(false) 54 | ent:SetDensity(1) 55 | ent:SetStrength(1) 56 | ent:SetLifetime(0) 57 | 58 | return ent 59 | end 60 | 61 | -- wiremod integration 62 | function ENT:TriggerInput(name, val) 63 | if name == "Active" then 64 | return self:SetOn(val > 0) 65 | end 66 | if name == "Density" then 67 | return self:SetDensity(math.max(1, math.min(20, val))) 68 | end 69 | if name == "Strength" then 70 | return self:SetStrength(math.max(1, math.min(10, val))) 71 | end 72 | if name == "Lifetime" then 73 | return self:SetLifetime(math.max(0, math.min(100, val))) 74 | end 75 | end 76 | 77 | function ENT:Use(_, _, type) 78 | self:EmitSound("buttons/lever1.wav") 79 | self:SetOn(not self:GetOn()) 80 | end 81 | 82 | if SERVER then return end 83 | 84 | function ENT:Think() 85 | if !gwater2 then return end 86 | 87 | if self:GetOn() then 88 | local pos = self:LocalToWorld(Vector(0, 0, -20)) 89 | local vel = self:GetVelocity() * FrameTime() 90 | local ppe = self:GetDensity() 91 | local fmul = self:GetStrength() 92 | local lifetime = self:GetLifetime() 93 | if lifetime <= 0 then lifetime = nil end 94 | 95 | for i = 0, ppe do 96 | gwater2.solver:AddParticle( 97 | pos + VectorRand(-10 + ppe, 10 - ppe), 98 | {vel = self:GetUp() * -5 * fmul + vel, lifetime = lifetime}) 99 | end 100 | end 101 | 102 | self:SetNextClientThink(CurTime() + 0.06) 103 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_sphere.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | -- "Refusing to load gwater2_cube because it is missing Type and Base keys!" 4 | ENT.Type = "point" 5 | ENT.Base = "base_point" 6 | -- 7 | 8 | local xyz = { 9 | 5, 10 | 10, 11 | 20 12 | } 13 | 14 | for k, v in ipairs(xyz) do 15 | local ENT = scripted_ents.Get("base_point") 16 | ENT.Type = "point" 17 | ENT.Base = "base_point" 18 | ENT.AdminOnly = false 19 | ENT.PrintName = "Sphere (" .. v .. ")" 20 | ENT.Category = "GWater2" 21 | ENT.Author = "AndrewEathan" 22 | ENT.Spawnable = true 23 | 24 | function ENT:SpawnFunction(ply, tr, ClassName) 25 | gwater2.AddSphere(gwater2.quick_matrix(tr.HitPos + tr.HitNormal * v * (gwater2.parameters.radius or 10)), v) 26 | 27 | return nil 28 | end 29 | 30 | scripted_ents.Register(ENT, "gwater2_sphere_" .. v) 31 | end -------------------------------------------------------------------------------- /lua/entities/gwater2_transmuter.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Transmuter" 8 | ENT.Author = "Meetric" 9 | ENT.Purpose = "Turns objects into water" 10 | ENT.Instructions = "Touch it" 11 | ENT.Spawnable = true 12 | ENT.AdminOnly = true 13 | ENT.RenderGroup = RENDERGROUP_OPAQUE -- make sure water sees this object 14 | ENT.GWATER2_TOUCHED = true 15 | 16 | if CLIENT then return end 17 | function ENT:SetupDataTables() 18 | self:NetworkVar("Bool", 0, "On", {KeyName = "On", Edit = {type = "Bool", order = 0}}) 19 | if CLIENT then return end 20 | -- wiremod integration 21 | if WireLib ~= nil then 22 | WireLib.CreateInputs(self, { 23 | "Active"}) 24 | end 25 | end 26 | 27 | -- wiremod integration 28 | function ENT:TriggerInput(name, val) 29 | if name == "Active" then 30 | return self:SetOn(val > 0) 31 | end 32 | end 33 | 34 | function ENT:UpdateMaterial() 35 | self:SetSubMaterial(1, self:GetOn() and "models/alyx/emptool_glow" or "Models/effects/vol_light001") 36 | end 37 | 38 | function ENT:Initialize() 39 | self:SetModel("models/props_phx/construct/plastic/plastic_panel2x2.mdl") 40 | self:UpdateMaterial() 41 | self:PhysicsInit(SOLID_VPHYSICS) 42 | self:SetMoveType(MOVETYPE_VPHYSICS) 43 | self:SetSolid(SOLID_VPHYSICS) 44 | self:DrawShadow(false) 45 | self:SetUseType(SIMPLE_USE) 46 | self:SetTrigger(true) 47 | 48 | util.PrecacheModel("models/props_c17/oildrum001.mdl") 49 | end 50 | 51 | function ENT:SpawnFunction(ply, tr, class) 52 | if not tr.Hit then return end 53 | local ent = ents.Create(class) 54 | ent:SetPos(tr.HitPos) 55 | ent:SetOn(true) 56 | ent:Spawn() 57 | ent:Activate() 58 | 59 | return ent 60 | end 61 | 62 | function ENT:StartTouch(ent) 63 | if !self:GetOn() or ent.GWATER2_TOUCHED or !self:GetTouchTrace().Hit then return end 64 | 65 | if ent:IsPlayer() then 66 | if ent:Alive() then 67 | ent:KillSilent() 68 | gwater2.AddModel(gwater2.quick_matrix(ent:GetPos(), nil, Vector(1, 1, 1.5)), "models/props_c17/oildrum001.mdl", {vel = ent:GetVelocity() * FrameTime()}) 69 | end 70 | 71 | return 72 | end 73 | 74 | local phys = ent:GetPhysicsObject() 75 | if !IsValid(phys) then return end 76 | 77 | local extra = { 78 | ent_vel = phys:GetVelocity() * FrameTime(), 79 | ent_angvel = phys:GetAngleVelocity() * FrameTime() 80 | } 81 | local model = ent:GetModel() 82 | local transform = gwater2.quick_matrix(phys:GetPos(), phys:GetAngles()) 83 | 84 | phys:EnableMotion(false) 85 | ent:SetNotSolid(true) 86 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 87 | ent.GWATER2_TOUCHED = true 88 | --ent:Remove() 89 | 90 | -- net is too fast and can cause water to explode sometimes 91 | timer.Simple(0.0, function() 92 | gwater2.AddModel(transform, model, extra) 93 | SafeRemoveEntity(ent) 94 | end) 95 | end 96 | 97 | ENT.Touch = ENT.StartTouch 98 | 99 | function ENT:Use(_, _, type) 100 | self:SetOn(!self:GetOn()) 101 | self:UpdateMaterial() 102 | end 103 | -------------------------------------------------------------------------------- /lua/entities/gwater2_transporter_recv.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Transporter" 8 | ENT.Author = "googer_" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = true 12 | ENT.Editable = true 13 | 14 | function ENT:SetupDataTables() 15 | self:NetworkVar("Int", 0, "RadiusX", {KeyName = "RadiusX", Edit = {type = "Int", order = 0, min = 1, max = 20}}) 16 | self:NetworkVar("Int", 1, "RadiusY", {KeyName = "RadiusY", Edit = {type = "Int", order = 1, min = 1, max = 20}}) 17 | self:NetworkVar("Float", 0, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 2, min = 1, max = 100}}) 18 | self:NetworkVar("Bool", 0, "On", {KeyName = "On", Edit = {type = "Bool", order = 3}}) 19 | 20 | if SERVER then return end 21 | 22 | hook.Add("gwater2_tick_particles", self, function() 23 | self.link = self.link or IsValid(self:GetNWEntity("GWATER2_Link")) and self:GetNWEntity("GWATER2_Link") 24 | if not self:GetOn() then return end 25 | if not self.link then return end 26 | 27 | local particle_radius = gwater2.solver:GetParameter("radius") 28 | local half_particle_radius = particle_radius / 2 29 | local radiusx, radiusy = self:GetRadiusX(), self:GetRadiusY() 30 | local strength = self:GetStrength() 31 | 32 | local offset 33 | local center = self:GetPos() + self:GetUp() * (6 + particle_radius) 34 | for y=-radiusy,radiusy do 35 | if not self.link.GWATER2_particles_drained or self.link.GWATER2_particles_drained <= 0 then break end 36 | for x=-radiusx,radiusx do 37 | if (x * x) + (y * y) >= (radiusx * radiusy) then continue end 38 | offset = self:GetForward() * x * half_particle_radius + self:GetRight() * y * half_particle_radius 39 | gwater2.solver:AddParticle(center + offset, {vel=self:GetUp() * strength}) 40 | self.link.GWATER2_particles_drained = self.link.GWATER2_particles_drained - 1 41 | if self.link.GWATER2_particles_drained <= 0 then break end 42 | end 43 | end 44 | end) 45 | end 46 | 47 | -- wiremod integration 48 | function ENT:TriggerInput(name, val) 49 | if name == "Active" then 50 | return self:SetOn(val > 0) 51 | end 52 | if name == "RadiusX" then 53 | return self:SetRadiusX(math.max(1, math.min(20, val))) 54 | end 55 | if name == "RadiusY" then 56 | return self:SetRadiusY(math.max(1, math.min(20, val))) 57 | end 58 | if name == "Strength" then 59 | return self:SetStrength(math.max(1, math.min(100, val))) 60 | end 61 | end 62 | 63 | function ENT:Initialize() 64 | if CLIENT then return end 65 | 66 | self:SetModel("models/mechanics/wheels/wheel_speed_72.mdl") 67 | self:PhysicsInit(SOLID_VPHYSICS) 68 | self:SetMoveType(MOVETYPE_VPHYSICS) 69 | self:SetSolid(SOLID_VPHYSICS) 70 | self:SetUseType(SIMPLE_USE) 71 | 72 | -- wiremod integration 73 | if WireLib ~= nil then 74 | WireLib.CreateInputs(self, { 75 | "Active", 76 | "RadiusX", "RadiusY", 77 | "Strength"}) 78 | end 79 | end 80 | 81 | function ENT:SpawnFunction(ply, tr, class) 82 | if not tr.Hit then return end 83 | local ent = ents.Create(class) 84 | ent:SetPos(tr.HitPos) 85 | ent:Spawn() 86 | ent:Activate() 87 | 88 | ent:SetRadiusX(6) 89 | ent:SetRadiusY(6) 90 | ent:SetStrength(10) 91 | ent:SetOn(true) 92 | --ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 93 | ent:SetMaterial("phoenix_storms/gear") 94 | 95 | local ent2 = ents.Create("gwater2_transporter_send") 96 | ent2:SetPos(tr.HitPos + vector_up * 50) 97 | ent2:Spawn() 98 | ent2:Activate() 99 | ent2:SetRadius(20) 100 | ent2:SetStrength(100) 101 | ent2:SetCollisionGroup(COLLISION_GROUP_WORLD) 102 | hook.Run("PlayerSpawnedSENT", ply, ent2) 103 | ent.link = ent2 104 | ent2.link = ent 105 | ent:SetNWEntity("GWATER2_Link", ent2) 106 | ent2:SetNWEntity("GWATER2_Link", ent) 107 | 108 | return ent 109 | end 110 | 111 | function ENT:OnRemove() 112 | if not SERVER then return end 113 | if not IsValid(self.link) then return end 114 | self.link:Remove() 115 | end 116 | 117 | function ENT:Use(_, _, type) 118 | self:SetOn(not self:GetOn()) 119 | end 120 | 121 | function ENT:Draw() 122 | self:DrawModel() 123 | 124 | self.link = self.link or IsValid(self:GetNWEntity("GWATER2_Link")) and self:GetNWEntity("GWATER2_Link") 125 | 126 | local pos, ang = self:GetPos(), self:GetAngles() 127 | ang:RotateAroundAxis(ang:Up(), 180) 128 | pos = pos + ang:Up()*7 129 | 130 | cam.Start3D2D(pos, ang, 0.1) 131 | draw.DrawText("Transporter Exit", "DermaDefault", 0, -72, color_white, TEXT_ALIGN_CENTER) 132 | 133 | draw.DrawText("["..self:EntIndex().."]", "DermaDefault", 0, -48, color_white, TEXT_ALIGN_CENTER) 134 | 135 | --draw.RoundedBox(0, -150, -150, 300, 300, color_black) 136 | draw.DrawText(language.GetPhrase("gwater2.ent.emitter.side"), "DermaLarge", 0, -24, color_white, TEXT_ALIGN_CENTER) 137 | 138 | if IsValid(self.link) then 139 | draw.DrawText(string.format(language.GetPhrase("gwater2.ent.transporter.link"), "["..self.link:EntIndex().."]"), 140 | "DermaDefault", 0, 48, color_white, TEXT_ALIGN_CENTER) 141 | 142 | draw.DrawText(string.format(language.GetPhrase("gwater2.ent.transporter.queue"), self.link.GWATER2_particles_drained), 143 | "DermaDefault", 0, 72, color_white, TEXT_ALIGN_CENTER) 144 | end 145 | 146 | draw.DrawText(string.format( 147 | language.GetPhrase("gwater2.ent."..(self:GetOn() and "on" or "off")).." ".. 148 | language.GetPhrase("gwater2.ent.strength").." ".. 149 | language.GetPhrase("gwater2.ent.radius2"), self:GetStrength() or "?", self:GetRadiusX() or "?", self:GetRadiusY() or "?" 150 | ), "DermaDefault", 0, 96, color_white, TEXT_ALIGN_CENTER) 151 | cam.End3D2D() 152 | end 153 | -------------------------------------------------------------------------------- /lua/entities/gwater2_transporter_send.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | ENT.Type = "anim" 4 | ENT.Base = "base_anim" 5 | 6 | ENT.Category = "GWater2" 7 | ENT.PrintName = "Transporter" 8 | ENT.Author = "googer_" 9 | ENT.Purpose = "" 10 | ENT.Instructions = "" 11 | ENT.Spawnable = false 12 | ENT.Editable = true 13 | 14 | function ENT:SetupDataTables() 15 | self:NetworkVar("Float", 0, "Radius", {KeyName = "Radius", Edit = {type = "Float", order = 0, min = 0, max = 100}}) 16 | self:NetworkVar("Float", 1, "Strength", {KeyName = "Strength", Edit = {type = "Float", order = 1, min = 0, max = 200}}) 17 | 18 | if SERVER then return end 19 | 20 | hook.Add("gwater2_tick_drains", self, function() 21 | gwater2.solver:AddForceField(self:GetPos(), self:GetRadius(), -self:GetStrength(), 0, true) 22 | self.GWATER2_particles_drained = math.max(0, 23 | (self.GWATER2_particles_drained or 0) + 24 | gwater2.solver:RemoveSphere(gwater2.quick_matrix(self:GetPos(), nil, self:GetRadius())) 25 | ) 26 | end) 27 | end 28 | 29 | function ENT:Initialize() 30 | if CLIENT then return end 31 | self:SetModel("models/xqm/button3.mdl") 32 | self:SetMaterial("phoenix_storms/dome") 33 | 34 | self:PhysicsInit(SOLID_VPHYSICS) 35 | self:SetMoveType(MOVETYPE_VPHYSICS) 36 | self:SetSolid(SOLID_VPHYSICS) 37 | 38 | -- wiremod integration 39 | if WireLib ~= nil then 40 | WireLib.CreateInputs(self, { 41 | "Radius", 42 | "Strength"}) 43 | end 44 | end 45 | 46 | function ENT:OnRemove() 47 | if not SERVER then return end 48 | if not IsValid(self.link) then return end 49 | self.link:Remove() 50 | end 51 | 52 | -- wiremod integration 53 | function ENT:TriggerInput(name, val) 54 | if name == "Radius" then 55 | return self:SetRadius(math.max(0, math.min(100, val))) 56 | end 57 | if name == "Strength" then 58 | return self:SetStrength(math.max(0, math.min(200, val))) 59 | end 60 | end 61 | 62 | function ENT:Draw() 63 | self:DrawModel() 64 | 65 | self.link = self.link or IsValid(self:GetNWEntity("GWATER2_Link")) and self:GetNWEntity("GWATER2_Link") 66 | 67 | local pos, ang = self:GetPos(), self:GetAngles() 68 | ang:RotateAroundAxis(ang:Right(), 180) 69 | pos = pos + ang:Up()*0.25 70 | 71 | cam.Start3D2D(pos, ang, 0.05) 72 | draw.DrawText("Transporter Entry", "DermaDefault", 0, -72, color_white, TEXT_ALIGN_CENTER) 73 | 74 | 75 | draw.DrawText("["..self:EntIndex().."]", "DermaDefault", 0, -48, color_white, TEXT_ALIGN_CENTER) 76 | 77 | --draw.RoundedBox(0, -150, -150, 300, 300, color_black) 78 | draw.DrawText(language.GetPhrase("gwater2.ent.drain.side"), "DermaLarge", 0, -24, color_white, TEXT_ALIGN_CENTER) 79 | 80 | if IsValid(self.link) then 81 | draw.DrawText(string.format(language.GetPhrase("gwater2.ent.transporter.link"), "["..self.link:EntIndex().."]"), 82 | "DermaDefault", 0, 48, color_white, TEXT_ALIGN_CENTER) 83 | 84 | draw.DrawText(string.format(language.GetPhrase("gwater2.ent.transporter.queue"), self.GWATER2_particles_drained), 85 | "DermaDefault", 0, 72, color_white, TEXT_ALIGN_CENTER) 86 | end 87 | 88 | draw.DrawText(string.format( 89 | language.GetPhrase("gwater2.ent.strength").." ".. 90 | language.GetPhrase("gwater2.ent.radius"), self:GetStrength() or "?", self:GetRadius() or "?" 91 | ), "DermaDefault", 0, 96, color_white, TEXT_ALIGN_CENTER) 92 | cam.End3D2D() 93 | end 94 | -------------------------------------------------------------------------------- /lua/gwater2_interactions.lua: -------------------------------------------------------------------------------- 1 | --if CLIENT then return end 2 | 3 | local GWATER2_PARTICLES_TO_SWIM = 40 4 | 5 | -- swim code provided by kodya (with permission) 6 | local gravity_convar = GetConVar("sv_gravity") 7 | local function in_water(ply) 8 | if gwater2.parameters.player_interaction == false then return false end 9 | if ply:OnGround() then return false end 10 | return ply:GetNW2Int("GWATER2_CONTACTS", 0) >= GWATER2_PARTICLES_TO_SWIM 11 | end 12 | 13 | hook.Add("CalcMainActivity", "gwater2_swimming", function(ply) 14 | if not in_water(ply) or ply:InVehicle() then return end 15 | return ACT_MP_SWIM, -1 16 | end) 17 | 18 | local function do_swim(ply, move) 19 | if not in_water(ply) then return end 20 | 21 | local vel = move:GetVelocity() 22 | local ang = move:GetMoveAngles() 23 | 24 | local acel = 25 | (ang:Forward() * move:GetForwardSpeed()) + 26 | (ang:Right() * move:GetSideSpeed()) + 27 | (ang:Up() * move:GetUpSpeed()) 28 | 29 | local aceldir = acel:GetNormalized() 30 | local acelspeed = math.min(acel:Length(), ply:GetMaxSpeed()) 31 | acel = aceldir * acelspeed * (gwater2.parameters["swimspeed"] or 2) 32 | 33 | if bit.band(move:GetButtons(), IN_JUMP) ~= 0 then 34 | acel.z = acel.z + ply:GetMaxSpeed() 35 | end 36 | 37 | vel = vel + acel * FrameTime() 38 | vel = vel * (1 - FrameTime() * 2) 39 | 40 | local pgrav = ply:GetGravity() == 0 and 1 or ply:GetGravity() 41 | local gravity = pgrav * gravity_convar:GetFloat() * (gwater2.parameters["swimbuoyancy"] or 0.49) 42 | vel.z = vel.z + FrameTime() * gravity 43 | 44 | move:SetVelocity(vel * (1 - (gwater2.parameters.swimfriction or 0))) 45 | end 46 | 47 | local function do_multiply(ply) 48 | if ply:GetNW2Int("GWATER2_CONTACTS", 0) < (gwater2.parameters["multiplyparticles"] or 60) then 49 | if not ply.GWATER2_MULTIPLIED then return end 50 | ply:SetWalkSpeed(ply.GWATER2_MULTIPLIED[1]) 51 | ply:SetRunSpeed(ply.GWATER2_MULTIPLIED[2]) 52 | ply:SetJumpPower(ply.GWATER2_MULTIPLIED[3]) 53 | ply.GWATER2_MULTIPLIED = nil 54 | return 55 | end 56 | if ply.GWATER2_MULTIPLIED then return end 57 | ply.GWATER2_MULTIPLIED = {ply:GetWalkSpeed(), ply:GetRunSpeed(), ply:GetJumpPower()} 58 | ply:SetWalkSpeed(ply.GWATER2_MULTIPLIED[1] * (gwater2.parameters["multiplywalk"] or 1)) 59 | ply:SetRunSpeed(ply.GWATER2_MULTIPLIED[2] * (gwater2.parameters["multiplywalk"] or 1)) 60 | ply:SetJumpPower(ply.GWATER2_MULTIPLIED[3] * (gwater2.parameters["multiplyjump"] or 1)) 61 | end 62 | 63 | -- serverside ONLY 64 | local function do_damage(ply) 65 | if (gwater2.parameters.touchdamage or 0) == 0 then return end 66 | if ply:GetNW2Int("GWATER2_CONTACTS", 0) < (gwater2.parameters["multiplyparticles"] or 60) then return end 67 | 68 | if gwater2.parameters.touchdamage > 0 then 69 | ply:TakeDamage(gwater2.parameters.touchdamage) 70 | else 71 | ply:SetHealth(math.min(ply:GetMaxHealth(), ply:Health() + -gwater2.parameters["touchdamage"])) 72 | end 73 | end 74 | 75 | hook.Add("Move", "gwater2_swimming", function(ply, move) 76 | if gwater2.parameters.player_interaction == false then return end 77 | 78 | if SERVER then 79 | ply:SetNW2Int("GWATER2_CONTACTS", ply.GWATER2_CONTACTS or 0) 80 | end 81 | 82 | do_swim(ply, move) 83 | do_multiply(ply) 84 | 85 | if SERVER then 86 | do_damage(ply) 87 | end 88 | end) 89 | 90 | hook.Add("FinishMove", "gwater2_swimming", function(ply, move) 91 | if not in_water(ply) then return end 92 | local vel = move:GetVelocity() 93 | local pgrav = ply:GetGravity() == 0 and 1 or ply:GetGravity() 94 | local gravity = pgrav * gravity_convar:GetFloat() * 0.5 95 | 96 | vel.z = vel.z + FrameTime() * gravity 97 | move:SetVelocity(vel) 98 | end) 99 | 100 | -- cancel fall damage when in water 101 | hook.Add("GetFallDamage", "gwater2_swimming", function(ply, speed) 102 | if ply:GetNW2Int("GWATER2_CONTACTS", 0) < GWATER2_PARTICLES_TO_SWIM then return end 103 | 104 | ply:EmitSound("Physics.WaterSplash") 105 | return 0 106 | end) 107 | 108 | if SERVER then 109 | -- explosions caused by props, rpg rockets, etc 110 | hook.Add("OnEntityCreated", "gwater2_explosion", function(ent) 111 | if !IsValid(ent) or ent:GetClass() != "env_explosion" then return end 112 | 113 | timer.Simple(0, function() -- wait for datatables to be set up 114 | if !IsValid(ent) then return end 115 | 116 | gwater2.AddForceField(ent:GetPos(), 250, 150, 1, true) 117 | end) 118 | end) 119 | 120 | -- Best I could do for grenade detection. has a few problems: 121 | -- does not detect instantly, can be a couple ticks behind 122 | -- grenades that get exploded by other grenades (chain grenade explosions) are not detected 123 | hook.Add("EntityRemoved", "gwater2_explosion", function(ent) 124 | if !IsValid(ent) then return end 125 | 126 | -- smg grenade, theres no way to detect whether it exploded or not, so we just assume it always does 127 | if ent:GetClass() == "grenade_ar2" then 128 | gwater2.AddForceField(ent:GetPos(), 250, 100, 1, true) 129 | end 130 | 131 | -- a grenade will explode (and is not just being removed with remover tool) 132 | if ent:GetClass() == "npc_grenade_frag" and ent:GetInternalVariable("m_flDetonateTime") != -CurTime() then 133 | gwater2.AddForceField(ent:GetPos(), 250, 100, 1, true) 134 | end 135 | end) 136 | 137 | -- gravity gun pickup code moved to "entities/gwater2_pickup.lua" 138 | end 139 | 140 | return in_water -------------------------------------------------------------------------------- /lua/gwater2_net.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | 3 | local admin_only = CreateConVar("gwater2_adminonly", "0", FCVAR_REPLICATED + FCVAR_ARCHIVE) 4 | 5 | if SERVER then 6 | -- TODO: too many network strings... 7 | util.AddNetworkString("GWATER2_ADDCLOTH") 8 | util.AddNetworkString("GWATER2_ADDPARTICLE") 9 | util.AddNetworkString("GWATER2_ADDCUBE") 10 | util.AddNetworkString("GWATER2_ADDCYLINDER") 11 | util.AddNetworkString("GWATER2_ADDSPHERE") 12 | util.AddNetworkString("GWATER2_ADDMODEL") 13 | util.AddNetworkString("GWATER2_ADDFORCEFIELD") 14 | util.AddNetworkString("GWATER2_RESETSOLVER") 15 | util.AddNetworkString("GWATER2_REMOVECLOTH") 16 | 17 | util.AddNetworkString("GWATER2_CHANGEPARAMETER") 18 | util.AddNetworkString("GWATER2_REQUESTPARAMETERSSNAPSHOT") 19 | util.AddNetworkString("GWATER2_REQUESTCOLLISION") 20 | 21 | gwater2 = { 22 | parameters = {}, 23 | 24 | AddCloth = function(translation, size, particle_data) 25 | net.Start("GWATER2_ADDCLOTH") 26 | net.WriteMatrix(translation) 27 | net.WriteUInt(size[1], 8) 28 | net.WriteUInt(size[2], 8) 29 | net.WriteTable(particle_data or {}) -- empty table only takes 3 bits 30 | net.Broadcast() 31 | end, 32 | 33 | AddCylinder = function(translation, size, particle_data) 34 | net.Start("GWATER2_ADDCYLINDER") 35 | net.WriteMatrix(translation) 36 | net.WriteUInt(size[1], 8) 37 | net.WriteUInt(size[2], 8) 38 | net.WriteUInt(size[3], 8) 39 | net.WriteTable(particle_data or {}) 40 | net.Broadcast() 41 | end, 42 | 43 | AddSphere = function(translation, radius, particle_data) 44 | net.Start("GWATER2_ADDSPHERE") 45 | net.WriteMatrix(translation) 46 | net.WriteUInt(radius, 8) 47 | net.WriteTable(particle_data or {}) 48 | net.Broadcast() 49 | end, 50 | 51 | AddCube = function(translation, size, particle_data, unreliable) 52 | net.Start("GWATER2_ADDCUBE", unreliable) 53 | net.WriteMatrix(translation) 54 | net.WriteUInt(size[1], 8) 55 | net.WriteUInt(size[2], 8) 56 | net.WriteUInt(size[3], 8) 57 | net.WriteTable(particle_data or {}) 58 | net.Broadcast() 59 | end, 60 | 61 | AddParticle = function(pos, particle_data, unreliable) 62 | net.Start("GWATER2_ADDPARTICLE", unreliable) 63 | net.WriteVector(pos) 64 | net.WriteTable(particle_data or {}) 65 | net.Broadcast() 66 | end, 67 | 68 | AddModel = function(translation, model, particle_data) 69 | net.Start("GWATER2_ADDMODEL") 70 | net.WriteMatrix(translation) 71 | net.WriteString(model) 72 | net.WriteTable(particle_data or {}) 73 | net.Broadcast() 74 | end, 75 | 76 | AddForceField = function(pos, radius, strength, mode, linear) 77 | net.Start("GWATER2_ADDFORCEFIELD") 78 | net.WriteVector(pos) 79 | net.WriteFloat(radius) 80 | net.WriteFloat(strength) 81 | net.WriteUInt(mode, 2) -- 0-2 inclusive 82 | net.WriteBool(linear) 83 | net.Broadcast() 84 | end, 85 | 86 | ChangeParameter = function(name, value, final, sender) 87 | if gwater2.parameters[name] == value then return end 88 | net.Start("GWATER2_CHANGEPARAMETER", not final) 89 | net.WriteString(name) 90 | net.WriteType(value) 91 | net.WriteEntity(sender) 92 | net.Broadcast() 93 | gwater2.parameters[name] = value 94 | end, 95 | 96 | ResetSolver = function() 97 | net.Start("GWATER2_RESETSOLVER") 98 | net.Broadcast() 99 | end, 100 | 101 | RemoveCloth = function() 102 | net.Start("GWATER2_REMOVECLOTH") 103 | net.Broadcast() 104 | end, 105 | 106 | quick_matrix = function(pos, ang, scale) 107 | local mat = Matrix() 108 | if pos then mat:SetTranslation(pos) end 109 | if ang then mat:SetAngles(ang) end 110 | if scale then mat:SetScale(Vector(1, 1, 1) * scale) end 111 | return mat 112 | end 113 | } 114 | 115 | net.Receive("GWATER2_CHANGEPARAMETER", function(len, ply) 116 | if admin_only:GetBool() and not ply:IsAdmin() then return end -- admin only :P 117 | 118 | gwater2.ChangeParameter(net.ReadString(), net.ReadType(), net.ReadBool(), ply) 119 | end) 120 | 121 | net.Receive("GWATER2_RESETSOLVER", function(len, ply) 122 | if admin_only:GetBool() and not ply:IsAdmin() then return end 123 | 124 | gwater2.ResetSolver() 125 | end) 126 | 127 | net.Receive("GWATER2_REMOVECLOTH", function(len, ply) 128 | if admin_only:GetBool() and not ply:IsAdmin() then return end 129 | 130 | gwater2.RemoveCloth() 131 | end) 132 | 133 | net.Receive("GWATER2_REQUESTPARAMETERSSNAPSHOT", function(len, ply) 134 | net.Start("GWATER2_REQUESTPARAMETERSSNAPSHOT") 135 | net.WriteTable(gwater2.parameters) 136 | net.Send(ply) 137 | end) 138 | 139 | net.Receive("GWATER2_REQUESTCOLLISION", function(len, ply) 140 | ply:SetNW2Bool("GWATER2_COLLISION", net.ReadBool()) 141 | end) 142 | else -- CLIENT 143 | gwater2.ChangeParameter = function(name, value, final) 144 | net.Start("GWATER2_CHANGEPARAMETER", not final) 145 | net.WriteString(name) 146 | net.WriteType(value) 147 | net.WriteBool(final) 148 | net.SendToServer() 149 | end 150 | 151 | gwater2.ResetSolver = function() 152 | net.Start("GWATER2_RESETSOLVER") 153 | net.SendToServer() 154 | end 155 | 156 | gwater2.RemoveCloth = function() 157 | net.Start("GWATER2_REMOVECLOTH") 158 | net.SendToServer() 159 | end 160 | 161 | local _util = include("menu/gwater2_util.lua") 162 | 163 | -- HUDPaint gets called only AFTER player is ready to receive data 164 | hook.Add("Think", "GWATER2_REQUESTPARAMETERSSNAPSHOT", function() 165 | hook.Remove("Think", "GWATER2_REQUESTPARAMETERSSNAPSHOT") 166 | net.Start("GWATER2_REQUESTPARAMETERSSNAPSHOT") 167 | net.SendToServer() 168 | end) 169 | 170 | net.Receive("GWATER2_REQUESTPARAMETERSSNAPSHOT", function(len, ply) 171 | local tbl = net.ReadTable() 172 | for k,v in pairs(tbl) do 173 | _util.set_gwater_parameter(k, v, ply) 174 | end 175 | end) 176 | net.Receive("GWATER2_CHANGEPARAMETER", function(len) 177 | _util.set_gwater_parameter(net.ReadString(), net.ReadType(), net.ReadEntity()) 178 | end) 179 | 180 | net.Receive("GWATER2_RESETSOLVER", function(len) 181 | gwater2.solver:Reset() 182 | end) 183 | 184 | net.Receive("GWATER2_REMOVECLOTH", function(len) 185 | gwater2.solver:ResetCloth() 186 | end) 187 | 188 | net.Receive("GWATER2_ADDCLOTH", function(len) 189 | local translation = net.ReadMatrix() 190 | local size_x = net.ReadUInt(8) 191 | local size_y = net.ReadUInt(8) 192 | local extra = net.ReadTable() -- the one time this function is actually useful 193 | gwater2.solver:AddCloth(translation, Vector(size_x, size_y), extra) 194 | gwater2.cloth_pos = translation:GetTranslation() 195 | end) 196 | 197 | net.Receive("GWATER2_ADDPARTICLE", function(len) 198 | local pos = net.ReadVector() 199 | local extra = net.ReadTable() 200 | gwater2.solver:AddParticle(pos, extra) 201 | end) 202 | 203 | net.Receive("GWATER2_ADDCYLINDER", function(len) 204 | local translation = net.ReadMatrix() 205 | local size_x = net.ReadUInt(8) 206 | local size_y = net.ReadUInt(8) 207 | local size_z = net.ReadUInt(8) 208 | local extra = net.ReadTable() 209 | gwater2.solver:AddCylinder(translation, Vector(size_x, size_y, size_z), extra) 210 | end) 211 | 212 | net.Receive("GWATER2_ADDSPHERE", function(len) 213 | local translation = net.ReadMatrix() 214 | local radius = net.ReadUInt(8) 215 | local extra = net.ReadTable() 216 | gwater2.solver:AddSphere(translation, radius, extra) 217 | end) 218 | 219 | net.Receive("GWATER2_ADDCUBE", function(len) 220 | local translation = net.ReadMatrix() 221 | local size_x = net.ReadUInt(8) 222 | local size_y = net.ReadUInt(8) 223 | local size_z = net.ReadUInt(8) 224 | local extra = net.ReadTable() 225 | gwater2.solver:AddCube(translation, Vector(size_x, size_y, size_z), extra) 226 | end) 227 | 228 | net.Receive("GWATER2_ADDMODEL", function(len) 229 | local translation = net.ReadMatrix() 230 | local model = net.ReadString() 231 | local extra = net.ReadTable() 232 | 233 | --[[ 234 | local model, offset = util.GetModelMeshes(model) 235 | if !model then return end 236 | 237 | for k, body in ipairs(model) do 238 | local offset = offset[k - 1] 239 | local succ 240 | if offset then 241 | succ = gwater2.solver:AddMesh(translation, body.triangles, extra) 242 | else 243 | succ = gwater2.solver:AddMesh(translation, body.triangles, extra) 244 | end 245 | end]] 246 | 247 | local cs_ent = ents.CreateClientProp(model) 248 | local mins, maxs = cs_ent:OBBMins(), cs_ent:OBBMaxs() 249 | local phys = cs_ent:GetPhysicsObject() 250 | if !IsValid(phys) then 251 | cs_ent:Remove() 252 | return 253 | end 254 | 255 | -- set up for GetVelocityAtPoint 256 | phys:SetPos(translation:GetTranslation()) 257 | phys:SetAngles(translation:GetAngles()) 258 | phys:SetVelocity(extra.ent_vel or Vector()) 259 | phys:SetAngleVelocity(extra.ent_angvel or Vector()) 260 | 261 | local colliders = CreatePhysCollidesFromModel(model) 262 | if !colliders then 263 | cs_ent:Remove() 264 | return 265 | end 266 | 267 | local radius = gwater2.solver:GetParameter("fluid_rest_distance") 268 | local offset = radius / 2 269 | mins = mins + Vector(offset, offset, offset) 270 | maxs = maxs + Vector(offset, offset, offset) 271 | 272 | local function trace_filter(e) return e == cs_ent end 273 | for z = mins[3], maxs[3], radius do 274 | for y = mins[2], maxs[2], radius do 275 | for x = mins[1], maxs[1], radius do 276 | local pos = Vector(x, y, z) 277 | --local hit = 0 278 | for _, v in ipairs(colliders) do 279 | if v:TraceBox(Vector(0, 0, 0), Angle(0), pos, pos, Vector(-offset, -offset, -offset), Vector(offset, offset, offset)) then 280 | --hit = 255 281 | -- Add particle 282 | local vel = extra.vel and extra.vel or phys:GetVelocityAtPoint(phys:LocalToWorld(pos)) 283 | gwater2.solver:AddParticle(translation * pos + Vector(0, 0, offset), {vel = vel}) 284 | if gwater2.solver:GetActiveParticles() >= gwater2.solver:GetMaxParticles() then 285 | goto megabreak 286 | end 287 | 288 | break 289 | end 290 | end 291 | --debugoverlay.BoxAngles(phys:LocalToWorld(pos), Vector(-offset, -offset, -offset), Vector(offset, offset, offset), phys:GetAngles(), 10, Color(255 - hit, hit, 0, 0)) 292 | end 293 | end 294 | end 295 | 296 | ::megabreak:: 297 | for k, v in ipairs(colliders) do v:Destroy() end 298 | cs_ent:Remove() 299 | end) 300 | 301 | net.Receive("GWATER2_ADDFORCEFIELD", function(len) 302 | local pos = net.ReadVector() 303 | local radius = net.ReadFloat() 304 | local strength = net.ReadFloat() 305 | local mode = net.ReadUInt(2) -- 0-2 inclusive 306 | local linear = net.ReadBool() 307 | gwater2.solver:AddForceField(pos, radius, strength, mode, linear) 308 | end) 309 | end -------------------------------------------------------------------------------- /lua/gwater2_shaders.lua: -------------------------------------------------------------------------------- 1 | -- The GWater 2 Render Pipeline 2 | 3 | local function get_gwater_rt(name, mult, depth) 4 | mult = mult or 1 5 | return GetRenderTargetEx(name, ScrW() * mult, ScrH() * mult, 6 | RT_SIZE_DEFAULT, 7 | depth or 0, 8 | 2 + 4 + 8 + 256, 9 | 0, 10 | IMAGE_FORMAT_RGBA16161616F 11 | ) 12 | end 13 | 14 | local cache_screen0 = render.GetScreenEffectTexture() 15 | local cache_screen1 = render.GetScreenEffectTexture(1) 16 | local cache_mipmap = get_gwater_rt("gwater2_mipmap", 1 / 1) 17 | local cache_absorption = get_gwater_rt("gwater2_absorption", 1 / 4, MATERIAL_RT_DEPTH_NONE) 18 | local cache_normals = get_gwater_rt("gwater2_normals", 1 / 1, MATERIAL_RT_DEPTH_SEPARATE) 19 | local cache_blur = get_gwater_rt("gwater2_blur", 1 / 2) 20 | 21 | local water = Material("gwater2/finalpass") 22 | local water_blur = Material("gwater2/smooth") 23 | local water_volumetric = Material("gwater2/volumetric") 24 | local water_normals = Material("gwater2/normals") 25 | local water_bubble = Material("gwater2/bubble") -- bubbles 26 | local water_mist = Material("gwater2/mist") 27 | local black = Material("gwater2/black") 28 | local cloth = Material("gwater2/cloth") 29 | 30 | local blur_passes = CreateClientConVar("gwater2_blur_passes", "3", true) 31 | local blur_scale = CreateClientConVar("gwater2_blur_scale", "1", true) 32 | 33 | local debug_absorption = CreateClientConVar("gwater2_debug_absorption", "0", false) 34 | local debug_normals = CreateClientConVar("gwater2_debug_normals", "0", false) 35 | local debug_mipmap = CreateClientConVar("gwater2_debug_mipmap", "0", false) 36 | 37 | -- sets up a lighting origin in sourceengine 38 | -- TODO: cache your fucking tables and csmodels!!! 39 | local function unfuck_lighting(pos0, pos1) 40 | render.OverrideColorWriteEnable(true, false) 41 | render.OverrideDepthEnable(true, false) 42 | render.Model({model = "models/shadertest/envballs.mdl",pos = pos0, angle = EyeAngles()}) -- cubemap 43 | render.Model({model = "models/shadertest/vertexlit.mdl",pos = pos1, angle = EyeAngles()}) -- lighting 44 | render.OverrideDepthEnable(false, false) 45 | render.OverrideColorWriteEnable(false, false) 46 | end 47 | 48 | local lightpos = EyePos() 49 | local function do_cloth() 50 | unfuck_lighting(gwater2.cloth_pos, gwater2.cloth_pos) -- fix cloth lighting, mostly 51 | render.SetMaterial(cloth) 52 | gwater2.renderer:DrawCloth() 53 | render.RenderFlashlights(function() gwater2.renderer:DrawCloth() end) 54 | 55 | -- setup water lighting 56 | --local tr = util.QuickTrace( EyePos(), LocalPlayer():EyeAngles():Forward() * 800, LocalPlayer()) 57 | --local dist = math.min(230, (tr.HitPos - tr.StartPos):Length() / 1.5) 58 | --lightpos = LerpVector(1.6 * FrameTime(), lightpos, EyePos() + (LocalPlayer():EyeAngles():Forward() * dist)) -- fucking hell 59 | unfuck_lighting(EyePos(), EyePos()) 60 | end 61 | 62 | local function do_absorption() 63 | render.UpdateScreenEffectTexture() -- _rt_framebuffer is used in refraction shader 64 | 65 | -- depth absorption (disabled when opaque liquids are enabled) 66 | local _, _, _, a = water:GetVector4D("$color2") 67 | if water_volumetric:GetFloat("$alpha") != 0 and a > 0 and a < 255 then 68 | -- ANTIALIAS FIX! (courtesy of Xenthio) 69 | -- how it works: 70 | -- Clear the main rendertarget, keeping depth 71 | -- Render to main buffer (still has depth), and copy the contents to another rendertarget 72 | -- Restore the main buffer 73 | 74 | -- clear screen w/o intruding translucents depth buffer 75 | render.SetMaterial(black) 76 | render.DrawScreenQuad() 77 | 78 | render.SetMaterial(water_volumetric) 79 | gwater2.renderer:DrawWater() 80 | render.CopyTexture(render.GetRenderTarget(), cache_absorption) 81 | render.DrawTextureToScreen(cache_screen0) 82 | 83 | --render.PushRenderTarget(cache_absorption) 84 | --render.SetMaterial(water_volumetric) 85 | --gwater2.renderer:DrawWater() 86 | --render.PopRenderTarget() 87 | else 88 | -- no absorption calculations, so just use solid color 89 | render.PushRenderTarget(cache_absorption) 90 | render.Clear(15, 15, 15, 10) 91 | render.PopRenderTarget() 92 | end 93 | end 94 | 95 | local function do_diffuse_inside() 96 | -- dont render bubbles underwater if opaque 97 | local _, _, _, a = water:GetVector4D("$color2") 98 | if a < 255 then 99 | -- Bubble particles inside water 100 | -- Make sure the water screen texture has bubbles but the normal framebuffer does not 101 | render.SetMaterial(water_bubble) 102 | render.UpdateScreenEffectTexture(1) 103 | gwater2.renderer:DrawDiffuse() 104 | render.RenderFlashlights(function() gwater2.renderer:DrawDiffuse() end) 105 | render.CopyTexture(render.GetRenderTarget(), cache_screen0) 106 | render.DrawTextureToScreen(cache_screen1) 107 | end 108 | end 109 | 110 | local function do_normals() 111 | local radius = gwater2.solver:GetParameter("radius") 112 | 113 | -- stencils are used to only blur the pixels we want 114 | render.SetStencilWriteMask(0xFF) 115 | render.SetStencilTestMask(0xFF) 116 | render.SetStencilReferenceValue(1) 117 | render.SetStencilCompareFunction(STENCIL_ALWAYS) 118 | render.SetStencilFailOperation(STENCIL_KEEP) 119 | render.SetStencilZFailOperation(STENCIL_KEEP) 120 | render.SetStencilPassOperation(STENCIL_REPLACE) 121 | render.ClearStencil() 122 | render.SetStencilEnable(true) 123 | 124 | -- grab normals 125 | water_normals:SetFloat("$radius", radius / 2) 126 | render.SetMaterial(water_normals) 127 | render.PushRenderTarget(cache_normals) 128 | render.SetRenderTargetEx(1, cache_mipmap) 129 | render.ClearDepth() 130 | gwater2.renderer:DrawWater() 131 | render.PopRenderTarget() 132 | render.SetRenderTargetEx(1, nil) 133 | 134 | render.SetStencilCompareFunction(STENCIL_EQUAL) 135 | render.SetStencilEnable(false) 136 | 137 | -- Blur normals 138 | local scrw = 1 / ScrW() 139 | local scrh = 1 / ScrH() 140 | 141 | water_blur:SetFloat("$radius", radius) 142 | water_blur:SetTexture("$depthtexture", cache_mipmap) 143 | render.SetMaterial(water_blur) 144 | for i = 1, blur_passes:GetInt() do 145 | local scale = (0.3 / i) * blur_scale:GetFloat() 146 | 147 | -- Blur X 148 | water_blur:SetTexture("$normaltexture", cache_normals) 149 | water_blur:SetVector("$scrs", Vector(scale * scrw, 0)) 150 | render.SetStencilEnable(false) -- cache_blur doesn't have a stencil buffer set up, so we cant use it 151 | render.PushRenderTarget(cache_blur) 152 | render.DrawScreenQuad() 153 | render.PopRenderTarget() 154 | 155 | -- Blur Y 156 | 157 | water_blur:SetTexture("$normaltexture", cache_blur) 158 | water_blur:SetVector("$scrs", Vector(0, scale * scrh)) 159 | render.SetStencilEnable(i < blur_passes:GetInt()) -- disable stencils on last pass 160 | render.PushRenderTarget(cache_normals) 161 | render.DrawScreenQuad() 162 | render.PopRenderTarget() 163 | end 164 | 165 | render.SetStencilEnable(false) 166 | end 167 | 168 | local function do_finalpass() 169 | local radius = gwater2.solver:GetParameter("radius") 170 | 171 | -- Setup water material parameters 172 | water:SetFloat("$radius", radius * 1.5) 173 | water:SetFloat("$reflectance", blur_passes:GetBool() and 0.7 or 0) 174 | water:SetTexture("$normaltexture", cache_normals) 175 | water:SetTexture("$depthtexture", cache_absorption) 176 | render.SetMaterial(water) 177 | gwater2.renderer:DrawWater() 178 | render.RenderFlashlights(function() gwater2.renderer:DrawWater() end) 179 | 180 | render.SetMaterial(water_mist) 181 | gwater2.renderer:DrawDiffuse() 182 | render.RenderFlashlights(function() gwater2.renderer:DrawDiffuse() end) 183 | end 184 | 185 | hook.Add("RenderScene", "gwater2_render", function(eye_pos, eye_angles, fov) 186 | if gwater2.options.render_mirrors:GetInt() != 1 then return end 187 | 188 | cam.Start3D(eye_pos, eye_angles, fov) 189 | gwater2.renderer:BuildMeshes(gwater2.solver, 0.25, false) 190 | cam.End3D() 191 | end) 192 | 193 | -- vrmod does not render to the main RT, force enable mirror rendering 194 | hook.Add("VRMod_Start", "gwater2_vrmodsupport", function(ply) 195 | if ply != LocalPlayer() then return end 196 | 197 | gwater2.options.render_mirrors:SetInt(1) 198 | end) 199 | 200 | -- gwater2 shader pipeline 201 | local vrmod_material = Material("models/wireframe") 202 | hook.Add("PostDrawOpaqueRenderables", "gwater2_render", function(depth, sky, sky3d) --PreDrawViewModels 203 | if sky3d then return end -- dont render in skybox 204 | if gwater2.solver:GetActiveParticles() < 1 then return end 205 | 206 | -- dont render in mirrors unless specified 207 | local mirrors = gwater2.options.render_mirrors:GetInt() 208 | if mirrors != 1 then 209 | if mirrors == 0 and render.GetRenderTarget() then return end 210 | gwater2.renderer:BuildMeshes(gwater2.solver, 0.25, true) 211 | end 212 | 213 | do_cloth() 214 | 215 | -- vrmod is fucked. do this for now 216 | if vrmod and vrmod.IsPlayerInVR(LocalPlayer()) then 217 | render.SetMaterial(vrmod_material) 218 | gwater2.renderer:DrawWater() 219 | 220 | return 221 | end 222 | 223 | -- Clear render targets 224 | render.ClearRenderTarget(cache_normals, Color(0, 0, 0, 0)) 225 | render.ClearRenderTarget(cache_mipmap, Color(0, 0, 0, 0)) 226 | render.ClearRenderTarget(cache_absorption, Color(0, 0, 0, 0)) 227 | render.ClearRenderTarget(cache_blur, Color(0, 0, 0, 0)) 228 | 229 | do_absorption() 230 | do_diffuse_inside() 231 | do_normals() 232 | do_finalpass() 233 | 234 | -- Debug Draw 235 | local dbg = 0 236 | if debug_absorption:GetBool() then render.DrawTextureToScreenRect(cache_absorption, ScrW() * 0.75, (ScrH() / 4) * dbg, ScrW() / 4, ScrH() / 4); dbg = dbg + 1 end 237 | if debug_normals:GetBool() then render.DrawTextureToScreenRect(cache_normals, ScrW() * 0.75, (ScrH() / 4) * dbg, ScrW() / 4, ScrH() / 4); dbg = dbg + 1 end 238 | if debug_mipmap:GetBool() then render.DrawTextureToScreenRect(cache_mipmap, ScrW() * 0.75, (ScrH() / 4) * dbg, ScrW() / 4, ScrH() / 4); dbg = dbg + 1 end 239 | 240 | --render.DrawTextureToScreenRect(cache_absorption, 0, 0, ScrW() / 4, ScrH() / 4) 241 | end) 242 | 243 | --hook.Add("NeedsDepthPass", "gwater2_depth", function() 244 | -- DOFModeHack(true) -- fixes npcs and stuff dissapearing 245 | -- return true 246 | --end) -------------------------------------------------------------------------------- /lua/menu/gwater2_paramstabs.lua: -------------------------------------------------------------------------------- 1 | local params = include("menu/gwater2_params.lua") 2 | local styling = include("menu/gwater2_styling.lua") 3 | local util = include("menu/gwater2_util.lua") 4 | 5 | local function init_tab_params(tabs, tab, tab_name, sname, sec, added_params, recursive) 6 | local pan = tab:Add("Panel") 7 | pan.help_text = tabs.help_text 8 | function pan:Paint(w, h) styling.draw_main_background(0, 0, w, h) end 9 | 10 | if recursive then 11 | util.make_title_label(pan, util.get_localised(tab_name .. "." .. sname:sub(5))).realkey = sname 12 | end 13 | 14 | for name, param in SortedPairs(sec) do 15 | if param.type == "scratch" then 16 | added_params[name:sub(5)] = util.make_parameter_scratch(pan, tab_name .. "." .. name:sub(5), name:sub(5), param) 17 | elseif param.type == "color" then 18 | added_params[name:sub(5)] = util.make_parameter_color(pan, tab_name .. "."..name:sub(5), name:sub(5), param) 19 | elseif param.type == "check" then 20 | added_params[name:sub(5)] = util.make_parameter_check(pan, tab_name .. "."..name:sub(5), name:sub(5), param) 21 | else 22 | error("got unknown parameter type in " .. tab_name .. " menu generation") 23 | end 24 | end 25 | 26 | local ttall = pan:GetTall()+5 27 | for _, i in pairs(pan:GetChildren()) do 28 | ttall = ttall + i:GetTall() 29 | end 30 | 31 | ttall = ttall - 20 32 | pan:SetTall(ttall) 33 | pan:Dock(TOP) 34 | pan:InvalidateChildren() 35 | pan:DockMargin(5, 5, 5, 5) 36 | pan:DockPadding(5, 5, 5, 5) 37 | end 38 | 39 | local function init_tab(tabs, tab_name, image, recursive) 40 | local tab = vgui.Create("DPanel", tabs) 41 | function tab:Paint() end 42 | tabs:AddSheet(util.get_localised(tab_name .. ".title"), tab, image).Tab.realname = tab_name 43 | tab = tab:Add("DScrollPanel") 44 | tab:Dock(FILL) 45 | 46 | styling.define_scrollbar(tab:GetVBar()) 47 | 48 | local _ = tab:Add("DLabel") _:SetText(" ") _:SetFont("GWater2Title") _:Dock(TOP) _:SizeToContents() 49 | function _:Paint(w, h) 50 | draw.DrawText(util.get_localised(tab_name .. ".titletext"), "GWater2Title", 6, 6, color_black, TEXT_ALIGN_LEFT) 51 | draw.DrawText(util.get_localised(tab_name .. ".titletext"), "GWater2Title", 5, 5, Color(187, 245, 255), TEXT_ALIGN_LEFT) 52 | end 53 | 54 | -- TODO: genuinely horrific code 55 | local added_params = {} 56 | if recursive then 57 | for sname, sec in SortedPairs(params[tab_name]) do 58 | init_tab_params(tabs, tab, tab_name, sname, sec, added_params, true) 59 | end 60 | else 61 | init_tab_params(tabs, tab, tab_name, nil, params[tab_name], added_params, false) 62 | end 63 | 64 | return added_params, tab 65 | end 66 | 67 | local function parameters_tab(tabs) 68 | return init_tab(tabs, "Parameters", "icon16/cog.png", true) 69 | end 70 | 71 | local function visuals_tab(tabs) 72 | return init_tab(tabs, "Visuals", "icon16/picture.png") 73 | end 74 | 75 | local function performance_tab(tabs) 76 | return init_tab(tabs, "Performance", "icon16/application_xp_terminal.png", true) 77 | end 78 | 79 | local function interaction_tab(tabs) 80 | return init_tab(tabs, "Interactions", "icon16/chart_curve.png", true) 81 | end 82 | 83 | local function developer_tab(tabs) 84 | return init_tab(tabs, "Developer", "icon16/bug.png") 85 | end 86 | 87 | return { 88 | parameters_tab=parameters_tab, 89 | visuals_tab=visuals_tab, 90 | performance_tab=performance_tab, 91 | interaction_tab=interaction_tab, 92 | developer_tab=developer_tab 93 | } -------------------------------------------------------------------------------- /lua/menu/gwater2_styling.lua: -------------------------------------------------------------------------------- 1 | ---@diagnostic disable: inject-field 2 | AddCSLuaFile() 3 | 4 | if SERVER or not gwater2 then return end 5 | 6 | local function draw_main_background(x, y, w, h) 7 | surface.SetDrawColor(0, 0, 0, 125) 8 | surface.DrawRect(x, y, w, h) 9 | 10 | surface.SetDrawColor(255, 255, 255) 11 | surface.DrawOutlinedRect(x, y, w, h) 12 | end 13 | 14 | local function draw_main_background_outline(x, y, w, h) 15 | surface.SetDrawColor(255, 255, 255) 16 | surface.DrawOutlinedRect(x, y, w, h) 17 | end 18 | 19 | local function define_scrollbar(sbar) 20 | function sbar:Paint(w, h) 21 | end 22 | function sbar.btnUp:Paint(w, h) 23 | draw_main_background(0, 0, w, h) draw_main_background(0, 0, w, h) 24 | surface.SetDrawColor(255, 255, 255, 255) 25 | surface.DrawLine(3, h-h/8-3, w/2, h-h/2-h/8) 26 | surface.DrawLine(w-3, h-h/8-3, w/2, h-h/2-h/8) 27 | end 28 | function sbar.btnDown:Paint(w, h) 29 | draw_main_background(0, 0, w, h) draw_main_background(0, 0, w, h) 30 | surface.SetDrawColor(255, 255, 255, 255) 31 | surface.DrawLine(3, 3+h/8, w/2, h/2+h/8) 32 | surface.DrawLine(w-3, 3+h/8, w/2, h/2+h/8) 33 | end 34 | function sbar.btnGrip:Paint(w, h) 35 | draw_main_background(0, 0, w, h) 36 | end 37 | end 38 | local function create_blocking_frame(mainFrame) 39 | local frame = vgui.Create("DFrame", mainFrame) 40 | frame:SetSize(400, 200) 41 | frame:Center() 42 | frame:SetTitle("gwater2 (" .. gwater2.VERSION .. ")") 43 | frame:MakePopup() 44 | frame:SetBackgroundBlur(true) -- doesn't actually blur the background 45 | frame:SetScreenLock(true) 46 | --frame:ShowCloseButton(false) 47 | 48 | function frame:Paint(w, h) 49 | -- Blur background 50 | local rt = render.GetRenderTarget() 51 | render.UpdateScreenEffectTexture() 52 | render.BlurRenderTarget(render.GetScreenEffectTexture(), 5, 5, 1) 53 | render.SetRenderTarget(rt) -- blurrendertarget doesnt restore the rt 54 | render.DrawScreenQuad() 55 | 56 | surface.SetDrawColor(0, 0, 0, 200) 57 | surface.DrawRect(0, 0, w, h) 58 | 59 | draw_main_background_outline(0, 0, w, h) 60 | end 61 | return frame 62 | end 63 | 64 | return { 65 | create_blocking_frame = create_blocking_frame, 66 | draw_main_background = draw_main_background, 67 | define_scrollbar = define_scrollbar, 68 | draw_main_background_outline = draw_main_background_outline 69 | } -------------------------------------------------------------------------------- /lua/starfall/libs_cl/gwater2module.lua: -------------------------------------------------------------------------------- 1 | AddCSLuaFile() 2 | local checkluatype = SF.CheckLuaType 3 | local registerprivilege = SF.Permissions.registerPrivilege 4 | 5 | -- TODO: rewrite? not sure if that's compatible with 0.6b 6 | 7 | --- Library for using gwater2 8 | -- @name gwaterlib 9 | -- @class library 10 | -- @libtbl gwater_library 11 | SF.RegisterLibrary("gwaterlib") 12 | 13 | local function main(instance) 14 | local gwater_library = instance.Libraries.gwaterlib 15 | local vec_meta, vwrap, vunwrap = instance.Types.Vector, instance.Types.Vector.Wrap, instance.Types.Vector.Unwrap 16 | --- Spawns a GWater particle 17 | -- @client 18 | -- @param Vector pos 19 | -- @param Vector vel 20 | function gwater_library.addParticle(pos, vel) 21 | if LocalPlayer() == instance.player then 22 | gwater2.solver:AddParticle(vunwrap(pos), vunwrap(vel), 1, 1) 23 | end 24 | end 25 | 26 | --- Spawns a GWater particle cube 27 | -- @client 28 | -- @param Vector pos 29 | -- @param Vector vel 30 | -- @param Vector size 31 | -- @param number apart 32 | function gwater_library.addCube(pos, vel, size, apart) 33 | if LocalPlayer() == instance.player then 34 | gwater2.solver:AddCube(vunwrap(pos), vunwrap(vel), vunwrap(size), apart) 35 | end 36 | end 37 | 38 | --- Clears All Gwater 39 | -- @client 40 | function gwater_library.clearAllParticles() 41 | if LocalPlayer() == instance.player then 42 | gwater2.solver:Reset() 43 | end 44 | end 45 | 46 | --- Changes the chosen Gwater parameter. 47 | -- @client 48 | -- @param string parameter 49 | -- @param number value 50 | function gwater_library.setParameter(parameter, value) 51 | if LocalPlayer() == instance.player then 52 | gwater2.solver:SetParameter(parameter, value) 53 | end 54 | end 55 | 56 | --- Gets the chosen Gwater parameter. 57 | -- @client 58 | -- @param string parameter 59 | -- @return number value 60 | function gwater_library.getParameter(parameter) 61 | if LocalPlayer() == instance.player then 62 | return gwater2.solver:GetParameter(parameter) 63 | end 64 | end 65 | 66 | --- Applies a force field to GWater particles 67 | -- @client 68 | -- @param Vector pos The position of the force field 69 | -- @param number radius The radius of the force field 70 | -- @param number strength The strength of the force field 71 | -- @param number mode The mode of the force field. 0 = Attraction, 1 = Repulsion, 2 = Vortex 72 | -- @param boolean linear Whether the force field should be the same strength regardless of distance 73 | function gwater_library.applyForceField(pos, radius, strength, mode, linear) 74 | if LocalPlayer() == instance.player then 75 | gwater2.solver:AddForceField(vunwrap(pos), radius, strength, mode, linear) 76 | end 77 | end 78 | 79 | --- Called before the GWater solver ticks 80 | -- You should use this hook to apply forces to the particles 81 | -- @name gwater2_pretick 82 | -- @class hook 83 | -- @client 84 | SF.hookAdd("gwater2_pretick") 85 | end 86 | 87 | return main 88 | -------------------------------------------------------------------------------- /lua/weapons/gmod_tool/stools/gwater2_transmuter.lua: -------------------------------------------------------------------------------- 1 | TOOL.Category = "GWater2" 2 | TOOL.Name = "#Tool.gwater2_transmuter.name" 3 | 4 | if CLIENT then 5 | language.Add("Tool.gwater2_transmuter.name", "Transmuter") 6 | language.Add("Tool.gwater2_transmuter.desc", "Turns props into liquid") 7 | 8 | TOOL.Information = { 9 | {name = "left"}, 10 | } 11 | 12 | language.Add("Tool.gwater2_transmuter.left", "Turns props into liquid. Complex models may lag!") 13 | end 14 | 15 | function TOOL:LeftClick(trace) 16 | local ent = trace.Entity 17 | if ent:IsWorld() or ent:IsPlayer() then -- no fun allowed 18 | return false 19 | end 20 | 21 | if SERVER then 22 | local phys = ent:GetPhysicsObject() 23 | if !IsValid(phys) then return end 24 | 25 | local transform = gwater2.quick_matrix(phys:GetPos(), phys:GetAngles()) 26 | local model = ent:GetModel() 27 | local extra = { 28 | ent_vel = phys:GetVelocity() * FrameTime(), 29 | ent_angvel = phys:GetAngleVelocity() * FrameTime() 30 | } 31 | 32 | phys:EnableMotion(false) 33 | ent:SetNotSolid(true) 34 | ent:SetCollisionGroup(COLLISION_GROUP_WORLD) 35 | --ent:Remove() 36 | 37 | -- net is too fast and can explode sometimes 38 | timer.Simple(0, function() 39 | gwater2.AddModel(transform, model, extra) 40 | SafeRemoveEntity(ent) 41 | end) 42 | end 43 | 44 | return true 45 | end -------------------------------------------------------------------------------- /lua/weapons/weapon_gw2_partseas.lua: -------------------------------------------------------------------------------- 1 | SWEP.PrintName = "Part The Seas" 2 | 3 | SWEP.Author = "Meetric" 4 | SWEP.Purpose = "roleplay as moses" 5 | SWEP.Instructions = "Left click to part the seas" 6 | SWEP.Category = "GWater2" 7 | SWEP.DrawAmmo = false 8 | SWEP.DrawCrosshair = true 9 | SWEP.DrawWeaponInfoBox = false 10 | 11 | SWEP.Spawnable = true 12 | SWEP.AdminOnly = false 13 | 14 | SWEP.AutoSwitchTo = false 15 | SWEP.AutoSwitchFrom = false 16 | SWEP.Weight = 1 17 | 18 | SWEP.Base = "weapon_base" 19 | 20 | SWEP.Primary.ClipSize = -1 21 | SWEP.Primary.DefaultClip = -1 22 | SWEP.Primary.Automatic = false 23 | SWEP.Primary.Ammo = "none" -- needs to be something to show ammo 24 | SWEP.Primary.Delay = 0 25 | 26 | SWEP.Base = "weapon_base" 27 | 28 | SWEP.Secondary.ClipSize = -1 29 | SWEP.Secondary.DefaultClip = -1 30 | SWEP.Secondary.Automatic = false 31 | SWEP.Secondary.Ammo = "none" 32 | 33 | SWEP.ViewModelFlip = false 34 | SWEP.ViewModelFOV = 70 35 | SWEP.ViewModel = "models/weapons/c_arms.mdl" 36 | SWEP.WorldModel = "" 37 | SWEP.UseHands = true 38 | 39 | function SWEP:Initialize() 40 | self:SetHoldType("magic") 41 | end 42 | 43 | if CLIENT then 44 | function SWEP:PrimaryAttack() end 45 | function SWEP:SecondaryAttack() end 46 | function SWEP:Reload() end 47 | return 48 | end 49 | 50 | function SWEP:create_black_holes(strength) 51 | if self.BLACK_HOLES then 52 | self:destroy_black_holes() 53 | end 54 | 55 | local owner = self:GetOwner() 56 | local start_pos = owner:GetPos() + owner:OBBCenter() / 2 57 | local end_pos = util.QuickTrace(start_pos, (owner:GetAimVector() * Vector(1, 1, 0)):GetNormalized() * 10000, owner).HitPos 58 | local max_points = math.floor(start_pos:Distance(end_pos) / 250) 59 | 60 | self.BLACK_HOLES = {} 61 | local points = 0 62 | timer.Create("gwater2_partseas_create" .. self:EntIndex(), 0.1, max_points, function() 63 | for i = 0, 1 do 64 | local black_hole = ents.Create("gwater2_blackhole") 65 | black_hole:SetPos(LerpVector(points / max_points, start_pos, end_pos) + Vector(0, 0, i * 500)) 66 | black_hole:SetRadius(300) 67 | black_hole:SetStrength(strength) 68 | black_hole:SetMode(1) 69 | black_hole:SetLinear(1) 70 | black_hole:Spawn() 71 | black_hole:SetNotSolid(true) 72 | black_hole:DrawShadow(false) 73 | black_hole:SetRenderMode(RENDERMODE_NONE) 74 | black_hole:GetPhysicsObject():EnableMotion(false) 75 | table.insert(self.BLACK_HOLES, black_hole) 76 | end 77 | points = points + 1 78 | end) 79 | 80 | timer.Create("gwater2_partseas_destroy" .. self:EntIndex(), 30, 1, function() 81 | self:destroy_black_holes() 82 | end) 83 | end 84 | 85 | function SWEP:destroy_black_holes() 86 | if !self.BLACK_HOLES then return end 87 | 88 | timer.Remove("gwater2_partseas_create" .. self:EntIndex()) 89 | timer.Remove("gwater2_partseas_destroy" .. self:EntIndex()) 90 | 91 | for k, v in ipairs(self.BLACK_HOLES) do 92 | SafeRemoveEntity(v) 93 | end 94 | 95 | self.BLACK_HOLES = nil 96 | end 97 | 98 | function SWEP:PrimaryAttack() 99 | self:create_black_holes(-100) 100 | end 101 | 102 | function SWEP:Reload() 103 | self:destroy_black_holes() 104 | end 105 | 106 | function SWEP:SecondaryAttack() 107 | self:create_black_holes(100) 108 | end 109 | 110 | function SWEP:OnDrop() 111 | self:destroy_black_holes() 112 | self:Remove() -- "You can't drop fists" 113 | end 114 | 115 | function SWEP:OnRemove() 116 | self:destroy_black_holes() 117 | end -------------------------------------------------------------------------------- /lua/weapons/weapon_gw2_watergun.lua: -------------------------------------------------------------------------------- 1 | SWEP.PrintName = "Water Gun" 2 | 3 | SWEP.Author = "Meetric" 4 | SWEP.Purpose = "Water Gun" 5 | SWEP.Instructions = "Left Click to spawn water. Right click to spawn BIG water. Reload to reset" 6 | SWEP.Category = "GWater2" 7 | SWEP.DrawAmmo = true 8 | SWEP.DrawCrosshair = true 9 | SWEP.DrawWeaponInfoBox = true 10 | 11 | SWEP.Spawnable = true 12 | SWEP.AdminOnly = false 13 | 14 | SWEP.AutoSwitchTo = false 15 | SWEP.AutoSwitchFrom = false 16 | SWEP.Weight = 1 17 | SWEP.WepSelectIcon = CLIENT and surface.GetTextureID("entities/weapon_gw2_watergun_icon") 18 | 19 | SWEP.Primary.ClipSize = -1 20 | SWEP.Primary.DefaultClip = 0 21 | SWEP.Primary.Automatic = true 22 | SWEP.Primary.Ammo = "Pistol" -- needs to be something to show ammo 23 | SWEP.Primary.Delay = 0 24 | 25 | SWEP.Base = "weapon_base" 26 | 27 | SWEP.Secondary.ClipSize = -1 28 | SWEP.Secondary.DefaultClip = 0 29 | SWEP.Secondary.Automatic = false 30 | SWEP.Secondary.Ammo = "none" 31 | SWEP.Secondary.Delay = 0 32 | 33 | SWEP.ViewModelFlip = false 34 | SWEP.ViewModelFOV = 70 35 | SWEP.ViewModel = "models/gwater2/water_gun.mdl" 36 | SWEP.WorldModel = "models/weapons/w_pistol.mdl" 37 | SWEP.UseHands = true 38 | 39 | local cardinal = { 40 | Vector(1, 0, 0), 41 | Vector(-1, 0, 0), 42 | Vector(0, 1, 0), 43 | Vector(0, -1, 0), 44 | Vector(0, 0, 1), 45 | Vector(0, 0, -1) 46 | } 47 | 48 | local function vector_abs(v) 49 | local abs = math.abs 50 | return Vector(abs(v[1]), abs(v[2]), abs(v[3])) 51 | end 52 | 53 | -- extrudes position from ground 54 | local function trace_extrude(ply, size, extrude) 55 | 56 | local radius = gwater2.parameters.radius or 10 57 | local scale = radius * size * (gwater2.parameters.fluid_rest_distance or 0.65) 58 | local initial_trace = util.TraceLine({ 59 | start = ply:EyePos(), 60 | endpos = ply:EyePos() + ply:EyeAngles():Right() * 20 - ply:EyeAngles():Up() * 8 + ply:GetAimVector() * 10 * math.max(extrude or radius, 5), 61 | filter = ply, 62 | }) 63 | 64 | local end_pos = initial_trace.HitPos + initial_trace.HitNormal 65 | 66 | for i = 1, 6 do 67 | local direction = cardinal[i]--Vector(0, 0, -1) 68 | local area = (Vector(1, 1, 1) - vector_abs(direction)) * scale 69 | local trace_data = { 70 | start = end_pos, 71 | endpos = end_pos + direction * scale, 72 | mins = -area, 73 | maxs = area, 74 | filter = ply 75 | } 76 | 77 | local trace = util.TraceHull(trace_data) 78 | if trace.StartSolid then trace = util.TraceLine(trace_data) end 79 | 80 | if !trace.StartSolid and trace.Hit then 81 | end_pos = end_pos - (0.999 - trace.Fraction) * direction * scale 82 | end 83 | end 84 | 85 | return end_pos 86 | end 87 | 88 | function SWEP:PrimaryAttack() 89 | if CLIENT then return end 90 | 91 | local owner = self:GetOwner() 92 | local radius = gwater2.parameters.radius or 10 93 | local pos = trace_extrude(owner, 4) + VectorRand(-1, 1) 94 | 95 | gwater2.AddSphere(gwater2.quick_matrix(pos), 4, {vel = owner:EyeAngles():Forward() * math.max(radius, 5) + owner:GetVelocity() * FrameTime()}) 96 | self:SetNextPrimaryFire(CurTime() + 1 / 13) 97 | owner:EmitSound("Water.ImpactSoft") 98 | end 99 | 100 | function SWEP:Reload() 101 | if CLIENT then return end 102 | 103 | gwater2.ResetSolver() 104 | end 105 | 106 | function SWEP:SecondaryAttack() 107 | if CLIENT then return end 108 | 109 | local owner = self:GetOwner() 110 | local radius = gwater2.parameters.radius or 10 111 | local pos = trace_extrude(owner, 20, 2.5 * radius) + VectorRand(-1, 1) 112 | 113 | gwater2.AddSphere(gwater2.quick_matrix(pos), 20, {vel = owner:EyeAngles():Forward() * math.Clamp(gwater2.parameters.radius or 10, 5, 10)}) 114 | owner:EmitSound("NPC_CombineGunship.CannonStartSound") 115 | self:SetNextSecondaryFire(CurTime() + 1 / 4) 116 | end 117 | 118 | if SERVER then return end 119 | 120 | local function format_int(i) 121 | return tostring(i):reverse():gsub("%d%d%d", "%1,"):reverse():gsub("^,", "") 122 | end 123 | 124 | -- visual counter on gun 125 | function SWEP:PostDrawViewModel(vm, weapon, ply) 126 | if !gwater2 then 127 | cam.Start2D() 128 | local a = 255*(math.sin(CurTime()*2)+1)/2 129 | draw.DrawText(language.GetPhrase("gwater2.gun.adv.notloaded"), "Trebuchet24", ScrW() / 2 + 1, ScrH() / 2 - 36 + 1, Color(0, 0, 0, a), TEXT_ALIGN_CENTER) 130 | draw.DrawText(language.GetPhrase("gwater2.gun.adv.notloaded"), "Trebuchet24", ScrW() / 2, ScrH() / 2 - 36, Color(255, 0, 0, a), TEXT_ALIGN_CENTER) 131 | cam.End2D() 132 | 133 | return 134 | end 135 | 136 | self.Weapon:SetClip1(gwater2.solver:GetMaxParticles() - gwater2.solver:GetActiveParticles()) 137 | end -------------------------------------------------------------------------------- /materials/entities/gwater2_blackhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_blackhole.png -------------------------------------------------------------------------------- /materials/entities/gwater2_bluetooth_hose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_bluetooth_hose.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cleanup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cleanup.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cloth_200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cloth_200.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cloth_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cloth_50.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cube_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cube_10.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cube_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cube_20.png -------------------------------------------------------------------------------- /materials/entities/gwater2_cube_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_cube_5.png -------------------------------------------------------------------------------- /materials/entities/gwater2_drain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_drain.png -------------------------------------------------------------------------------- /materials/entities/gwater2_emitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_emitter.png -------------------------------------------------------------------------------- /materials/entities/gwater2_forcefield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_forcefield.png -------------------------------------------------------------------------------- /materials/entities/gwater2_mentoscola.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_mentoscola.png -------------------------------------------------------------------------------- /materials/entities/gwater2_rain_emitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_rain_emitter.png -------------------------------------------------------------------------------- /materials/entities/gwater2_showerhead.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_showerhead.png -------------------------------------------------------------------------------- /materials/entities/gwater2_sphere_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_sphere_10.png -------------------------------------------------------------------------------- /materials/entities/gwater2_sphere_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_sphere_20.png -------------------------------------------------------------------------------- /materials/entities/gwater2_sphere_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_sphere_5.png -------------------------------------------------------------------------------- /materials/entities/gwater2_transmuter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_transmuter.png -------------------------------------------------------------------------------- /materials/entities/gwater2_transporter_recv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/gwater2_transporter_recv.png -------------------------------------------------------------------------------- /materials/entities/weapon_gw2_advwatergun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/weapon_gw2_advwatergun.png -------------------------------------------------------------------------------- /materials/entities/weapon_gw2_partseas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/weapon_gw2_partseas.png -------------------------------------------------------------------------------- /materials/entities/weapon_gw2_watergun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/weapon_gw2_watergun.png -------------------------------------------------------------------------------- /materials/entities/weapon_gw2_watergun_icon.vmt: -------------------------------------------------------------------------------- 1 | UnlitGeneric { 2 | $basetexture "entities/weapon_gw2_watergun_icon" 3 | $translucent 1 4 | } 5 | -------------------------------------------------------------------------------- /materials/entities/weapon_gw2_watergun_icon.vtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/entities/weapon_gw2_watergun_icon.vtf -------------------------------------------------------------------------------- /materials/gwater2/black.vmt: -------------------------------------------------------------------------------- 1 | UnlitGeneric { 2 | $ignorez 1 3 | $color2 "[0 0 0 0]" 4 | $basetexture "lights/white" 5 | } -------------------------------------------------------------------------------- /materials/gwater2/blackhole.vmt: -------------------------------------------------------------------------------- 1 | UnlitGeneric { 2 | $translucent 1 3 | $color2 "[0 0 0]" 4 | $additive 0 5 | $basetexture gwater2/sphere 6 | } -------------------------------------------------------------------------------- /materials/gwater2/bubble.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture gwater2/bubble 3 | $translucent 1 4 | //$additive 1 5 | $alpha 0.3 6 | } -------------------------------------------------------------------------------- /materials/gwater2/bubble.vtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/gwater2/bubble.vtf -------------------------------------------------------------------------------- /materials/gwater2/cloth.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $envmap env_cubemap 3 | $envmaptint "[0.0 0.0 0.0]" 4 | $color2 "[0.5 0.7 0.9 1]" 5 | $basetexture lights/white 6 | $nocull 1 7 | } -------------------------------------------------------------------------------- /materials/gwater2/clouds.vmt: -------------------------------------------------------------------------------- 1 | UnlitGeneric { 2 | $basetexture "gwater2/clouds" 3 | $model 1 4 | $nocull 0 5 | $translucent 1 6 | $frame 0 7 | $basetexturetransform "center 0.5 0.5 scale 0.7 0.7 rotate 0 translate 0 0" 8 | } 9 | -------------------------------------------------------------------------------- /materials/gwater2/clouds.vtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/gwater2/clouds.vtf -------------------------------------------------------------------------------- /materials/gwater2/finalpass.vmt: -------------------------------------------------------------------------------- 1 | GWaterFinalpass { 2 | $envmap "env_cubemap" 3 | $radius 10 4 | $ior 1.333 5 | $reflectance 0.7 6 | $screentexture "_rt_fullframefb" 7 | $color2 "[209 237 255 25]" 8 | $flashlight 1 9 | } -------------------------------------------------------------------------------- /materials/gwater2/mist.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture gwater2/splash 3 | //$additive 1 4 | $translucent 1 5 | $alpha 0.15 6 | } -------------------------------------------------------------------------------- /materials/gwater2/normals.vmt: -------------------------------------------------------------------------------- 1 | GWaterNormals { 2 | $radius 10 3 | $depthfix 0 4 | } 5 | -------------------------------------------------------------------------------- /materials/gwater2/smooth.vmt: -------------------------------------------------------------------------------- 1 | GWaterSmooth { 2 | $ignorez 1 3 | } -------------------------------------------------------------------------------- /materials/gwater2/sphere.vtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/gwater2/sphere.vtf -------------------------------------------------------------------------------- /materials/gwater2/splash.vtf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/materials/gwater2/splash.vtf -------------------------------------------------------------------------------- /materials/gwater2/volumetric.vmt: -------------------------------------------------------------------------------- 1 | GWaterVolumetric { 2 | $basetexture gwater2/sphere 3 | $additive 1 4 | $alpha 0.125 5 | $translucent 1 6 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/base.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $color2 "[0.9 0.9 0.1]" 4 | 5 | $phong 1 6 | $phongboost 10 7 | $phongexponent 200 8 | $phongfresnelranges "[0.2 0.6 1]" 9 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/handle.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $color2 "[0.4 0.9 1]" 4 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/nozzle.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $color2 "[1 0.5 0]" 4 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/pipe.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/screw.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $color2 "[0.8 1.8 2]" 4 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/strut.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $envmap env_cubemap 4 | $color2 "[0.5 0.5 0.5]" 5 | } -------------------------------------------------------------------------------- /materials/gwater2/water_gun/tank.vmt: -------------------------------------------------------------------------------- 1 | VertexLitGeneric { 2 | $basetexture "lights/white" 3 | $envmap env_cubemap 4 | $envmaptint "[0.3 0.3 0.3]" 5 | $halflambert 1 6 | $color2 "[0.3 0.9 0.3]" 7 | } -------------------------------------------------------------------------------- /materials/gwater2/whitehole.vmt: -------------------------------------------------------------------------------- 1 | UnlitGeneric { 2 | $translucent 1 3 | $additive 1 4 | $basetexture gwater2/sphere 5 | } -------------------------------------------------------------------------------- /models/gwater2/water_gun.dx80.vtx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/models/gwater2/water_gun.dx80.vtx -------------------------------------------------------------------------------- /models/gwater2/water_gun.dx90.vtx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/models/gwater2/water_gun.dx90.vtx -------------------------------------------------------------------------------- /models/gwater2/water_gun.mdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/models/gwater2/water_gun.mdl -------------------------------------------------------------------------------- /models/gwater2/water_gun.vvd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/models/gwater2/water_gun.vvd -------------------------------------------------------------------------------- /resource/fonts/RobotoMonoVariable.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/resource/fonts/RobotoMonoVariable.ttf -------------------------------------------------------------------------------- /resource/fonts/RobotoVariable.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/resource/fonts/RobotoVariable.ttf -------------------------------------------------------------------------------- /resource/fonts/SpaceMonoRegular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/resource/fonts/SpaceMonoRegular.ttf -------------------------------------------------------------------------------- /resource/fonts/TitilliumWeb-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/resource/fonts/TitilliumWeb-Regular.ttf -------------------------------------------------------------------------------- /resource/fonts/coolvetica.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/resource/fonts/coolvetica.ttf -------------------------------------------------------------------------------- /sound/gwater2/menu/confirm.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/confirm.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/reset.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/reset.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/rollover.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/rollover.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/select.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/select.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/select_deny.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/select_deny.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/select_ok.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/select_ok.wav -------------------------------------------------------------------------------- /sound/gwater2/menu/toggle.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/menu/toggle.wav -------------------------------------------------------------------------------- /sound/gwater2/paint_loop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/paint_loop.wav -------------------------------------------------------------------------------- /sound/gwater2/soda_launch.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/soda_launch.wav -------------------------------------------------------------------------------- /sound/gwater2/water_loop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/meetric1/gwater2/a870f9aed003ad97e9e45d556b9a6b3d3e1fa7d2/sound/gwater2/water_loop.wav --------------------------------------------------------------------------------