Skip to content

Commit 2a02a15

Browse files
committed
Finished rendering proof of concept; starting git repo for continued development
1 parent b3b5c43 commit 2a02a15

File tree

5 files changed

+241
-0
lines changed

5 files changed

+241
-0
lines changed

gmod_worldportal.fgd

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//=============================================================================
2+
//
3+
// Purpose: Garry's Mod world portal declarations
4+
//
5+
//=============================================================================
6+
7+
@include "base.fgd"
8+
9+
@BaseClass = LinkedPortalDoor : "An entity that can be linked to another door and create a passage between them dynamically."
10+
[
11+
input SetPair(integer) : "Changes the pair of portals this portal belongs to"
12+
input Open(void) : "Open the door and cause the portal to activate."
13+
input Close(void) : "Close the door and cause the portal to deactivate."
14+
15+
output OnOpen(void) : "Called when the door has started its open animation."
16+
output OnClose(void) : "Called when the door has started its close animation."
17+
output OnEntityTeleportFromMe(void) : "When any entity is teleported from this portal to the linked partner."
18+
output OnPlayerTeleportFromMe(void) : "When the player is teleported from this portal to the linked partner."
19+
output OnEntityTeleportToMe(void) : "When any entity is teleported from this linked partner to the portal."
20+
output OnPlayerTeleportToMe(void) : "When the player is teleported from this linked partner to the portal."
21+
]
22+
23+
@PointClass base(Targetname, Parentname, Angles, LinkedPortalDoor) studio("models/editor/axis_helper_thick.mdl") = linked_portal_door :
24+
"A door which is linked by a portal to another 'linked_portal_door' entity."
25+
[
26+
pair(integer) : "Pair" : 1 : "Unique identifier for a set of portals."
27+
width(integer) : "Width" : 128 : "Width of the desired portal."
28+
height(integer) : "Height" : 128 : "Height of the desired portal."
29+
startactive(integer) : "Start Active" : 1 : "Whether to start the linkage as active from the start."
30+
]

lua/autorun/client/init.lua

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
2+
local portals
3+
local matView = CreateMaterial(
4+
"UnlitGeneric",
5+
"GMODScreenspace",
6+
{
7+
["$basetexturetransform"] = "center .5 .5 scale -1 -1 rotate 0 translate 0 0",
8+
["$texturealpha"] = "0",
9+
["$vertexalpha"] = "1",
10+
}
11+
)
12+
local matDummy = Material( "debug/white" )
13+
14+
15+
-- Render the portal views
16+
local drawing = false
17+
18+
hook.Add( "RenderScene", "WorldPortalRenderHook", function( plyOrigin, plyAngles)
19+
20+
if ( not portals ) then return end
21+
if ( drawing ) then return end
22+
23+
local oldWepColor = LocalPlayer():GetWeaponColor()
24+
LocalPlayer():SetWeaponColor( Vector(0, 0, 0) ) --no more phys gun glaw or beam
25+
26+
for _, portal in ipairs( portals ) do
27+
-- Render view from portal
28+
local oldRT = render.GetRenderTarget()
29+
render.SetRenderTarget( portal.texture )
30+
render.Clear( 0, 0, 0, 255 )
31+
render.ClearDepth()
32+
render.ClearStencil()
33+
34+
render.EnableClipping(true)
35+
--render.PopCustomClipPlane()
36+
render.PushCustomClipPlane(portals[portal.exit].forward, portals[portal.exit].forward:Dot(portals[portal.exit].pos) )
37+
38+
local rotation = portals[portal.exit].forward:Angle() - portal.forward:Angle()
39+
rotation = rotation + Angle( 0, 180, 0)
40+
local offset = LocalPlayer():EyePos() - portal.pos
41+
--offset = calculateNewOffset( portal, offset )
42+
offset:Rotate( rotation )
43+
local camPos = portals[portal.exit].pos + offset
44+
45+
local camAngles = plyAngles + rotation
46+
47+
drawing = true
48+
render.RenderView( {
49+
x = 0,
50+
y = 0,
51+
w = ScrW(),
52+
h = ScrH(),
53+
origin = camPos,
54+
angles = camAngles,
55+
drawpostprocess = true,
56+
drawhud = false,
57+
drawmonitors = false,
58+
drawviewmodel = false,
59+
} )
60+
drawing = false
61+
62+
render.PopCustomClipPlane()
63+
render.EnableClipping(false)
64+
render.SetRenderTarget( oldRT )
65+
end
66+
67+
LocalPlayer():SetWeaponColor( oldWepColor )
68+
end )
69+
hook.Add( "PreDrawOpaqueRenderables", "WorldPortalRenderHook", function()
70+
71+
render.UpdateScreenEffectTexture()
72+
73+
if ( not portals ) then return end
74+
if ( drawing ) then return end
75+
76+
for _, portal in ipairs( portals ) do
77+
78+
-- Draw view over portal
79+
render.ClearStencil()
80+
render.SetStencilEnable( true )
81+
82+
render.SetStencilWriteMask( 1 )
83+
render.SetStencilTestMask( 1 )
84+
85+
render.SetStencilFailOperation( STENCILOPERATION_KEEP )
86+
render.SetStencilZFailOperation( STENCILOPERATION_KEEP )
87+
render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
88+
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
89+
render.SetStencilReferenceValue( 1 )
90+
91+
render.SetMaterial( matDummy )
92+
render.SetColorModulation( 1, 1, 1 )
93+
94+
render.DrawQuadEasy( portal.pos, portal.forward, portal.width, portal.height, Color( 255, 255, 255, 255) )
95+
96+
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
97+
render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
98+
render.SetStencilReferenceValue( 1 )
99+
100+
matView:SetTexture( "$basetexture", portal.texture )
101+
render.SetMaterial( matView )
102+
render.DrawScreenQuad()
103+
104+
render.SetStencilEnable( false )
105+
end
106+
end )
107+
108+
-- Receive portal info
109+
net.Receive("WorldPortalUpdate", function()
110+
portals = {}
111+
112+
for i = 1, net.ReadInt( 16 ) do
113+
portals[i] = {}
114+
portals[i].pos = net.ReadVector()
115+
portals[i].width = net.ReadInt( 16 )
116+
portals[i].height = net.ReadInt( 16 )
117+
portals[i].forward = net.ReadVector()
118+
portals[i].exit = net.ReadInt( 16 )
119+
portals[i].texture = GetRenderTarget("portal" .. i,
120+
ScrW(),
121+
ScrH(),
122+
false
123+
)
124+
end
125+
126+
end )
127+
128+
-- Set it to draw the player while rendering portals
129+
-- Calling Start3D to fix this is incredibly hacky
130+
131+
hook.Add( "PostDrawEffects", "WorldPortalPotentialFix", function()
132+
cam.Start3D( EyePos(), EyeAngles() )
133+
cam.End3D()
134+
end)
135+
136+
hook.Add( "ShouldDrawLocalPlayer", "WorldPortalRenderHook", function()
137+
return drawing
138+
end)

