Stencil testing in XNA 4 - xna-4.0

I was able to do this in XNA 3.1, however I see that we now use state objects in XNA 4, which is certainly an improvement, although I can't accomplish what I want so far :)
I am trying to:
Clear the stencil buffer to 0.
Draw a texture to the stencil buffer, setting the stencil buffer to 1 where the texture is drawn.
Draw another texture that will only appear where the stencil buffer is not 1.
Here is what I have so far, which appears to have no effect on the drawing of texture 2:
BlendState blend = new BlendState();
blend.ColorWriteChannels = ColorWriteChannels.None;
_preSparkStencil = new DepthStencilState();
_preSparkStencil.StencilEnable = true;
_preSparkStencil.StencilFunction = CompareFunction.Always;
_preSparkStencil.ReferenceStencil = 1;
_preSparkStencil.DepthBufferEnable = true;
_sparkStencil = new DepthStencilState();
_sparkStencil.StencilEnable = true;
_sparkStencil.StencilFunction = CompareFunction.NotEqual;
_sparkStencil.ReferenceStencil = 1;
_sparkStencil.DepthBufferEnable = true;
gd.DepthStencilState = _preSparkStencil;
gd.Clear(ClearOptions.Stencil, Color.Black, 0, 0);
sb.Begin(SpriteSortMode.Deferred, blend);
DrawTexture1();
sb.End();
gd.DepthStencilState = _sparkStencil;
sb.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied);
DrawTexture2();
sb.End();
gd.DepthStencilState = old;

The problem was that the RenderState needs to be passed into SpriteBatch, or else the SpriteBatch will use it's own RenderState.
sb.Begin(SpriteSortMode.Deferred, BlendState.Opaque,
SamplerState.LinearWrap, _preSparkStencil,
RasterizerState.CullCounterClockwise, CLM.AlphaClip);

Related

Three js OrbitControls control rotation direct with mousemove (without mousedown)

The target(object) has a fixed rotate animation. So i'm trying to use OrbitControls for rotating camera around the target. Here is the standard set:
this.control = new OrbitControls(this.camera, this.renderer.domElement);
this.control.rotateSpeed = 0.3; // control the rotate speed
this.control.autoRotateSpeed = 0;
this.control.enableZoom = false;
this.control.enablePan = false;
this.control.enableDamping = true;
this.control.target.set(0, 0, 0);
I also can use smooth moving
this.control.update()
It works well with mousedrag (mousedown and start to move).
My goal is only that i do not use "mousedown". I just want my target to rotate by mousemove directly.
I already read the docs https://threejs.org/docs/#examples/en/controls/OrbitControls
But i can not find for controlling "mousedown, mousemove, mouseup".
Isn't it impossible?

how to handle hairs better in three.js?

The result I have right now is on the left. I want to make the result close as possbile to the one from the right. Hairs only. Here's my model.
How can I achieve that?
here's the code I use right now:
m.color.set( 0xffffff );
m.map.magFilter = THREE.NearestFilter;
m.map.minFilter = THREE.NearestFilter;
m.transparent = true;
m.alphaTest = 0.001;
m.alphaMap = null;
m.side = THREE.DoubleSide;
m.shininess = 6;
m.depthTest = true;
m.depthWrite = true;
m.skinning = true;
m.map.needsUpdate = true;
I've tried different variations of code but I don't know the three.js well. I see the problem with sorting, overlapping, etc. How can I can solve this?
I see some succesfull results with webgl here:
https://sketchfab.com/3d-models/knight-princess-6495fc2ab3ac4fce84315453ab0a6809
https://sketchfab.com/3d-models/jolly-roser-31008c461a2644ea95f57f938f3e42a8
https://sketchfab.com/3d-models/subsurface-scattering-sss-demo-lara-a231143a88e44951820bdf11ab4cbf53

Three.js - repositioning vertices in a 'particle' mesh

