Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411508 Posts in 69379 Topics- by 58435 Members - Latest Member: graysonsolis

April 30, 2024, 04:53:30 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsVatnsmyrkr【submarine exploration】
Pages: 1 ... 9 10 [11] 12 13 ... 18
Print
Author Topic: Vatnsmyrkr【submarine exploration】  (Read 42733 times)
leblackdragon
Level 0
***



View Profile
« Reply #200 on: September 12, 2015, 04:41:33 AM »


UPDATE 3



All right, it's 3 AM and I think I'll be giving up for tonight. I refactored my test light code from the submarine's file into an actual system and so I can now add as many functioning light sources as I want. They still work like before – we'll have to see what happens there eventually.



Also, these tiny window sizes from all the previous images aren't going to be the actual viewport. I'm just keeping it small for testing. The game won't be that claustrophobic. This is the normal space around the submarine at the standard 1920x1080 resolution intended:



The camera is going to be slightly dynamic, tho, adjusting for specific areas, sometimes zooming in, sometimes out.

Down the line, do you see it possible to make the edges of the light soft and blurred?
Logged

Welcome to the Cat's Manor:
A Cat's Manor Devlog

Twitter @as3adya

oahda
Level 10
*****



View Profile
« Reply #201 on: September 12, 2015, 05:57:17 AM »

Nah, haven't touched it yet. We'll have to see. Maybe I can do something with my new knowledge of rendering to texture in OpenGL, rendering the light cone's polygon to a texture, blurring it and then using that texture as an alpha mask in the light shader, perhaps.
Logged

Battlefrog
Level 0
**


Broc W.


View Profile
« Reply #202 on: October 25, 2015, 08:59:59 AM »

I read through ALL of your devlog today and wow, all I can say right now is that if you finish this project, it will turn out GREAT! Grin
Logged
ProgramGamer
Administrator
Level 10
******


aka Mireille


View Profile
« Reply #203 on: October 28, 2015, 10:25:16 PM »

I read through ALL of your devlog today and wow, all I can say right now is that if you finish this project, it will turn out GREAT! Grin
I know right!?
Logged

oahda
Level 10
*****



View Profile
« Reply #204 on: November 04, 2015, 12:36:09 AM »