lua/autorun/server/init.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
2+
3+
-- Send portal render code
4+
AddCSLuaFile( "autorun/client/init.lua" )
5+
6+
-- Precache network string
7+
util.AddNetworkString( "WorldPortalUpdate" )
8+
9+
-- Send info about portals to clients
10+
local function WorldPortalUpdate( ply )
11+
12+
ply:DrawViewModel(false)
13+
local portals = ents.FindByClass( "linked_portal_door" )
14+
15+
net.Start( "WorldPortalUpdate" )
16+
net.WriteInt( #portals, 16 )
17+
18+
for _, portal in ipairs( portals ) do
19+
net.WriteVector( portal:GetPos() )
20+
net.WriteInt( portal.width, 16 )
21+
net.WriteInt( portal.height, 16 )
22+
net.WriteVector( portal.forward )
23+
net.WriteInt( table.KeyFromValue( portals, portal.exit ), 16 )
24+
end
25+
net.Send( ply )
26+
end
27+
hook.Add( "PlayerInitialSpawn", "WorldPortalUpdateTransmission", WorldPortalUpdate )
28+
29+
-- Set up visibility through portals
30+
hook.Add( "SetupPlayerVisibility", "WorldPortalVisibility", function( ply, ent )
31+
for _, portal in ipairs( ents.FindByClass( "linked_portal_door" ) ) do
32+
AddOriginToPVS( portal:GetPos() )
33+
end
34+
end )
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
ENT.Type = "point"
3+
4+
5+
-- Find paired entity
6+
-- not the most efficient implementation, but good enough for now
7+
function ENT:Think()
8+
-- Determine exit portal
9+
if ( !self.exit ) then
10+
for _, ent in ipairs( ents.FindByClass( "linked_portal_door" ) ) do
11+
if ( ent ~= self and ent.pair == self.pair ) then
12+
self.exit = ent
13+
end
14+
end
15+
end
16+
end
17+
18+
-- Collect properties
19+
function ENT:KeyValue( key, value )
20+
if ( key == "pair" ) then
21+
self.pair = tonumber( value )
22+
23+
elseif ( key == "width" ) then
24+
self.width = tonumber( value )
25+
26+
elseif ( key == "height" ) then
27+
self.height = tonumber( value )
28+
29+
elseif ( key == "angles" ) then
30+
local args = value:Split( " " )
31+
32+
for k, arg in pairs( args ) do
33+
args[k] = tonumber(arg)
34+
end
35+
36+
self.forward = Angle( unpack(args) ):Forward()
37+
print( value, forward )
38+
end
39+
end

maps/spacial_bullshit.bsp

317 KB
Binary file not shown.

0 commit comments

Comments
 (0)