I have a basic three.js game working and I'd like to add particles. I've been searching online, including multiple questions here, and the closest I've come to getting a 'particle system' working is using a THREE.BufferGeometry, a THREE.BufferAttribute and a THREE.Points mesh. I set it up like this:
const particleMaterial = new THREE.PointsMaterial( { size: 10, map: particleTexture, blending: THREE.AdditiveBlending, transparent: true } );
const particlesGeometry = new THREE.BufferGeometry;
const particlesCount = 300;
const posArray = new Float32Array(particlesCount * 3);
for (let i = 0; i < particlesCount; i++) {
posArray[i] = Math.random() * 10;
}
const particleBufferAttribute = new THREE.BufferAttribute(posArray, 3);
particlesGeometry.setAttribute( 'position', particleBufferAttribute );
const particlesMesh = new THREE.Points(particlesGeometry, particleMaterial);
particlesMesh.counter = 0;
scene.add(particlesMesh);
This part works and displays the particles fine, at their initial positions, but of course I'd like to move them.
I have tried all manner of things, in my 'animate' function, but I am not happening upon the right combination. I'd like to move particles, ideally one vertex per frame.
The current thing I'm doing in the animate function - which does not work! - is this:
particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
particlesGeometry.setAttribute( 'position', particleBufferAttribute );
//posArray[particlesMesh.counter] = objects[0].position;
particlesMesh.counter ++;
if (particlesMesh.counter > particlesCount) {
particlesMesh.counter = 0;
}
If anyone has any pointers about how to move Points mesh vertices, that would be great.
Alternatively, if this is not at all the right approach, please let me know.
I did find Stemkoski's ShaderParticleEngine, but I could not find any information about how to make it work (the docs are very minimal and do not seem to include examples).
You don't need to re-set the attribute, but you do need to tell the renderer that the attribute has changed.
particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
particleBufferAttribute.needsUpdate = true; // This is the kicker!
By setting needsUpdate to true, the renderer knows to re-upload that attribute to the GPU.
This might not be concern for you, but just know that moving particles in this way is expensive, because you re-upload the position attribute every single frame, which includes all the position data for every particle you aren't moving.

three.js loaded model is disappearing while switch to FirstPerson control from Orbitcontrol

am having an option to switch Orbit control to FirstPerson control, but while switch my model is disappearing from the scene
my code is below
controls = new THREE.FirstPersonControls( camera );
controls.movementSpeed = 70;
controls.lookSpeed = 0.04;
controls.noFly = true;
controls.lookVertical = false;
i need that switch from one control to another the object should be fixed on the position at present
Unlike OrbitControl, in the FirstPersonControl the camera points to an artbitrary directions. So use camControl.lon and camControl.lat to control the initial direction of camera.
camControl = new THREE.FirstPersonControls(camera);
camControl.lookSpeed = 0.1;
camControl.movementSpeed = 4;
camControl.noFly = true;
camControl.lookVertical = true;
camControl.lon = -90;
camControl.lat = 0;
Also make sure your mouse is not over the window as the scene is moving because as another poster pointed out, as soon as the mouse is on the cavas FirstPersonControl will start rotating the camera.
As of three.js R101, it's possible to use FirstPersonControls.lookAt(). FirstPersonControls.lat and FirstPersonControls.lon have been removed.
Besides, when creating FirstPersonControls the initial orientation of the camera is now respected.

Why are transparent pixels showing up black in my image?

I am saving an image bytes array as a thumbnail. The problem is that the transparent background color is black in my image.
Below is my code:
MemoryStream memoryStream = new MemoryStream(pbytImageByteArray);
System.Drawing.Image imgImageSource = System.Drawing.Image.FromStream(memoryStream);
double dblOrgnWidth = imgImageSource.Width;
double dblOrgnHeight = imgImageSource.Height;
double dblRatio = (dblOrgnWidth / dblOrgnHeight) * 100;
double dblScaledWidth = pintWidth;
double dblScaledHeight = 0;
dblScaledHeight = (dblScaledWidth / dblRatio) * 100;
System.Drawing.Bitmap bitmapImage = new System.Drawing.Bitmap(System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight));
bitmapImage.SetResolution(imgImageSource.HorizontalResolution, imgImageSource.VerticalResolution);
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(bitmapImage);
graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
ImageAttributes imageAttributes = new ImageAttributes();
graphics.DrawImage(imgImageSource, new System.Drawing.Rectangle(0, 0, System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight)), 0, 0, System.Convert.ToInt32(dblOrgnWidth), System.Convert.ToInt32(dblOrgnHeight), System.Drawing.GraphicsUnit.Pixel);
MemoryStream outputMemoryStream = new MemoryStream();
bitmapImage.Save(outputMemoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
bitmapImage.GetThumbnailImage(System.Convert.ToInt32(dblScaledWidth), System.Convert.ToInt32(dblScaledHeight), null, IntPtr.Zero);
imgImageSource.Dispose();
bitmapImage.Dispose();
graphics.Dispose();
return outputMemoryStream.ToArray();
JPEG doesn't support transparency. Save as a PNG.
Alternatively, if you know the background color that this will be on, you could set the transparent pixels to that color. If you are using semi-transparent pixels, then you would have to blend the pixels with that color.
Here is an article that explains alpha blending:
http://www.c-sharpcorner.com/UploadFile/mahesh/DrawTransparentImageUsingAB10102005010514AM/DrawTransparentImageUsingAB.aspx
If you are interested in a commercial solution for that (Disclaimer: I work for Atalasoft), DotImage Photo has a class, FlattenAlphaCommand, that can do this in a couple of lines of code.

Resources