#Tardis Rendering
1 messages · Page 1 of 1 (latest)
I made a real basic and badly-written version of the Render Target-free idea I was talking about before
AddCSLuaFile()
ENT.Type = "anim"
ENT.Base = "base_gmodentity"
ENT.PrintName = "Rendering Test"
ENT.Category = "Test entities"
ENT.Spawnable = true
function ENT:Initialize()
if SERVER then
self:SetModel( "models/hunter/misc/lift2x2.mdl" )
self:PhysicsInit( SOLID_VPHYSICS )
self:SetMoveType( MOVETYPE_VPHYSICS )
self:SetSolid( SOLID_VPHYSICS )
local phys = self:GetPhysicsObject()
if phys:IsValid() then
phys:Wake()
end
end
end
if not CLIENT then return end
-- This is where we're pretending the tardis is in the world when the player is inside of it
local function GetFakeTardisPosAng()
local time = CurTime()
local pos = Vector( math.sin( time * 0.3 ) * 5, math.cos( time * 0.2 ) * 7, math.sin( time * 0.1 ) * 9 )
local ang = Angle( math.sin( time * 0.1 ) * 10, math.cos( time * 0.2 ) * 20, math.sin( time * 0.3 ) * 30 )
return pos, ang
end
-- Really low-quality and bad check for if the player is inside of the tardis
-- This also changes the render bounds of the entity so it calls the draw function in its fake location when the player is inside of it
function ENT:Think()
if self:GetPos():Distance(LocalPlayer():GetPos()) > 75 then
LocalPlayer().Tardis = nil
self:SetRenderBounds( self:OBBMins(), self:OBBMaxs() )
else
LocalPlayer().Tardis = self
local fakePos, fakeAng = GetFakeTardisPosAng()
self:SetRenderBoundsWS( fakePos + self:OBBMins() * 2, fakePos + self:OBBMaxs() * 2 )
end
end
function ENT:Draw()
-- If the player is inside the tardis, render the tardis at its fake position/angles
if IsValid( LocalPlayer().Tardis ) then
local fakePos, fakeAng = GetFakeTardisPosAng()
self:SetRenderOrigin( fakePos )
self:SetRenderAngles( fakeAng )
end
self:DrawModel()
-- Reset its offsets
self:SetRenderOrigin()
self:SetRenderAngles()
end
-- Move the camera to be relative to the tardis if the player is inside of it
hook.Add( "CalcView", "A1_RenderTest_MoveCamera", function( ply, pos, angles, fov )
local view = {}
view.origin = pos
view.angles = angles
view.fov = fov
local tardis = ply.Tardis
-- If we're not in the tardis, return the normal view
if not IsValid( tardis ) then return view end
-- Calculate the player's view relative to where the tardis actually is so
local localPos = tardis:WorldToLocal( pos )
local localAng = tardis:WorldToLocalAngles( angles )
local fakePos, fakeAng = GetFakeTardisPosAng()
-- Use the player's view relative to the tardis to calculate where the player's view should be relative to the fake tardis position/angle
local adjustedPos, adjustedAng = LocalToWorld( localPos, localAng, fakePos, fakeAng )
view.origin = adjustedPos
view.angles = adjustedAng
return view
end )
-- Move the viewmodel to be relative to the tardis if the player is inside of it
-- This is the same logic as CalcView with slightly different formatting
hook.Add( "CalcViewModelView", "A1_RenderTest_MoveViewmodel", function( wep, vm, oldPos, oldAng, actualPos, actualAng )
local tardis = LocalPlayer().Tardis
if not IsValid( tardis ) then return end
local localPos = tardis:WorldToLocal( actualPos )
local localAng = tardis:WorldToLocalAngles( actualAng )
local fakePos, fakeAng = GetFakeTardisPosAng()
local adjustedPos, adjustedAng = LocalToWorld( localPos, localAng, fakePos, fakeAng )
return adjustedPos, adjustedAng
end )
This is, of course, much less complicated than an actual implementation of this idea would need to be in order to actually be used for your project, but I hope it gets the idea across
The player and the tardis don't actually move
I'm using the CalcView and CalcViewModelView hooks to move where the player's camera is while they're inside the tardis
I'm also using ENT:SetRenderOrigin and ENT:SetRenderAngles to move where the tardis's interior (And exterior in this example, but your usage would be different) renders while the player is inside of the tardis
They're both "pretending" to be far away from where they actually are
so the actual player is still inside the mirror room?
but wouldnt the skybox still be unrendered youre far enough away or looking in the wrong direction
like the real tardis entity also just places a seperate interior model somewhere on the map, i could literally place it into the mirror room aswell
As far as the game's rendering system is concerned, the player IS standing above ground, so the skybox should render as normal
You can see that fact with the lighting here
i can make it land inside itself due to this
Which is something we can all enjoy
so what it does differently to render targets is that there's no portal, it literally moves where your view is?
Correct
so that means the interior model also has to physically be there?
Physically? No. Visually? Yes.
I should mention that this strategy of moving the camera around in tricky ways to make it look like you're positioned somewhere you aren't is actually how Portal's portals work
that sounds like an issue when there are a hundred entities that need to be there
since each control element is a seperate entity, its not all one model
You can have as many of those as you want
In the code above I'm using the per-entity ENT:SetRenderOrigin function, but there are other methods for doing the same to multiple models
Namely cam.PushModelMatrix which allows you to move, rotate, and scale all rendering until you call cam.PopModelMatrix
I should clarify briefly that I'm not necessarily trying to tell you that this change is worth the amount of time and work it would take to implement it.
I really don't know how much effort that would take to do, practically.
I'm just trying to make you aware of something that would solve some of the issues you seem to be running into
Whether that solution is worth the time and effort is up to you
im not concerned with the time and effort honestly..
my concern is that i dont have the actual skill to do any of this
i still cant figure out how to fix basic rendering issues, let alone rewrite the entire addon's rendering core
If you don't mind a suggestion on that front: I would really recommend doing the learning part and the implementing part as separate steps.
Don't try to learn something new while also trying to use that new thing to implement a change or fix to your project.
Instead, learn that new thing totally separately from your project and—Once you understand that new topic pretty well from experimenting—apply it to your project
Doing both at once can be daunting and it can lead to a bit of a code mess if you're not careful and lucky