字幕表 動画を再生する 英語字幕をプリント [MUSIC PLAYING] COLTON OGDEN: All right. Good afternoon, everybody. Thank you so much for coming to today's talk. My name is Colton Ogden. I'm the course instructor for GD50, which is CS50's new Introduction to Game Development course. We started this last spring and we've been having lectures every week so far for the last semester. Last week we took a look at Portal, which is a famous game by Valve, whereby you get a gun that can essentially shoot these portals that defy the laws of space onto different services in the game. Walk in and out of them and teleport through them and see through them. And there are a host of interesting challenges associated with implementing a game like this. Now last week we looked at a simple version of it in Unity, but today we are joined by Dave Kircher and Tejeev Kohli of Valve Software who actually were on the Portal team and implemented all of the interesting sort of design and technical decisions that went about making it work and making it fun and believable. So without any further ado, this is the "Portal Problems." Thank you. [APPLAUSE] TEJEEV KOHLI: Hi. So we're just going to run through. Both me and Dave were actually students when we were hired by Valve, and we were hired to recreate the work we did as a student project for Valve for Portal 1 and for Portal 2. And today we just wanted to talk to you about some of the issues we had trying to create the mechanic for portals, and then also some of the design, both the technical and some of the design issues that we had to tackle and work on to make the mechanic work properly. So Dave is going to start off and then I'll jump in later. DAVE KIRCHER: Hey, folks. As he mentioned, my name is Dave Kircher I was hired on specifically to work for Portal. So I'm going to go ahead and preface. We're jumping through a lot of topics today and jumping very quickly, so this is a very video heavy presentation so that we can jump quickly in and out. And I'm sorry if I go a little too fast. I'm kind of optimizing for the stream. So hopefully, if I have gone too quickly over something, you can review the stream and see it a second time. So without further ado, let's start off-- just quickly. I'm assuming that most of the people here have played Portal or at least are familiar with it in some sense. That's just an assumption. And that, for at least the technical portions, that you are at least somewhat familiarized with 3D rendering. If you're not, you may need to study up a little bit and then come back. But let's start off with just what is a portal? A portal is a discontinuity in 3D space. It's a 2D discontinuity where we basically define a 2D rectangle somewhere in space such that the front face-- sorry, the back face of the 2D rectangle is defined as the front face of another 2D rectangle. So I've got my simple little example here of this blue portal and this orange portal. We're defining them to be back to back, which gets us this result over here. So from the perspective of this little portal guy, it should look like there's another room attached with a cube in it. But we're not actually moving 3D space at all because otherwise we're trying to make sure that this perspective is true for both this guy and the cube. And then you'd have this weird overlapping space that doesn't make any sense to anybody. So we do a lot of hacks to make it seem like space is folding in these interesting ways without actually moving space. Another way to think of it is that it's a door. If you look closely at this doorway, it's a very standard door. It's a door like you walk through it, different stuff happens. But what I'm not telling you initially is that this actually isn't a door. For technical reasons, this level required a portal here because we needed this room to move. So even though it looks like a doorway, it's completely fake. And that it's a doorway that actually takes you about a half mile across the level. But it looks like a door, and so my job on the Portal series was to make sure that when we're creating portals that they feel to the player like a doorway. And if you think of them in terms of a doorway, all the interesting stuff for a portal happens on the inside of the doorway and nothing interesting happens on the outside. And it's my job to make sure that all the interesting things that are happening outside the door don't happen. Because that's all stuff that doesn't make any sense. So as you can see, I just flew across the level. And that's the other side of that door that we just looked at. And I'm walking through it and it's a doorway. So it's a door that doesn't take you a couple of inches. It takes you about a half mile across the level. Now we're into our rendering section, which is basically one of my main expertises in the portal area. So we're going be talking about quite a few things and I'm going to jump in quickly, so hopefully I don't spew it out too quickly. That's kind of my problem. So there are primarily two layers to render a portal of view. There might be more, but these are the two that I am primarily familiar with. The preliminary way that we did it with Narbacular Drop, which was the predecessor to Portal was with rendered texture. And then when we got to working on the Portal franchise, we switched to a method where you draw it all in a single pass using what's known as a stencil buffer and I'll be talking more about that in a bit. But there are tradeoffs to each method. So with a texture, you have to have separate textures per portal view. And if you have support for recursion, you have to have many, many textures pre-allocated to do this. So your memory growth gets big very fast. You have to use the Painter's Algorithm or something like it to render your portals. You basically have to figure out the deepest portal you can see into and render that one first. And then any outward ones from that you're going to render them because they're going to contain a view of that first portal. So you have to render it in that order. And I don't know if it's true anymore. It definitely was when I originally was working on the first portal. That you couldn't effectively use anti-aliasing, so you get small visual artifacts as you get close to a portal because it would be rendered as a texture that doesn't quite render the same way as the rest of the back buffer. But it is the simplest to implement, especially if you don't support recursion at all. It is super simple to do because you can ignore the Painter's Algorithm and just render all of them before you of your main view. By contrast, when you render with stencils, it renders the entire frame to the back buffer so you don't have any extra texture memory requirements. You're doing it all in a single pass. You're starting from your main view and working your way in. You actually have to nest it a little bit, so it's interesting. You are guaranteed to get homogeneous visual quality because it's a single pass. The way you're rendering the rest of your frame. But it has a lot of extra complexity of when you render them and how you render them. So this rendering portion is going to require quite a bit of spatial thinking. So I'm going to show you this video. Basically this is a layout I'm going to use a couple of times. Does this play? Hopefully-- yes, OK. This is a room layout that I'm going to use a couple of times where I've got an orange portal and a blue portal. And behind each one is a thin wall with some stuff behind it. But hopefully to help illustrate what's in front of the blue portal, you can see there's a whole bunch of blue stuff over there. So yes, that is the example layout I want you to kind of keep in your head because spatial thinking is important to actually have reference. Let this finish one more time. OK. Now this is something that pertains to both rendering with textures and stencils and I'm going to let this play once because I was advised that if I front load this too much, it sounds confusing. So while I'm playing this, I want you to look at the fact that when the orange portal is on screen and when it's not, everything inside where the orange oval is looks exactly the same for when it is and when it is not there. And so what I'm doing here is as I'm toggling between the views is I am teleporting to where the virtual camera is. That's rendering out of the orange portal. Whoops-- come on, go back. Oh, God. OK. I'm toggling back and forth. I'm looking into the orange portal, but I'm toggling to where the virtual camera is behind the blue portal. So if you remember back to when I said that we're defining the back face of one rectangle to be the front face of another rectangle, that means that they should be coplanar at all times. And so if you think of my player model in terms of walking it to the orange portal. When I'm rendering my exit view, I should end up behind the blue portal as I'm rendering out of it. So it's important to remember that all the angles carry over from that. And most importantly that whether you're rendering textures or rendering to stencil that nothing inside ever moves because it should be the exact same view angles, the pixels should be in the exact same place. If they're not in the same place, your math is wrong. And this is especially important when rendering with textures because one of the first mistakes I've seen several people do is that they render the entire screen to a texture. And then they map the entire texture to this little quadratic here and it looks all weird depending on how close or far away you are. But as long as you project the-- sorry. Trying to work with videos is not the easiest. So as long as you project where the vertices of your mesh are in screen space, you can reuse those coordinates as your texture coordinates and then it will line up perfectly. So that's the point of why it's rendering as one-to-one. You just want to make sure that you're rendering the same parts to the same part of the screen. Now I said I'd be using that previous layout a bunch and I swear I'm going to get back to there. But this is a much better layout for rendering with stencils, and so now you need to learn a new layout just for a minute. It's only used in stencils. But I've got these two portals looking at each other. They're kind of-- one stacked on top of the other, and they've got these light bridges that are just serving to show you that transparencies are kind of a special case. So I'm going to play it one more time. So you just got two portals facing each other. And even though they're tiny, it does make an infinite recursion down into the portals. So rendering with stencils. I'm kind of assuming that for this part of the talk that you have some idea what a depth buffer is. You may need to read up on that if you don't. The stencil buffer is very similar to the depth buffer in that it defines rules and operations for when we can wholesale just not draw a pixel or when we do want to draw it. And then also while we are drawing pixels, you can define several operations of how to modify the depth buffer. But for all intents and purposes, it's invisible to the user except for the end result. So stencil buffer, a lot like a depth buffer, but you're controlling the values in code instead of by vertex depth. So before we render any scene using stencils, what we're going to do is we're going to clear our stencil buffer at the same time as we clear our depth buffer. We're going to clear it to all zero values. And the stencil buffer we were working with with Portal 1-- I believe it only had two bits. I could be wrong. It might be up to eight bits, but it's not a lot of bits. So we need to be very conservative with the values we put in there. So we're going to clear it to zero. So everything in it is zero. And then we're going to render all of the OPEC objects in our scene and that's where we get to the visual I'm showing you here. So you'll notice that none of the light bridges are here.