Scrolling texture on quad is laggy - scroll

What could be the reason of lag while I scroll a simple texture on a quad using Unity 4? The lag is not consistent, the scroll works for like 3 or 4 seconds smooth and than comes the lag and so on.
Here is the code
public float speed = 0.01f;
manager.scroll_speed = Mathf.Repeat(Time.time *speed, 1);
renderer.sharedMaterial.SetTextureOffset("_MainTex", new Vector2(manager.scroll_speed, 0));
What should I do to get rid of the lag?

Modifying sharedMaterial will change the appearance of all objects using this material, and change material settings that are stored in the project too. I'm guessing you wanted to do this on purpose but maybe scrolling textures on a whole bunch of objects is just not efficient. If it's just one object then just use renderer.material. Actually try using renderer.material anyway and just having different instances of the script

Related

Render texture doesn't update changes made, how to ensure this happens?

I'm building a system which has a set of quads in front of each other, forming a layer system. This layers are being rendered by a orthographic camera with a render texture, which is used to generate a texture and save it to disk after the layers are populated. It happens that I need to disable some of those layers before the final texture is generated. So I built a module that disable those specific layers' mesh renderers and raise an event to start the render to texture conversion.
To my surprise, the final image still presents the disabled layers in the final image. I'm really confused about this, cause I already debugged the code in every way I could and those specific layers shouldn't be visible at all considering the code. It must have something to do with how often render textures update or some other obscure execution order. The entire module is composed of 3 or 4 classes with dozens of lines, so to exemplify the issue in a more succinct way, I'll post only the method where the RT is being converted into a texture with some checks I made just before the RT pixels are read into the new texture:
public void SaveTexture(string textureName, TextureFormat textureFormat)
{
renderTexture = GetComponent<Camera>().targetTexture;
RenderTexture.active = renderTexture;
var finalTexture = new Texture2D(renderTexture.width,
renderTexture.height, textureFormat, false);
/*First test, confirming that the marked quad' mesh renderer
is, in fact, disabled, meaning it shouldn't be visible in the camera,
consequently invisible in the RT. The console shows "false", meaning it's
disabled. Even so, the quad still being rendered in the final image.*/
//Debug.Log(transform.GetChild(6).GetChild(0).GetComponent<MeshRenderer>().enabled);
/*Second test, changing the object' layer, because the projection camera
has a culling mask enabled to only capture objects in one specific layer.
Again, it doesn't work and the quad content still being saved in the final image.*/
//transform.GetChild(6).GetChild(0).gameObject.layer = 0;
/*Final test, destroying the object to ensure it doesn't appear in the RT.
This also doesn't work, confirming that no matter what I do, the RT is
"fixed" at this point of execution and it doesn't update any changes made
on it's composition.*/
//Destroy(transform.GetChild(6).GetChild(0).gameObject);
finalTexture.ReadPixels(new Rect(0, 0, renderTexture.width,
renderTexture.height), 0, 0);
finalTexture.Apply();
finalTexture.name = textureName;
var teamTitle = generationController.activeTeam.title;
var kitIndex = generationController.activeKitIndex;
var customDirectory = saveDirectory + teamTitle + "/"+kitIndex+"/";
StorageManager<Texture2D>.Save(finalTexture, customDirectory, finalTexture.name);
RenderTexture.active = null;
onSaved();
}
Funny thing is, if I manually disable that quad in inspector (at runtime, just before trigger the method above), it works, and the final texture is generated without the disabled layer.
I tried my best to show my problem, this is one of those issues that are kinda hard to show here but hopefully somebody will have some insight of what is happening and what should I do to solve that.
There are two possible solutions to my issue (got the answer at Unity Forum). The first one, is to use the methods OnPreRender and OnPostRender to properly organize what should happens before or after the camera render update. What I end up doing though was calling the manual render method in the Camera, using the "GetComponenent().Render();" line, which updates the camera render manually. Considering that my structure was ready already, this single line solved my problem!

Unity 3D - Dynamically 'slicing' background image