Down the line, do you see it possible to make the edges of the light soft and blurred?
Nah, haven't touched it yet. We'll have to see. Maybe I can do something with my new knowledge of rendering to texture in OpenGL, rendering the light cone's polygon to a texture, blurring it and then using that texture as an alpha mask in the light shader, perhaps.
Dang it. I had apparently misread your post when writing my reply. I thought you were asking whether I did see it possible (as in I'd already gotten it to work), not whether I do see it possible (in the future).

Of course, I do see it possible. And since my last reply I've actually finally learned how to blur images and written a quick shader test as I mentioned in this thread. And I actually did update the code like I said to render the light cone to a texture and using it as an alpha mask instead of doing triangle intersection tests directly in the shader like before, so I do have a texture I can try applying blurs to now. But it's not my highest priority and I have other stuff I want to mess around with first.

I read through ALL of your devlog today and wow, all I can say right now is that if you finish this project, it will turn out GREAT! Grin
I know right!?
o pls u guise Screamy
Logged

Cranktrain
Level 4
****


making gams


View Profile WWW
« Reply #205 on: November 04, 2015, 03:45:49 AM »

The jelly-fish tentacle physics look really good! Nice to see how this is progressing.
Logged

oahda
Level 10
*****



View Profile
« Reply #206 on: November 06, 2015, 08:34:33 AM »

 Smiley

Thanks!




UPDATE 67



 Who, Me?

Finally time for a real update, with a number and all!

I've been doing a bunch of engine stuff again which I'll just ignore and instead just show you what I've been doing with the game during the last two or three days or so. I've also been exploring blur effects which I have yet to put to use altho I do have ideas.



Water shader work

Let's start with the most immediately eye-catching news even tho that makes this post slightly out of order, shall we?

Yesterday and today I've spend countless hours just messing around and testing lots of stuff in the water shader as well as some of the water logic, to see if I could make it better in various different ways. One new addition was the use of textures to accomplish more detailed effects — everything up until now had just been done doing various mathematical operation on colours and stuff. But now there are two textures loaded into the water shader!


Foam and additional sprinkles!



There's more to this picture than what's mentioned in the title above, but lets focus on those two things first and then we'll use a static image that hasn't been destroyed by the limited palette of the GIF format to look at the rest of the details.

As seen in earlier posts, I already had sort of a white line going through wiggling waves upon impact, but now I've made it look a bit more like actual foam with irregularities instead of a completely smooth wave. This was done using a simple 128x128 texture I made in GIMP using the seamless difference cloud filter and fiddling a bit with the brightness and contrast. That's it. Loaded it into the shader and read the brightness values from it and applied it to my old code through various modifications and lots of trial and error.

Here's the texture. I might experiment more with it, looking at results of making it smoother and so forth.



As for sprinkles, well, that refers to the foamy particles. I made them also spray above the water unlike before when they only appeared below.


Caustics and stuff

Caustics! Did you know this word? I did not. I knew what it was, of course, which is why I set out yesterday trying to search for reference images and technical musings without much luck until I finally found an image that had the proper name attached to it. Now I know how to refer to those pretty, dancing lights underwater.

Found lots of really technical stuff (like this) on how this could be generated and simulated if I really wanted to, but in the end I decided just to find or make some seamless caustics texture and then mess around with that in the shader. It doesn't look 100% like it "should" in motion but I'm pleased with it and think it's good enough for my purposes — I don't want it to be too intrusive either, so it's mostly supposed to be a subtle backgroundish effect.

So here's a screenshot where you can see those caustics and more:



Very subtle as you can see, altho it is clearer in motion. It is also brighter on the submarine and anything else in the foreground than on the background. You may also notice some vertical rays of light. They were actually made using the same texture, only stretched a lot vertically and squeezed together horizontally. They also move. Finally you will notice that the surface of the water has gotten a similar addition, squeezed together vertically to emulate the 3D surface stretching back into the room.

Here is the texture, which I did not make but got from the bottom of this page (actually generated using the caustics algorithms that I decided to pass on) and subsequently blurred, desaturated and made a bit darker:



Just like with the foam texture I simply read the brightness values from this texture and transposed the lines onto the final image in the shader.



Camera movement redux

Yesterday I ended up watching this GDC talk on camera scrolling in 2D games by Itay Keren. It was a very informative hour packed full with examples of how real games out there have been doing cameras and scrolling all the way back to the '80s. I'd personally never imagined they'd given it as much thought as they apparently did in some games back in the day.

Anyhow, I got some ideas and decided to try out a new system for making the camera follow the submarine in a smoother way than before. The concept revolves around (or perhaps I should say inside of) these two circles:



The submarine has free movement within the inner circle and the camera will not move so long as it stays in there. This removes annoying camera twitching on every minor movement. But when the player starts moving out of the inner circle, the camera will smoothly begin to accelerate until it reaches full speed when the submarine reaches the edge of the outer circle. After that, it locks on to the submarine along that outer rim and never stays farther behind than that. When the player stops moving, the camera deäccelerates back to the edge of the inner circle where it stops. All very smooth!

This is really hard to capture in a GIF so I went and recorded a video instead. It doesn't do it full justice, as my computer couldn't really handle recording the game in HD too well, but it's not horrible (except for the brief moment I tried turning the spotlight on), so it'll have to suffice.




Like before, the camera locks onto the small rooms and stays static in there, but I've now made the transition in position and zoom use a nice ease-in-ease-out tween (cosine wave) making it a lot smoother.



That'll have to be it for now! We've also been working a bit on PUSE but not enough to post a new update just yet. We'll probably end up giving the camera there a go as well.
« Last Edit: November 06, 2015, 08:41:36 AM by Prinsessa » Logged

oahda
Level 10
*****



View Profile
« Reply #207 on: November 08, 2015, 03:50:39 AM »


UPDATE 68



Ninja Smooth spotlight~

Finally got around to fading/blurring/smoothing out the edges of that spotlight yesterday (yo, leblackdragon!). I didn't do it with a blur kernel (well, okay: I used that as well to smooth out some remaining pixellated edges where the light gets cut off), but with a bit of vector maths.



I've been brushing up a bunch on my linear algebra lately. Despite how fundamental it is to somewhat more advanced game development, I haven't really dug too deep into it until recently. I knew the basic stuff, but I never really knew what dot products or cross products were good for. I didn't really know why OpenGL works with matrices, nor why they have more dimensions than I render. I didn't know why arc this and arc that is used to get angles. But I know it all now! I read through Wollfire's old articles on linear algebra a couple of times recently and I've started thinking in new ways and seeing new solutions to problems. It's really helpful.

After reading up on that, I actually went back to an old article on lighting in modern OpenGL as well as some more in the same series which I hadn't read before, all of which I completely understood this time around, so that was fun as well and has given me ideas altho it actually doesn't really have anything to do with the particular spotlight (which doesn't really work using proper lighting calculations ATM).


Dot product to the rescue!

If you look at part two of Wolfire's aforementioned articles on linear algebra, and scroll a bit down to the dot product explanation, there's an example with a guard that has an angular line of sight showing how to use the dot product between the guard's direction and the direction from the guard to the player character in order to figure out whether the player is within that field of view.

I ended up finding some use for this exact code some time later — yesterday — when I went and coded a system for speaking to NPC's in my other game PUSE and wound up solving it by giving NPC's the same kind of field of view:



The basic gist of the dot product is that it allows us to find out how much two different directional vectors are pointing in the same direction. I used this technique to figure out how far away each pixel/fragment in the spotlight is from the line going straight through the light in the direction it's pointing in, by using the dot product between the direction of the light and the direction towards each fragment.

That part was easy. What was really fiddly and took a long, long time was to figure out how to get it to look exactly right. For one, the distance from that center line would of course be the same no matter how wide or narrow the spotlight is, so I needed to fade the fragments out at a faster rate if the angle was smaller. I also needed to find the right falloff rate to make it fade out in a nice way. A completely linear falloff wasn't suitable, as the light would fade out at a constant rate from the center when what I really wanted to have it be fairly bright inside most of the cone but then fade out quickly towards the edges.

Of course I needed some sort of curve to do this. I ended up just messing around with magic constants and operations (raising stuff to the power of other stuff in my case) to find the correct values visually instead of actually thinking too hard about it from some theoretical point of view.

The final GLSL code is really short, but finding that sweet spot for the falloff still made it take a very long time:

Code:
vec2 dirLight = vec2(cos(karhu__light_angle), sin(karhu__light_angle));
vec2 dirFrag = normalize(karhu__light_pos - gl_FragCoord.xy);
karhu__result_frag.a *= pow(abs(dot(dirLight, dirFrag)), 0.2f / pow(karhu__light_FOV * 0.34f, 5.5f));

Note that the light now is rendered to a texture of which the alpha values are used to map the light values onto other stuff in a different shader. So what I'm doing above is actually modifying that texture before it gets passed to the next shader, modifying its alpha values.

As you can see in the final line, the power operator is used twice with some random values I fine-tuned manually to get the right look, so they don't really mean much. Actually meaningful, however, is the FOV (field of view) value, as mentioned before, since it makes sure that the falloff is faster if the FOV is smaller, so that smaller cones fade out just as nicely as bigger cones.

Of course, using the dot product to figure out how far something is from the middle of the cone means that the light doesn't get smoothed when its broken by something in its way as seen above, but Marte and I seem to be in agreement: it should be like that. I did apply a little blur to the final texture just to make sure those lines weren't pixellated tho.
Logged

oahda
Level 10
*****



View Profile
« Reply #208 on: November 10, 2015, 03:34:01 PM »


UPDATE 69



Door script is back



I had this working a long time ago, of course, but a lot has changed in the engine since then and it hadn't been working for a while. Started fresh yesterday and began to rewrite it and finished up today.

One of the new additions I made to the script this time around, which can be seen in the GIF above, is that if you approach the opener from an angle, the submarine will adjust itself automatically before inserting or pulling out the key thingy. It's a little jaggy and not completely natural, but it sure looks better than just snapping to the right position and angle, and allowed me to make the area triggering this a bit bigger, to make it very easy to interact with these door openers.



Grippables

One of the reasons that the script was no longer working was that I hadn't properly reïmplemented gripping with the claw after completely redoing the claw/magnet code.

I got it back in a cleaner and easier to work with fashion this type, by writing up a quick component type called 'grippable'. These can be attached to physical bodies with the only information given being the radius and position of the area within which the claw must be to pick the grippables up, and then the rest is set up from inside the component. Part of this is setting up a collision event to have the grippable object get notified whenever the claw tries to grip it, handling it correctly.

This was also necessary for a different reason, putting the collision event in the grippable rather than the claw, because apparently Box2D is failing to send a bunch of collision events to the magnet as it is right now, which may or may not have something to do with how I'm moving it about. Either way, the events don't fail inside of the grippables and so this was a simple solution.

So here's what I need to add to the key in the level's XML file (still no level editor) in order to make it grippable:

Code:
<c t="Grippable" cx="0.5" cy="0.5">
<number key="radius">40</number>
</c>

And if I don't care about the specifics I don't actually have to specify anything:

Code:
<c t="Grippable"></c>

Default radius and so on.



Secretive story thoughts

So I started thinking a bit more about the story and what I wish to convey today and while I won't really say much, I might as well add the fact to the devlog.

I am thinking about removing almost all of the verbal elements, including even the diaries mentioned in the first post, tho I might just keep the little speech bubble thingy, but not so much for actual written speech, but to use different icons to symbolise the character's thoughts and reactions, a bit like the ones I put into this LD jam game:



I've also been reconsidering the intro, making some changes to it but keeping most of it intact — however, these changes set the tone in a very different way and open up for a very different story arc, even tho it too is based on things that was already planned in some ways.

Right now I'm struggling a bit with putting it all together in my head, and trying to see how older areas (such as the tower I'm currently working on) might fit into the new narrative, should I choose to go with it.

Anyhow, I'm going to be considering the emotional arc I want to send the player along in more detail, and I'll admit Journey, which I played again yesterday, is a big inspiration, and at least since I made the LD game mentioned above I have been a lot more interested in trying to get things done with fewer means. I've already said before how I want the game to be very minimalistic with few things to learn mechanically (you start with the same three tools and never upgrade anything) and little to no clutter on the screen (no GUI besides possibly the little speech bubbles — an open window into the game world), and these ideas I had long before I ever knew what Journey was like, just to put that out there...

But I am mostly unhappy with games in general and Journey is one of the few out there that really speaks to me in nearly every way, so I won't hide the fact that I feel like I can draw ideas from it and its design. There's a great talk on it by Jenova Chen on GDC Vault too, BTW.

I'll keep pondering it.



Bug fixing and so on

Apparently whenever I initially wrote the water shader I had thought it a good idea to put the last part, the one that renders the fake 3D surface, after all of the lighting has been applied in the main shader, even tho everything else in the water shader is before it so that the lighting gets properly applied to it. Weird of me. Moved it back into the right place and now it is in its current state actually dimmed down a bit by the lack of strong light.

Also finally got around to adding support for letting physics colliders ignore certain other colliders, which was done using a b2ContactFilter in Box2D, which I accidentally found when trying to search for b2ContactListener and wrote the wrong thing but ended up finding something that actually exists, that I had needed for a long time, but didn't know whether it even existed. Durr...?




Moses! Waaagh!

I interrupted writing this post to see what would happen if I dropped something big and heavy into the water. It didn't look good at all. It didn't split the water creating waves on either side like it should. So I fixed that!



Do note that the rock slows down under water!

Broke magnet interaction with surface just to make this look okay for the GIF so next time I'm going to have to fine-tune everything to make sure the outcome is always good with all objects, no matter whether big or small or coming from above or below.

But it was fun to see how quickly I could achieve this difference within my current system by simply generating one impact on either side going up and one in the middle going down, instead of just a single one going up, when something like this hits the water.

Cheers for now~
« Last Edit: November 11, 2015, 12:58:02 AM by Prinsessa » Logged

marcgfx
Level 8
***


if you don't comment, who will?


View Profile WWW
« Reply #209 on: November 10, 2015, 04:55:48 PM »

I don't really understand the camera-lock. what is the advantage of it not following the sub the whole time? wont this mean you don't see possible dangers ahead of you? if this is not an issue, it looks good Smiley hard to tell how it would feel while playing though.

that impact effect looks great and the slowing down of the heavy ball makes it look very believable. but maybe the bubbles should be going up?
Logged

oahda
Level 10
*****



View Profile
« Reply #210 on: November 10, 2015, 09:25:56 PM »

I don't really understand the camera-lock. what is the advantage of it not following the sub the whole time? wont this mean you don't see possible dangers ahead of you?
It's not really that kind of game, so that wouldn't be an issue. But I did notice myself yesterday that I found the circle a bit too big (didn't see enough when moving down or up) so I'm going to make it smaller, or perhaps into an ellipse that's wider than it's tall.

The point of it is to avoid jagginess when the player just wants to turn around or something and not necessarily move, which I don't think should move the camera right away. It's abrupt which I don't like, and might also increase the risk of simulation sickness in those who are sensitive to that.

But yeah, I'm going to make the area smaller.

if this is not an issue, it looks good Smiley hard to tell how it would feel while playing though.
Yeah, I'll have people try it out eventually!

that impact effect looks great and the slowing down of the heavy ball makes it look very believable. but maybe the bubbles should be going up?
Yeah, I noticed that too (and it has been said before). I'm going to add something there.
Logged

oahda
Level 10
*****



View Profile
« Reply #211 on: November 16, 2015, 04:17:26 PM »


UPDATE 70



I'm happy to be able to bring you this update today at all! Last night I accidentally lost a lot of Vatnsmyrkr files but after a couple of hours I finally had them all back and I was able to continue today where I'd left off, instead of having to recreate the last few months of work. I need to back up more often. But backing up was in fact was I was trying to do when this accident happened. Gee. It was a scare. But all good now! Crazy



Deferred rendering!

Oh, wow. This is magnificent. So, I've been learning so much about graphics rendering this year and especially during the last few months.

I've reworked the engine Karhu from time to time to reflect new knowledge. But the game was still not running well enough on this computer (I'm doing it all on an old mid-2012 MacBook Pro — cheapest model — which I find to be a good way to set the bar so that the game will run fine on regular computers and not just on monster rigs) IMO and I ended up reading a bunch about deferred rendering and decided to give it a shot.


What is deferred rendering?

Well, the way I was rendering the game before was quite straightforward (it is in fact called forward rendering) and probably how most of us have done it at least historically or still do, which is simply to render everything in order and apply any shaders as we go to everything we draw.

This is all good and well for many intents and purposes, but when you start adding a bunch of lights and a water shader and so on, a lot of unnecessary calculations happen since for everything that is drawn, the shaders have to do their thing, even if objects end up overlapping and so on.

In this sense, the word deferred can sort of be thought of as backwards, as opposed to forward rendering. Deferred rendering splits the render cycle into several passes, rendering only some of the information in the scene (such as colours or normals) to different buffers (images) for everything that is drawn, and then one or more final passes are applied only once to these final images at the end of the render cycle. Using information from the other buffers, lights (and water) may be calculated only once for the entire scene (running the relevant shaders only once) each frame, potentially increasing the framerate.

Here is an example of three buffers used to make up a final image, nicked from this page which has a good description of the fundamentals of deferred rendering:



These three images (from left to right holding colour, depth and normal information, respectively) get combined in a final pass to produce a final image, in this case with light and shadows as you can see if you follow the link to the page.


Does it work?

In my case, it did! Even tho I render to many buffers the size of the screen each frame now, as opposed to only one buffer the size of my screen back when I used forward rendering, I can actually get to 60 FPS with light sources now, which I couldn't before, and the game wouldn't even go above 55 without them.

So I'm pleased to announce that the game now runs a lot better. Hand Thumbs Up Right


Karhu pipelines

To easily work with render pipelines in my engine Karhu I added a new concept to the library: pipelines. They work similarly to the engine's shaders in that they can be accessed and created globally and one pipeline can be set as the primary one which gets reset at the beginning of each frame, and the pipeline can still be changed midway through a draw call to render to a custom texture/buffer and then the course of the primary pipeline may continue.

Pipelines are assigned any number of ordered passes which can be marked as final or not. Non-final passes get used for everything in the normal draw loop, while final passes are only handled once at the end of each frame. To passes any number of buffers may be assigned with some basic settings such as size, format, clear colour and whether alpha blending should be done for them.

Basic setup of my primary pipeline's first pass and first colour buffer (there are in reality more passes and buffers):

Code:
// Create the primary pipeline.
pipeline("__final").primary().select();

// Colour pass renders colour/texture as RGB.
pipeline().pass("__pre").
program(shader("__pre")).
buffer("__colour", 1920, 1080, FormatTexture::RGBA, {100, 100, 100}, true);

I use the double underscores to mark sort of official engine names.



New light code

So there was some talk early on in this thread, revisited at the top of this page, about how using Box2D's raycasting (Box2D is the physics engine I'm using) to find where the submarine's spotlight intersects with stuff to clip it might be a bit slow. Especially if I want other lights to get clipped in the future, and I do want to put a certain amount of focus on good lighting in a dark game like this, so I ended up reading up a bit on how others have done similar effects generalised to all of their lights.

