Sunday, August 19, 2018

unity - Unity3D sprites vs Mesh Quads - Depth, Blending, Shadows


I'm new to unity but not new to game development. In my OpenGL ES 2.0 (mobile) games I create a vertex array of all my "sprites" and stuff it in a VBO. Then draw them as I need them one at a time, back to front, and turning on and off depth test and blending as I go to build my scene. Probably not super efficient (as maybe batch drawing) but I get 60fps on modern devices.


This particular scene has a "paper" background, writing ON that paper (same Z depth), then 3d objects over top of that. The 3d objects cast shadows on to the paper. (I can post a screenshot if necessary.)


To accomplish this I render my shadow map of any object that casts shadows. Then render my scene with a shadow shader on the paper, not on the stuff that's on the paper, but then back on for the 3d objects floating above or sitting on the paper.



Now I'm switching to Unity3D and porting this working game over.


I'm having 2 problems that I can't figure out.



  1. Being new to unity I brought in my sprite sheets and set them "Advanced" but as sprites and sliced them up with the Sprite Editor. But the Sprite Renderer doesn't have checkboxes for Casting or Receiving shadows. Are sprites only for 2d games with no shadows and lighting? Do I have to switch to all Mesh Quads and use the mesh renderer and manually handle all my "sprites"?

  2. In Unity with the paper and all the stuff that is drawn on the paper at the same Z I'm having depth issues. In my OpenGL version I do glDisable(GL_DEPTH_TEST); and enable blending, draw the "ink" stuff, and then re-enable depth and draw the rest of the 3d scene. In Unity I can't figure out how to turn off depth or to get blending to work. Since the ink has to be drawn ON the paper and thing drawn over that I can't use a different camera.



Answer



A couple days of googling, testing, coding and I have it all figured out.


1. Shadows on Sprites..


There is a work around to having sprites cast and receive shadows. This thread in the unity forum has a way to do it with sprites: http://forum.unity3d.com/threads/why-cant-sprites-gameobjects-cast-shadows.215461/



The other way is to create your own sprite manager and create a mesh of a bunch of quads. This was the route I took. There are also sprite managers already out there but I wrote my own.


2. Depth testing, draw ordering, and blending...


In my situation I had written a custom shader to do ZTest Always and had even tried offsetting the test with Offset 0, -1, but it still wasn't drawing the object in front. The reason was the draw order. It was drawing the front object first and then the back object. So the ZTest Always on the front object didn't matter cause it was being overwritten by the background.


This page: (http://docs.unity3d.com/Manual/SL-SubshaderTags.html) explains it but it took a little while to sink in. This guy explains it well: (http://www.burgzergarcade.com/tutorials/game-engines/unity3d/unity-ios-shaderlab-tutorial-9-ztest)


Basically you have to do both. Set the ZTest setting AND make sure you're dealing with the draw order. Unity renders things in batches. So I set the paper to be "Queue" = "Background" and the stuff being applied to the paper as "Queue" = "Transparent". But you just have to set the queues to make sure the batch draws are happening in the correct order.


Also, as described in the above unity docs link, you can set up your own queues and dial in the draw order to your needs. "Queue" = "Transparent+1" or "Queue" = "Transparent+10"


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...