Creating custom shaders with SpriteKit and Swift - swift

For my game, I am trying to implement a custom shader that creates a zoom blur effect (I am quite new at using shaders so bear with me if I use improper terms). I have the .fsh shader file in my project, and I'm trying to apply it using SKShader.
I create the shader with this:
let testShader = SKShader(fileNamed: "ZoomBlur.fsh");
My shader takes two uniforms as input, blurCenter (vec2) and blurSize (float), so I try adding them to my shader:
testShader.addUniform(SKUniform(name: "blurSize", float: 50);
When trying to add blurCenter, there doesn't appear to be an initializer for a vec2, just float and texture. Looking at the class reference, it looks like I should be able to use this:
testShader.addUniform(SKUniform(name: "blurCenter", floatVector2: ...);
...But Xcode throws this error:
Incorrect argument label in call (have 'name:floatVector2:', expected 'name:float:')
How can I add a vec2 uniform? Am I completely missing something?

GLKVector2 is a union type, and Swift doesn't import those as of Beta 2. Any API that requires use of a non-imported type is itself not imported. Might not be a bad idea to file a bug.
For now, you'll need to work around this by writing your own C/ObjC functions/methods that forward to the non-imported API, and calling those from Swift via a bridging header.

Related

Unity, how to set the shader tag "DisableBatching" = "True" in the Shader Graph?

I am creating my first shader using the the Shader Graph, and I am seeing weird behaviour with my vertex positions when I have several objects in the scene using the Shader/Material I have created.
It looks like Unity is batching the objects, not sure yet what does mean, but it looks like I have to deactivate the batching so the vertex positions on my shader remain relative to the object and not to the objects.
Some open threads without solution:
https://forum.unity.com/threads/shader-graph-object-position-node-is-wrong-on-multiple-objects.744917/
https://answers.unity.com/questions/267794/mark-object-do-not-batch-it-dynamic.html
https://forum.unity.com/threads/how-to-add-a-pass-tag-to-a-shadergraph.865594/
Long story short: How can I add tags, and specifically the DisableBatching tag in my shader created using Shader Graph?
This does not answer your question, but I ended up doing what d2clon did in the forum post you posted, which is to duplicate the material at runtime through a script that you add to the object.
I'm posting this as an answer so people can try out something that worked (for me), without having to read all the threads you posted. I'm also wondering how to disable the batching flag myself, but this will suffice.
public class MaterialDuplicator : MonoBehaviour
{
void Awake()
{
Renderer renderer = gameObject.GetComponent<Renderer>();
renderer.material = new Material(renderer.material);
}
}

Why aren't Image and SpriteRenderer components inherited from one common base class?

I'm righting a script that loads some sprites and want to use it on both UI and in the game.
But there are two types of renderers for each and without any common base class, although they both have Sprite in common!
I want to use both Image and SpriteRenderer, so i want to write sth like this:
class SpriteLoader<T> where T: SomeRendererBaseClass {
T renderer;
void Load(){
renderer.sprite = GetSprite();
}
}
but to use "renderer.sprite" i have to specify T, for which i found no common base class.
If i'm gonna show game characters in UI i should load sprites on Image component, but in the game, i have to do the same behaviour but on SpriteRenderer, and as programmers we don't like duplicate codes.
Just because they both have a sprite doesn't mean anything.
You're going to just have to deal with the fact that the two classes aren't related to each other in the way that you'd like. This is no different than having a Player class that has a name property and trying to find a common parent class with GameObject ("it has a name too!")
The two classes have nothing else in common and should not inherit from some common ancestor (beyond whatever ancestor they do share).
At least they should have a common interface. I've seen that Unity API doesn't use interface at there best like .Net Does

How to access custom shader properties and fields via GetProperties / PropertyInfo?

I have a method that takes any object as an argument and it should go through the properties, whatevery they are. I'm trying to get properties for a custom shader (created with ShaderForge). This is the method:
public void save(object objectToSave) {
var newProperties = new List<PropertyInfo>(objectToSave.GetType().GetProperties());
foreach (PropertyInfo property in newProperties)
{
object value = property.GetValue(objectToSave, null);
}
}
When I pass an object of type Material (I'm passing the RenderSettings.skybox in my tests) with a custom shader as an argument, I get this error:
Material doesn't have a color property '_Color'
Maybe this is because objectToSave.GetType() returns the type Material instead of the custom parameters implemented by ShaderForge shader (which doesn't implement _Color). How can I tell the method this is a Material with custom shader so it doesn't try to find the regular fields and properties? How to make it get a list of the actual properties and fields?
When I open the material in Unity, it has these parameters. How do I access them via GetProperties?
UnityEditor class has ShaderUtil, which contains the following methods:
GetPropertyCount - Get the number of properties in Shader s.
GetPropertyDescription - Get the description of the shader propery at index propertyIdx of Shader s.
GetPropertyName - Get the name of the shader propery at index propertyIdx of Shader s.
GetPropertyType - Get the ShaderProperyType of the shader propery at index propertyIdx of Shader s.
GetRangeLimits - Get Limits for a range property at index propertyIdx of Shader s.
GetTexDim - Gets texture dimension of a shader property.
IsShaderPropertyHidden - Is the shader propery at index propertyIdx of Shader s hidden?
To use it, you include "using UnityEditor" in your script and then access it by typing ShaderUtil.(methodname).
With these methods you can iterate through the custom shader properties. It's weird that you can't do this with GetProperties like you do on types, but this worked for me.
The type RANGE was a mystery to me, but what it does is it returns a float value of the actual value and ALSO the min and max values of the parameter so you know what its range is (because it's not a known type).
Please note that this is only for editor, so you have to use conditional #if XXXXX conditions around it, because UnityEditor class and this method won't work runtime.
Unity documentation on ShaderUtil: https://docs.unity3d.com/ScriptReference/ShaderUtil.html

(UE4) Is there a method of getting all actors in camera view?

Like the title says, i want to be able to get all actors that are within the camera view in Unreal Engine 4.
I have thought of two ways i could do this: 1) using a shape trace in the form of a "boxtracebyobject" which works but seems to be glitchy at times and has trouble recognizing multiple overlapping actors. 2) using a "BoxOverlappingActors", though i havent quite figured out how to use it yet.
If anyone knows of a proper method to getting actors in cameria view, my ears are open!
Update
A much better answer has been posted on Unreal Answers by Rama:
Use the AActor::GetLastRenderTime() to find out for each actor when last drawn or UPrimitiveComponent::LastRenderTime for the primitive itself. His answer explains how you can use this.
Original answer:
As you suggested, it seems weird that you would have to do something to do with collision volumes when Unreal must be checking to do culling so I found the following method to query that information:
First we have to create a FSceneView from the camera. This code is taken from the UE Answers question.
APlayerCameraManager* Manager = World->GetFirstPlayerController()->PlayerCameraManager;
ULocalPlayer* LocalPlayer = World->GetFirstLocalPlayerFromController();
FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
LocalPlayer->ViewportClient->Viewport,
World->Scene,
LocalPlayer->ViewportClient->EngineShowFlags)
.SetRealtimeUpdate(true));
FVector ViewLocation;
FRotator ViewRotation;
FSceneView* SceneView = LocalPlayer->CalcSceneView(&ViewFamily, /*out*/ ViewLocation, /*out*/ ViewRotation, LocalPlayer->ViewportClient->Viewport);
Once we've created the view we can iterate through all primitive components (includes meshes) and then we can use the bounds from the SceneProxy of the Static Mesh and the bounds of the view to do our own culling.
for (TObjectIterator<UPrimitiveComponent> ScenePrimitsItr; ScenePrimitsItr; ++ScenePrimitsItr)
{
// Using the Object iterator so we have to skip objects not in the
// relevant world
if (ScenePrimitsItr->GetWorld() == World)
{
FPrimitiveSceneProxy* Proxy = ScenePrimitsItr->SceneProxy;
if (Proxy)
{
bool bIsShown =
SceneView->ViewFrustum.IntersectSphere(Proxy->GetBounds().Origin, Proxy->GetBounds().SphereRadius)||
SceneView->ViewFrustum.IntersectBox(Proxy->GetBounds().Origin, Proxy->GetBounds().BoxExtent);
}
}
}
The frustrum check came from SceneVisibility.cpp in the method FrustumCull This method isn't ideal as a) involves duplicating that check and b) performing the test twice. However, I couldn't find a way to actually query the result. It appears to be stored in a bit array in the FViewInfo. Unfortunately this info is not exposed outside of the renderer module.
You could try this to create an array of actors:
But I don't know if it's good performance wise if there are too many actors of the class you want.

How do you dynamically render quads in UE4?

There are some hand wavey answers for this on answers.unrealengine.com, but they seem to lack any detail or examples.
Specifically, and in detail, if you wanted to implement a set of dynamic textured quads which rendered in the 3d game world, how would you do it?
For use case, consider a 2dish side scroller that uses Spriter animations. The 2D animations are loaded from XML easily enough, but how do you then render this 2D set of textured, rotated and scaled quads dynamically on the scene?
Is the problem you are facing concern spawning the mesh or with obtaining the right orientation? (i.e. orthographic projection, facing the camera)
Spawning the mesh is easy enough, can be done either through Blueprints or in code.
In Blueprints, you would set up certain preconditions and then choose to spawn actors based on the conditions.
The actual coding solution would look much the same.
If it is regarding orientation, then this answer will be of help to you, found on the UnrealEngine forums:
https://answers.unrealengine.com/questions/62126/how-do-i-render-a-dynamic-mesh-with-orthographic-p.html
EDIT:
After much hair pulling and documentation surfing, here's the code that made things work.
ADynamicMeshSpawner::ADynamicMeshSpawner()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Using a SphereComponent is not particularly necessary or relevant, but the cube refused to spawn without a root component to attach to, or so I surmise. Yay Unreal. =/
USphereComponent* CubeComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
RootComponent = CubeComponent;
CubeComponent->InitSphereRadius(40.0f);
CubeComponent->SetCollisionProfileName(TEXT("Pawn"));
// Create and position a mesh component so we can see where our cube is
UStaticMeshComponent* CubeVisual = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("VisualRepresentation"));
CubeVisual->AttachTo(RootComponent);
static ConstructorHelpers::FObjectFinder<UStaticMesh> SphereVisualAsset(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube'"));
if (SphereVisualAsset.Succeeded())
{
CubeVisual->SetStaticMesh(SphereVisualAsset.Object);
CubeVisual->SetRelativeLocation(FVector(-200.0f, 0.0f, 100.0f));
CubeVisual->SetWorldScale3D(FVector(2.0f));
}
// Create a material to be applied on the StaticMeshComponent
static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/StarterContent/Materials/M_Tech_Hex_Tile_Pulse.M_Tech_Hex_Tile_Pulse'"));
if (Material.Object != NULL)
{
TheMaterial = (UMaterial*)Material.Object;
}
CubeVisual->SetMaterial(0, TheMaterial);
}
The headerfile looks like this:
UCLASS()
class MYPROJECT_API ADynamicMeshSpawner : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ADynamicMeshSpawner();
// Called when the game starts or when spawned
virtual void BeginPlay() override;
// Called every frame
virtual void Tick( float DeltaSeconds ) override;
// Pointer to the material that needs to be used
UMaterial* TheMaterial;
};
The final output looked like this in the editor:
I set it up so that an instance of my class 'DynamicMeshSpawner' would be spawned everytime I hit 'P' on the keyboard. When the instance of this class is created, it calls the constructor, which spawns the cube with the material applied. I did the class instance spawning stuff in BluePrints using the SpawnActor node.
The conditions that you require for spawning stuff would obviously depend on the application.
This method works for normal Materials but NOT Material Instances. I believe you would have to make changes to the type of TheMaterial, the ConstructorHelper call, and the cast from the material reference into TheMaterial in order to make it function.
I'm confident that this would work with Animated materials as well, meaning that the 2D animations would need to be converted into a Material of some sort.
Perhaps the link below would help.
https://forums.unrealengine.com/showthread.php?6744-Flipbook-material-to-recreate-an-animated-gif
EDIT 2:
Below are a very good set of examples on how to procedurally create objects in Unreal. Leaving it here for posterity and in case anyone comes looking.
https://github.com/SiggiG/ProceduralMeshes/