Among other things I found this thread on TIGSource which further led me on to pages describing rather complicated techniques using image distortion and whatnot. I was hoping to do something simpler so I disregarded all information online and started messing around a bit, and I actually managed to do something (still through raycasting but on pixels and on the GPU and not in a physics simulation on the CPU) that works well enough for now, so here goes.


Occlusion map

First, I flagged the objects that should occlude light as occlusive in their materials, and then used that information in the first render pass to generate an occlusion map, showing where light should be occluded (the submarine isn't actually going to be occlusive but I'm making it occlusive here to show how well my new, pixel-perfect lights do with complex shapes):




Light map

Then in a final pass that only runs once, just before the truly final pass that writes to the screen, a final buffer — a lightmap — is created. The white pixels from the occlusion map that was rendered in the previous pass are used as a collision mask.

For each pixel on the screen, every pixel along a vector representing the direction between the light source and the current pixel is checked until an occluded one is found. If the occluded pixel is closer to the light than the pixel we are checking, the current pixel won't be lit (because the light can't reach it) or else it will. Pixels marked as occluded on the map or pixels outside of the range of the light (not a single pixel outside of the cone or circle) will of course completely ignore the raycast test and be marked as unlit right away.

That's a lot of pixels getting checked, but to my surprise the GPU does one heck of a job at it and crunches away. Still >60 FPS with one light and it takes a few to bring it down. Of course, I don't actually check every pixel. I experimented with how many pixels I can jump forwards between each check on the ray without losing too much light quality and ended up skipping every 10 pixels.

