loading mesh with DirectXTK - directx

I use DirectXTK to load mesh. First, I import .fbx into vs2015 and build, then get .cmo file. Then I use DirectXTK load .cmo as follow:
bool MeshDemo::BuildModels()
{
m_fxFactory.reset(new EffectFactory(m_pd3dDevice));
m_states.reset(new CommonStates(m_pd3dDevice));
m_model = Model::CreateFromCMO(m_pd3dDevice, L"T54.cmo", *m_fxFactory, true, true);
return true;
}
void MeshDemo::Render()
{
m_pImmediateContext->ClearRenderTargetView(m_pRenderTargetView, Colors::Silver);
m_pImmediateContext->ClearDepthStencilView(m_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
XMVECTOR qid = XMQuaternionIdentity();
const XMVECTORF32 scale = { 0.01f, 0.01f, 0.01f };
const XMVECTORF32 translate = { 0.f, 0.f, 0.f };
XMMATRIX world = XMLoadFloat4x4(&m_world);
XMVECTOR rotate = XMQuaternionRotationRollPitchYaw(0, XM_PI / 2.f, XM_PI / 2.f);
rotate = XMQuaternionRotationRollPitchYaw(0, XM_PI / 2.f, XM_PI / 2.f);
XMMATRIX local = XMMatrixMultiply(world, XMMatrixTransformation(
g_XMZero, qid, scale, g_XMZero, rotate, translate));
local *= XMMatrixRotationX(-XM_PIDIV2);
m_model->Draw(m_pImmediateContext, *m_states, local, XMLoadFloat4x4(&m_view),
XMLoadFloat4x4(&m_proj));
m_pSwapChain->Present(0, 0);
}
But I can't get correct results,the angle of wheel and some details are different with the .fbx model.
what should I do? Any idear?

Your model is fine, but your culling is inverted, and this is why the render is wrong.
Triangles sent to the GPU have a winding order, it has to be consistent, clock wise or counter clock wise by rearranging the triangle vertices. Then, a render state define what is the front side, and what has to be culled away, front, back or none.

Related

Alpha values below 0.5f are invisible

I am currently developing on a new mechanism to visualize laser beam hits on spaceships' shields. The development on the CPU side is done and the Vertex Shader is working fine, but I have an issue while creating the Pixel Shader: Any transparency value below 0.5 is invisible.
The following Pixel Shader is incredible simple: If the pixel is inside the hit radius, I show a semi-transparent blue pixel, otherwise nothing is shown.
float4 PS(PS_IN input) : SV_Target
{
if (input.impactDistances.x > 0.0f && input.impactDistances.x < 2.0f)
{
return float4(0.0f, 0.0f, 1.0f, 0.5f);
}
return float4(1.0f, 1.0f, 1.0f, 0.0f);
}
This results in something like this (see blue area above the yellow arrow).
Now, if I change the line
return float4(0.0f, 0.0f, 1.0f, 0.5f);
to
return float4(0.0f, 0.0f, 1.0f, 0.4f);
then the impact areas are completely invisible and I can't think of anything that causes this behaviour. Do you have any idea?
If it helps, here are my settings for the blend state that I use for the entire game.
var blendStateDescription = new SharpDX.Direct3D11.BlendStateDescription();
blendStateDescription.RenderTarget[0].IsBlendEnabled = true;
blendStateDescription.RenderTarget[0].RenderTargetWriteMask = SharpDX.Direct3D11.ColorWriteMaskFlags.All;
blendStateDescription.RenderTarget[0].SourceBlend = SharpDX.Direct3D11.BlendOption.SourceAlpha;
blendStateDescription.RenderTarget[0].BlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
blendStateDescription.RenderTarget[0].DestinationBlend = SharpDX.Direct3D11.BlendOption.InverseSourceAlpha;
blendStateDescription.RenderTarget[0].SourceAlphaBlend = SharpDX.Direct3D11.BlendOption.Zero;
blendStateDescription.RenderTarget[0].AlphaBlendOperation = SharpDX.Direct3D11.BlendOperation.Add;
blendStateDescription.RenderTarget[0].DestinationAlphaBlend = SharpDX.Direct3D11.BlendOption.One;
blendStateDescription.AlphaToCoverageEnable = true;
_blendState = new SharpDX.Direct3D11.BlendState(_device, blendStateDescription);
_deviceContext.OutputMerger.SetBlendState(_blendState);
blendStateDescription.AlphaToCoverageEnable = true;
will definitely create an issue in your case, setting it to false will apply correct alpha blending.

Rotation Error on Object at 90° and -90°

I'm working on an app which allows the user to rotate an object with iOS touch controls.
I have the following script working fine, with 1 issue that I can't seem to crack.
GameObject mainCamera;
public Camera camMain;
// One Touch Rotation
public float rotateSpeed = 0.5f;
static float pitch = 0.0f, yaw = 0.0f, zed = 0.0f, pitchBravo = 0.0f, yawBravo = 0.0f;
// Two Touch Zoom
public float perspectiveZoomSpeed = 0.1f;
// Three Touch Pan
public float panSpeed = 0.5f;
private float xAxis = 0.0f, yAxis = 0.0f;
private float xMain, yMain, zMain;
// Game Objects, Public or Private
private GameObject bravo;
void Update()
{
// Grabs Bravo
bravo = GameObject.Find ("bravo");
pitch = bravo.transform.eulerAngles.x;
yaw = bravo.transform.eulerAngles.y;
// One Touch controls rotation of Bravo
if (Input.touchCount == 1)
{
// Retrieves a single touch and names it TouchZero
Touch touchZero = Input.GetTouch (0);
// The start of the rotation will be aligned with Bravo's current rotation
//pitch = bravo.transform.eulerAngles.x;
//yaw = bravo.transform.eulerAngles.y;
// Times the difference in position of touch between frames by the rotation speed. deltaTime to keep movement consistent on all devices
pitch += touchZero.deltaPosition.y * rotateSpeed * Time.deltaTime;
yaw -= touchZero.deltaPosition.x * rotateSpeed * Time.deltaTime;
// Assigns the new eulerAngles to Bravo
bravo.transform.eulerAngles = new Vector3 (pitch, yaw, 0.0f);
}
// Two Touch contols the Field of View of the Camera aka. Zoom
if (Input.touchCount == 2)
{
mainCamera = GameObject.Find("main");
// Store both touches.
Touch touchZero = Input.GetTouch(0);
Touch touchOne = Input.GetTouch(1);
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
// Otherwise change the field of view based on the change in distance between the touches.
camMain.fieldOfView += deltaMagnitudeDiff * perspectiveZoomSpeed;
// Clamp the field of view to make sure it's between 0 and 180.
camMain.fieldOfView = Mathf.Clamp(camMain.fieldOfView, 2.0f, 30.0f);
xAxis -= touchOne.deltaPosition.x * panSpeed * Time.deltaTime;
yAxis -= touchOne.deltaPosition.y * panSpeed * Time.deltaTime;
zMain = mainCamera.transform.position.z;
mainCamera.transform.position = new Vector3 (xAxis, yAxis, zMain);
}
}
With this script the object rotates left and right perfectly, 360°. But when the model is rotated up and down it gets to the 90° or -90° mark and bugs out, not allowing the user to carry on rotating.
I've done a bit of research and I believe it may have something to do with gimbal lock, my lack of knowledge on the subject means I haven't been able to come up with a fix.
Any help is appreciated.
GIF of bugged rotation

Canvas zoomIn/zoomOut: how to avoid loss of image quality?

I have this code that I used for scaling images. To zoomIn and zoomOut is use the code scalePicture(1.10, drawingContext); and scalePicture(0.90, drawingContext);. I perform that operations on a off screen canvas and then copy the image back to the original screen.
I make use of the offscreen processing since the browser optimizes the image operations by using double buffering. I am still having the issue that when I zoomIn by around 400% and then zoomOut back to the original size, there is a significant loss of image quality.
I am not depending on the original image because the user can perform many operations such as clip, crop, rotate, annotate and I need to stack all the operations on the original image.
Can anyone throw some advice/suggestions around any means to preserve the quality of the image while not sacrificing the performance and quality.
scalePicture : function(scalePercent, operatingCanvasContext) {
var w = operatingCanvasContext.canvas.width,
h = operatingCanvasContext.canvas.height,
sw = w * scalePercent,
sh = h * scalePercent,
operatingCanvas = operatingCanvasContext.canvas;
var canvasPic = new Image();
operatingCanvasContext.save();
canvasPic.src = operatingCanvas.toDataURL();
operatingCanvasContext.clearRect (0,0, operatingCanvas.width, operatingCanvas.height);
operatingCanvasContext.translate(operatingCanvas.width/2, operatingCanvas.height/2);
canvasPic.onload = function () {
operatingCanvasContext.drawImage(canvasPic, -sw/2 , -sh/2 , sw, sh);
operatingCanvasContext.translate(-operatingCanvas.width/2, -operatingCanvas.height/2);
operatingCanvasContext.restore();
};
}
Canvas is draw and forget. There is no way to preserve original quality without referencing the original source.
I would suggest to reconstruct the recorded stack but using a transformation matrix for the changes in scale, rotation etc. Then apply the accumulated matrix on the original image. This will preserve the optimal quality as well as provide some gain in performance (as you only draw the last and current state).
Similar for clipping, calculate and merge the clipping regions using the same matrix and apply clip before drawing in the original image in the final step. And similar with text etc.
It's a bit too broad to show an example that does all these steps, but here is an example showing how to use accumulated matrix transforms on the original image preserving optimal quality. You can see that you can zoom in and out, rotate and the image will in each instance render at optimal quality.
Example of Concept
var ctx = c.getContext("2d"), img = new Image; // these lines just for demo init.
img.onload = demo;
ctx.fillText("Loading image...", 20, 20);
ctx.globalCompositeOperation = "copy";
img.src = "http://i.imgur.com/sPrSId0.jpg";
function demo() {
render();
zin.onclick = zoomIn; // accumulates transform, but render
zout.onclick = zoomOut; // based on original image using.
zrot.onclick = rotate; // current transformation matrix
}
function render() {ctx.drawImage(img, 0, 0)} // render original image
function zoomIn() {
ctx.translate(c.width * 0.5, c.height * 0.5); // pivot = center
ctx.scale(1.05, 1.05);
ctx.translate(-c.width * 0.5, -c.height * 0.5);
render();
}
function zoomOut() {
ctx.translate(c.width * 0.5, c.height * 0.5);
ctx.scale(1/1.05, 1/1.05);
ctx.translate(-c.width * 0.5, -c.height * 0.5);
render();
}
function rotate() {
ctx.translate(c.width * 0.5, c.height * 0.5);
ctx.rotate(0.3);
ctx.translate(-c.width * 0.5, -c.height * 0.5);
render();
}
<button id=zin>Zoom in</button>
<button id=zout>Zoom out</button>
<button id=zrot>Rotate</button><br>
<canvas id=c width=640 height=378></canvas>

SlimDX Camera setup

Please, tell me what I'm doing wrongly:
that's my Camera class
public class Camera
{
public Matrix view;
public Matrix world;
public Matrix projection;
public Vector3 position;
public Vector3 target;
public float fov;
public Camera(Vector3 pos, Vector3 tar)
{
this.position = pos;
this.target = tar;
view = Matrix.LookAtLH(position, target, Vector3.UnitY);
projection = Matrix.PerspectiveFovLH(fov, 1.6f, 0.001f, 100.0f);
world = Matrix.Identity;
}
}
that's my Constant buffer struct:
struct ConstantBuffer
{
internal Matrix mWorld;
internal Matrix mView;
internal Matrix mProjection;
};
and here I'm drawing the triangle and setting camera:
x+= 0.01f;
camera.position = new Vector3(x, 0.0f, 0.0f);
camera.view = Matrix.LookAtLH(camera.position, camera.target, Vector3.UnitY);
camera.projection = Matrix.PerspectiveFovLH(camera.fov, 1.6f, 0.0f, 100.0f);
var buffer = new Buffer(device, new BufferDescription
{
Usage = ResourceUsage.Default,
SizeInBytes = sizeof(ConstantBuffer),
BindFlags = BindFlags.ConstantBuffer
});
////////////////////////////// camera setup
ConstantBuffer cb;
cb.mProjection = Matrix.Transpose(camera.projection);
cb.mView = Matrix.Transpose(camera.view);
cb.mWorld = Matrix.Transpose(camera.world);
var data = new DataStream(sizeof(ConstantBuffer), true, true);
data.Write(cb);
data.Position = 0;
context.UpdateSubresource(new DataBox(0, 0, data), buffer, 0);
//////////////////////////////////////////////////////////////////////
// set the shaders
context.VertexShader.Set(vertexShader);
context.PixelShader.Set(pixelShader);
// draw the triangle
context.Draw(4, 0);
swapChain.Present(0, PresentFlags.None);
Please, if you can see what's wrong, tell me! :) I have spent two days writing this already..
Attempt the second:
#paiden I initialized fov now ( thanks very much :) ) but still no effect (now it's fov = 1.5707963267f;) and #Nico Schertler , thank you too, I put it in use by
context.VertexShader.SetConstantBuffer(buffer, 0);
context.PixelShader.SetConstantBuffer(buffer, 0);
but no effect still... probably my .fx file is wrong? for what purpose do I need this:
cbuffer ConstantBuffer : register( b0 ) { matrix World; matrix View; matrix Projection; }
Attepmpt the third:
#MHGameWork
Thank you very much too, but no effect still ;)
If anyone has 5 minutes time, I can just drop source code to his/her e-mail and then we will publish the answer... I guess it will help much to some newbies like me :)
unsafe
{
x+= 0.01f;
camera.position = new Vector3(x, 0.0f, 0.0f);
camera.view = Matrix.LookAtLH(camera.position, camera.target, Vector3.UnitY);
camera.projection = Matrix.PerspectiveFovLH(camera.fov, 1.6f, 0.01f, 100.0f);
var buffer = new Buffer(device, new BufferDescription
{
Usage = ResourceUsage.Default,
SizeInBytes = sizeof(ConstantBuffer),
BindFlags = BindFlags.ConstantBuffer
});
THE PROBLEM NOW - I SEE MY TRIANGLE BUT THE CAMERA DOESN'T MOVE
You have set your camera's nearplane to 0. This makes all the value in your matrix divide by zero, so you get a matrix filled with 'NAN's
Use a near plane value of about 0.01 in your case, it will solve the problem
I hope you still need help. Here is my camera class, which can be used, and can be easily moved around the scene using mouse/keyboard.
http://pastebin.com/JtiUSiHZ
Call the "TakeALook()" method in each frame (or when you move the camera).
You can move around it with the "CameraMove" method. It takes a Vector3 - where you want to move your camera (dont give it huge values, I use 0,001f for each frame)
And with the "CameraRotate()" you can turn it around - it take a Vector2 as a Left-Right and Up-Down rotation.
Its pretty easy. I use EventHandlers to call there two function, but feel free to edit as you wish.

2D Pixel Shader has no effect?

I set up a basic pixel shader (right now, its configured for testing), and it doesn't seem to do anything. I set it up like so:
uniform extern texture ScreenTexture;
const float bloomThreshhold = 0.4;
const float existingPixelColorMult = 1.1;
sampler ScreenS = sampler_state
{
Texture = <ScreenTexture>;
};
float4 BloomedColor(float2 texCoord: TEXCOORD0) : COLOR
{
// pick a pixel on the screen for this pixel, based on
// the calculated offset and direction
float2 temp = texCoord;
temp.x += 1;
float4 mainPixelColor = 0;
/*
float4 pixelPlus1X = tex2D(ScreenS, temp);
temp.x -= 2;
float4 pixelMinus1X = tex2D(ScreenS, temp);
temp.x += 1;
temp.y += 1;
float4 pixelPlus1Y = tex2D(ScreenS, temp);
temp.y -= 2;
float4 pixelMinus1Y = tex2D(ScreenS, temp);
*/
return mainPixelColor;
}
technique Bloom
{
pass P0
{
PixelShader = compile ps_1_1 BloomedColor();
}
}
with the loading code like:
glowEffect = Content.Load<Effect>("GlowShader");
glowEffect.CurrentTechnique = glowEffect.Techniques[0];
and use code is:
spriteBatch.Begin();
glowEffect.Begin();
glowEffect.CurrentTechnique.Passes[0].Begin();
spriteBatch.Draw(screenImage, Vector2.Zero, Color.White);
spriteBatch.End();
glowEffect.CurrentTechnique.Passes[0].End();
glowEffect.End();
Loading seems to work fine, and there are no errors thrown when I use that method to render the texture, but it acts like the effect code isn't in there. It can't be that I'm using the wrong version of shaders (I tested with 2.0 and 1.1 versions), so why? (Using XNA 3.1)
You're returning 0 for every pixel. You have commented out any code that would return a different value than 0. 0 is black and if you're doing any sort of render you'll either get black (if the blend mode shows this as a color) or no change (if the blend mode multiplies the result). You can of course (if you were just attempting to see if the shader is being loaded and operated) try using an oddball color. Neon green anyone? Then, once you confirm it is being at least processed, start uncommenting that code and assessing the result.
Finally, if Bloom is what you're after, Microsoft has a very useful sample you will probably learn a lot from here:
http://create.msdn.com/en-US/education/catalog/sample/bloom
If you're using XNA 4.0, see what Shawn Hargreaves has to say about this.

Resources