Skip to content

Commit

Permalink
Finished rendering proof of concept; starting git repo for continued …
Browse files Browse the repository at this point in the history
…development
  • Loading branch information
bliptec committed Jun 7, 2014
1 parent b3b5c43 commit 2a02a15
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 0 deletions.
30 changes: 30 additions & 0 deletions gmod_worldportal.fgd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//=============================================================================
//
// Purpose: Garry's Mod world portal declarations
//
//=============================================================================

@include "base.fgd"

@BaseClass = LinkedPortalDoor : "An entity that can be linked to another door and create a passage between them dynamically."
[
input SetPair(integer) : "Changes the pair of portals this portal belongs to"
input Open(void) : "Open the door and cause the portal to activate."
input Close(void) : "Close the door and cause the portal to deactivate."

output OnOpen(void) : "Called when the door has started its open animation."
output OnClose(void) : "Called when the door has started its close animation."
output OnEntityTeleportFromMe(void) : "When any entity is teleported from this portal to the linked partner."
output OnPlayerTeleportFromMe(void) : "When the player is teleported from this portal to the linked partner."
output OnEntityTeleportToMe(void) : "When any entity is teleported from this linked partner to the portal."
output OnPlayerTeleportToMe(void) : "When the player is teleported from this linked partner to the portal."
]

@PointClass base(Targetname, Parentname, Angles, LinkedPortalDoor) studio("models/editor/axis_helper_thick.mdl") = linked_portal_door :
"A door which is linked by a portal to another 'linked_portal_door' entity."
[
pair(integer) : "Pair" : 1 : "Unique identifier for a set of portals."
width(integer) : "Width" : 128 : "Width of the desired portal."
height(integer) : "Height" : 128 : "Height of the desired portal."
startactive(integer) : "Start Active" : 1 : "Whether to start the linkage as active from the start."
]
138 changes: 138 additions & 0 deletions lua/autorun/client/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@

local portals
local matView = CreateMaterial(
"UnlitGeneric",
"GMODScreenspace",
{
["$basetexturetransform"] = "center .5 .5 scale -1 -1 rotate 0 translate 0 0",
["$texturealpha"] = "0",
["$vertexalpha"] = "1",
}
)
local matDummy = Material( "debug/white" )


-- Render the portal views
local drawing = false

hook.Add( "RenderScene", "WorldPortalRenderHook", function( plyOrigin, plyAngles)

if ( not portals ) then return end
if ( drawing ) then return end

local oldWepColor = LocalPlayer():GetWeaponColor()
LocalPlayer():SetWeaponColor( Vector(0, 0, 0) ) --no more phys gun glaw or beam

for _, portal in ipairs( portals ) do
-- Render view from portal
local oldRT = render.GetRenderTarget()
render.SetRenderTarget( portal.texture )
render.Clear( 0, 0, 0, 255 )
render.ClearDepth()
render.ClearStencil()

render.EnableClipping(true)
--render.PopCustomClipPlane()
render.PushCustomClipPlane(portals[portal.exit].forward, portals[portal.exit].forward:Dot(portals[portal.exit].pos) )

local rotation = portals[portal.exit].forward:Angle() - portal.forward:Angle()
rotation = rotation + Angle( 0, 180, 0)
local offset = LocalPlayer():EyePos() - portal.pos
--offset = calculateNewOffset( portal, offset )
offset:Rotate( rotation )
local camPos = portals[portal.exit].pos + offset

local camAngles = plyAngles + rotation

drawing = true
render.RenderView( {
x = 0,
y = 0,
w = ScrW(),
h = ScrH(),
origin = camPos,
angles = camAngles,
drawpostprocess = true,
drawhud = false,
drawmonitors = false,
drawviewmodel = false,
} )
drawing = false

render.PopCustomClipPlane()
render.EnableClipping(false)
render.SetRenderTarget( oldRT )
end

LocalPlayer():SetWeaponColor( oldWepColor )
end )
hook.Add( "PreDrawOpaqueRenderables", "WorldPortalRenderHook", function()

render.UpdateScreenEffectTexture()

if ( not portals ) then return end
if ( drawing ) then return end

for _, portal in ipairs( portals ) do

-- Draw view over portal
render.ClearStencil()
render.SetStencilEnable( true )

render.SetStencilWriteMask( 1 )
render.SetStencilTestMask( 1 )

render.SetStencilFailOperation( STENCILOPERATION_KEEP )
render.SetStencilZFailOperation( STENCILOPERATION_KEEP )
render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_ALWAYS )
render.SetStencilReferenceValue( 1 )