Here is the resulting light map:




Final pass

Then we move on into the very last pass where everything gets assembled, including also water and whatnot. I apply a slight blur to the light texture and multiply the final colour by its brightness et voilà:



Light perfectly tracing the shape of the submarine (the thin tentacles were not marked as occlusive) as well as the wall it it hits on the way.


Final words

Of course, the lights don't have to be cones (they could also be circles by increasing the radius, or I might extend the code to support rectangles) and I might end up using this in more places than just the spotlight to create nicely dynamic lights in various places. The dot product came to the rescue once again to let me cut the originally circular lights off into cones!

All in all, I was actually getting ready to rework the entire light system with more customisation possibilities and just generally better rendering algorithms even before I had implemented deferred rendering, so it's nice to have that half-done now (I just hardcoded the position and other settings of this light in the shader to test the algorithm and haven't made light objects use it yet).

And here it is in motion (with no occlusion on the submarine):

« Last Edit: November 17, 2015, 05:45:26 AM by Prinsessa » Logged

oldblood
Level 10
*****

...Not again.


View Profile
« Reply #212 on: November 16, 2015, 06:46:13 PM »

Been making some great progress on this! All these awesome and subtle little effects add up really quick. This is looking really gorgeous...
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #213 on: November 16, 2015, 06:56:55 PM »

