SceneKit repeat texture - objective-c

For some reason, using the following material on an SCNBox keeps resulting in a stretched texture. Any idea where I'm missing something?
material.diffuse.contents = [SKTexture textureWithImageNamed:#"arrowtexture.jpg"];
material.diffuse.wrapS = SCNWrapModeRepeat;
material.diffuse.wrapT = SCNWrapModeRepeat;

You can control SKTexture's stretch this way:
material.diffuse.contentsTransform = SCNMatrix4MakeScale(3, 1, 1);

Related

Vulkan Instanced Rendering Weird Depth Buffer Behaviour

I am rendering a single mesh test object that contains 8000 cubes, 1 monkey, and 1 plane. I checked normals and winding orders. all seems correct for mesh.
if I render a single instance, the depth buffer works correctly. if I render using instanced when instant number increase depth buffer doesn't work correctly.
//Depth Attachment
//Create Depth Image
depthImage = new Image(
physicalDevice_,
logicalDevice_,
VK_IMAGE_TYPE_2D,
depthFormat,
VK_IMAGE_TILING_OPTIMAL,
swapChainExtent.width,
swapChainExtent.height,
1,
sampleCount_, //do we really need to sample depth????
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
depthImageView = new ImageView(
logicalDevice_,
VK_IMAGE_VIEW_TYPE_2D,
depthImage->handle,
depthFormat,
1,
VK_IMAGE_ASPECT_DEPTH_BIT);
//Render pass Depth Attachment
VkAttachmentDescription depthAttachment{};
depthAttachment.format = depthFormat;
depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT;
depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
//Graphics Pipeline
VkPipelineDepthStencilStateCreateInfo depthStencil{};
depthStencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depthStencil.depthTestEnable = VK_TRUE;
depthStencil.depthWriteEnable = VK_TRUE;
depthStencil.depthCompareOp = VK_COMPARE_OP_LESS;
depthStencil.depthBoundsTestEnable = VK_FALSE;
depthStencil.minDepthBounds = 0.0f; // Optional
depthStencil.maxDepthBounds = 1.0f; // Optional
depthStencil.stencilTestEnable = VK_FALSE;
depthStencil.front = {}; // Optional
depthStencil.back = {}; // Optional
Below the screen is the view from the 100th instance of that mesh.
The higher the instance number, the more the depth buffer deteriorates.
The result is still the same if I use a different model.
What am I missing?
Result:
Depth Buffer:
For those who may struggle with similar issue. I found a solution.
Actually, this issue is not related to instancing directly but it's a bit confusing issue becomes visible as the instance index increases.
the cause is projection matrix z-near value was so small.
...
fieldOfView = 65.0f;
znear = 0.001f; // ! this much small value cause this problem
zfar = 5000.0f;
...
changed z-near to an acceptable value. Problem solved.
...
fieldOfView = 65.0f;
znear = 0.1f;
zfar = 5000.0f;
...

How do you get motion blur working in SceneKit?

According to WWDC 2017, motionBlurIntensity was added as a property to SCNCamera. I've tried the following and failed to get SceneKit to blur my scene when the camera is moved:
Set wantsHDR to true
Add SCNDisableWideGamut as a Boolean with the value of YES in every Info.plist in my Xcode project
Move a SCNBox by changing its SCNNode's position in front of the camera with motionBlurIntensity set to 1.0
Move the camera itself by changing its SCNNode's position with motionBlurIntensity set to 1.0
Animate the camera using an SCNTransaction with motionBlurIntensity set to 1.0 instead of changing its position each frame
Do the above with motionBlurIntensity set to 500 or greater
I run the following code every rendered frame like so:
camNode.position = SCNVector3Make(cx, cy, cz);
camNode.eulerAngles = SCNVector3Make(rotx, roty, rotz);
camNode.camera.wantsDepthOfField = enableDOF;
camNode.camera.wantsHDR = enableHDR;
camNode.camera.zNear = camNearVal;
camNode.camera.zFar = camFarVal;
camNode.camera.focalLength = camFocalLength;
camNode.camera.usesOrthographicProjection = usingOrthoProjection;
if(!usingOrthoProjection)
{
camNode.camera.projectionTransform = SCNMatrix4FromGLKMatrix4(GLKMatrix4MakeWithArray(projection));
}
else
{
// Ortho options
camNode.camera.orthographicScale = orthoScale;
if(cam_projectionDir == 1)
camNode.camera.projectionDirection = SCNCameraProjectionDirectionHorizontal;
else
camNode.camera.projectionDirection = SCNCameraProjectionDirectionVertical;
}
// DOF
camNode.camera.sensorHeight = dof_sensorHeight;
camNode.camera.focusDistance = dof_focusDistance;
camNode.camera.fStop = dof_fStop;
camNode.camera.apertureBladeCount = dof_apertureBladeCount;
camNode.camera.focalBlurSampleCount = dof_focalBlurSampleCount;
// Motion blur
camNode.camera.motionBlurIntensity = motionBlurIntensity;
And here is where the SCNRenderer sets its pointOfView to the camera:
mainRenderer.scene = mainScene;
mainRenderer.pointOfView = camNode;
id<MTLCommandBuffer> myCommandBuffer = [_commandQueue commandBuffer];
[mainRenderer updateAtTime: currentFrame];
[mainRenderer renderWithViewport:CGRectMake(0,0,(CGFloat)_viewWidth, (CGFloat)_viewHeight) commandBuffer:myCommandBuffer passDescriptor:_renderPassDescriptor];
[myCommandBuffer commit];
HDR effects like Bloom and SSAO work properly, just not motion blur.
I'm using Xcode Version 10.1 on macOS Mojave.
I ran the Badger sample app and the motion blur in that project works on my computer.
Am I missing something here? Any insight would be greatly appreciated.
The default value of a motionBlurIntensity property is 0.0. It results in no motion blur effect. Higher values (toward a maximum of 1.0) create more pronounced motion blur effects. Motion blur is not supported when wide-gamut color rendering is enabled. Wide-gamut rendering is enabled by default on supported devices; to opt out, set the SCNDisableWideGamut key in your app's Info.plist file.
Test it with my code:
let cameraNode1 = SCNNode()
cameraNode1.camera = SCNCamera()
cameraNode1.camera?.motionBlurIntensity = 3 // MOTION BLUR
scene.rootNode.addChildNode(cameraNode1)
let move = CABasicAnimation(keyPath: "translation")
move.fromValue = NSValue(scnVector3: SCNVector3(x: 7, y: -5, z: 0))
move.toValue = NSValue(scnVector3: SCNVector3(x: 7, y: 5, z: 0))
move.duration = 0.5
move.repeatCount = 20
move.autoreverses = true
move.repeatCount = .infinity
let sphereNode1 = SCNNode()
sphereNode1.geometry = SCNSphere(radius: 2)
sphereNode1.addAnimation(move, forKey: "back and forth")
scene.rootNode.addChildNode(sphereNode1)
Works perfectly.

merge two sprite nodes in sprite kit

I am designing a sprite kit game where I want to merge two sprite nodes (rect shapes) together and then act and move them as one sprite node ?
I've been searching lot and I didn't find results
Is that possible in sprite kit ? and how can I do it ?
I'll appreciate any help, Thanks
Add one node as a child of the other. If you set it's node2.physicsbody.dynamic=NO; it will move as a single node. There will be separate physicsbodies but you can set them to the same category bitmask.
The answer linked here may help with notation: How to detect contact on different areas of a physicsbody
If you have two sprite nodes, you simply do this :
[firstSprite addChild:secondSprite]
Here is an answer with which I have achieved what you are looking for using SpriteKit (Swift)
First apply Physics to your scene
Example:
self.physicsWorld.gravity = CGVectorMake(0, -9.8)
physicsWorld.contactDelegate = self
let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sceneBody.friction = 1
self.physicsBody = sceneBody
self.physicsBody?.categoryBitMask = PhysicsCategory.Boarder
self.physicsBody?.contactTestBitMask = PhysicsCategory.None
self.physicsBody?.collisionBitMask = PhysicsCategory.Item
Second, Apply Physics to the two skspritenode's that you want to join together
Example
func mySpritetie1() {
spritetie1 = SKSpriteNode(imageNamed: "img1")
spritetie1.name = kAnimalNodeName
spritetie1.position = CGPoint(x: 170, y: 35)
spritetie1.size = CGSizeMake(36, 100)
spritetie1.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(22, 100))
spritetie1.physicsBody?.affectedByGravity = false
spritetie1.physicsBody?.categoryBitMask = PhysicsCategory.Item
spritetie1.physicsBody?.collisionBitMask = PhysicsCategory.Boarder
spritetie1.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
self.addChild(spritetie1)
}
func mySpritetie2() {
spritetie2 = SKSpriteNode(imageNamed: "img2")
spritetie2.name = kAnimalNodeName
spritetie2.position = CGPoint(x: 250, y: 60)
spritetie2.size = CGSizeMake(90, 79)
spritetie2.physicsBody = SKPhysicsBody(circleOfRadius: 25)
spritetie2.physicsBody?.affectedByGravity = false
spritetie2.physicsBody?.categoryBitMask = PhysicsCategory.Item
spritetie2.physicsBody?.collisionBitMask = PhysicsCategory.Boarder
spritetie2.physicsBody?.contactTestBitMask = PhysicsCategory.Monster
self.addChild(spritetie2)
}
Third, now joining them
Example
let joint = SKPhysicsJointFixed.jointWithBodyA(spritetie1.physicsBody!, bodyB: spritetie2.physicsBody!,
anchor: CGPointMake(CGRectGetMidX(spritetie1.frame), CGRectGetMinY(spritetie2.frame)))
self.physicsWorld.addJoint(joint)
This will join the two body at the anchor point you give.
Now you can animate any one of that (spritetie1 or spritetie2) using SKAction and the other will animate as if they are one and the same joined at the anchor point you defined.
If you feel this answer helped please do approve it. Hope it will help someone out there.
Please use this two link to learn about all thats in my code:
https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Physics/Physics.html
A very basic and good tutorial to learn about simulating physics https://www.youtube.com/playlist?list=PLa41xEuH5n_pwuNm7Z3L5qxDhVE0sOEqb
Thanks

Photoshop Automation of alignment of text layer with image

I have never scripted in photoshop before, so I am wondering if this is possible. The following is currently done manually for over than 300 files. The next time round is for 600 files, therefore I am looking into automating it.
Steps:
Make Image Size to 54pixels Hight and 500px Width -- Found that this is doable.
Align Image Left.
Create a text layer and insert text -- Found that this is doable.
Align Text layer 1px to the right of the image.
Trim empty space.
Would appreciate any help and pointers. Thanks.
This script will get you started: Note that in your request you didn't mention what what the original image was going to be and shrinking it to 500 x 54 is going to stretch it one way or another. Step 2, Align the image left, was omitted as you didn't mention what you are aligning this image to. I suspect you are dealing with a large image and what to shrink it down (as long as it's not smaller than 500 x 54) and work from there. I've also omitted stage 4 as I've hard coded the position of the text to be 1 px from the right hand edge (and it vertically centered with Arial font size 18)
Anhyoo.. you should be able to alter the script to your needs.
// set the source document
srcDoc = app.activeDocument;
//set preference units
var originalRulerPref = app.preferences.rulerUnits;
var originalTypePref = app.preferences.typeUnits;
app.preferences.rulerUnits = Units.POINTS;
app.preferences.typeUnits = TypeUnits.POINTS;
// resize image (ignoring the original aspect ratio)
var w = 500;
var h = 54;
var resizeRes = 72;
var resizeMethod = ResampleMethod.BICUBIC;
srcDoc.resizeImage(w, h, resizeRes, resizeMethod)
//create the text
var textStr = "Some text";
createText("Arial-BoldMT", 18.0, 0,0,0, textStr, w-1, 34)
srcDoc.activeLayer.textItem.justification = Justification.RIGHT
//set preference units back to normal
app.preferences.rulerUnits = originalRulerPref;
app.preferences.typeUnits = originalTypePref;
//trim image to transparent width
app.activeDocument.trim(TrimType.TRANSPARENT, true, true, true, true);
// function CREATE TEXT(typeface, size, R, G, B, text content, text X pos, text Y pos)
// --------------------------------------------------------
function createText(fface, size, colR, colG, colB, content, tX, tY)
{
// Add a new layer in the new document
var artLayerRef = srcDoc.artLayers.add()
// Specify that the layer is a text layer
artLayerRef.kind = LayerKind.TEXT
//This section defines the color of the hello world text
textColor = new SolidColor();
textColor.rgb.red = colR;
textColor.rgb.green = colG;
textColor.rgb.blue = colB;
//Get a reference to the text item so that we can add the text and format it a bit
textItemRef = artLayerRef.textItem
textItemRef.font = fface;
textItemRef.contents = content;
textItemRef.color = textColor;
textItemRef.size = size
textItemRef.position = new Array(tX, tY) //pixels from the left, pixels from the top
}
Everything you listed is doable in a script. I suggest you start by reading 'Adobe Intro To Scripting' in your ExtendScript Toolkit program files directory (e.g. C:\Program Files (x86)\Adobe\Adobe Utilities - CS6\ExtendScript Toolkit CS6\SDK\English)

endless background for the level

Could you please help with the endless background for the level?
I'm currently writing a primitive game using slick2d, the gameplay is similar to Mario.
I have two pictures - img1 and img2 (both 1280x480, while the screen resolution is 640x480).
Initially the X of the img2 is == (X of img1 + width of img1). I.e. its glued to the end of the img1.
When the img1 is out of the left screen border, it's X coordinate becomes img2X + imgWidth.
The logic looks right for me, but sometimes the pictures getting overstriked (a lot, approx 1/4 of the screen).
Is there any mistakes in the logic? Does the approach is good? Maybe there is more simple and right way to do so?
The pseudo-code look like below:
class BkgDrawer {
Image img1 = new Image("imgs/background/bkg1.png");
Image img2 = new Image("imgs/background/bkg2.png");
int img1Width = img1.getWidth(); //1280
int img2Width = img2.getWidth(); //1280
int screenResolution = game.getResolution; //640
Vector2f position1 = new Vector2f (0,0);
Vector2f position2 = new Vector2f (position1.x+img1.getWidth(), 0); //initially position2 is glued to the end of img1
public void render( ) {
if (position1.x + img1Width < 0) { //the img is over the left border of the screen
position1.x = position2.x + img2Width; //glue it to the end of img2
}
//the same for the img2
if (position2.x + img2Width < 0) { //the img is over the left border of the screen
position2.x = position1.x + img2Width; //glue it to the end of img2
}
img1.draw(position1.x, position1.y);
img2.draw(position2.x, position2.y);
//move coordinate to get the background moving.
position1.x -= MOVING_STEP;
position2.x -= MOVING_STEP;
}
}
Sorry for the lot of text and thanks
I have found only one bug and it will only have an affect if the two images have different widths: Your two if-statements use the same width img2Width
You may have noticed that you have duplicate code to handle the rendering and repositioning of each background. Might I suggest that you refactor the background code into a Background class that contains the background image, position, and and update method that repositions it by MOVING_STEP. You will avoid mistakes like the one I mentioned above.