Is there a way to use instancing with deferred effects and scene objects? I am having some difficulties converting the example, which uses forward rendering; it could be that I use a (simple) custom mesh and a custom POM shader.
If not, are there good ways to optimize the repetition of large numbers of custom meshes? So far, my code just places them like this:
model = Content.Load<Model>("Models/landscape/ground/tile1"); for (int x = 0; x < heightMap.Width; x++) for (int y = 0; y < heightMap.Height; y++) { { objecttoworld = Matrix.CreateScale(0.5f) * Matrix.CreateTranslation(new Vector3(98.0f + (x - heightMap.Width / 2) * 6f, 18.0f + (colors2D[x, y].R - 122) * 0.05f / SCALE + 0.01f * (x + 2) + 0.01f * (y), 128.0f + (y - heightMap.Height / 2) * 6f)); renderManager.SubmitRenderableObject( model, objecttoworld, ObjectVisibility.Rendered | ObjectVisibility.CastShadows, ObjectLifeSpan.Scene); } }
for (int x = 0; x < heightMap.Width; x++) for (int y = 0; y < heightMap.Height; y++) { { objecttoworld = Matrix.CreateScale(0.5f) *
Matrix.CreateTranslation(new Vector3(98.0f + (x - heightMap.Width / 2) * 6f,
18.0f + (colors2D[x, y].R - 122) * 0.05f / SCALE + 0.01f * (x + 2) + 0.01f * (y),
128.0f + (y - heightMap.Height / 2) * 6f)); renderManager.SubmitRenderableObject(
model, objecttoworld, ObjectVisibility.Rendered |
ObjectVisibility.CastShadows, ObjectLifeSpan.Scene);
} }
Also, is there a way to implement LOD with scene objects - ie: unload them and reload them, as a camera gets closer or farther away?
Hi style88,
I just did a quick conversion to deferred here and it worked - here's what I had to change:
Instancing is the best way to render lots of objects. It avoids two of the biggest rendering bottlenecks (effect parameter changes and draw calls).
LOD can be accomplished by giving the object a Frame lifespan, then during the beginning of each frame determining which object LOD to Submit to the render manager.
Let me know if this helps!
Follow me on Twitter – development and personal tweetsAwesome XNA Videos – Lighting, Rendering, and game videos
I was able to get it running, but I have a large drop in framerate when I zoom in close to the models - < 1 fps.
I am using a "DeferredSasEffect," is there any way to optimize that?
I've tracked down the custom shader problem somewhat. It seems that the custom shader messes up the relocation of the bones.
Hence, all instances are repeated on top of each other, slowing down the framerate. However, I am unsure how to fix that.
Is there a way to convert a custom shader to a DeferredObjectEffect shader?
In the shader you'll need to add a matrix array variable bound to the "Sas.Skeleton.MeshToJointToWorld[*]" SAS semantic (the number of elements depends on the instance count you're using - SunBurn uses 75) and add the vertex element BLENDINDICES0 to the vertex struct:
float4x3 meshToWorld[75] <string SasBindAddress = "Sas.Skeleton.MeshToJointToWorld[*]";>;
struct InputData{ // existing members... float4 meshToWorldIndex : BLENDINDICES0;};
Then when transforming the vertex use the X component of the blendindex as an index into the matrix array to retrieve the meshToWorld transform. Make sure not to transform the vertex using the world in addition to the meshToWorld transform.
float4 worldspace_position = float4(mul(input.position, meshToWorld[input.meshToWorldIndex.x]), 1.0f);
Edit: Updated for correctness - originally suggested float4x4 matrices, which exceed available constants, also "Sas.Skeleton.MeshToJointToWorld[*]" converts to world space as the name suggests.
Update: It seems a similar implementation on the deferred wobble shader from the custom effects sample causes the same error message to appear. I've removed the code as it is not the code that is the problem but rather the implementation.
It appears it is the "input.meshToObjectIndex.x" variable is suspect, as giving it a defined value (ie: input.meshToObjectIndex.x = 1) enables the program to run.
Strangely enough, a conditional statement like "if (input.meshToObjectIndex.x != 1) input.meshToObjectIndex.x = 1" does not seem to solve this problem.
Thank you for your help so far, I hope this is the final issue. This modified POM effect is incredible, and I look forward to sharing it with the community!
***
I still seem to be having difficulties. When I attempt to initialize the program with the modifications, an error message appears stating:
"Both a valid vertex shader and pixel shader (or valid effect) must be set on the device before any draw operations may be performed."
I am uncertain why this is. I have included the modified code which produces this error (it's long and I don't know how to add a scrollbar, sorry):
(Code removed, see edit)
Ok, I've updated the code above - I made a mistake when typing up the original code suggestions. The xna exception was caused by exceeding the number of shader constants (not sure why the content pipeline doesn't report this during the build :/ ), the array of 75 float4x4 matrices alone exceed the available constants by a considerable amount. Switching the matrices to float4x3 allows them to fit.
Also the "Sas.Skeleton.MeshToJointToWorld[*]" sas binding transforms the vertex all the way into world space, so you should not include the world transform in the calculations.
Using these changes I was able to run the shaders from the Custom Effects Example (both forward and deferred) in the Instancing Example.
Sorry for any confusion, and let me know if this helps!
Everything is running well now. I am working on implementing the dynamic LOD system, as larger environments impact performance, but it seems I have all of the technicalities worked out for the time being.
Thank you very much for your help! Hopefully I can get the framerate between 20-40 FPS by the end of the week.
Hi, everyone. I've had to take a break from my' recreational (I intend to incorporate it into my resume eventually, but recreational is the best way to describe it currently)' coding to focus on school-related projects.
Luckily, my Summer courses are nearing completion, I've set up my elliptical (which enables me to exercise and code at the same time), and I'll have about 3-4 weeks to code/exercise non-stop, which I am looking forward to.
I've had a few hours to use my exercise-coding platform to reload my old code (I had a virus-related mishap) and reinstall the latest version of C#, XNA, and Sunburn. Luckily I've done a majority of the conversion.
I intend to migrate the completed code in chunks to the Instancing example, which I will then use to instance various models and create my demo. However, I'm not sure as to how to convert the new format to a deferred shader - I've done the usual steps outlined above, but it will not run with the "DeferredSAS" effects in place. I've included a screencap for reference purposes.
In the original, I can make the program run, but it will not display the Parallax Occlusion Effect. Hence, I've concluded the best decision would be to migrate the program bit by bit to the instancing example, as I did last time to implement instancing in the previous version (~6 months ago).
How can I go about completely converting the new Instancing example to a deferred system?
Hi style,
To switch from forward to deferred (and vice-versa) make sure to change the model content processors from the forward processors to deferred, also make sure to change the deferred argument passed to SceneInterface.CreateDefaultManagers().