I’m trying to create a Splaton effect on mobile. I’m trying to adapt the vertex paint technique used here
https://forum.unity.com/threads/how-do-they-do-the-painting-in-splatoon.460663/
because i need to count the painted area in real time as well in the less expensive way.
i created this code for the painting in c++
// Fill out your copyright notice in the Description page of Project Settings.
#include "ActorMeshPainter.h"
#include "DrawDebugHelpers.h"
// Sets default values for this component's properties
UActorMeshPainter::UActorMeshPainter()
{
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
// off to improve performance if you don't need them.
PrimaryComponentTick.bCanEverTick = false;
// ...
}
// Called when the game starts
void UActorMeshPainter::BeginPlay()
{
Super::BeginPlay();
SMComp = GetOwner()->FindComponentByClass< UStaticMeshComponent>();
UStaticMesh* SM = SMComp->GetStaticMesh();
if (SM)
{
//Get the vertex buffer from the 1st lod
//FPositionVertexBuffer* PositionVertexBuffer = &SM->RenderData->LODResources[0].VertexBuffers.PositionVertexBuffer;
//Make sure that we have at least 1 LOD
SMComp->SetLODDataCount(1, SMComp->LODData.Num());
FStaticMeshComponentLODInfo* LODInfo = &SMComp->LODData[0]; //We're going to modify the 1st LOD only
//Empty the painted vertices and assign a new color vertex buffer which will contain the new colors for each vertex
LODInfo->PaintedVertices.Empty();
LODInfo->OverrideVertexColors = new FColorVertexBuffer();
//We're going to use the LODResources to get the total number of vertices that the provided mesh has
FStaticMeshLODResources& LodResources = SM->RenderData->LODResources[0];
FColor fillColor = FColor::Black;
fillColor.A = 255;
//Since we know beforehand the number of elements we might as well reserve the memory now
if (colorArray.Num() == 0)
{
colorArray.Reserve(LodResources.GetNumVertices() - 1);
for (int32 i = 0; i < LodResources.GetNumVertices(); i++)
{
colorArray.Add(fillColor);
}
}
playerColorIndex.Init(-1, LodResources.GetNumVertices());
//Initialize the new vertex colros with the array we created above
LODInfo->OverrideVertexColors->InitFromColorArray(colorArray);
//Initialize resource and mark render state of object as dirty in order for the engine to re-render it
BeginInitResource(LODInfo->OverrideVertexColors);
SMComp->MarkRenderStateDirty();
}
}
// Called every frame
void UActorMeshPainter::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
// ...
}
void UActorMeshPainter::PaintSMVertices(FVector _hitLocation,int32 _playerColorIndex, FColor _paintColor,float _innerRadius,float _outerRadius)
{
if (!SMComp) return;
if (colorArray.Num() == 0)return;
//Get the static mesh that we're going to paint
UStaticMesh* SM = SMComp->GetStaticMesh();
if (SM)
{
//Get the vertex buffer from the 1st lod
//FPositionVertexBuffer* PositionVertexBuffer = &SM->RenderData->LODResources[0].VertexBuffers.PositionVertexBuffer;
//Make sure that we have at least 1 LOD
SMComp->SetLODDataCount(1, SMComp->LODData.Num());
FStaticMeshComponentLODInfo* LODInfo = &SMComp->LODData[0]; //We're going to modify the 1st LOD only
//Empty the painted vertices and assign a new color vertex buffer which will contain the new colors for each vertex
LODInfo->PaintedVertices.Empty();
LODInfo->OverrideVertexColors = new FColorVertexBuffer();
//We're going to use the LODResources to get the total number of vertices that the provided mesh has
FStaticMeshLODResources& LodResources = SM->RenderData->LODResources[0];
FVector tmPos, vexPos;
float tFactor = 1.0 / (_outerRadius - _innerRadius);
//UE_LOG(LogTemp, Warning, TEXT(" dist %f > %f color %s "), dist,diff, *colorArray*.ToString());
bool bSameColor = false;
for (int32 i = 0; i < LodResources.GetNumVertices(); i++)
{
tmPos = GetOwner()->GetTransform().InverseTransformPosition(_hitLocation);
vexPos = LodResources.VertexBuffers.PositionVertexBuffer.VertexPosition(i);
float dist = FVector::Dist(tmPos, vexPos);
if(dist>_outerRadius)continue;
int a = colorArray*.A;
colorArray* = _paintColor;
bSameColor = _playerColorIndex == playerColorIndex*;
playerColorIndex* = _playerColorIndex;
if (dist < _innerRadius)
{
colorArray*.A = 255;
}else
{
uint8 blobA = (uint8)(255 - 255 * (dist - _innerRadius)*tFactor);
if (blobA >= a) colorArray*.A = blobA;
// colorArray*.A = 0;
}
// RandomColorArray* = dist < 500? FColor::Red:FColor::White;
}
//Initialize the new vertex colros with the array we created above
LODInfo->OverrideVertexColors->InitFromColorArray(colorArray);
//Initialize resource and mark render state of object as dirty in order for the engine to re-render it
BeginInitResource(LODInfo->OverrideVertexColors);
SMComp->MarkRenderStateDirty();
}
}
but im an unable to achieve the shader code to avoid the blocky side