I need a way to censore part of characters' bodies like Cyberpunk 2077.this is mean I want to apply Image effect only to specific parts of bodies that you can see in the below Image:
1 Answer
Solution 1
Using GrabPass
GrabPass is a special pass type - it grabs the contents of the screen where the object is about to be drawn into a texture. This texture can be used in subsequent passes to do advanced image based effects.
Just GrabPass { } grabs the current screen contents into a texture. The texture can be accessed in further passes by _GrabTexture name. Note: this form of grab pass will do the time-consuming screen grabbing operation for each object that uses it.
GrabPass { "TextureName" }
grabs the current screen contents into a texture, but will only do that once per frame for the first object that uses the given texture name. The texture can be accessed in further passes by the given texture name. This is a more performant method when you have multiple objects using GrabPass in the scene
so first you should grab behind of object:
GrabPass{ "_GrabTexture" }
Initializing position and grab position in shader:
v2f vert(appdata_base v) {
v2f o;
// use UnityObjectToClipPos from UnityCG.cginc to calculate
// the clip-space of the vertex
o.pos = UnityObjectToClipPos(v.vertex);
// use ComputeGrabScreenPos function from UnityCG.cginc
// to get the correct texture coordinate
o.grabPos = ComputeGrabScreenPos(o.pos);
return o;
}
pixelating results:
float _PixelSize;
sampler2D _GrabTexture;
float4 frag(v2f IN) : COLOR
{
float2 steppedUV = IN.grabPos.xy / IN.grabPos.w;
steppedUV /= _PixelSize / _ScreenParams.xy;
steppedUV = round(steppedUV);
steppedUV *= _PixelSize / _ScreenParams.xy;
//Sampling GrabTexture according to screen capture positon, tex2DProj is equivalent to tex2D (grabPos.xy / grabpos.w)
return tex2D(_GrabTexture, steppedUV);
}
so this is our pixelate shader:
Shader "Custom/Pixelate"
{
Properties
{
_PixelSize("Pixel Size", Float) = 10
}
SubShader
{
Tags{ "Queue" = "Transparent" "IgnoreProjector" = "True" }
Blend Off
Lighting Off
Fog{ Mode Off }
ZWrite Off
LOD 200
Cull Off
GrabPass{ "_GrabTexture" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 grabPos : TEXCOORD0;
};
v2f vert(appdata_base v) {
v2f o;
// use UnityObjectToClipPos from UnityCG.cginc to calculate
// the clip-space of the vertex
o.pos = UnityObjectToClipPos(v.vertex);
// use ComputeGrabScreenPos function from UnityCG.cginc
// to get the correct texture coordinate
o.grabPos = ComputeGrabScreenPos(o.pos);
return o;
}
float _PixelSize;
sampler2D _GrabTexture;
float4 frag(v2f IN) : COLOR
{
float2 steppedUV = IN.grabPos.xy / IN.grabPos.w;
steppedUV /= _PixelSize / _ScreenParams.xy;
steppedUV = round(steppedUV);
steppedUV *= _PixelSize / _ScreenParams.xy;
//Sampling GrabTexture according to screen capture positon, tex2DProj is equivalent to tex2D (grabPos.xy / grabpos.w)
return tex2D(_GrabTexture, steppedUV);
}
ENDCG
}
}
}
Solution 2
Using two cameras that I explained before
1.Make secondary camera
2.On second camera, in Clear Flags set it to Don't clear
Solution 3
Using Command Buffer
we know, that the GPU can work on stuff in parallel. But what’s about the communication between CPU and GPU? Does the CPU has to wait until the GPU finished the job before it can receive new commands?
No! because this communication would create bottlenecks (e.g. when the CPU can’t deliver commands fast enough) and would make parallel working impossible.bottleneck, as for how it is named, occurs when there is a limit on how much data is being sent for processing or how much data can be processed at the same time.
The solution is a list where commands can be added by the CPU and read by the GPU – independent from each other! This list is called: Command Buffer.
What is Command Buffer?
Command buffers hold list of rendering commands ("set render target, draw mesh, ..."). They can be set to execute at various points during camera rendering (see Camera.AddCommandBuffer), light rendering (see Light.AddCommandBuffer) or be executed immediately (see Graphics.ExecuteCommandBuffer).
How it work?
The command buffer makes it possible that CPU and GPU can work independent from each other. When the CPU wants something to be rendered, it can push that command into the queue and when the GPU has free resources, it can take the command out of the list and execute it (but the list works as a FIFO – so the GPU can only take the oldest item in the list (which was first/earlier added than all others) and work on that).
By the way: there are different commands possible. One example is a draw call, another would be to change the render state.
https://vulkan-tutorial.com/Drawing_a_triangle/Drawing/Command_buffers
https://developer.nvidia.com/engaging-voyage-vulkan
Let's Start to use command buffer Masking part of character with sphere:
Stencil
{
Ref 1
Comp Always
Pass Replace
}
create a command:
var commandBuffer = new CommandBuffer();
commandBuffer.name = "pixelate";
Temporarily copy the rendering result to the Render Texture:
int tempTextureIdentifier = Shader.PropertyToID("_PostEffect");
commandBuffer.GetTemporaryRT(tempTextureIdentifier, -1, -1);
commandBuffer.Blit(BuiltinRenderTextureType.CameraTarget, tempTextureIdentifier);
Apply the rendering result to the material that you want to apply image effects:
commandBuffer.Blit(tempTextureIdentifier, BuiltinRenderTextureType.CameraTarget, material);
Release temporary render texture:
commandBuffer.ReleaseTemporaryRT(tempTextureIdentifier);
Register where you want to add the command buffer Below is a high-level overview of how Cameras use the Forward or Deferred pipeline to render a Scene in Unity.
- Black boxes represent an internal Unity process. Blue boxes represent
- a CameraEvent where you can add Command Buffers.
camera.AddCommandBuffer(CameraEvent.BeforeImageEffects, commandBuffer);
add Image effects to where Ref is equal to 1
Stencil
{
Ref 1
Comp Equal
}
adding color to pixelated area
More Examples!
pixelating specific objects
grayscale where that is not equal to Ref 1
Stencil
{
Ref 1
Comp NotEqual
}
References: