[solved]My tessellation pipeline that draws nothing.

Started by
27 comments, last by Jason Z 10 years, 12 months ago

Hmm, I am starting to suspect the matrices. There is some confusion here because my camera class began with XNA, changed to SlimDX under DX9 and then to SharpDX under DX11, and I'm not sure if the methods with the same name are doing the same thing anymore. Here is the code to my update method in the camera.


        public override void Update()
        {
            Quaternion rot = Quaternion.RotationYawPitchRoll(input.Yaw,input.Pitch,input.Roll);
            avatarRotation = rot * avatarRotation;

            avatarPosition += Vector3.TransformCoordinate(new Vector3(0.0f, 0.0f, input.Velocity), Matrix.RotationQuaternion(avatarRotation));

            Matrix rotMatrix = Matrix.RotationQuaternion(avatarRotation);
            Vector3 transformedRef = Vector3.TransformCoordinate(thirdPersonRef, rotMatrix);

            cameraPosition = transformedRef + avatarPosition;
//            Vector4 upVector4 = rotMatrix.get_Rows(1);
            Vector4 upVector4 = rotMatrix.Row1;
            Vector3 upVector3 = new Vector3(upVector4.X, upVector4.Y, upVector4.Z);
            view = Matrix.LookAtRH(cameraPosition, avatarPosition, upVector3);
            projection = Matrix.PerspectiveFovRH(UsefulFunctions.ToRadians(45.0f),
                        aspectRatio, 0.1f, 500.0f);

            Matrix frustumMatrix = view * Matrix.PerspectiveFovRH(UsefulFunctions.ToRadians(50.0f),
                        aspectRatio, 0.1f, 500.0f);
            frustum.BuildViewFrustum(frustumMatrix);

            base.Update();
        }

Hmm, when I debug this code, I am getting a different View matrix from my DX9 version than with my DX11 version. The Projection matrix is the same in both versions. I'm not sure what's going on here.

EDIT: I have another clue, when I move the camera at all with my controls, PIX showed no draw calls. I realized that my frustum checker was rejecting everything as being outside the frustum. That doesn't actually solve the problem, but it definately indicates that the matrices are wrong. I just need to know why I'm getting different matrices with the same code.

Advertisement

Ok, I found one mistake in my camera code. It turns out that SlimDX uses a zero base index on the row getter method, while SharpDX uses a one base index. You can see the commented out old SlimDX code above, instead of Row1, I needed Row2 to match the old Rows(1). Now that my initial up vector is (0,1,0) like it is supposed to be, all my matrices are the same between my DX9 version and my DX11 version. Unfortunately the problem still exists and I can't see anything. I'll have to test this again with my computer that allows PIX to run to see if my W values become sane. Although having the wrong up vector shouldn't make things invisible.

Shot in the dark: Forgot to transpose the matrices ?

How do you update your constant buffers ?

Ok, fixing that glich with the up vector gets rid of the weird W values. Now that I think about it, if you have an up vector that is nowhere close to perpendicular with your view direction, you're going to get skewed results. Here is my new screenshot:

[attachment=14883:PIXpic2.png]

Shot in the dark: Forgot to transpose the matrices ?

How do you update your constant buffers ?

I used to know what that means... but I forget now. Transpose them where? Since this is a terrain map of sorts, it actually defines world space in a way. The world matrix for this data would be the identity matrix, so I left it out of my calculations. Tell me if I'm mistaken, but m * identity == m correct?

The constant buffer is something I had doubts about, according to PIX it appears that it is being updated, but it's hard to tell if it's being done correctly. My code for creating and updating is as follows:


            perFrameBuffer = new Buffer(Game.GraphicsDevice, new BufferDescription { 
                Usage = ResourceUsage.Dynamic, 
                SizeInBytes = PerFrameBuffer.SizeOf, 
                BindFlags = SharpDX.Direct3D11.BindFlags.ConstantBuffer,
                CpuAccessFlags = CpuAccessFlags.Write
            });


            //Take a snapshot of the camera properties so that they don't change in mid draw
            Vector2 cameraPos = new Vector2(camera.Position.X, camera.Position.Z);
            Matrix viewMatrix = camera.View;
            Matrix projectionMatrix = camera.Projection;
            Vector3 vecEye = camera.Position;

            DataBox box = Game.GraphicsDevice.ImmediateContext.MapSubresource(perFrameBuffer, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None);
            var cb = new PerFrameBuffer();
            cb.ProjectionView = Matrix.Multiply(viewMatrix,projectionMatrix);
            cb.VecEye = new Vector4(vecEye,1);
            cb.LightDirection = new Vector4(0.0f, 0.6f, -0.9f, 1);
            cb.LightColor = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);

            Utilities.Write(box.DataPointer, ref cb);
            Game.GraphicsDevice.ImmediateContext.UnmapSubresource(perFrameBuffer, 0);

Bullseye!

cb.ProjectionView = Matrix.Multiply(viewMatrix,projectionMatrix);

Should (usually) be

cb.ProjectionView = Matrix.Transpose(Matrix.Multiply(viewMatrix,projectionMatrix));
EDIT Ooops. put an invert first, sorry. Corrected

Explanation: Shaders default to column-major packing in constant buffers, unless you compile with a flag telling otherwise. There are also corresponding HLSL keywords. So, you have to transpose your matrices this way (The effect framework took care of that automatically).

Tell me if I'm mistaken, but m * identity == m correct?

Yup, thats fine. Identity is "the 1", the matrix multiplications neutral element.

Dang. I was really hoping that would fix it, but I still am not seeing anything. I'm away from my PIX computer at the moment unfortunately so I can't check to see if the viewport geometry has changed.

Interesting, I had no idea that the effect framework did that automatically. There's probably a lot of stuff that I have no concept to even check.

I have one question about the PIX windows.

The Post-GS window in the above example is almost exactly what I was hoping to see in my viewport. The triangle shaped gaps are there because I do the hex field in two passes, first with the triangle pointing up(uh..north) and then a pass pointing down, and the displayed geometry is only the first draw call out of two needed for a block of hexes.

Since the final screen positioning is all handled in the domain shader, before the geometry shader, why is the Post-GS window correct and the viewport window so messed up? What could be changing between the GS and the output if the GS is just a pass thru?

Two things:
  • Conversion from homogenous to cartesian coordinates aka perspective divide (x/w,y/w,z/w)
  • Viewport transformation (denormalizing to fit to your render target)
Note: PIX does sort of a "zoom to extent" for every view except the last, so even if your vertices are in a very big or very small scale, you will see them all.

If your matrices are fine and the viewport too, you should now see something more sensible. But maybe you have still other bugs.

Ooh! I'm getting closer. Check out the PIX. The viewport is now exactly right.

[attachment=14884:PIXpic3.png]

I still am not seeing anything on screen. Just in case the triangle windings are backwards, (I'm using clockwise) I tried to move the camera downward to look up at the terrain, but I was unable to do that. It's hard to know what the camera is doing when you can't see anything.

This is what happens when you code for 3 months straight without debugging, which I did because I didn't really know how to debug in this new environment. You have to debunk 50 unfounded theories one... at... a... time. Thanks everyone for sticking with me, I don't think I could have persevered without your help.

So the geometry appears correct. Period. What else could be the problem?

Did you try to set all your shaders to null after your drawing is done?

I remember having a problem with my GShader sometime ago where i didnt set it to null.

This ended up that another call to a different vertex/pixel shader was using the GS Stage too displayed wierd stuff on the screen.

For testing i would set all the stages you are using for your tesselation to null after your are done with drawing.

And disable all other drawing you are doing beside your terrain rendering.

Can you do a PIX pixel history to see where the pixels generated from that geometry get dumped? Typically you should be looking for something like a viewport not set (which appears not to be the case now) rasterizer state not correct (i.e. backface culling), scissor rect not set correctly (but the default state is neutral, so unless you set one it can't be the problem), and then depth test, stencil test, and blending.

Can you show us the rasterizer state and output merger state that are being used for your tessellation draw call?

This topic is closed to new replies.

Advertisement