Oh there is two games! Shocked
Logged

oahda
Level 10
*****



View Profile
« Reply #214 on: November 17, 2015, 02:49:48 AM »

Been making some great progress on this! All these awesome and subtle little effects add up really quick. This is looking really gorgeous...
Yeah, maybe it's a bit boring to follow more engine and graphics updates than updates on the actual game, but I'm learning so much and I really want to play with it and I do care about the final look of the game, so I think it's worth it. Can't wait to normal map everything to really give it some substance!

Oh there is two games! Shocked
Mais oui! Gotta mix it up.
Logged

oahda
Level 10
*****



View Profile
« Reply #215 on: November 17, 2015, 04:06:32 PM »


UPDATE 71



Maybe I should wait until this has been worked on a bit more, but let's try to write a shorter update this time instead of letting the news accumulate for too long, eh? Today's topic is what you see in this image below:





More normal mapping — fake 3D lighting

I said in my last post that I couldn't wait to normal map everything. I didn't lie! At least to some extent. I got normal mapping back into the engine, this time actually understanding what I was doing now that I know that the basic calculation for light is N•L (i.e. the dot product of the normal of the surface receiving the light and the normalised direction of the light), which is just as applicable to normals in a normal map as to normals in real 3D geometry.


What do I mean by this?

Well, it's a 2D game, but I want more or less 3D lighting, and to achieve this I can model my art assets in 3D and then export their normals, i.e. the direction in which each individual point of the object is facing, as 2D images that can be mapped onto 2D graphics in order to receive light as tho they were really 3D objects in the engine still. If you've seen normal maps before, you might recognise their generally purple~pink~blue nuances:



