├── .editorconfig ├── LICENSE ├── README.md └── lua ├── autorun └── stencil_tutorial.lua ├── entities ├── sent_stencil_test.lua └── sent_stencil_test_big.lua └── stencil_tutorial ├── 00_nothing.lua ├── 01_basic_clipping.lua ├── 02_basic_pass_operation.lua ├── 03_basic_fail_operation.lua ├── 04_basic_zfail_operation.lua ├── 05_clear_buffers_obey_stencil.lua ├── 06_cutting_holes_in_props.lua ├── 07_cutting_holes_in_the_world.lua ├── 08_masks.lua ├── 09_advanced_masks.lua ├── 10_2d_stencils.lua └── 11_3d2d_stencils.lua /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | indent_size = 4 6 | tab_width = 4 7 | end_of_line = crlf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lex's Stencil Tutorial 2 | 3 | While working out how to use the stencil buffer in [Garry's Mod][gmod] I had 4 | to read a lot of tutorials and then mangle a whole bunch of code to get a 5 | proper idea on what things were actually doing. 6 | 7 | This repository is an attempt to distill all that knowledge into a series of 8 | documented runnable examples that I hope will help people, and enrich the 9 | sadly unfilled [Garry's Mod Wiki][wiki]. 10 | 11 | The examples will make great use of the entity `sent_stencil_test` which is 12 | just a prop that doesn't draw itself by default. You could easily substitute 13 | it for any other entity of your own. 14 | 15 | It is under the category "Dev Stuff" in the Sandbox spawn menu. If you spawn 16 | one but lose it, run `stencil_tutorial_draw_ents 1` in console and it will 17 | start rendering. Run `stencil_tutorial_draw_ents 0` to hide it again. 18 | 19 | When running an example, use `lua_openscript_cl`, for example 20 | 21 | ] lua_openscript_cl stencil_tutorial/basic_clipping.lua 22 | 23 | Each example will override the previous, so you can just run them 24 | sequentially. To end an example, run the console command 25 | `stencil_tutorial_end_example`. 26 | 27 | [gmod]: https://gmod.facepunch.com/ 28 | [wiki]: https://wiki.garrysmod.com/ 29 | -------------------------------------------------------------------------------- /lua/autorun/stencil_tutorial.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | if ( SERVER ) then 17 | AddCSLuaFile() 18 | return 19 | end 20 | 21 | 22 | concommand.Add( "stencil_tutorial_end_example", function() 23 | 24 | hook.Remove( "PostDrawOpaqueRenderables", "Stencil Tutorial Example" ) 25 | hook.Remove( "HUDPaint", "Stencil Tutorial Example" ) 26 | 27 | end ) 28 | -------------------------------------------------------------------------------- /lua/entities/sent_stencil_test.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | AddCSLuaFile() 17 | 18 | DEFINE_BASECLASS( "base_anim" ) 19 | 20 | ENT.PrintName = "Stencil Test" 21 | ENT.Author = "Lexi" 22 | ENT.Spawnable = true 23 | ENT.Category = "Dev Stuff" 24 | 25 | if ( SERVER ) then 26 | 27 | function ENT:Initialize() 28 | 29 | self:SetModel( "models/hunter/plates/plate1x1.mdl" ) 30 | self:PhysicsInit( SOLID_VPHYSICS ) 31 | 32 | end 33 | 34 | else 35 | 36 | local cvar = CreateConVar( "stencil_tutorial_draw_ents", 0, FCVAR_NONE, "If the stencil test entities should draw normally" ) 37 | cvars.AddChangeCallback( cvar:GetName(), function(_, old, new) 38 | 39 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test*" ) ) do 40 | 41 | ent:SetNoDraw( not tobool( new ) ) 42 | 43 | end 44 | 45 | end, "sent_stencil_test" ) 46 | 47 | function ENT:Initialize() 48 | 49 | self:SetNoDraw( not cvar:GetBool() ) 50 | 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /lua/entities/sent_stencil_test_big.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | AddCSLuaFile() 17 | 18 | DEFINE_BASECLASS( "sent_stencil_test" ) 19 | 20 | ENT.PrintName = "Big Stencil Test" 21 | ENT.Author = "Lexi" 22 | ENT.Spawnable = true 23 | ENT.Category = "Dev Stuff" 24 | 25 | if ( SERVER ) then 26 | 27 | function ENT:Initialize() 28 | 29 | self:SetModel( "models/hunter/plates/plate2x3.mdl" ) 30 | self:PhysicsInit( SOLID_VPHYSICS ) 31 | 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/00_nothing.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | 28 | -- Enable stencils 29 | render.SetStencilEnable( true ) 30 | -- Set the reference value to 1. This is what the compare function tests against 31 | render.SetStencilReferenceValue( 1 ) 32 | -- Refuse to write things to the screen unless that pixel's value is 1 33 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 34 | -- Set the entire screen to 0 35 | render.ClearStencil() 36 | 37 | -- Attempt to draw our entities. Nothing will draw, because nothing in the buffer is 1. 38 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 39 | ent:DrawModel() 40 | end 41 | 42 | -- Let everything render normally again 43 | render.SetStencilEnable( false ) 44 | end ) 45 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/01_basic_clipping.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Refuse to write things to the screen unless that pixel's value is 1 34 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 35 | -- Write a 1 to the centre third of the screen. Because we cleared it earlier, everything is currently 0 36 | local w, h = ScrW() / 3, ScrH() / 3 37 | local x_start, y_start = w, h 38 | local x_end, y_end = x_start + w, y_start + h 39 | render.ClearStencilBufferRectangle( x_start, y_start, x_end, y_end, 1 ) 40 | 41 | -- Draw our entities. They will only draw in the area cleared above 42 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 43 | ent:DrawModel() 44 | end 45 | 46 | -- Let everything render normally again 47 | render.SetStencilEnable( false ) 48 | end ) 49 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/02_basic_pass_operation.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | -- render.SetStencilPassOperation( STENCIL_KEEP ) 25 | render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Only draw things if their pixels are NOT 1. Currently this is everything. 34 | render.SetStencilCompareFunction( STENCIL_NOTEQUAL ) 35 | -- If something draws to the screen, set the pixels it draws to 1 36 | render.SetStencilPassOperation( STENCIL_REPLACE ) 37 | 38 | -- Draw our entities. They will draw as normal 39 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 40 | ent:DrawModel() 41 | end 42 | 43 | -- At this point, we cannot draw on top of anything that we have already drawn. 44 | -- So, if we flush the screen, our entities will still be there. 45 | render.ClearBuffersObeyStencil(0, 148, 133, 255, false); 46 | 47 | -- Let everything render normally again 48 | render.SetStencilEnable( false ) 49 | end ) 50 | 51 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/03_basic_fail_operation.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Only draw things if their pixels are currently 1. Currently this is nothing. 34 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 35 | -- If something fails to draw to the screen, set the pixels it would have drawn to 1 36 | -- This includes if it's behind something. 37 | render.SetStencilFailOperation( STENCIL_REPLACE ) 38 | 39 | -- Draw our entities. They will not draw, because everything is 0 40 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 41 | ent:DrawModel() 42 | end 43 | 44 | -- If we were to re-draw our entities, we'd see them, but otherwise they're invisible. 45 | -- If we flush the screen, we can show the "holes" they've left in the stencil buffer 46 | render.ClearBuffersObeyStencil(0, 148, 133, 255, false); 47 | 48 | -- Let everything render normally again 49 | render.SetStencilEnable( false ) 50 | end ) 51 | 52 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/04_basic_zfail_operation.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | render.SetStencilFailOperation( STENCIL_KEEP ) 26 | -- render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Always draw everything 34 | render.SetStencilCompareFunction( STENCIL_ALWAYS ) 35 | -- If something would draw to the screen but is behind something, set the pixels it draws to 1 36 | render.SetStencilZFailOperation( STENCIL_REPLACE ) 37 | 38 | -- Draw our entities. They will draw as normal 39 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 40 | ent:DrawModel() 41 | end 42 | 43 | -- Now, only draw things that have their pixels set to 1. This is the hidden parts of the stencil tests. 44 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 45 | -- Flush the screen. This will draw teal over all hidden sections of the stencil tests 46 | render.ClearBuffersObeyStencil(0, 148, 133, 255, false); 47 | 48 | -- Let everything render normally again 49 | render.SetStencilEnable( false ) 50 | end ) 51 | 52 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/05_clear_buffers_obey_stencil.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Refuse to write things to the screen unless that pixel's value is 1 34 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 35 | -- Write a 1 to the centre third of the screen. Because we cleared it earlier, everything is currently 0 36 | local w, h = ScrW() / 3, ScrH() / 3 37 | local x_start, y_start = w, h 38 | local x_end, y_end = x_start + w, y_start + h 39 | render.ClearStencilBufferRectangle( x_start, y_start, x_end, y_end, 1 ) 40 | 41 | -- Tell the render library to clear the screen, but obeying the stencil test function. 42 | -- This means it will only clear the centre third. 43 | render.ClearBuffersObeyStencil(0, 148, 133, 255, false); 44 | 45 | -- Let everything render normally again 46 | render.SetStencilEnable( false ) 47 | end ) 48 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/06_cutting_holes_in_props.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set the reference value to 1. This is what the compare function tests against 32 | render.SetStencilReferenceValue( 1 ) 33 | -- Force everything to fail 34 | render.SetStencilCompareFunction( STENCIL_NEVER ) 35 | -- Save all the things we don't draw 36 | render.SetStencilFailOperation( STENCIL_REPLACE ) 37 | 38 | -- Fail to draw our entities. 39 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 40 | ent:DrawModel() 41 | end 42 | 43 | -- Render all pixels that don't have their stencil value as 1 44 | render.SetStencilCompareFunction( STENCIL_NOTEQUAL ) 45 | -- Don't modify the stencil buffer when things fail 46 | render.SetStencilFailOperation( STENCIL_KEEP ) 47 | 48 | -- Draw our big entities. They will have holes in them wherever the smaller entities were 49 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test_big" ) ) do 50 | ent:DrawModel() 51 | end 52 | 53 | -- Let everything render normally again 54 | render.SetStencilEnable( false ) 55 | end ) 56 | 57 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/07_cutting_holes_in_the_world.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | -- Set up a global flag to avoid double rendering 18 | local drawing = false; 19 | -- Create a rendertarget the size of the screen to store the back of our window in 20 | local rt = GetRenderTarget("Stencil Tutorial", ScrW(), ScrH()) 21 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 22 | -- We're going to recursively render everything, so don't run the stencils twice 23 | if ( drawing ) then 24 | return 25 | end 26 | 27 | -- We need to store a copy of the world before we modify it with stencils 28 | -- To do this, we first start rendering to our texture instead of the screen 29 | render.PushRenderTarget( rt ) 30 | -- Set the flag 31 | drawing = true; 32 | -- Render the current world, but a bit less of it 33 | render.RenderView({ 34 | -- This needs to be the distance from EyePos to the wall you're cutting a hole in + a bit more. 35 | -- In this case I've cheated and picked a number that works with my static camera. You will need to be more clever. 36 | znear = 150; 37 | }); 38 | -- Put everything back how it was 39 | drawing = false; 40 | render.PopRenderTarget() 41 | 42 | 43 | -- Reset everything to known good 44 | render.SetStencilWriteMask( 0xFF ) 45 | render.SetStencilTestMask( 0xFF ) 46 | render.SetStencilReferenceValue( 0 ) 47 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 48 | render.SetStencilPassOperation( STENCIL_KEEP ) 49 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 50 | render.SetStencilZFailOperation( STENCIL_KEEP ) 51 | render.ClearStencil() 52 | 53 | -- Enable stencils 54 | render.SetStencilEnable( true ) 55 | -- Set the reference value to 1. This is what the compare function tests against 56 | render.SetStencilReferenceValue( 1 ) 57 | -- Force everything to fail 58 | render.SetStencilCompareFunction( STENCIL_NEVER ) 59 | -- Save all the things we don't draw 60 | render.SetStencilFailOperation( STENCIL_REPLACE ) 61 | 62 | -- Fail to draw our entities. 63 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 64 | ent:DrawModel() 65 | end 66 | 67 | -- Only render where our entities are 68 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 69 | -- Don't modify the stencil buffer when things fail 70 | render.SetStencilFailOperation( STENCIL_KEEP ) 71 | 72 | -- Draw the copy of the world we just drew 73 | render.DrawTextureToScreen( rt ) 74 | 75 | -- Let everything render normally again 76 | render.SetStencilEnable( false ) 77 | end ) 78 | 79 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/08_masks.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | --[[ 19 | To understand this tutorial you need to already understand the basics 20 | of binary and bitwise operations. 21 | 22 | It would also help to understand hexadecimal notation, since Lua 23 | doesn't have a bitmask input, but I will include binary notation in 24 | comments to help. 25 | --]] 26 | 27 | -- Reset everything to known good 28 | -- render.SetStencilWriteMask( 0xFF ) 29 | -- render.SetStencilTestMask( 0xFF ) 30 | render.SetStencilReferenceValue( 0 ) 31 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 32 | render.SetStencilPassOperation( STENCIL_KEEP ) 33 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 34 | render.SetStencilZFailOperation( STENCIL_KEEP ) 35 | render.ClearStencil() 36 | 37 | -- Enable stencils 38 | render.SetStencilEnable( true ) 39 | -- Force everything to fail 40 | render.SetStencilCompareFunction( STENCIL_NEVER ) 41 | -- Save all the things we don't draw 42 | render.SetStencilFailOperation( STENCIL_REPLACE ) 43 | 44 | -- Set the reference value to 00011100 45 | render.SetStencilReferenceValue( 0x1C ) 46 | -- Set the write mask to 01010101 47 | -- Any writes to the stencil buffer will be bitwise ANDed with this mask. 48 | -- With our current reference value, the result will be 00010100. 49 | render.SetStencilWriteMask( 0x55 ) 50 | 51 | -- Fail to draw our entities. 52 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 53 | ent:DrawModel() 54 | end 55 | 56 | -- Set the test mask to 11110011. 57 | -- Any time a pixel is read out of the stencil buffer it will be bitwise ANDed with this mask. 58 | render.SetStencilTestMask( 0xF3 ) 59 | -- Set the reference value to 00011100 & 01010101 & 11110011 60 | render.SetStencilReferenceValue( 0x10 ) 61 | -- Pass if the masked buffer value matches the unmasked reference value 62 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 63 | 64 | -- Draw our entities 65 | render.ClearBuffersObeyStencil( 0, 148, 133, 255, false ); 66 | 67 | -- Let everything render normally again 68 | render.SetStencilEnable( false ) 69 | end ) 70 | 71 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/09_advanced_masks.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | --[[ 19 | To understand this tutorial you need to already understand the basics 20 | of binary and bitwise operations. 21 | 22 | It would also help to understand hexadecimal notation, since Lua 23 | doesn't have a bitmask input, but I will include binary notation in 24 | comments to help. 25 | --]] 26 | 27 | -- Reset everything to known good 28 | -- render.SetStencilWriteMask( 0xFF ) 29 | -- render.SetStencilTestMask( 0xFF ) 30 | render.SetStencilReferenceValue( 0 ) 31 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 32 | render.SetStencilPassOperation( STENCIL_KEEP ) 33 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 34 | render.SetStencilZFailOperation( STENCIL_KEEP ) 35 | render.ClearStencil() 36 | 37 | -- Enable stencils 38 | render.SetStencilEnable( true ) 39 | 40 | -- Only write to the upper 4 bits of the stencil buffer 41 | render.SetStencilWriteMask( 0xF0 ) 42 | -- Wipe the stencil buffer to be 0001111. This is not affected by the write mask. 43 | render.ClearStencilBufferRectangle( 0, 0, ScrW(), ScrH(), 0x0F ) 44 | 45 | -- Always fail 46 | render.SetStencilCompareFunction( STENCIL_NEVER ) 47 | -- Don't read any bits from the stencil buffer 48 | render.SetStencilTestMask( 0x00 ) 49 | -- When an operation fails, read the current value from the stencil buffer, add 50 | -- one to it and then write it back to the buffer 51 | -- This is not affected by the test mask, but it is affected by the write mask 52 | -- This means we will read 00001111, then write 00010000. 53 | -- However, due to the write mask, this won't affect the last four bits already 54 | -- in the buffer, resulting in 00011111. 55 | render.SetStencilFailOperation( STENCIL_INCR ) 56 | 57 | -- Add something interesting to the stencil buffer 58 | for _, ent in pairs( ents.FindByClass( "sent_stencil_test" ) ) do 59 | ent:DrawModel() 60 | end 61 | 62 | 63 | -- Go back to reading the full value from the stencil buffer 64 | render.SetStencilTestMask( 0xFF ) 65 | -- Set the reference value to 00011111 66 | render.SetStencilReferenceValue( 0x1F ) 67 | -- Render the result 68 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 69 | render.ClearBuffersObeyStencil( 0, 148, 133, 255, false ); 70 | 71 | -- Let everything render normally again 72 | render.SetStencilEnable( false ) 73 | end ) 74 | 75 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/10_2d_stencils.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | local AAAA = string.rep( string.rep( "A", 83 ) .. "\n", 37 ) 18 | local poly = { 19 | { x = 200, y = 50 }, 20 | { x = 600, y = 200 }, 21 | { x = 790, y = 400 }, 22 | { x = 500, y = 600 }, 23 | { x = 400, y = 600 }, 24 | { x = 300, y = 500 }, 25 | { x = 100, y = 300 }, 26 | { x = 55, y = 100 }, 27 | } 28 | 29 | hook.Add( "HUDPaint", "Stencil Tutorial Example", function() 30 | 31 | -- Reset everything to known good 32 | render.SetStencilWriteMask( 0xFF ) 33 | render.SetStencilTestMask( 0xFF ) 34 | render.SetStencilReferenceValue( 0 ) 35 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 36 | render.SetStencilPassOperation( STENCIL_KEEP ) 37 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 38 | render.SetStencilZFailOperation( STENCIL_KEEP ) 39 | render.ClearStencil() 40 | 41 | -- Enable stencils 42 | render.SetStencilEnable( true ) 43 | -- Set everything up everything draws to the stencil buffer instead of the screen 44 | render.SetStencilReferenceValue( 1 ) 45 | render.SetStencilCompareFunction( STENCIL_NEVER ) 46 | render.SetStencilFailOperation( STENCIL_REPLACE ) 47 | 48 | -- Draw a weird shape to the stencil buffer 49 | draw.NoTexture() 50 | surface.SetDrawColor( color_white ) 51 | surface.DrawPoly( poly ) 52 | 53 | -- Only draw things that are in the stencil buffer 54 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 55 | render.SetStencilFailOperation( STENCIL_KEEP ) 56 | 57 | -- Draw our clipped text 58 | draw.DrawText( AAAA, "TargetID", 50, 50 ) 59 | 60 | -- Let everything render normally again 61 | render.SetStencilEnable( false ) 62 | 63 | end ) 64 | -------------------------------------------------------------------------------- /lua/stencil_tutorial/11_3d2d_stencils.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | Copyright 2018 Lex Robinson 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | --]] 16 | 17 | hook.Add( "PostDrawOpaqueRenderables", "Stencil Tutorial Example", function() 18 | 19 | -- Reset everything to known good 20 | render.SetStencilWriteMask( 0xFF ) 21 | render.SetStencilTestMask( 0xFF ) 22 | render.SetStencilReferenceValue( 0 ) 23 | -- render.SetStencilCompareFunction( STENCIL_ALWAYS ) 24 | render.SetStencilPassOperation( STENCIL_KEEP ) 25 | -- render.SetStencilFailOperation( STENCIL_KEEP ) 26 | render.SetStencilZFailOperation( STENCIL_KEEP ) 27 | render.ClearStencil() 28 | 29 | -- Enable stencils 30 | render.SetStencilEnable( true ) 31 | -- Set everything up everything draws to the stencil buffer instead of the screen 32 | render.SetStencilReferenceValue( 1 ) 33 | render.SetStencilCompareFunction( STENCIL_NEVER ) 34 | render.SetStencilFailOperation( STENCIL_REPLACE ) 35 | 36 | -- Draw a rectangle at a weird angle and location into the stencil buffer 37 | cam.Start3D2D(Vector( 1014, -24, -40 ), Angle( -30, -120, 90 ), 0.5) 38 | surface.SetDrawColor( color_white ) 39 | -- Note that if you draw something transluncent in here (like a rounded box or text) 40 | -- you will end up with a solid rectangle the size of what you just drew. 41 | -- The reason for this due to how blending works, but can be summarised as "because". 42 | -- For more information, see https://www.khronos.org/opengl/wiki/Blending 43 | surface.DrawRect( 0, 0, 200, 200 ) 44 | cam.End3D2D() 45 | 46 | -- Render the result 47 | render.SetStencilCompareFunction( STENCIL_EQUAL ) 48 | render.ClearBuffersObeyStencil( 0, 148, 133, 255, false ); 49 | 50 | -- Let everything render normally again 51 | render.SetStencilEnable( false ) 52 | 53 | end ) 54 | --------------------------------------------------------------------------------