Files
2024-11-20 15:21:28 +01:00

430 lines
12 KiB
GLSL

// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
Shader "Hidden/Gaia/BaseOperation" {
Properties {
//The main texture
_MainTex ("Main Texture", any) = "" {}
//The global mask texture
_GlobalMaskTex ("Global Mask Texture", any) = "" {}
//Flag to determine whether the image mask affects the total stamp result (global) or the stamp itself only (local)
// _ImageMaskIsGlobal("Image Mask is Global", Float) = 0
//Flag to determine whether the image mask is inverted or not
//_InvertImageMask("Invert Image Mask", Float) = 0
//1-pixel high gradient texture to bring the distance mask curve information in the shader
//_DistanceMaskTex ("Distance Mask Texture", any) = "" {}
//Flag to determine whether the distance mask affects the total stamp result (global) or the stamp itself only (local)
//_DistanceMaskIsGlobal("Distance Mask is Global", Float) = 0
//1-pixel high gradient texture to bring the transform height curve information in the shader
//_TransformHeightTex ("Transform Height Texture", any) = "" {}
//the y position of the stamp, in 0 to 1 relative to terrain height
_yPos ("y Position", Float) = 0
//the base level of the stamp
_BaseLevel ("Base Level", Float) = 0
//Flag to determine whether the base should be stamped or not
_StampBase("Stamp Base", Float) = 0
//Flag to determine whether the stamp should be adjusted automatically to the terrain when a base level is used
_AdaptiveBase("Adaptive Base", Float) = 0
//Blend strength from 0 to 1 for the blend terrain pass
//_BlendStrength ("Blend Strength", Float) = 0
//Erosion texture, contains the original heightmap changed by Erosion
//_ErosionTex("Erosion Texture", any) = ""
}
SubShader {
ZTest Always Cull Off ZWrite Off
CGINCLUDE
#include "UnityCG.cginc"
#include "TerrainTool.cginc"
sampler2D _MainTex;
sampler2D _GlobalMaskTex;
//float _ImageMaskIsGlobal;
//float _InvertImageMask;
//sampler2D _DistanceMaskTex;
//float _DistanceMaskIsGlobal;
//sampler2D _TransformHeightTex;
float _yPos;
float _BaseLevel;
float _StampBase;
float _AdaptiveBase;
float _BlendStrength;
//sampler2D _ErosionTex;
float4 _MainTex_TexelSize; // 1/width, 1/height, width, height
sampler2D _BrushTex;
float4 _BrushParams;
#define BRUSH_STRENGTH (_BrushParams[0])
#define BRUSH_TARGETHEIGHT (_BrushParams[1])
struct appdata_t {
float4 vertex : POSITION;
float2 pcUV : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 pcUV : TEXCOORD0;
};
v2f vert(appdata_t v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.pcUV = v.pcUV;
return o;
}
float ApplyBrush(float height, float brushStrength)
{
float targetHeight = BRUSH_TARGETHEIGHT;
if (targetHeight > height)
{
height += brushStrength;
height = height < targetHeight ? height : targetHeight;
}
else
{
height -= brushStrength;
height = height > targetHeight ? height : targetHeight;
}
return height;
}
float GetFinalHeight(v2f i)
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
// out of bounds multiplier
float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
//value from the image mask texture multiplied with the multiplicator
float globalMaskValue = UnpackHeightmap(tex2D(_GlobalMaskTex, brushUV));
float brushShape = oob * UnpackHeightmap(tex2D(_BrushTex, brushUV));
float finalBrushLevel = BRUSH_STRENGTH * brushShape; // * transformheight * localMaskValue;
//only return the height value changed by the brush if we are actually in bounds
//otherwise we get an ugly square base when rotating stamps
if(all(saturate(brushUV) == brushUV))
{
float finalResult = _yPos + finalBrushLevel;
return clamp(((_yPos + finalBrushLevel) * globalMaskValue) + height * (1.0f - globalMaskValue), 0, 1.0f);
}
else
{
return height;
}
}
ENDCG
Pass // 0 raise heights
{
Name "Raise Heights"
CGPROGRAM
#pragma vertex vert
#pragma fragment RaiseHeight
float4 RaiseHeight(v2f i) : SV_Target
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float finalheight = GetFinalHeight(i);
//process baseLevel
if(_StampBase>0 || finalheight>_BaseLevel)
{
if(!all(saturate(brushUV) == brushUV))
{
_BaseLevel = 0;
}
if(_AdaptiveBase && _BaseLevel > height)
{
finalheight -= _BaseLevel - height;
}
else
{
finalheight = clamp (finalheight, _BaseLevel,0.5f);
}
}
else
{
finalheight = 0;
}
if(finalheight>=height)
return PackHeightmap(finalheight);
else
return PackHeightmap(height);
}
ENDCG
}
Pass // 1 Lower heights
{
Name "Lower Heights"
CGPROGRAM
#pragma vertex vert
#pragma fragment LowerHeight
float4 LowerHeight(v2f i) : SV_Target
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float finalheight = GetFinalHeight(i);
//process baseLevel
if(_StampBase>0 || finalheight<_BaseLevel)
{
if(!all(saturate(brushUV) == brushUV))
{
_BaseLevel = 0.5f;
}
if(_AdaptiveBase && _BaseLevel < height)
{
finalheight += height - _BaseLevel;
}
else
{
finalheight = clamp (finalheight, 0.0f, _BaseLevel);
}
}
else
{
finalheight = 0.5f;
}
if(finalheight<=height)
return PackHeightmap(finalheight);
else
return PackHeightmap(height);
}
ENDCG
}
Pass // 2 Blend Heights
{
Name "Blend Heights"
CGPROGRAM
#pragma vertex vert
#pragma fragment BlendHeight
float4 BlendHeight(v2f i) : SV_Target
{
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float finalheight = GetFinalHeight(i);
return PackHeightmap((finalheight * _BlendStrength) + (height * (1-_BlendStrength)));
}
ENDCG
}
Pass // 3 Set Height
{
Name "Set Height"
CGPROGRAM
#pragma vertex vert
#pragma fragment SetHeight
float4 SetHeight(v2f i) : SV_Target
{
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float finalheight = GetFinalHeight(i);
return PackHeightmap(finalheight);
}
ENDCG
}
Pass // 4 Add Height
{
Name "Add Height"
CGPROGRAM
#pragma vertex vert
#pragma fragment AddHeight
float4 AddHeight(v2f i) : SV_Target
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
if(!oob)
{
return height;
}
float finalheight = GetFinalHeight(i);
//add the existing height
finalheight += height;
//process baseLevel
if(_StampBase>0 || finalheight>_BaseLevel)
{
if(!all(saturate(brushUV) == brushUV))
{
_BaseLevel = 0;
}
if(_AdaptiveBase && _BaseLevel > height)
{
finalheight -= _BaseLevel - height;
}
else
{
finalheight = clamp (finalheight, _BaseLevel,0.5f);
}
}
else
{
finalheight = 0;
}
if(finalheight>=height)
return PackHeightmap(finalheight);
else
return PackHeightmap(height);
}
ENDCG
}
Pass // 5 Subrtract Height
{
Name "Subtract Height"
CGPROGRAM
#pragma vertex vert
#pragma fragment SubtractHeight
float4 SubtractHeight(v2f i) : SV_Target
{
//invert ypos for better usability
_yPos*=-1;
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
if(!oob)
{
return height;
}
float finalheight = GetFinalHeight(i);
//subtract the existing height
finalheight = height - finalheight;
//process baseLevel
if(_StampBase>0 || finalheight<_BaseLevel)
{
if(!all(saturate(brushUV) == brushUV))
{
finalheight = height;
}
else
{
if(_AdaptiveBase && _BaseLevel < height)
{
finalheight += height - _BaseLevel;
}
else
{
finalheight = clamp (finalheight, 0.0f, _BaseLevel);
}
}
}
else
{
finalheight = height;
}
if(finalheight<=height)
return PackHeightmap(finalheight);
else
return PackHeightmap(height);
}
ENDCG
}
//This pass is special in so far as it relies on the heightmap changes being passed in
//_MainTex, it will not alter the heightmap by itself
Pass // 6 Effects
{
Name "Effects"
CGPROGRAM
#pragma vertex vert
#pragma fragment Effects
float4 Effects(v2f i) : SV_Target
{
float2 brushUV = PaintContextUVToBrushUV(i.pcUV);
float2 heightmapUV = PaintContextUVToHeightmapUV(i.pcUV);
float height = UnpackHeightmap(tex2D(_MainTex, heightmapUV));
float finalheight = GetFinalHeight(i);
return PackHeightmap(finalheight);
//float erodedHeight = UnpackHeightmap(tex2D(_ErosionTex, heightmapUV));
// out of bounds multiplier
/*float oob = all(saturate(brushUV) == brushUV) ? 1.0f : 0.0f;
//value from the image mask texture multiplied with the multiplicator
float imageMask = UnpackHeightmap(tex2D(_ImageMaskTex, brushUV));
if(_InvertImageMask>0)
{
//Invert the imagemask
imageMask=1.0f-imageMask;
}
float distanceMask = UnpackHeightmap(tex2D(_DistanceMaskTex, smoothstep(0,sqrt(1)/2,distance(brushUV,float2(0.5f,0.5f)))));
float globalMaskValue = 1.0f;
globalMaskValue *= imageMask;
globalMaskValue *= distanceMask;*/
//only return the height value changed by the brush if we are actually in bounds
//otherwise we get an ugly square base when rotating stamps
/*if(all(saturate(brushUV) == brushUV))
{
return PackHeightmap(clamp(erodedHeight, 0, 0.5f));
}
else
{
return PackHeightmap(height);;
}*/
}
ENDCG
}
}
Fallback Off
}