Rendering multiple objects with directx and problem with displaying them

Started by
7 comments, last by kauna 10 years, 9 months ago

Hi.

I have problem with rendering multiple objects in DirectX. From logic engine I'm getting vertices, indices and also some constant data per object. All data from logic engine is valid so this is not the problem.

To draw this objects I'm using this scenario:

  1. RSSetViewports() to set viewport
  2. Set OMSetRenderTargets() to proper target view
  3. Clearing render target view
  4. Clearing stencil and depth buffer. (with D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL)
  5. Drawing an actual object (methods from dx in order) - i'm repeating this point for every single object that I have
    • IASetIndexBuffer()
    • VSSetConstantBuffers()
    • VSSetShader() - for each object can be used other vertex shader
    • PSSetShader() - for each object can be used other pixel shader
    • IASetVertexBuffers() - stride is set to size of used data in vertex shader
    • IASetPrimitiveTopology() - it can change for every object
    • IASetInputLayout() - respectively to used vertex shader
    • Mapping data to indices buffer (using Map() with WRITE_DISCARD)
    • Mapping constant data to constant buffer (also Map() with WRITE_DISCARD)
    • Mapping data to verticles buffer (also Map() with WRITE_DISCARD)
    • DrawIndexed() to draw

First rendering works just fine - all objects are visible on display. But when I need to update objects something is not ok - on display there are no objects at all or I see only some parts of objects (in general only those in top left corner).

I have one instance of ID3D11Buffer for vertices, one for constant, and one for indices. All buffers are set with DYNAMIC flag. Objects are drawn to Texture2d buffer and after rendering this texture is displayed on the screen. I don't have access to SwapChain because I'm using combined project (UI is in C# and dx engine in is c++). From the system I'm receiving 3 different render target view so that's the reason why I'm using Texture2D buffer. There is no need to render objects every single time so I'm just drawing Texture2D when I get new render target view. Of course when I'm drawing "on" texture I use my own render target view which is connected to texture2d. When I receive target view from the system I'm drawing texture on it.

Do You have any ideas why after first drawing objects are not drawing (or displaying) properly?

I've spent a lot of time to overcome this problem but with no luck.

I really need help. I appreciate any suggestions.

Please forgive me any grammar/spelling mistakes.

Thanks,
Artur

Advertisement

How do you store your instancing data? In the constant buffer?

If you see only part of the objects (ie. missing faces etc) there might be problem with the indices/type/amount of primitives you are asked to be drawn

If you see only some of the objects (drawn fully) then your instancing data may be incorrect, or the amount of instanced asked to be drawn is incorrect.

Cheers!

Objects which I'm creating are not instanced. Every single object is different than the other one so there is no need to use instancing(?)

I see only part of objects. Objects seems to be rendered in right place but, as I told , I see only some part of them (small piece). For single DrawIndexed() I'm settting max. 20k indices, but often it's much less than this (2k-3k). Typology is always triangle list or line list.

Amount, I think, is not the case because first render is always alright. Only if I want to render again the same set of objects I'm getting small piceces of rendered objects.

Sorry, I didn't read the question correctly.

Are you storing your objects in main memory and copying the data to the GPU memory every frame?

I have (let say) 3 objects. All these objects has its own indices, vertices and some constant data. To render each of them I'm copying indices, vertices and constant data to proper buffers using Map() and Unmap() methods from d3d11context. So in one cycle (frame) I'm using 3 times Map()/Unmap() to copy data to proper buffer and after copying I'm using DrawIndexed().

So "the process" looks like this:

  1. Take object
  2. Map/Unmap vertices for this object
  3. Map/unmap indices for this object
  4. Map/unmap const. data for this object
  5. DrawIndexed() for this object
  6. If any other object left go to 1st point.
  7. End of drawing frame

I forget to mention that when I'm using Map(), i do it with WRITE_DISCARD flag.

Yes, you are describing your method of drawing pretty well and I don't see any problem with it. I think that it is necessary to see the actual code in order to spot the bug / bugs.

Cheers!

It's all that I can upload. I'll try to tell you how does this code work - without explanation code is worthless.

Original drawing code is written in OpenGL but on windows phone 8 there is no such thing so I'm writing class(es) with methods which will emulate those from ogl.

So first of all I'm creating program (GetProgramId) than I'm attaching pixel shader and vertex shader to it. I have different vertex and pixel shaders and they are used with different struct layout (as you can see in CreateVertexShader() method). After init I'm setting proper program (UseProgram()) so I know which vertex and pixel shader I should use for object which I'm currently rendering. To vertexshader is attached struct layout so I know what I should pass to DX's IASetInputLayout().

Than I set (and map) constant data to shader - it depends on object and what (and how much) data I need to transfer to shader so it an by achieved with SetAreasShaderBuffer() or SetPoints2DWithColor() or SetLinesAsPolygonsBuffer().

Later I'm setting vertices (it also depends on what object I'm currently rendering) so I use one of SetVerticles() methods.

Last point in rendering is using DrawElements(). I pass to this method indices, count of them, and size of single element. At this place I'm invoking methods from 1st point on list in first post.

Before creating frame I'm calling Rendering() method to attach and clean DX.

CopyBuffer() method seems to be ok. It's used to show earlier generated objects - as I told I'm getting 3 different render target view from system and I don't want to re-render all object without reason.

I realize that code might not be clear and it can be mysterious but I can't provide any batter and any more than this sad.png I hope that my explanation is somehow useful for reading code.

If you have more questions please ask - you are my only hope.

Thanks in advance,

Ok. I'm really confused. Whole drawing is from main thread. When I put breakpoint (for example: in DrawArray()) sometimes I get more (or even all) objects. Why? Is it because I'm switching too fast vertex, pixel shaders or input layout? Or maybe because of fast changes in vertices, indices, constant buffers?

I thought that the Map()/Unmap() are blocking methods (as well as memcpy() while updating data on VRAM).

Don't know what to do. :/

Or maybe texture (which I use as a buffer) isn't ready for drawing to display? But how I should know when it's ready to be drawn (texture is rendered in 100%)?

I took a look in to the code, but it is rather difficult to find out problems in code written by other person.

As far as I know, you can't "switch shaders" too quickly. For Map / Unmap I don't know the exact implementation, but as far as I know, there isn't any requirement to keep the data available after the function call.

If you are using just one thread for drawing and updating things and you have done all the required function calls, you are good to call the drawing command.

You should narrow down the problem by disabling any code that isn't part of the problem.

Cheers!

This topic is closed to new replies.

Advertisement