I'm fairly new to Unity and not quite sure how to handle this problem.
I have two images, one has clouds on it (day) and one has stars on it (night). What I want to do is show the clouds in the top of my scene and the stars on the bottom. There is a ground object in the middle of the screen where the player will be walking on, this should be the dividing line between the two images. The ground however is not one straight line but can have height differences.
The "solution" I came up with is to use the ground object(s) to slice the images so it kinda serves as a dividing line. But not sure if this is even possible. Maybe I could do something with 2 different camera's or mask the images somehow.. (Just throwing my own thoughts in here as well) I'll be fumbling around with these things in between and try to keep the topic up to date with what I tried.
I put in an attachment to (hopefully) make it more clear.
Greets,
Lukie
attachment: https://imgur.com/a/lblJXPi
The first solution to my mind was preparing a tileset. If you're not going to design a different section every time. So if you're not going to do a computer design. You can do it yourself by adjusting the size.
You can also dynamically generate the stars with the -y axis of the ground object and the clouds with the + y-axis. You can use instantiate function
Example:
public GameObject clouds;
public GameObject stars;
// Start is called before the first frame update
private void Awake()
{
Instantiate(clouds, new Vector3(this.transform.position.x, this.transform.position.y + 3.625f, this.transform.position.z), Quaternion.identity);
Instantiate(stars, new Vector3(this.transform.position.x, this.transform.position.y - 3.625f, this.transform.position.z), Quaternion.identity);
}
Of course, the background design that you will use here must be sustainable.
Dynamic Background

Group of objects on top but added to a camera

As a precision I already noticed threads about this but didn't find a way to achieve exactly what I need.
Basicaly I have a board of objects that I need remaining always on top of everything but also attached to the camera.
I first tried to add the group to the camera and it stayed as wished always in the viewport. But in this configuration the group of objects still be a part of the scene so while zooming to regular objects in the "editor" the board goes into/among these objects of the scene.
My second trial was based on this thread and work wonderfully in order to get all of the board objects rendered above everything. But on such a configuration when rotating around the axis (with orbit control) both scenes rotates. So I tried to update the foreground scene with coordinates of the camera but the update was not immediate and this scene is flickering (I suppose that while rotating the update function is not called immediately).
My best wish would have been to "attach" the foreground scene to the camera so that it would stay on top and sticked on the screen/viewport but I don't even know if it is possible and how to do that (as only groups of objects seem to be capable to be attached to the camera).
I am really stuck on that point. Thanks you for any help!
If this is what you need,
just set object.material.depthTest = false; and object.renderOrder = 1000; for all objects you need to be always on top and attached to the camera.

Single OpenGL context, multiple views

I have a Windows app which can create several view windows which can render some models using OpenGL (3.2+). Each window can either render it's own independent object, or two (or more) windows can render the same object (but for example from different camera perspectives):
After reading various posts here on stackoverflow I decided to create a single OpenGL context (HGLRC), and for each window that I am rendering to (HDC) I switch with
wglMakeCurrent(targetWindowHDC, m_deviceContext)
As you can see in the screenshot, that principally seems to work fine (the window code is happening on the main thread, and for Rendering I have my own RenderThread to which all the OpenGL operations are limited to). For each of the windows I render to an FBO (which has MSAA support if the user activates it), which only gets updated in case something in the scene changes, otherwise it will just draw it to the window as is.
My question is now, what states do I have to set every time I switch to drawing to another window? And is my approach reasonable in terms of performance?
This is what I now set every time after I make the context current for another HDC:
glClearDepth( 1.0f );
glClearColor( color.r, color.g, color.b, 1.0f );
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glPointSize(3.0f);
glEnable(GL_BLEND);
glBlendFunc( srcBlend, dstBlend );
glPolygonMode( GL_FRONT_AND_BACK, targetType );
glEnable( GL_CULL_FACE );
glCullFace( GL_BACK );
glViewport( 0, 0, vp.width, vp.height );
These are basically all the settings that could be changed when the user sets up the render windows, so I need to be sure they are set correctly before rendering each window.
But is it really necessary to do all those calls? It means in the above example with 4 render windows I need to call those 4 times each frame. Is there a better way? Would it be more efficient with several GL contexts?
The absolute minimum set of state you need to track between windows is the viewport, clearing color, color and depth masks, depth test function and depth range; you've got those covered in your code snippet already, so you're good.
Most other OpenGL state should be set on-demand right before it's needed anyway (and also cleaned up when no longer needed). So I'd say setting blend modes, face culling and so on actually is superfluous in your snippet.
Using the same context for multiple windows makes sense if the kind of rendering is the same for all the windows. For example in a typical 3D modeler there's a "quad view". If those subviews are implemented using multiple windows, then reusing a single context makes sense.
I'm one of those guys who keeps reminding people, that there's no need to have a separate OpenGL context for each window. That doesn't mean doing this is a bad thing if it makes your life simpler.
If your concern is about multiple windows with largely different rendering settings, then using separate render contexts is sensible.
So how do you decide if to use multiple context or a single one. Well, that's easy:
If the windows are sharing much of the render code and conceptually show the same thing (the same scene from different vantage points, different objects that make use of the same texture and are rendered using the same code) then context reuse it is.
If the contents of the windows differ a lot, then multiple contexts.

