How do I define a custom preprocessor macro in my shader? - unity3d

I'm trying to use a preprocessor macro in my custom shader so it performs a different step if it's in the Unity Editor:
#if defined(IS_UNITY_EDITOR)
// something
#else
// other thing
#endif
To achieve this, I'm trying the Shader.EnableKeyword() method in a MonoBehavior:
if (Application.isEditor) {
Shader.EnableKeyword("IS_UNITY_EDITOR");
}
However, it looks like my shader is being compiled before the MonoBehavior can check if it's in the unity editor. I've tried running it on Start(), on Awake(), OnEnable() but the shader never receives the IS_UNITY_EDITOR definition. How can I define IS_UNITY_EDITOR in my shader before the shader is compiled?

Just stumbled upon this doc page that explains how multi compile works. In order to be able to create two branches, I have to tell the compiler I'll be using the IS_UNITY_EDITOR keyword by writing a #pragma multi_compile line:
SubShader {
Pass {
CGPROGRAM
#pragma multi_compile __ IS_UNITY_EDITOR
#pragma vertex vertShader
#pragma fragment fragShader
// ...
The double underscore __ means one version of the shader will have IS_UNITY_EDITOR and the other version will have nothing defined.

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);
}
}

Blueprints reset variable values every compile

Using UE 4.23.1
Basically, i'm following a very simple tutorial.
I've extended multiple base classes, and it seems in ANY of my extensions, the variables for all components (e.g., physics, collision, static mesh, etc) all reset EVERY TIME i do a full project compile.
For instance:
I've extended UStaticMeshComponent with custom functionality (TankTrack). I set the static mesh component, and adjust the Collision to "Simulation GEnerates Hit Events". This sticks, but as soon as i recompile the entire game, EVERYTHING is reverted to its original state. Help!!
Note: This happens on variables I declare (and make UPROPERTY(EditAnywhere)) as well as those defaulted to that component type (e.g., Physics, collision, etc)
Here is an example with a UActorComponent called "Grabber". Only the .h file should matter if the issue is with blueprint?
If i change maxPickupWeightKg, then recompile, the change does NOT persist.
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "Grabber.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class FPSExample_API UGrabber : public UActorComponent
{
GENERATED_BODY()
public:
// Sets default values for this component's properties
UGrabber();
protected:
// Called when the game starts
virtual void BeginPlay() override;
public:
// Called every frame
virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
/// Grabber functions and variables
UPROPERTY(EditAnywhere, Category = "Grab Setup")
float maxPickupWeightKg = 50.f;
};
.cpp Constructor is nothing fancy:
#include "Grabber.h"
#include "Math/UnrealMathUtility.h"
#include "CollisionQueryParams.h"
#include "Engine/EngineTypes.h"
#include "Engine/World.h"
#include "Components/ActorComponent.h"
#include "Components/PrimitiveComponent.h"
#include "GameFramework/Actor.h"
#define OUT
// Sets default values for this component's properties
UGrabber::UGrabber()
{
PrimaryComponentTick.bCanEverTick = true;
}
.
.
.
My Hierarchy for the FPS Blueprint this is on:
FirstPersonCharacter(self)
-
CapsuleComponent (This is where all the player meshes are)
-
CharacterMovement
PhysicsHandle
Grabber
Thanks !
I am placing this here because I've had the same issue. After many hours of testing and research, I found this answer in the unreal forums. I hope it helps.
https://forums.unrealengine.com/development-discussion/c-gameplay-programming/1530690-uproperty-value-keeps-resetting-on-every-compile?p=1651757#post1651757
Using 4.25.3 this has still not been fixed. My workaround is to create a child blueprint of the component and use that on my Actor. This way the property values do not get reset when compiling.

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

Creating custom shaders with SpriteKit and 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.

Errors about the macro defination and header files

I'm working on a project based on MSP430 microchip, using IAR compiler. Here is the simplified problem:
In my project I have 3 files:
In clock.h:
#define MCLK_8MHZ
void clk_init(void);
In clock.c:
#include "clock.h"
void clk_init(void)
{
#ifdef MCLK_8MHZ
#define delay_ms(x) __delay_cycles((long)(1000000*(double)x/1000.0))
#endif
#ifdef MCLK_12MHZ
...
#endif
}
In main.c:
#include "clock.h"
clk_init();
delay_ms(5);
And the compiler would say function "delay_ms" declared implicitly
I think it mistook the delay_ms() as a function instead of a macro. Sure I could define it as a real function. But I thought it would damage the accuracy of time controlling.
How to solve this problem?
Do you need quotes around your include in main.c like:
#include "clock.h"
?
If that is your only warning, it's something else.