render.SetMaterial( matDummy )
render.SetColorModulation( 1, 1, 1 )

render.DrawQuadEasy( portal.pos, portal.forward, portal.width, portal.height, Color( 255, 255, 255, 255) )

render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL )
render.SetStencilPassOperation( STENCILOPERATION_REPLACE )
render.SetStencilReferenceValue( 1 )

matView:SetTexture( "$basetexture", portal.texture )
render.SetMaterial( matView )
render.DrawScreenQuad()

render.SetStencilEnable( false )
end
end )

-- Receive portal info
net.Receive("WorldPortalUpdate", function()
portals = {}

for i = 1, net.ReadInt( 16 ) do
portals[i] = {}
portals[i].pos = net.ReadVector()
portals[i].width = net.ReadInt( 16 )
portals[i].height = net.ReadInt( 16 )
portals[i].forward = net.ReadVector()
portals[i].exit = net.ReadInt( 16 )
portals[i].texture = GetRenderTarget("portal" .. i,
ScrW(),
ScrH(),
false
)
end

end )

-- Set it to draw the player while rendering portals
-- Calling Start3D to fix this is incredibly hacky

hook.Add( "PostDrawEffects", "WorldPortalPotentialFix", function()
cam.Start3D( EyePos(), EyeAngles() )
cam.End3D()
end)

hook.Add( "ShouldDrawLocalPlayer", "WorldPortalRenderHook", function()
return drawing
end)
34 changes: 34 additions & 0 deletions lua/autorun/server/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@


-- Send portal render code
AddCSLuaFile( "autorun/client/init.lua" )

-- Precache network string
util.AddNetworkString( "WorldPortalUpdate" )

-- Send info about portals to clients
local function WorldPortalUpdate( ply )

ply:DrawViewModel(false)
local portals = ents.FindByClass( "linked_portal_door" )

net.Start( "WorldPortalUpdate" )
net.WriteInt( #portals, 16 )

for _, portal in ipairs( portals ) do
net.WriteVector( portal:GetPos() )
net.WriteInt( portal.width, 16 )
net.WriteInt( portal.height, 16 )
net.WriteVector( portal.forward )
net.WriteInt( table.KeyFromValue( portals, portal.exit ), 16 )
end
net.Send( ply )
end
hook.Add( "PlayerInitialSpawn", "WorldPortalUpdateTransmission", WorldPortalUpdate )

-- Set up visibility through portals
hook.Add( "SetupPlayerVisibility", "WorldPortalVisibility", function( ply, ent )
for _, portal in ipairs( ents.FindByClass( "linked_portal_door" ) ) do
AddOriginToPVS( portal:GetPos() )
end
end )
39 changes: 39 additions & 0 deletions lua/entities/linked_portal_door/init.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

ENT.Type = "point"


-- Find paired entity
-- not the most efficient implementation, but good enough for now
function ENT:Think()
-- Determine exit portal
if ( !self.exit ) then
for _, ent in ipairs( ents.FindByClass( "linked_portal_door" ) ) do
if ( ent ~= self and ent.pair == self.pair ) then
self.exit = ent
end
end
end
end

-- Collect properties
function ENT:KeyValue( key, value )
if ( key == "pair" ) then
self.pair = tonumber( value )

elseif ( key == "width" ) then
self.width = tonumber( value )

elseif ( key == "height" ) then
self.height = tonumber( value )

elseif ( key == "angles" ) then
local args = value:Split( " " )

for k, arg in pairs( args ) do
args[k] = tonumber(arg)
end

self.forward = Angle( unpack(args) ):Forward()
print( value, forward )
end
end
Binary file added maps/spacial_bullshit.bsp
Binary file not shown.

0 comments on commit 2a02a15

Please sign in to comment.