AS3 tile map rendering (with 1000's of tiles)

Just first off I'll say that the context here is Actionscript 3.0 (IDE: Flashbuilder) along with the Starling Framework.
So, I want to create a Tile Map that could be used for a platformer or something similar.
I want to use 8x8 pixel tiles on an 800x600 pixel stage, and the problem I am having is that I don't know how to add these 7500+ tile objects to the stage without dramatically reducing the framerate.
I've found that the drop in performance comes from adding each tile to the stage, not from initializing each Tile object.
I know I'm not giving much specific information, but what I'm asking for is if there is a standardized way to draw thousands of static objects onto the stage without a loss of performance. I feel like there is a way, and I just have yet to find it.
Update:
After all of your kind help, I have found what seems to be a great solution. At first I wanted to implement Amy's solution, using copyPixels() and draw() to make one large bitmap data for the whole map and then render that to the screen. Then, though, I wanted to know if there was a Starling equivalent to this, because everything would be so much simpler if I didn't have to mix Starling with Native Flash.
Thanks to Amy again, I looked into Starling's RenderTexture class a bit more, and found that using it's "drawBundled()" and "draw()" methods, I could easily draw all of the tiles into a RenderTexture, and then put the RenderTexture into an Image (Starling's Image Class) and then just add that Image to the screen.
That solution is a million times faster than the silly slow solutions I tried before, with flattening sprites and such. Its faster both in it's initialization time and there seems to be no drop in framerate while the renderTexture's Image is on the screen.
The one thing I want to test with this is if it is easy to update the graphics of a tile during the gameplay. Say, if water spreads from a source (or something) and a "Grass" tile had to become a "Water" tile, would the RenderTexture and it's image be able to change their appearance without some sort of lag spike or performance hiccup. I will test this out soon.
Thank you all for your help!
Don't add that many objects to the stage. Instead, create a BitmpaData the size of your stage and use copyPixels() or draw() to draw onto it. Here's an article that should get you started. You can then take the concepts you learned in that post and learn anything specific you need to do that's not covered (flashandmath.com has a lot of good tutorials about pixel manipulation)
You need to manage the tiles that need to be added and removed as you move around the game. Only add to stage tiles that are with in 800 px of the center of the screen. Once the tile is beyond 800 px from center remove it. That should keep everything moving smoothly. Good luck.
or look into drawing/coping your tiles into one bitmap. You would be basically stamping your tiles onto the new bitmap. Here is an example from adobe:
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;
var bmd1:BitmapData = new BitmapData(40, 40, false, 0x000000FF);
var bmd2:BitmapData = new BitmapData(80, 40, false, 0x0000CC44);
var rect:Rectangle = new Rectangle(0, 0, 20, 20);
var pt:Point = new Point(10, 10);
bmd2.copyPixels(bmd1, rect, pt);
var bm1:Bitmap = new Bitmap(bmd1);
this.addChild(bm1);
var bm2:Bitmap = new Bitmap(bmd2);
this.addChild(bm2);
bm2.x = 50;
More Info on the bitmapData class. I think copyPixels is what you are after.

Resources