Normals are three-dimensional vectors, i.e. x, y and z values, and these values are written into the r, g and b colour values of the image, respectively. Very handy for graphics programming.

I have a rougher version of the normal map with more texture and little bumps on the submarine, but I wanted to try it out with only the basic shape for now.


The Blender setup

So I work in Blender, and I made the 3D model for the submarine, on which the old sprite was based, years ago already. So I had it there waiting and all I had to do was to open my old project up and mess around a bit with the render settings in order to produce this normal map thanks to the information on the correct node setup that I found here. The nodes look like this:




The shader setup

I already had a buffer that I was drawing normals to (I already had some on the wall), so I just needed to make my shaders actually make use of the information in there. Here is what the normal pass looks like:



The calculations are done along with the rest of the lighting calculations when rendering the light map in the first final pass, and the light map now looks like this:



Trying it out with a new texture that Marte briefly started working on (we'll finish it!), the final image is this:



The rocks look extra awful because they were too dark so I did a quick brightness and contrast edit in GIMP that didn't turn out that well, but it's only temporary. The important thing is that the lighting is correct, and it is!

If I move about a little bit, you can indeed see that it is in fact fully dynamic:




Showing it off in action

Another GIF in addition to the one at the top of the post, to show you a point light moving around and affecting the submarine and the wall from various angles. This one was recorded before we added the texture and I just used a grey image with a little bit of ambient occlusion that I rendered in Blender.



Note that there is currently no normal mapping on the door opening, which is why it was just black in the normal pass above.


Issues

So there a few things I had to figure out along the way. Of course, if I render a normal map in Blender from the submarine in a particular angle, the normals are actually only going to be correct from that angle. So I had to make sure to rotate the normals programmatically along with the submarine. I also had to flip them on the relevant axis when the submarine image gets mirrored.

One weird thing was that apparently I had to invert the x value from the normal maps, both in the one I had gotten online for the temporary wall graphics and the one I had rendered in Blender for the submarine. Wasn't expecting that coördinate to behave like that — it sometimes is the y one that does. Blender is also quite notorious for having y and z switched when compared to most other 3D systems, but those values were fine.
« Last Edit: November 17, 2015, 04:25:37 PM by Prinsessa » Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #216 on: November 17, 2015, 04:45:58 PM »

Technically you can save one channel by reconstructing the z because it's always pointing toward the camera

Code:
half3 decode (half2 enc, float3 view)
{
    half3 n;
    n.xy = enc*2-1;
    n.z = sqrt(1-dot(n.xy, n.xy));
    return n;
}
http://aras-p.info/texts/CompactNormalStorage.html

Who, Me?

/Geeking
Logged

oahda
Level 10
*****



View Profile
« Reply #217 on: November 17, 2015, 05:10:47 PM »

Good point! Maybe I have something else I can use that precious slot for that would make sense to put in the same buffer.

EDIT:
Oh, missed the link. I actually stumbled across that page yesterday or so.
« Last Edit: November 17, 2015, 05:33:50 PM by Prinsessa » Logged

oahda
Level 10
*****



View Profile
« Reply #218 on: November 18, 2015, 07:54:54 AM »

I just tried blurring the lights again but realised I was also blurring the highlights from the normal maps as I'm writing it all into one light map before applying it to the scene. Any good ideas on how I can blur the lights without having to store one buffer for each light source or something, or having to recalculate the lights twice?

The current pipeline is this:

  • Pass 1 is applied to every draw call and gives me a colour buffer, a normal buffer and an occlusion buffer.

  • Pass 2 is applied only once at the end of each frame, calculating lights by ray casting against the occlusion buffer and taking into account any normal maps from the normal buffer that are inside of each light so that I only have to calculate lights and normals once and write them all into one light buffer.

  • Pass 3 is applied only once each frame after pass 2 and assembles everything, applying the water shader on top of the colour map and then blending the result with the light map.

Anywhere I can squeeze in the blur (which has to be done in one horizontal pass followed by a vertical pass for performance reasons) without breaking this pipeline up too much more?
Logged

gimymblert
Level 10
*****


The archivest master, leader of all documents


View Profile
« Reply #219 on: November 18, 2015, 08:03:46 AM »

You mean a bloom effect (blurring light)?
Occlusion is a repurposed z buffer?
By highlight you mean the specular contribution?
Logged

Pages: 1 ... 9 10 [11] 12 13 ... 18
Print
Jump to:  

Theme orange-lt created by panic