Baking Update

This commit is contained in:
Josef 2025-05-07 14:18:01 +02:00
parent 7b68cc7f1f
commit ae58b96fd8
67 changed files with 2094 additions and 284 deletions

View File

@ -1,22 +1,38 @@
shader_type spatial; shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_disabled,diffuse_burley,specular_schlick_ggx; render_mode blend_mix,depth_draw_opaque,cull_disabled, unshaded;
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Math.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Transform.gdshaderinc"
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc"
uniform vec4 albedo_color : source_color; uniform vec4 albedo_color : source_color;
uniform sampler2D albedo_texture : source_color; uniform sampler2D albedo_texture : source_color;
uniform sampler2D normal_texture : source_color; uniform sampler2D normal_texture : source_color;
uniform bool use_normalmap = false; uniform bool use_normalmap = false;
uniform bool uncompressNormalMap = true;
uniform bool use_alpha_texture = false; uniform bool use_alpha_texture = false;
uniform bool useCustomNormals = true;
uniform float alpha_scissor_threshold : hint_range(0,1); uniform float alpha_scissor_threshold : hint_range(0,1);
uniform float normal_scale : hint_range(-5,5); uniform float normal_scale : hint_range(-5,5) = 1;
uniform vec3 uv1_scale; uniform vec3 uv1_scale = vec3( 1, 1, 1 );
uniform vec3 uv1_offset; uniform vec3 uv1_offset;
varying vec3 vertexNormal;
varying vec3 vertexTangent;
varying vec3 vertexBinormal;
uniform float binormalMix:hint_range(0,1);
void vertex() void vertex()
{ {
UV = UV * uv1_scale.xy + uv1_offset.xy; UV = UV * uv1_scale.xy + uv1_offset.xy;
vertexNormal = localToViewDirection( NORMAL, MODELVIEW_NORMAL_MATRIX );
vertexTangent = localToViewDirection( TANGENT, MODELVIEW_NORMAL_MATRIX );
vertexBinormal = cross( vertexNormal, vertexTangent );
//NORMAL = localToViewDirection( NORMAL, MODELVIEW_NORMAL_MATRIX );
} }
void fragment() void fragment()
@ -24,18 +40,41 @@ void fragment()
vec2 base_uv = UV; vec2 base_uv = UV;
vec4 albedo = texture( albedo_texture, base_uv ) * albedo_color; vec4 albedo = texture( albedo_texture, base_uv ) * albedo_color;
vec4 normal_tex = texture( normal_texture, base_uv ); vec4 normal_tex = texture( normal_texture, base_uv );
vec3 RENDER_NORMAL = useCustomNormals ? vertexNormal : NORMAL;
if ( ! useCustomNormals && ! FRONT_FACING )
{
RENDER_NORMAL = - RENDER_NORMAL;
}
//ALBEDO = mix( vertexNormal, NORMAL, normalMix );
// 0.5 + -1.0 == -1.0 + 0.5 // 0.5 + -1.0 == -1.0 + 0.5
//ALBEDO = vec3(1.0 - NORMAL.y, 1.0 - NORMAL.x, - NORMAL.z)* 0.5; //ALBEDO = vec3(1.0 - NORMAL.y, 1.0 - NORMAL.x, - NORMAL.z)* 0.5;
if ( use_normalmap ) if ( use_normalmap )
{ {
vec3 normalmap; vec3 normalmap;
normalmap.xy = normal_tex.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); if ( uncompressNormalMap )
NORMAL = normalize(mix(NORMAL, TANGENT * normalmap.x + BINORMAL * normalmap.y + NORMAL * normalmap.z, normal_scale)); {
normalmap.xy = normal_tex.xy * 2.0 - 1.0;
normalmap.z = sqrt( max( 0.0, 1.0 - dot( normalmap.xy, normalmap.xy ) ) );
}
else
{
normalmap = normal_tex.xyz * 2.0 - 1.0;
}
vec3 textureNormal = vertexTangent * normalmap.x +
vertexBinormal * normalmap.y +
vertexNormal * normalmap.z;
RENDER_NORMAL = normalize( mix( RENDER_NORMAL, textureNormal, normal_scale ) );
//NORMAL = textureNormal;
} }
ALBEDO = vec3( -NORMAL.x, NORMAL.y, -NORMAL.z) * 0.5 + 0.5; vec3 rn = vec3( RENDER_NORMAL.x, RENDER_NORMAL.y, RENDER_NORMAL.z ) * 0.5 + 0.5;
ALBEDO = rn;
if ( use_alpha_texture ) if ( use_alpha_texture )
{ {

View File

@ -12,8 +12,8 @@ namespace Rokojori
public partial class Baker:Node public partial class Baker:Node
{ {
[ExportToolButton( "Update")] [ExportToolButton( "Apply Camera Settings")]
public Callable BakeButton => Callable.From( () => Bake() ); public Callable ApplyCamerySettingsButton => Callable.From( () => ApplyCameraSettings() );
[Export] [Export]
public bool updateAlways = false; public bool updateAlways = false;
@ -77,11 +77,11 @@ namespace Rokojori
return; return;
} }
Bake(); ApplyCameraSettings();
} }
public void Bake() public void ApplyCameraSettings()
{ {
if ( viewport == null || target == null || camera == null ) if ( viewport == null || target == null || camera == null )
{ {
@ -91,6 +91,12 @@ namespace Rokojori
if ( autoTargetPivot ) if ( autoTargetPivot )
{ {
Box3 box = target.GetWorldBounds(); Box3 box = target.GetWorldBounds();
if ( box == null )
{
return;
}
targetPivot = new Vector3( 0, -box.center.Y, 0 ); targetPivot = new Vector3( 0, -box.center.Y, 0 );
} }

View File

@ -0,0 +1,72 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class BakingOutput:Resource
{
[Export]
public BakingTarget bakingTarget;
[Export]
public Texture2D bakedTexture;
public static BakingOutput With( BakingTargetType type, Texture2D texture2D )
{
var bo = new BakingOutput();
bo.bakingTarget = new BakingTarget();
bo.bakingTarget.type = type;
bo.bakedTexture = texture2D;
return bo;
}
public static BakingOutput Lit( Texture2D texture2D = null )
{
return With( BakingTargetType.Lit, texture2D );
}
public static BakingOutput Albedo( Texture2D texture2D = null )
{
return With( BakingTargetType.Albedo, texture2D );
}
public static BakingOutput Normals( Texture2D texture2D = null )
{
return With( BakingTargetType.Normals, texture2D );
}
public static BakingOutput Depth( Texture2D texture2D = null )
{
return With( BakingTargetType.Depth, texture2D );
}
public static BakingOutput UV( Texture2D texture2D = null )
{
return With( BakingTargetType.UV, texture2D );
}
public static BakingOutput ORM( Texture2D texture2D = null )
{
return With( BakingTargetType.ORM, texture2D );
}
public bool IsType( BakingTargetType type, string customType = null )
{
if ( type == BakingTargetType.Custom && bakingTarget.type == type )
{
return bakingTarget.customType == customType;
}
return type == bakingTarget.type;
}
}
}

View File

@ -0,0 +1 @@
uid://b75n4nbcvnu4c

View File

@ -0,0 +1,35 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
public enum BakingTargetType
{
Albedo,
Normals,
Depth,
UV,
Lit,
Occlusion,
Roughness,
Metallic,
ORM,
Custom
}
[Tool]
[GlobalClass]
public partial class BakingTarget:Resource
{
[Export]
public BakingTargetType type;
[Export]
public string customType;
}
}

View File

@ -0,0 +1 @@
uid://63mge3pjf5ir

View File

@ -1,6 +1,6 @@
[gd_resource type="Resource" script_class="MaterialTransfer" load_steps=3 format=3 uid="uid://h2ypphdx3inw"] [gd_resource type="Resource" script_class="MaterialTransfer" load_steps=3 format=3 uid="uid://h2ypphdx3inw"]
[ext_resource type="Script" path="res://addons/rokojori_action_library/Runtime/Shading/Materials/MaterialTransfer.cs" id="1_0hco5"] [ext_resource type="Script" uid="uid://drbmjiqfk51c3" path="res://addons/rokojori_action_library/Runtime/Shading/Materials/MaterialTransfer.cs" id="1_0hco5"]
[ext_resource type="Resource" uid="uid://dgyihly620ymm" path="res://addons/rokojori_action_library/Runtime/Procedural/Baking/BakingMaterials/Normal/Normal From Standard.tres" id="2_cufcd"] [ext_resource type="Resource" uid="uid://dgyihly620ymm" path="res://addons/rokojori_action_library/Runtime/Procedural/Baking/BakingMaterials/Normal/Normal From Standard.tres" id="2_cufcd"]
[resource] [resource]

View File

@ -0,0 +1,25 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class LitBaker:_XX_MultiTextureBaker
{
[Export]
public LitBakingPass litBakingPass = new LitBakingPass();
protected override void _IntitializePasses()
{
_SetPasses( litBakingPass );
}
}
}

View File

@ -0,0 +1 @@
uid://dn2fffnlg8wac

View File

@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class PBRBaker:_XX_MultiTextureBaker
{
[Export]
public AlbedoBakingPass albedoBakingPass = new AlbedoBakingPass();
[Export]
public NormalsBakingPass normalsBakingPass = new NormalsBakingPass();
[Export]
public ORMBakingPass ormBakingPass = new ORMBakingPass();
[Export]
public DepthBakingPass depthBakingPass = new DepthBakingPass();
[Export]
public UVBakingPass uvBakingPass = new UVBakingPass();
[Export]
public LitBakingPass litBakingPass = new LitBakingPass();
protected override void _IntitializePasses()
{
_SetPasses(
albedoBakingPass,
normalsBakingPass,
ormBakingPass,
depthBakingPass,
uvBakingPass,
litBakingPass
);
litBakingPass.isEnabled = false;
depthBakingPass.isEnabled = false;
uvBakingPass.isEnabled = false;
}
}
}

View File

@ -0,0 +1 @@
uid://rojkq3fjdrvf

View File

@ -0,0 +1,105 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class AlbedoBakingPass: _XX_BakingPass
{
public AlbedoBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.Albedo() ];
}
protected override bool KeepsOriginalState()
{
return false;
}
protected override bool KeepsCompositors()
{
return true;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.Albedo );
SetMaterial();
await multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( true, true );
Set( BakingTargetType.Albedo, texture );
return;
}
public void SetMaterial()
{
Dictionary<Material,Material> materials = new Dictionary<Material, Material>();
Nodes.ForEach<Node3D>( multiBaker.X_bakingTargetContainer,
( n )=>
{
SetMaterial( n, materials );
}
);
}
void SetMaterial( Node3D n, Dictionary<Material,Material> materials )
{
var material = Materials.Get<Material>( n );
if ( material == null )
{
n.LogInfo( "No material found" );
return;
}
if ( ! materials.ContainsKey( material ) )
{
var appliedMaterial = new StandardMaterial3D();
if ( material is StandardMaterial3D sm )
{
n.LogInfo( "StandardMaterial3D found" );
appliedMaterial.AlbedoColor = sm.AlbedoColor;
appliedMaterial.AlbedoTexture = sm.AlbedoTexture;
appliedMaterial.Uv1Scale = sm.Uv1Scale;
appliedMaterial.Uv1Offset = sm.Uv1Offset;
appliedMaterial.Transparency = sm.Transparency;
appliedMaterial.AlphaScissorThreshold = sm.AlphaScissorThreshold;
appliedMaterial.AlphaAntialiasingMode = sm.AlphaAntialiasingMode;
appliedMaterial.AlphaAntialiasingEdge = sm.AlphaAntialiasingEdge;
appliedMaterial.ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded;
}
else
{
n.LogInfo( "No StandardMaterial3D found", material.GetType().Name );
}
materials[ material ] = appliedMaterial;
}
Materials.Set( n, materials[ material ] );
}
}
}

View File

@ -0,0 +1 @@
uid://0sm8nqqyogth

View File

@ -0,0 +1,52 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class DepthBakingPass: _XX_BakingPass
{
public DepthBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.Depth() ];
}
protected override bool KeepsOriginalState()
{
return true;
}
protected override bool KeepsCompositors()
{
return false;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.Depth );
multiBaker.AddCompositorEffect( new DepthViewEffect() );
await multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( true, false );
Set( BakingTargetType.Depth, texture );
return;
}
void EnsureBakingOutputs()
{
bakingOutputs = [ BakingOutput.Lit() ];
}
}
}

View File

@ -0,0 +1 @@
uid://dqk8nmdbotxhc

View File

@ -0,0 +1,50 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class LitBakingPass: _XX_BakingPass
{
public LitBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.Lit() ];
}
protected override bool KeepsOriginalState()
{
return true;
}
protected override bool KeepsCompositors()
{
return true;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.Lit );
await textureBaker.multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( true, true );
Set( BakingTargetType.Lit, texture );
return;
}
void EnsureBakingOutputs()
{
bakingOutputs = [ BakingOutput.Lit() ];
}
}
}

View File

@ -0,0 +1 @@
uid://oqmyrtxqtk2x

View File

@ -0,0 +1,114 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class NormalsBakingPass: _XX_BakingPass
{
public NormalsBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.Normals() ];
}
protected override bool KeepsOriginalState()
{
return false;
}
protected override bool KeepsCompositors()
{
return true;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.Normals );
SetNormalMaterial();
await multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( false, false );
Set( BakingTargetType.Normals, texture );
return;
}
public void SetNormalMaterial()
{
Dictionary<Material,Material> materials = new Dictionary<Material, Material>();
Nodes.ForEach<Node3D>( multiBaker.X_bakingTargetContainer,
( n )=>
{
SetMaterial( n, materials );
}
);
}
public static readonly CachedResource<Shader> shader = new CachedResource<Shader>(
"res://addons/rokojori_action_library/External/Imposter/materials/normal_baker.gdshader"
);
void SetMaterial( Node3D n, Dictionary<Material,Material> materials )
{
var material = Materials.Get<Material>( n );
if ( material == null )
{
n.LogInfo( "No material found" );
return;
}
if ( ! materials.ContainsKey( material ) )
{
var appliedMaterial = new ShaderMaterial();
appliedMaterial.Shader = shader.Get();
appliedMaterial.SetShaderParameter( "use_alpha_texture", true );
if ( material is StandardMaterial3D sm )
{
n.LogInfo( "StandardMaterial3D found" );
appliedMaterial.SetShaderParameter( "use_normalmap", sm.NormalTexture != null );
appliedMaterial.SetShaderParameter( "normal_texture", sm.NormalTexture );
appliedMaterial.SetShaderParameter( "normal_scale", sm.NormalScale );
appliedMaterial.SetShaderParameter( "albedo_texture", sm.AlbedoTexture );
appliedMaterial.SetShaderParameter( "albedo_color", sm.AlbedoColor );
appliedMaterial.SetShaderParameter( "alpha_scissor_threshold", sm.AlphaScissorThreshold );
appliedMaterial.SetShaderParameter( "uv1_scale", sm.Uv1Scale );
appliedMaterial.SetShaderParameter( "uv1_offset", sm.Uv1Offset );
appliedMaterial.SetShaderParameter( "uncompressNormalMap", false );
appliedMaterial.SetShaderParameter( "useCustomNormals", true );
}
else
{
n.LogInfo( "No StandardMaterial3D found", material.GetType().Name );
}
materials[ material ] = appliedMaterial;
}
Materials.Set( n, materials[ material ] );
}
}
}

View File

@ -0,0 +1 @@
uid://dwmwibrf8rfux

View File

@ -0,0 +1,143 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class ORMBakingPass: _XX_BakingPass
{
public ORMBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.ORM() ];
}
protected override bool KeepsOriginalState()
{
return false;
}
protected override bool KeepsCompositors()
{
return true;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.ORM );
SetMaterial();
await multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( false, false );
Set( BakingTargetType.ORM, texture );
return;
}
public void SetMaterial()
{
Dictionary<Material,Material> materials = new Dictionary<Material, Material>();
Nodes.ForEach<Node3D>( multiBaker.X_bakingTargetContainer,
( n )=>
{
SetMaterial( n, materials );
}
);
}
public static readonly CachedResource<Shader> shader = new CachedResource<Shader>(
"res://addons/rokojori_action_library/Runtime/Shading/Shaders/Baking/ChannelCopy.gdshader"
);
void SetChannel( string channel, ShaderMaterial material, Texture2D texture2D, int index )
{
material.SetShaderParameter( "channelTexture" + channel, texture2D );
material.SetShaderParameter( "gamma" + channel, 1.0f );
var projection = Projection.Zero;
if ( texture2D != null )
{
projection[ index ] = new Vector4(
index == 0 ? 1:0,
index == 1 ? 1:0,
index == 2 ? 1:0,
1
);
}
material.SetShaderParameter( "colorMatrix" + channel, projection );
}
void SetMaterial( Node3D n, Dictionary<Material,Material> materials )
{
var material = Materials.Get<Material>( n );
if ( material == null )
{
n.LogInfo( "No material found" );
return;
}
if ( ! materials.ContainsKey( material ) )
{
var appliedMaterial = new ShaderMaterial();
appliedMaterial.Shader = shader.Get();
if ( material is StandardMaterial3D sm )
{
n.LogInfo( "StandardMaterial3D found" );
SetChannel( "A", appliedMaterial, sm.AOTexture, 0 );
SetChannel( "B", appliedMaterial, sm.RoughnessTexture, 1 );
SetChannel( "C", appliedMaterial, sm.MetallicTexture, 2 );
appliedMaterial.SetShaderParameter( "uv1_scale", sm.Uv1Scale );
appliedMaterial.SetShaderParameter( "uv1_offset", sm.Uv1Offset );
// appliedMaterial.SetShaderParameter( "use_normalmap", sm.NormalTexture != null );
// appliedMaterial.SetShaderParameter( "normal_texture", sm.NormalTexture );
// appliedMaterial.SetShaderParameter( "normal_scale", sm.NormalScale );
// appliedMaterial.SetShaderParameter( "albedo_texture", sm.AlbedoTexture );
// appliedMaterial.SetShaderParameter( "albedo_color", sm.AlbedoColor );
// appliedMaterial.SetShaderParameter( "alpha_scissor_threshold", sm.AlphaScissorThreshold );
// appliedMaterial.SetShaderParameter( "uv1_scale", sm.Uv1Scale );
// appliedMaterial.SetShaderParameter( "uv1_offset", sm.Uv1Offset );
// appliedMaterial.SetShaderParameter( "uncompressNormalMap", false );
// appliedMaterial.SetShaderParameter( "useCustomNormals", true );
}
else
{
n.LogInfo( "No StandardMaterial3D found", material.GetType().Name );
}
materials[ material ] = appliedMaterial;
}
Materials.Set( n, materials[ material ] );
}
}
}

View File

@ -0,0 +1 @@
uid://wtsyw4idd6nb

View File

@ -0,0 +1,101 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class UVBakingPass: _XX_BakingPass
{
public UVBakingPass():base(){}
protected override void CreateBakingOutputs()
{
bakingOutputs = [ BakingOutput.UV() ];
}
protected override bool KeepsOriginalState()
{
return false;
}
protected override bool KeepsCompositors()
{
return true;
}
protected override async Task _Bake()
{
Clear( BakingTargetType.UV );
SetMaterial();
await multiBaker.RequestNextFrame();
var texture = await GrabDilatedTexture( false, false );
Set( BakingTargetType.UV, texture );
return;
}
public void SetMaterial()
{
Dictionary<Material,Material> materials = new Dictionary<Material, Material>();
Nodes.ForEach<Node3D>( multiBaker.X_bakingTargetContainer,
( n )=>
{
SetMaterial( n, materials );
}
);
}
public static readonly CachedResource<Shader> shader = new CachedResource<Shader>(
"res://addons/rokojori_action_library/Runtime/Shading/Shaders/Baking/UVBaker.gdshader"
);
void SetMaterial( Node3D n, Dictionary<Material,Material> materials )
{
var material = Materials.Get<Material>( n );
if ( material == null )
{
n.LogInfo( "No material found" );
return;
}
if ( ! materials.ContainsKey( material ) )
{
var appliedMaterial = new ShaderMaterial();
appliedMaterial.Shader = shader.Get();
if ( material is StandardMaterial3D sm )
{
n.LogInfo( "StandardMaterial3D found" );
appliedMaterial.SetShaderParameter( "uv1_scale", sm.Uv1Scale );
appliedMaterial.SetShaderParameter( "uv1_offset", sm.Uv1Offset );
}
else
{
n.LogInfo( "No StandardMaterial3D found", material.GetType().Name );
}
materials[ material ] = appliedMaterial;
}
Materials.Set( n, materials[ material ] );
}
}
}

View File

@ -0,0 +1 @@
uid://dwrqxwtundxgk

View File

@ -0,0 +1,168 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class _XX_BakingPass:Resource
{
[Export]
public bool isEnabled = true;
public _XX_BakingPass()
{
CreateBakingOutputs();
}
protected virtual bool KeepsOriginalState()
{
return false;
}
protected virtual bool KeepsCompositors()
{
return false;
}
protected virtual void CreateBakingOutputs()
{
}
protected virtual async Task _Bake()
{
return;
}
public async Task Bake()
{
if ( bakingOutputs == null || bakingOutputs.Length == 0 )
{
CreateBakingOutputs();
}
await _Bake();
if ( ! KeepsOriginalState() )
{
textureBaker.multiBaker.SetTargetDirty();
}
if ( ! KeepsCompositors() )
{
textureBaker.multiBaker.SetCompositorsDirty();
}
return;
}
public async Task<Texture2D> GrabDilatedTexture( bool srgb, bool alpha, bool mipmaps = true )
{
var texture = await textureBaker.multiBaker.GrabDilatedTexture( srgb, alpha, mipmaps );
return texture;
}
public _XX_MultiTextureBaker textureBaker;
public MultiBaker multiBaker => textureBaker.multiBaker;
[Export]
public BakingOutput[] bakingOutputs = [];
public static Texture2D Get( List<_XX_BakingPass> passes, params BakingTargetType[] bakingTargetType )
{
for ( int i = 0 ; i < bakingTargetType.Length; i++ )
{
var t = Get( passes, bakingTargetType[ i ] );
if ( t != null )
{
return t;
}
}
return null;
}
protected void Clear( BakingTargetType type, string customType = null )
{
Set( type, customType, null );
}
protected void Set( BakingTargetType type, Texture2D texture2D )
{
var index = Array.Find( bakingOutputs, b => b.IsType( type, null ) );
if ( index == null )
{
return;
}
index.bakedTexture = texture2D;
}
protected void Set( BakingTargetType type, string customType, Texture2D texture2D )
{
var index = Array.Find( bakingOutputs, b => b.IsType( type, customType ) );
if ( index == null )
{
return;
}
index.bakedTexture = texture2D;
}
public static Texture2D Get( List<_XX_BakingPass> passes, string customType = null )
{
return Get( passes, BakingTargetType.Custom, customType );
}
public static Texture2D Get( List<_XX_BakingPass> passes, BakingTargetType bakingTargetType, string customType = null )
{
var pass = passes.Find( p => p.ContainsBakingOutput( bakingTargetType ) );
if ( pass == null )
{
return null;
}
var output = Array.Find( pass.bakingOutputs, p => p.IsType( bakingTargetType, customType ) );
if ( output == null )
{
return null;
}
return output.bakedTexture;
}
public bool ContainsBakingOutput( BakingTargetType bakingTargetType, string customType = null )
{
for ( int i = 0; i < bakingOutputs.Length; i++ )
{
if ( bakingOutputs[ i ].bakingTarget.type == bakingTargetType )
{
if ( bakingTargetType == BakingTargetType.Custom )
{
return customType == bakingOutputs[ i ].bakingTarget.customType;
}
return true;
}
}
return false;
}
}
}

View File

@ -0,0 +1 @@
uid://du0r1hyfhie6j

View File

@ -0,0 +1,48 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class _XX_MultiTextureBaker:Resource
{
protected MultiBaker _multiBaker;
public MultiBaker multiBaker => _multiBaker;
protected List<_XX_BakingPass> _passes;
protected void _SetPasses( params _XX_BakingPass[] passes )
{
_passes = [.. passes];
_passes.ForEach( p => p.textureBaker = this );
}
protected virtual void _IntitializePasses()
{
}
public List<_XX_BakingPass> GetPasses( MultiBaker multiBaker )
{
_multiBaker = multiBaker;
if ( _passes != null )
{
return Lists.Filter( _passes, p => p.isEnabled );
}
_IntitializePasses();
return Lists.Filter( _passes, p => p.isEnabled );
}
}
}

View File

@ -0,0 +1 @@
uid://dtpu1n5h6j61t

View File

@ -49,7 +49,7 @@ namespace Rokojori
var outputScale = multiBaker.GetOutputScale(); var outputScale = multiBaker.GetOutputScale();
RJLog.Log( "outputScale", outputScale ); RJLog.Log( "outputScale", outputScale );
var _bakers = multiBaker.bakers; var _bakers = multiBaker.bakerCameras;
var mb = multiBaker; var mb = multiBaker;

View File

@ -53,11 +53,11 @@ namespace Rokojori
var distance = multiBaker.GetCameraDistance(); var distance = multiBaker.GetCameraDistance();
var outputScale = multiBaker.GetOutputScale(); var outputScale = multiBaker.GetOutputScale();
var _bakers = multiBaker.bakers; var bakerCameras = multiBaker.bakerCameras;
var mb = multiBaker; var mb = multiBaker;
_bakers.ForEach( bakerCameras.ForEach(
bk => bk =>
{ {
var vs = bk.viewSettings; var vs = bk.viewSettings;
@ -75,13 +75,13 @@ namespace Rokojori
if ( cylinderTop ) if ( cylinderTop )
{ {
_bakers[ index ].viewSettings.yaw = 0; bakerCameras[ index ].viewSettings.yaw = 0;
_bakers[ index ].viewSettings.pitch = 90f; bakerCameras[ index ].viewSettings.pitch = 90f;
var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true ); var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
var q = new MeshGeometry(); var q = new MeshGeometry();
q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max ); q.AddQuad( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );
if ( cylinderTopOffset != 0 ) if ( cylinderTopOffset != 0 )
@ -103,13 +103,13 @@ namespace Rokojori
if ( cylinderBottom ) if ( cylinderBottom )
{ {
_bakers[ index ].viewSettings.yaw = 0; bakerCameras[ index ].viewSettings.yaw = 0;
_bakers[ index ].viewSettings.pitch = -90f; bakerCameras[ index ].viewSettings.pitch = -90f;
var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true ); var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
var q = new MeshGeometry(); var q = new MeshGeometry();
q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max ); q.AddQuad( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );
if ( cylinderBottomOffset != 0 ) if ( cylinderBottomOffset != 0 )
{ {
@ -132,18 +132,18 @@ namespace Rokojori
for ( int i = 0; i < cylinderSides; i++ ) for ( int i = 0; i < cylinderSides; i++ )
{ {
var angle = ( 360f * i ) / (float) cylinderSides; var angle = ( 360f * i ) / (float) cylinderSides;
_bakers[ index ].viewSettings.yaw = angle; bakerCameras[ index ].viewSettings.yaw = angle;
_bakers[ index ].viewSettings.pitch = 0; bakerCameras[ index ].viewSettings.pitch = 0;
var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true ); var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
var q = new MeshGeometry(); var q = new MeshGeometry();
q.AddQuad( _bakers[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max ); q.AddQuad( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );
if ( cylinderSideOffset != 0 ) if ( cylinderSideOffset != 0 )
{ {
var sideOffset = Vector3.Forward *_bakers[ index ].viewSettings.bakingRotation * cylinderSideOffset * outputScale * -0.5f; var sideOffset = Vector3.Forward *bakerCameras[ index ].viewSettings.bakingRotation * cylinderSideOffset * outputScale * -0.5f;
q.ApplyTranslation( sideOffset, -4 ); q.ApplyTranslation( sideOffset, -4 );
} }

View File

@ -0,0 +1,70 @@
using System.Collections;
using System.Collections.Generic;
using Godot;
using System;
using System.Threading.Tasks;
namespace Rokojori
{
[Tool][GlobalClass]
public partial class Flat_Baker:_XX_MultiBakeModeBillboardBase
{
[Export]
public float yawOffset = 0;
public override int GetNumViews()
{
return 2;
}
public override void CreateBakers()
{
var fov = multiBaker.GetCameraFOV();
var distance = multiBaker.GetCameraDistance();
var outputScale = multiBaker.GetOutputScale();
RJLog.Log( "outputScale", outputScale );
var bakerCameras = multiBaker.bakerCameras;
var mb = multiBaker;
bakerCameras.ForEach(
bk =>
{
var vs = bk.viewSettings;
vs.fovDistance = Manual_BakingFDSettings.Create( fov, distance );
vs.rotationMode = BakingViewSettings.RotationMode.Yaw_Pitch;
}
);
var mg = new MeshGeometry();
var numTextures = GetNumViews();
var textureAlignment = TextureMerger.ComputeTextureAlignment( numTextures );
var angle = yawOffset;
for ( int i = 0; i < numTextures; i++ )
{
var index = i;
bakerCameras[ index ].viewSettings.yaw = angle + i * 180f;
bakerCameras[ index ].viewSettings.pitch = 0;
var uv = TextureMerger.GetUVRectangle( textureAlignment, index, true );
var q = new MeshGeometry();
q.AddQuad( bakerCameras[ index ].viewSettings.bakingRotation, outputScale, uv.min, uv.max );
mg.Add( q );
}
mb.X_outputMesh.Mesh = mg.GenerateMesh();
}
}
}

View File

@ -0,0 +1 @@
uid://b4d382v6hcer3

View File

@ -4,6 +4,7 @@ using Godot;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Linq;
namespace Rokojori namespace Rokojori
{ {
@ -26,21 +27,28 @@ namespace Rokojori
Simple_Prebaked Simple_Prebaked
} }
[ExportGroup("Material")] // [ExportGroup("Textures")]
[Export]
public MaterialMode materialMode;
[Export] [Export]
public int dilationRadius = 64; public _XX_MultiTextureBaker textureBaker;
[ExportGroup("Material/Full Seperated")]
[Export]
public bool mmfs_Normals = true;
[Export]
public bool mmfs_Depth = true;
[Export]
public bool mmfs_ORM = true;
// [Export]
// public MaterialMode materialMode;
// [Export]
// public int dilationRadius = 64;
// [ExportGroup("Material/Full Seperated")]
// [Export]
// public bool mmfs_Normals = true;
// [Export]
// public bool mmfs_Depth = true;
// [Export]
// public bool mmfs_ORM = true;
[Export]
public BakingViewSettings viewSettings;
[ExportGroup( "Object")] [ExportGroup( "Object")]
[Export] [Export]
@ -53,11 +61,8 @@ namespace Rokojori
public Vector3 targetPivot; public Vector3 targetPivot;
[ExportGroup( "Camera")]
[Export]
public BakingViewSettings viewSettings;
public float cameraZoom public float cameraZoom
{ {
@ -78,27 +83,6 @@ namespace Rokojori
} }
} }
/*
[Export]
public Baker.CameraDistanceDetectionType distanceDetectionType = Baker.CameraDistanceDetectionType.Automatic_Distance_Detection;
[Export]
public float customDistance = 50;
[Export]
public float cameraZoom = 1;
[Export]
public Baker.CameraFOVMode fovMode = Baker.CameraFOVMode.Compute_Fov_With_Distance;
[Export]
public float originalFOV = 75;
[Export]
public float fovPlacingDistance = 200;
[Export]
public float customFOV = 75;
*/
[ExportGroup( "Output")] [ExportGroup( "Output")]
@ -178,7 +162,7 @@ namespace Rokojori
Nodes.RemoveAndDeleteChildren( this ); Nodes.RemoveAndDeleteChildren( this );
_bakers = null; _bakerCameras = null;
X_bakingViewport = this.CreateChild<SubViewport>( "Multi Baker Viewport" ); X_bakingViewport = this.CreateChild<SubViewport>( "Multi Baker Viewport" );
@ -197,7 +181,7 @@ namespace Rokojori
X_textureMerger = this.CreateChild<TextureMerger>( "Texture Merger" ); X_textureMerger = this.CreateChild<TextureMerger>( "Texture Merger" );
X_textureMerger.multiBaker = this; X_textureMerger.multiBaker = this;
X_textureMerger.dilationRadius = dilationRadius; // X_textureMerger.dilationRadius = dilationRadius;
X_textureMerger.Initialize(); X_textureMerger.Initialize();
X_textureDilate = this.CreateChild<TextureDilate>( "Texture Dilate" ); X_textureDilate = this.CreateChild<TextureDilate>( "Texture Dilate" );
@ -223,6 +207,70 @@ namespace Rokojori
} }
public async Task<Texture2D> GrabDilatedTexture( bool srgb, bool alpha, bool mipmaps )
{
X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport;
var maxRadius = X_textureMerger.GetMaxTextureDimension() / 2;
X_textureDilate.SetDilationRadius( maxRadius );
var texture = await X_textureDilate.Grab( srgb, alpha, mipmaps );
return texture;
}
bool _targetIsInInitialState = false;
public void SetTargetDirty()
{
_targetIsInInitialState = false;
}
public void ResetOriginalTargetState()
{
if ( _targetIsInInitialState )
{
return;
}
// _bakerCameras.ForEach( b => b.viewport.en)
Nodes.RemoveAndDeleteChildren( X_bakingTargetContainer );
target.DeepCopyTo( X_bakingTargetContainer );
_targetIsInInitialState = true;
return;
}
bool _compositorsClean = false;
public void SetCompositorsDirty()
{
_compositorsClean = false;
}
public void ResetCompositorStates()
{
X_worldEnvironment.Compositor = null;
_compositorsClean = true;
}
public void AddCompositorEffect( CompositorEffect compositorEffect )
{
if ( X_worldEnvironment.Compositor == null )
{
X_worldEnvironment.Compositor = new Compositor();
}
var compositorEffects = X_worldEnvironment.Compositor.CompositorEffects;
compositorEffects.Add( compositorEffect );
X_worldEnvironment.Compositor.CompositorEffects = compositorEffects;
_compositorsClean = false;
}
public async Task Bake() public async Task Bake()
{ {
@ -238,109 +286,118 @@ namespace Rokojori
{ {
bakeMode.multiBaker = this; bakeMode.multiBaker = this;
_targetIsInInitialState = false;
this.LogInfo( "Started baking" ); this.LogInfo( "Started baking" );
Nodes.RemoveAndDeleteChildren( X_bakingTargetContainer ); ResetOriginalTargetState();
target.DeepCopyTo( X_bakingTargetContainer );
if ( _bakers == null || _bakers.Count != GetNumViews() ) if ( _bakerCameras == null || _bakerCameras.Count != GetNumViews() )
{ {
CreateViews(); CreateBakerCameras();
await this.RequestNextFrame(); await this.RequestNextFrame();
} }
SetupViews(); SetupBakerCameras();
this.LogInfo( "Views set up" ); this.LogInfo( "Bake Cameras set up" );
await this.RequestNextFrame(); await this.RequestNextFrame();
this.LogInfo( "Render passes" );
X_setBakingMaterials.SetTarget( X_bakingTargetContainer ); var passes = textureBaker.GetPasses( this );
var bakingMaterialModes = new List<BakingMaterialMode>();
var preview_QuickMaterial = MaterialMode.Simple_Prebaked == materialMode;
bakeMode.CreateMaterial( preview_QuickMaterial );
if ( preview_QuickMaterial ) // X_setBakingMaterials.SetTarget( X_bakingTargetContainer );
{
bakingMaterialModes.Add( BakingMaterialMode.Preview );
}
else
{
bakingMaterialModes.Add( BakingMaterialMode.Albedo );
if ( mmfs_Normals ) // var bakingMaterialModes = new List<BakingMaterialMode>();
{
bakingMaterialModes.Add( BakingMaterialMode.Normals );
}
if ( mmfs_Depth ) // var preview_QuickMaterial = MaterialMode.Simple_Prebaked == materialMode;
{
bakingMaterialModes.Add( BakingMaterialMode.Depth );
}
if ( mmfs_ORM ) // bakeMode.CreateMaterial( preview_QuickMaterial );
{
bakingMaterialModes.Add( BakingMaterialMode.ORM ); bakeMode.CreateMaterial( passes );
}
} // if ( preview_QuickMaterial )
// {
// bakingMaterialModes.Add( BakingMaterialMode.Preview );
// }
// else
// {
// bakingMaterialModes.Add( BakingMaterialMode.Albedo );
// if ( mmfs_Normals )
// {
// bakingMaterialModes.Add( BakingMaterialMode.Normals );
// }
// if ( mmfs_Depth )
// {
// bakingMaterialModes.Add( BakingMaterialMode.Depth );
// }
// if ( mmfs_ORM )
// {
// bakingMaterialModes.Add( BakingMaterialMode.ORM );
// }
// }
this.LogInfo( "Prepared baking modes" ); this.LogInfo( "Prepared baking modes" );
X_textureMerger.textureSize = outputTextureSize; X_textureMerger.textureSize = outputTextureSize;
X_textureMerger.Initialize(); X_textureMerger.Initialize();
X_textureMerger.CreateLayout(); X_textureMerger.CreateLayout();
this.LogInfo( "Prepared texture merger" );
// this.LogInfo( "Prepared texture merger" );
// var fovDistance = viewSettings.fovDistance.ComputeFOVDistance( // var fovDistance = viewSettings.fovDistance.ComputeFOVDistance(
var objectDistance = GetCameraDistance(); // var objectDistance = GetCameraDistance();
this.LogInfo( "Set Camera Distance", objectDistance ); // this.LogInfo( "Set Camera Distance", objectDistance );
for ( int i = 0; i < bakingMaterialModes.Count; i++ )
{
this.LogInfo( "Baking mode:", bakingMaterialModes[ i ] );
X_setBakingMaterials.mode = bakingMaterialModes[ i ];
X_setBakingMaterials.ApplyBakingMaterials( objectDistance, _targetBoundingSphere.radius );
this.LogInfo( "Materials changed:", bakingMaterialModes[ i ] );
_bakers.ForEach( b => b.Bake() );
for ( int i = 0; i < passes.Count; i++ )
{
ResetOriginalTargetState();
_bakerCameras.ForEach( b => b.ApplyCameraSettings() );
await passes[ i ].Bake();
await this.RequestNextFrame(); await this.RequestNextFrame();
// Texture2D texture = X_textureMerger.X_textureMergerViewport.GetTexture(); }
// this.LogInfo( "Texture created:", bakingMaterialModes[ i ] ); bakeMode.AssignMaterial( passes );
// await this.RequestNextFrame(); // for ( int i = 0; i < bakingMaterialModes.Count; i++ )
// {
// this.LogInfo( "Baking mode:", bakingMaterialModes[ i ] );
// X_setBakingMaterials.mode = bakingMaterialModes[ i ];
// X_setBakingMaterials.ApplyBakingMaterials( objectDistance, _targetBoundingSphere.radius );
X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport; // this.LogInfo( "Materials changed:", bakingMaterialModes[ i ] );
Texture2D texture = await X_textureDilate.Grab();
// _bakers.ForEach( b => b.ApplyCameraSettings() );
// await this.RequestNextFrame();
// X_textureDilate.viewport = X_textureMerger.X_textureMergerViewport;
// Texture2D texture = await X_textureDilate.Grab();
this.LogInfo( "Assigning Texture", bakingMaterialModes[ i ] ); // this.LogInfo( "Assigning Texture", bakingMaterialModes[ i ] );
bakeMode.AssignMaterial( bakingMaterialModes[ i ], texture ); // bakeMode.AssignMaterial( bakingMaterialModes[ i ], texture );
this.LogInfo( "Baking done:", bakingMaterialModes[ i ] ); // this.LogInfo( "Baking done:", bakingMaterialModes[ i ] );
await this.RequestNextFrame(); // await this.RequestNextFrame();
} // }
await this.RequestNextFrame(); // await this.RequestNextFrame();
X_outputMesh.GlobalPosition = target.GlobalPosition - targetPivot; X_outputMesh.GlobalPosition = target.GlobalPosition - targetPivot;
X_outputMesh.Scale = Vector3.One * cameraZoom; X_outputMesh.Scale = Vector3.One * cameraZoom;
if ( cleanUpAfterBaking )
{
this.LogInfo( "Cleaning Up" );
CleanUp();
}
this.LogInfo( "All Baking done" ); this.LogInfo( "All Baking done" );
} }
@ -350,6 +407,13 @@ namespace Rokojori
this.LogError( e ); this.LogError( e );
} }
if ( cleanUpAfterBaking )
{
this.LogInfo( "Cleaning Up" );
CleanUp();
}
X_baking = false; X_baking = false;
return; return;
@ -360,26 +424,26 @@ namespace Rokojori
return Nodes.AllIn<SubViewport>( X_views, null, false ); return Nodes.AllIn<SubViewport>( X_views, null, false );
} }
public void CacheTexture( BakingMaterialMode mode, Texture2D texture ) // public void CacheTexture( BakingMaterialMode mode, Texture2D texture )
{ // {
if ( BakingMaterialMode.Albedo == mode ) // if ( BakingMaterialMode.Albedo == mode )
{ // {
X_bakedTextureAlbedo = texture; // X_bakedTextureAlbedo = texture;
} // }
else if ( BakingMaterialMode.Normals == mode ) // else if ( BakingMaterialMode.Normals == mode )
{ // {
X_bakedTextureNormal = texture; // X_bakedTextureNormal = texture;
} // }
else if ( BakingMaterialMode.ORM == mode ) // else if ( BakingMaterialMode.ORM == mode )
{ // {
X_bakedTextureORM = texture; // X_bakedTextureORM = texture;
} // }
else if ( BakingMaterialMode.Depth == mode ) // else if ( BakingMaterialMode.Depth == mode )
{ // {
X_bakedTextureDepth = texture; // X_bakedTextureDepth = texture;
} // }
} // }
public void CleanUp() public void CleanUp()
{ {
@ -398,6 +462,8 @@ namespace Rokojori
X_textureMerger = null; X_textureMerger = null;
X_textureDilate = null;
X_setBakingMaterials = null; X_setBakingMaterials = null;
X_texturePreview = null; X_texturePreview = null;
@ -424,21 +490,24 @@ namespace Rokojori
return bakeMode.GetNumViews(); return bakeMode.GetNumViews();
} }
List<Baker> _bakers; List<Baker> _bakerCameras;
public List<Baker> bakers => _bakers; public List<Baker> bakerCameras => _bakerCameras;
public void CreateViews() public void CreateBakerCameras()
{ {
Nodes.RemoveAndDeleteChildren( X_views ); Nodes.RemoveAndDeleteChildren( X_views );
var numViews = GetNumViews(); var numViews = GetNumViews();
_bakers = new List<Baker>(); _bakerCameras = new List<Baker>();
var minViewsPerAxis = TextureMerger.ComputeTextureAlignment( numViews ).Y; var alginment = TextureMerger.ComputeTextureAlignment( numViews );
var minViewsPerAxis = Mathf.Max( alginment.X, alginment.Y );
this.LogInfo( "Size per Baker:", "nv", numViews, "al", alginment, "mvpa", minViewsPerAxis,"s", (Vector2I) ( outputTextureSize / minViewsPerAxis ) );
for ( int i = 0; i < numViews; i++ ) for ( int i = 0; i < numViews; i++ )
{ {
var userIndex = ( i + 1 ); var userIndex = ( i + 1 );
@ -452,15 +521,17 @@ namespace Rokojori
baker.camera = bakingCamera; baker.camera = bakingCamera;
baker.target = X_bakingTargetContainer; baker.target = X_bakingTargetContainer;
baker.viewport = bakingView; baker.viewport = bakingView;
baker.viewport.Msaa3D = Viewport.Msaa.Msaa8X;
_bakers.Add( baker ); _bakerCameras.Add( baker );
} }
} }
public void SetupViews() public void SetupBakerCameras()
{ {
var numViews = GetNumViews(); var numViews = GetNumViews();
var minViewsPerAxis = TextureMerger.ComputeTextureAlignment( numViews ).Y; var minViewsPerAxis = TextureMerger.ComputeTextureAlignment( numViews ).Y;
@ -469,7 +540,7 @@ namespace Rokojori
for ( int i = 0; i < numViews; i++ ) for ( int i = 0; i < numViews; i++ )
{ {
var baker = _bakers[ i ]; var baker = _bakerCameras[ i ];
var bakingView = baker.viewport as SubViewport; var bakingView = baker.viewport as SubViewport;
bakingView.Size = (Vector2I) ( outputTextureSize / minViewsPerAxis ); bakingView.Size = (Vector2I) ( outputTextureSize / minViewsPerAxis );
} }
@ -532,9 +603,21 @@ namespace Rokojori
_targetBoundingBox = X_bakingTargetContainer.GetWorldBounds(); _targetBoundingBox = X_bakingTargetContainer.GetWorldBounds();
if ( _targetBoundingBox == null )
{
return;
}
if ( autoTargetPivot ) if ( autoTargetPivot )
{ {
Box3 box = target.GetWorldBounds(); Box3 box = target.GetWorldBounds();
if ( box == null )
{
_targetBoundingSphere = null;
return;
}
targetPivot = new Vector3( 0, -box.center.Y, 0 ); targetPivot = new Vector3( 0, -box.center.Y, 0 );
} }

View File

@ -27,7 +27,7 @@ namespace Rokojori
return views; return views;
} }
public override void CreateMaterial( bool preview ) public override void CreateMaterial( List<_XX_BakingPass> passes )
{ {
var mb = multiBaker; var mb = multiBaker;
var material = new ShaderMaterial(); var material = new ShaderMaterial();
@ -39,11 +39,10 @@ namespace Rokojori
Materials.Set( mb.X_outputMesh, material ); Materials.Set( mb.X_outputMesh, material );
} }
public override void AssignMaterial( BakingMaterialMode mode, Texture2D texture ) public override void AssignMaterial( List<_XX_BakingPass> passes )
{ {
var mb = multiBaker; var mb = multiBaker;
mb.CacheTexture( mode, texture );
var material = Materials.Get<ShaderMaterial>( mb.X_outputMesh ); var material = Materials.Get<ShaderMaterial>( mb.X_outputMesh );
if ( material == null ) if ( material == null )
@ -52,23 +51,18 @@ namespace Rokojori
return; return;
} }
if ( BakingMaterialMode.Albedo == mode || BakingMaterialMode.Preview == mode )
{ material.SetShaderParameter( "imposterTextureAlbedo",
material.SetShaderParameter( "imposterTextureAlbedo", texture ); _XX_BakingPass.Get( passes, BakingTargetType.Albedo, BakingTargetType.Lit ) );
}
else if ( BakingMaterialMode.Normals == mode ) material.SetShaderParameter( "imposterTextureNormal",
{ _XX_BakingPass.Get( passes, BakingTargetType.Normals ) );
material.SetShaderParameter( "imposterTextureNormal", texture );
}
else if ( BakingMaterialMode.ORM == mode )
{
material.SetShaderParameter( "imposterTextureOrm", texture );
}
else if ( BakingMaterialMode.Depth == mode )
{
material.SetShaderParameter( "imposterTextureDepth", texture );
}
material.SetShaderParameter( "imposterTextureOrm",
_XX_BakingPass.Get( passes, BakingTargetType.ORM ) );
material.SetShaderParameter( "imposterTextureDepth",
_XX_BakingPass.Get( passes, BakingTargetType.Depth ) );
} }
@ -78,7 +72,7 @@ namespace Rokojori
var distance = multiBaker.GetCameraDistance(); var distance = multiBaker.GetCameraDistance();
var outputScale = multiBaker.GetOutputScale(); var outputScale = multiBaker.GetOutputScale();
var _bakers = multiBaker.bakers; var _bakers = multiBaker.bakerCameras;
var mb = multiBaker; var mb = multiBaker;

View File

@ -22,12 +22,12 @@ namespace Rokojori
} }
public virtual void AssignMaterial( BakingMaterialMode mode, Texture2D texture ) public virtual void AssignMaterial( List<_XX_BakingPass> passes )
{ {
} }
public virtual void CreateMaterial( bool preview ) public virtual void CreateMaterial( List<_XX_BakingPass> passes )
{ {
} }

View File

@ -10,44 +10,50 @@ namespace Rokojori
[Tool][GlobalClass] [Tool][GlobalClass]
public partial class _XX_MultiBakeModeBillboardBase:_XX_MultiBakeMode public partial class _XX_MultiBakeModeBillboardBase:_XX_MultiBakeMode
{ {
public override void CreateMaterial( bool preview ) public override void CreateMaterial( List<_XX_BakingPass> passes )
{ {
var preview = passes.Find( p => p.ContainsBakingOutput( BakingTargetType.Albedo ) ) == null;
var mb = multiBaker; var mb = multiBaker;
var material = new StandardMaterial3D(); var material = new StandardMaterial3D();
material.ShadingMode = preview ? BaseMaterial3D.ShadingModeEnum.Unshaded : BaseMaterial3D.ShadingModeEnum.PerPixel; material.ShadingMode = preview ? BaseMaterial3D.ShadingModeEnum.Unshaded : BaseMaterial3D.ShadingModeEnum.PerPixel;
material.Transparency = BaseMaterial3D.TransparencyEnum.AlphaScissor; material.Transparency = BaseMaterial3D.TransparencyEnum.AlphaScissor;
material.AlphaScissorThreshold = 0.5f; material.AlphaScissorThreshold = 0.01f;
material.AlphaAntialiasingMode = BaseMaterial3D.AlphaAntiAliasing.AlphaToCoverageAndToOne; material.AlphaAntialiasingMode = BaseMaterial3D.AlphaAntiAliasing.AlphaToCoverageAndToOne;
material.AlphaAntialiasingEdge = 0.3f; material.AlphaAntialiasingEdge = 0.95f;
material.NormalEnabled = ! preview; material.NormalEnabled = ! preview;
Materials.Set( mb.X_outputMesh, material ); Materials.Set( mb.X_outputMesh, material );
} }
public override void AssignMaterial( BakingMaterialMode mode, Texture2D texture ) public override void AssignMaterial( List<_XX_BakingPass> passes )
{ {
var mb = multiBaker; var mb = multiBaker;
mb.CacheTexture( mode, texture );
var material = Materials.Get<StandardMaterial3D>( mb.X_outputMesh ); var material = Materials.Get<StandardMaterial3D>( mb.X_outputMesh );
if ( BakingMaterialMode.Albedo == mode || BakingMaterialMode.Preview == mode ) material.AlbedoTexture = _XX_BakingPass.Get( passes, BakingTargetType.Albedo, BakingTargetType.Lit );
{ material.NormalTexture = _XX_BakingPass.Get( passes, BakingTargetType.Normals );
RJLog.Log( "Assign albedo" );
material.AlbedoTexture = texture;
} material.AOTexture = _XX_BakingPass.Get( passes, BakingTargetType.ORM );
else if ( BakingMaterialMode.Normals == mode ) material.RoughnessTexture = _XX_BakingPass.Get( passes, BakingTargetType.ORM );
{ material.MetallicTexture = _XX_BakingPass.Get( passes, BakingTargetType.ORM );
RJLog.Log( "Assign normal" ); material.AOEnabled = true;
material.NormalTexture = texture;
} material.AOLightAffect = 1;
else if ( BakingMaterialMode.ORM == mode )
{ material.AOTextureChannel = BaseMaterial3D.TextureChannel.Red;
material.OrmTexture = texture; material.RoughnessTextureChannel = BaseMaterial3D.TextureChannel.Green;
} material.MetallicTextureChannel = BaseMaterial3D.TextureChannel.Blue;
material.MetallicSpecular = 0;
// material.Anisotropy = 1;
// material.AnisotropyEnabled = true;
material.TextureFilter = BaseMaterial3D.TextureFilterEnum.LinearWithMipmapsAnisotropic;
} }
} }

View File

@ -29,12 +29,12 @@ namespace Rokojori
return views; return views;
} }
public override void CreateMaterial( bool preview ) public override void CreateMaterial( List<_XX_BakingPass> passes )
{ {
} }
public override void AssignMaterial( BakingMaterialMode mode, Texture2D texture ) public override void AssignMaterial( List<_XX_BakingPass> passes )
{ {
} }

View File

@ -1,7 +1,6 @@
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using Godot; using Godot;
using System;
@ -9,7 +8,7 @@ namespace Rokojori
{ {
[Tool] [Tool]
[GlobalClass] [GlobalClass]
public partial class SetBakingMaterials:Node public partial class SetBakingMaterials:Action
{ {
[Export] [Export]
public Node targetContainer; public Node targetContainer;
@ -17,8 +16,20 @@ namespace Rokojori
[Export] [Export]
public BakingMaterialMode mode; public BakingMaterialMode mode;
[Export]
public float distance;
[Export]
public float radius;
MapList<VisualInstance3D,Material> _originalMaterials; MapList<VisualInstance3D,Material> _originalMaterials;
protected override void _OnTrigger()
{
SetTarget( targetContainer );
ApplyBakingMaterials( distance, radius );
}
public void SetTarget( Node targetContainer ) public void SetTarget( Node targetContainer )
{ {
_originalMaterials = new MapList<VisualInstance3D, Material>(); _originalMaterials = new MapList<VisualInstance3D, Material>();

View File

@ -22,15 +22,28 @@ namespace Rokojori
[Export( PropertyHint.Range, "0,15" ) ] [Export( PropertyHint.Range, "0,15" ) ]
public int steps = 0; public int steps = 0;
[Export]
public bool useSRGB = true;
[ExportToolButton( "Grab Texture")] [ExportToolButton( "Grab Texture")]
public Callable GrabButton => Callable.From( public Callable GrabButton => Callable.From(
() => () =>
{ {
Grab(); Grab( useSRGB, true );
} }
); );
public async Task<Texture2D> Grab() public void SetDilationRadius( int pixelSize )
{
steps = ( Mathf.RoundToInt( MathX.Exponent( 2, pixelSize ) ) - 1 );
}
public void SetDilationRadius( Vector2 size )
{
SetDilationRadius( Mathf.RoundToInt( Mathf.Max( size.X, size.Y ) ) );
}
public async Task<Texture2D> Grab( bool srgb, bool alpha, bool mipmaps = false )
{ {
var updateMode = viewport.RenderTargetUpdateMode; var updateMode = viewport.RenderTargetUpdateMode;
@ -50,7 +63,7 @@ namespace Rokojori
this.LogInfo( "Creating context" ); this.LogInfo( "Creating context" );
var ctx = RDContext.Local(); var ctx = RDContext.Local();
ctx.computeSize = viewPortSize; ctx.computeSize = viewPortSize;
ctx.messageLogLevel = Messages.GetLevel( MessageType.Verbose ); // ctx.messageLogLevel = Messages.GetLevel( MessageType.Verbose );
this.LogInfo( "Creating textures" ); this.LogInfo( "Creating textures" );
@ -90,13 +103,13 @@ namespace Rokojori
var gammaConversion = 0; var gammaConversion = 0;
if ( RenderingDevice.DataFormat.R16G16B16A16Sfloat == viewPortFormat ) if ( RenderingDevice.DataFormat.R16G16B16A16Sfloat == viewPortFormat && srgb )
{ {
gammaConversion = -1; gammaConversion = -1;
} }
var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ), gammaConversion ); var buffer = TextureCombinerBuffer.From( ImageTexture.CreateFromImage( image ), gammaConversion );
var texture = buffer.CreateImageTexture(); var texture = buffer.CreateImageTexture( alpha, mipmaps );
@ -121,7 +134,7 @@ namespace Rokojori
ctx.Verbose( "Init Texture:", initTexture.GetTexture() ); ctx.Verbose( "Init Texture:", initTexture.GetTexture() );
var jfaInititialize = new CEG_JFAInitialize( graph ); var jfaInititialize = new CEG_JFAInitialize( graph );
jfaInititialize.constants.Set( 0.5f ); jfaInititialize.constants.Set( 0.95f );
var copy = new CEG_Copy( graph ); var copy = new CEG_Copy( graph );
var jfaIterate = new CEG_JFAIterate( graph ); var jfaIterate = new CEG_JFAIterate( graph );
@ -132,7 +145,7 @@ namespace Rokojori
( Mathf.RoundToInt( MathX.Exponent( 2, it.maxDimension ) ) - 1 ) : ( Mathf.RoundToInt( MathX.Exponent( 2, it.maxDimension ) ) - 1 ) :
steps; steps;
RJLog.Log( "Steps >>", numSteps, Mathf.Pow( 2, numSteps ) ); // RJLog.Log( "Steps >>", numSteps, Mathf.Pow( 2, numSteps ) );
repeat.repeats = numSteps; repeat.repeats = numSteps;
repeat.imageProcessor = jfaIterate; repeat.imageProcessor = jfaIterate;
@ -143,7 +156,6 @@ namespace Rokojori
var stepIndex = numSteps - ( index + 1 ); var stepIndex = numSteps - ( index + 1 );
var jump = Mathf.RoundToInt( Mathf.Pow( 2, stepIndex ) ); var jump = Mathf.RoundToInt( Mathf.Pow( 2, stepIndex ) );
this.LogInfo( "Jump:", jump );
jfaIterate.constants.Set( jfaIterate.constants.Set(
jump jump
); );

View File

@ -25,7 +25,7 @@ namespace Rokojori
public bool createLayout; public bool createLayout;
[Export] [Export]
public int dilationRadius = 64; public int dilationRadius = 3;
[ExportGroup("Source")] [ExportGroup("Source")]
@ -211,6 +211,23 @@ namespace Rokojori
return new Vector2( x, y ); return new Vector2( x, y );
} }
public Vector2 GetGridTextureSize()
{
var alignment = ComputeTextureAlignment( _textures.Count );
return new Vector2( textureSize.X / alignment.X, textureSize.Y / alignment.Y );
}
public int GetMaxTextureDimension()
{
var size = GetGridTextureSize();
return Mathf.RoundToInt( Mathf.Max( size.X, size.Y ) );
}
int dilationAlphaTreshold = 30;
int dilationAssignedMinimum = 0;
void CreateGridLayout() void CreateGridLayout()
{ {
var alignment = ComputeTextureAlignment( _textures.Count ); var alignment = ComputeTextureAlignment( _textures.Count );
@ -232,8 +249,8 @@ namespace Rokojori
dilatedMaterial.textureAlbedo.Set( _textures[ i ] ); dilatedMaterial.textureAlbedo.Set( _textures[ i ] );
dilatedMaterial.resolution.Set( _textures[ i ].GetSize() ); dilatedMaterial.resolution.Set( _textures[ i ].GetSize() );
dilatedMaterial.maxRadius.Set( dilationRadius ); dilatedMaterial.maxRadius.Set( dilationRadius );
dilatedMaterial.alphaTreshold.Set( 1 ); dilatedMaterial.alphaTreshold.Set( dilationAlphaTreshold );
dilatedMaterial.assignedColorAlphaMinimum.Set( 254 ); dilatedMaterial.assignedColorAlphaMinimum.Set( dilationAssignedMinimum );
dilatedMaterial.genericAlphaOffset.Set( 0 ); dilatedMaterial.genericAlphaOffset.Set( 0 );
dilatedMaterial.amount.Set( 1 ); dilatedMaterial.amount.Set( 1 );
@ -264,9 +281,9 @@ namespace Rokojori
dilatedMaterial.textureAlbedo.Set( _textures[ i ] ); dilatedMaterial.textureAlbedo.Set( _textures[ i ] );
dilatedMaterial.resolution.Set( _textures[ i ].GetSize() ); dilatedMaterial.resolution.Set( _textures[ i ].GetSize() );
dilatedMaterial.maxRadius.Set( dilationRadius ); dilatedMaterial.maxRadius.Set( dilationRadius );
dilatedMaterial.alphaTreshold.Set( 10 ); dilatedMaterial.alphaTreshold.Set( dilationAlphaTreshold );
dilatedMaterial.assignedColorAlphaMinimum.Set( 10 ); dilatedMaterial.assignedColorAlphaMinimum.Set( dilationAssignedMinimum );
dilatedMaterial.genericAlphaOffset.Set( 50 ); dilatedMaterial.genericAlphaOffset.Set( 0 );
dilatedMaterial.amount.Set( 1 ); dilatedMaterial.amount.Set( 1 );

View File

@ -44,16 +44,6 @@ namespace Rokojori
*/ */
[ExportGroup( "Debug Readonly" )]
[Export]
public float _XX_ComputedFOV = 75;
[Export]
public float _XX_ComputedDistance = 1;
[Export]
public float _XX_ComputedOutputScale = 1;
/* /*
@ -94,7 +84,7 @@ namespace Rokojori
public float pitch = 0; public float pitch = 0;
[Export] [Export]
public Quaternion rotationQuaternion; public Quaternion rotationQuaternion = Quaternion.Identity;
public Quaternion bakingRotation => RotationMode.Yaw_Pitch == rotationMode ? public Quaternion bakingRotation => RotationMode.Yaw_Pitch == rotationMode ?
@ -102,7 +92,17 @@ namespace Rokojori
rotationQuaternion; rotationQuaternion;
[ExportGroup( "Debug Readonly" )]
[Export]
public float _XX_ComputedFOV = 75;
[Export]
public float _XX_ComputedDistance = 1;
[Export]
public float _XX_ComputedOutputScale = 1;
public void ApplySettings( Camera3D camera, Node3D target, Vector3 pivot ) public void ApplySettings( Camera3D camera, Node3D target, Vector3 pivot )
@ -144,7 +144,9 @@ namespace Rokojori
var offset = ( Vector3.Back * _XX_ComputedDistance ) * cameraRotation ; var offset = ( Vector3.Back * _XX_ComputedDistance ) * cameraRotation ;
camera.GlobalPosition = target.GlobalPosition + offset - pivot; camera.GlobalPosition = target.GlobalPosition + offset - pivot;
camera.SetGlobalQuaternion( cameraRotation.Inverse() );
var inverse = cameraRotation.Normalized().Inverse();
camera.SetGlobalQuaternion( inverse );
_XX_ComputedOutputScale = Cameras.ComputeCameraFittingScale( camera.Fov, _XX_ComputedDistance ); _XX_ComputedOutputScale = Cameras.ComputeCameraFittingScale( camera.Fov, _XX_ComputedDistance );

View File

@ -904,7 +904,7 @@ namespace Rokojori
public ArrayMesh GenerateMesh( Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null ) public ArrayMesh GenerateMesh( Mesh.PrimitiveType type = Mesh.PrimitiveType.Triangles, ArrayMesh arrayMesh = null, bool generateTangents = true )
{ {
if ( arrayMesh == null ) if ( arrayMesh == null )
{ {
@ -946,6 +946,11 @@ namespace Rokojori
arrayMesh.AddSurfaceFromArrays( Mesh.PrimitiveType.Triangles, surfaceArray ); arrayMesh.AddSurfaceFromArrays( Mesh.PrimitiveType.Triangles, surfaceArray );
if ( generateTangents )
{
arrayMesh.RegenNormalMaps();
}
return arrayMesh; return arrayMesh;
} }

View File

@ -37,19 +37,23 @@ namespace Rokojori
} }
} }
public static TextureCombinerBuffer From( Texture2D texture, int srgbConversion = 0) public static TextureCombinerBuffer From( Texture2D texture, int srgbConversion = 0 )
{ {
var buffer = Create( texture.GetWidth(), texture.GetHeight() ); var buffer = Create( texture.GetWidth(), texture.GetHeight() );
buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion ); buffer.CopyFrom( texture.GetImage(), 0, 0, 0, 0, texture.GetWidth(), texture.GetHeight(), srgbConversion);
return buffer; return buffer;
} }
public ImageTexture CreateImageTexture() public ImageTexture CreateImageTexture( bool alpha = true, bool generateMipmaps = false )
{ {
var image = Image.CreateEmpty( width, height, true, Image.Format.Rgba8 ); var image = Image.CreateEmpty( width, height, generateMipmaps, alpha ? Image.Format.Rgba8 : Image.Format.Rgb8);
CopyTo( 0, 0, 0, 0, width, height, image ); CopyTo( 0, 0, 0, 0, width, height, image, alpha );
image.GenerateMipmaps();
if ( generateMipmaps )
{
image.GenerateMipmaps();
}
return ImageTexture.CreateFromImage( image ); return ImageTexture.CreateFromImage( image );
} }
@ -120,15 +124,30 @@ namespace Rokojori
} }
} }
public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, Image image ) public void CopyTo( int ownX, int ownY, int targetX, int targetY, int w, int h, Image image, bool alpha = true )
{ {
for ( int i = 0; i < w; i++ ) if ( ! alpha )
{ {
for ( int j = 0; j < h; j++ ) for ( int i = 0; i < w; i++ )
{ {
var ownPixel = GetAt( ownX + i, ownY + j ); for ( int j = 0; j < h; j++ )
image.SetPixel( targetX + i, targetY + j, ownPixel ); {
var ownPixel = GetAt( ownX + i, ownY + j );
ownPixel.A = 1;
image.SetPixel( targetX + i, targetY + j, ownPixel );
}
}
}
else
{
for ( int i = 0; i < w; i++ )
{
for ( int j = 0; j < h; j++ )
{
var ownPixel = GetAt( ownX + i, ownY + j );
image.SetPixel( targetX + i, targetY + j, ownPixel );
}
} }
} }
} }

View File

@ -0,0 +1,81 @@
using Godot;
using Godot.Collections;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class DepthAOEffect:SingleShaderCompositorEffect
{
public static readonly string shaderPath = Path( "DepthAO/DepthAOShader.glsl" );
RDSampler sampler;
[Export( PropertyHint.Range, "0,1") ]
public float greyAmount;
[Export( PropertyHint.Range, "0,1") ]
public float depthAmount;
[Export( PropertyHint.Range, "0,5") ]
public float effectStrength = 1;
[Export( PropertyHint.Range, "2,8") ]
public float depthEdgeTreshold = 2f;
[Export( PropertyHint.Range, "1,10") ]
public float depthEdgeIntensity = 1f;
[Export( PropertyHint.Range, "0,8") ]
public float radius = 2f;
[Export( PropertyHint.Range, "0.001,1") ]
public float jump = 1f;
[Export( PropertyHint.Range, "0,1") ]
public float debugView = 0f;
protected override void OnConfigure()
{
EffectCallbackType = EffectCallbackTypeEnum.PostTransparent;
_shaderPath = shaderPath;
_groupSize = 8;
}
protected override void OnInitialize()
{
base.OnInitialize();
sampler = context.Sampler( RenderingDevice.SamplerFilter.Nearest, RenderingDevice.SamplerRepeatMode.ClampToEdge );
}
protected override void SetConstants()
{
constants.Set(
(Vector2)context.internalSize,
new Vector2( greyAmount, depthAmount ),
effectStrength,
depthEdgeTreshold / 100f,
depthEdgeIntensity * 20f,
radius,
jump,
debugView
);
}
protected override void RenderView()
{
context.AssignScreenColorTexture();
context.AssignScreenDepthTexture( sampler );
context.pushConstants = constants;
context.ProcessComputeProgram();
}
}
}

View File

@ -0,0 +1 @@
uid://b2sqklu6pcdcr

View File

@ -0,0 +1,146 @@
#[compute]
#version 450
layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in;
layout( rgba16f, set = 0, binding = 0 )
uniform image2D color_image;
layout( set = 1, binding = 0 )
uniform sampler2D depth_sampler;
layout( push_constant, std430 )
uniform Params
{
vec2 rasterSize;
vec2 amounts;
float effectStrength;
float edgeThreshold;
float edgeIntensity;
float contrastThreshold;
float contrastIntensity;
float debugView;
} params;
float sampleDepth( ivec2 coord )
{
coord = clamp( coord, ivec2( 0 ), ivec2( params.rasterSize ) - ivec2( 1 ) );
vec2 uv = ( vec2( coord ) + 0.5 ) / params.rasterSize;
return texture( depth_sampler, uv ).r;
}
float getEdgeStrength( ivec2 uvOffset )
{
float centerDepth = sampleDepth( uvOffset );
float top = sampleDepth( uvOffset + ivec2( 0, -1 ) );
float left = sampleDepth( uvOffset + ivec2( -1, 0 ) );
float gx = left - centerDepth;
float gy = top - centerDepth;
gx = 1.0 - clamp( abs( 10 * abs( gx ) - params.edgeThreshold ) * params.edgeIntensity, 0.0, 1.0 );
gy = 1.0 - clamp( abs( 10 * abs( gy ) - params.edgeThreshold ) * params.edgeIntensity, 0.0, 1.0 );
return length( vec2( gx, gy ) );
}
void main( )
{
ivec2 uv = ivec2( gl_GlobalInvocationID.xy );
ivec2 size = ivec2( params.rasterSize );
if ( uv.x >= size.x || uv.y >= size.y )
{
return;
}
// float centerDepth = sampleDepth( uv );
// float top_left = sampleDepth( uv + ivec2( -1, -1 ) );
// float top = sampleDepth( uv + ivec2( 0, -1 ) );
// float top_right = sampleDepth( uv + ivec2( 1, -1 ) );
// float left = sampleDepth( uv + ivec2( -1, 0 ) );
// float right = sampleDepth( uv + ivec2( 1, 0 ) );
// float bottom_left = sampleDepth( uv + ivec2( -1, 1 ) );
// float bottom = sampleDepth( uv + ivec2( 0, 1 ) );
// float bottom_right = sampleDepth( uv + ivec2( 1, 1 ) );
// // ( l - c ) + ( c - r );
// //
// float gx = left - centerDepth;
// float gy = top - centerDepth;
// gx = 1.0 - clamp( abs( 10 * abs( gx ) - params.edgeThreshold ) * params.edgeIntensity, 0.0, 1.0 );
// gy = 1.0 - clamp( abs( 10 * abs( gy ) - params.edgeThreshold ) * params.edgeIntensity, 0.0, 1.0 );
float edgeStrength = 0;
float amount = 0;
int radius = int( params.contrastThreshold );
for ( int x = -radius; x <= radius; x ++ )
{
for ( int y = -radius; y <= radius; y ++ )
{
ivec2 xy = ivec2( x, y );
float es = getEdgeStrength( uv + xy );
float a = 1.0 / ( 1.0 + length( xy ) );
edgeStrength += es;
amount += pow( a, params.contrastIntensity );
}
}
edgeStrength /= amount;
/*
edgeStrength = min( abs( edgeStrength - params.edgeThreshold ) * params.edgeIntensity, 1.0 );
// float edgeStrength = abs( left - right );
// edgeStrength = clamp( ( edgeStrength - params.edgeThreshold ) * params.edgeIntensity, 0.0, 1.0 );
float edge = edgeStrength;
vec4 color = imageLoad( color_image, uv );
vec4 color_left = imageLoad( color_image, uv + ivec2( -1, 0 ) );
vec4 color_left2 = imageLoad( color_image, uv + ivec2( -2, 0 ) );
vec4 color_right = imageLoad( color_image, uv + ivec2( 1, 0 ) );
vec4 color_right2 = imageLoad( color_image, uv + ivec2( 2, 0 ) );
float c = ( length( color_left - color_right ) - params.contrastThreshold ) * params.contrastIntensity;
float d = min( 1.0, c );
edge = max( d, edge );
vec4 smoothedColor = color_left + color_left2 +
2.0 * color +
color_right + color_right2;
smoothedColor /= 6.0;
smoothedColor =vec4( 0.0, 0.0, 0.0, 1.0 );
float gray = color.r * 0.2125 + color.g * 0.7154 + color.b * 0.0721;
vec3 debugViewColor = vec3( params.amounts.x * gray, params.amounts.y * centerDepth, edge );
color.rgb = mix( color.rgb, smoothedColor.rgb, edge * params.effectStrength );
color.rgb = mix( color.rgb, debugViewColor, params.debugView );
*/
vec4 color = imageLoad( color_image, uv );
color = mix( color, vec4( 0.0, 0.0, 0.0, 1.0 ), edgeStrength * params.effectStrength );
imageStore( color_image, uv, color );
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bshg7rg0k6pre"
path="res://.godot/imported/DepthAOShader.glsl-68a7bb82d9ad472873dfcaa383972842.res"
[deps]
source_file="res://addons/rokojori_action_library/Runtime/Rendering/Compositor/CompositorEffects/DepthAO/DepthAOShader.glsl"
dest_files=["res://.godot/imported/DepthAOShader.glsl-68a7bb82d9ad472873dfcaa383972842.res"]
[params]

View File

@ -14,13 +14,13 @@ namespace Rokojori
RDSampler sampler; RDSampler sampler;
[Export( PropertyHint.Range, "0,1") ] [Export( PropertyHint.Range, "0,1") ]
public float greyAmount; public float depthAmount = 1;
[Export( PropertyHint.Range, "0,1") ]
public float depthAmount;
[Export( PropertyHint.Range, "0.001,3") ] [Export( PropertyHint.Range, "0.001,3") ]
public float depthPower; public float depthPower = 1;
[Export( PropertyHint.Range, "0,1") ]
public float grayAmount = 0f;
protected override void OnConfigure() protected override void OnConfigure()
{ {
@ -39,9 +39,9 @@ namespace Rokojori
protected override void SetConstants() protected override void SetConstants()
{ {
constants.Set( constants.Set(
(Vector2)context.internalSize, depthAmount,
new Vector2( greyAmount, depthAmount ), depthPower,
depthPower grayAmount
); );
} }

View File

@ -4,45 +4,49 @@
layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in; layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in;
layout( rgba16f, set = 0, binding = 0) layout( rgba16f, set = 0, binding = 0)
uniform image2D color_image; uniform image2D colorImage;
layout( set = 1, binding = 0) layout( set = 1, binding = 0)
uniform sampler2D depth_sampler; uniform sampler2D depthSampler;
layout(push_constant, std430) layout(push_constant, std430)
uniform Params uniform Parameters
{ {
vec2 raster_size; float depthAmount;
vec2 amounts; float depthPower;
float power; float grayAmount;
} params; } parameters;
float sample_depth( ivec2 coord ) float sampleDepth( ivec2 coord, ivec2 size )
{ {
coord = clamp( coord, ivec2( 0 ), ivec2( params.raster_size ) - ivec2( 1 ) ); coord = clamp( coord, ivec2( 0 ), size - ivec2( 1 ) );
vec2 uv = ( vec2( coord ) + 0.5 ) / params.raster_size; vec2 uv = ( vec2( coord ) + 0.5 ) / size;
return texture( depth_sampler, uv ).r; return texture( depthSampler, uv ).r;
} }
void main() void main()
{ {
ivec2 uv = ivec2( gl_GlobalInvocationID.xy ); ivec2 uv = ivec2( gl_GlobalInvocationID.xy );
ivec2 size = ivec2( params.raster_size ); ivec2 size = imageSize( colorImage );
if ( uv.x >= size.x || uv.y >= size.y ) if ( uv.x >= size.x || uv.y >= size.y )
{ {
return; return;
} }
vec4 color = imageLoad( color_image, uv ); vec4 color = imageLoad( colorImage, uv );
float depth = sample_depth( uv ); float depth = sampleDepth( uv, size );
float gray = color.r * 0.2125 + color.g * 0.7154 + color.b * 0.0721; float gray = color.r * 0.2 + color.g * 0.7 + color.b * 0.1;
color.rgb = vec3( params.amounts.x * gray, pow( params.amounts.y * depth, params.power ), 0.0 ); float depthValue = pow( parameters.depthAmount * depth, parameters.depthPower );
imageStore( color_image, uv, color ); depthValue = mix( depthValue, depthValue * gray, parameters.grayAmount );
color.rgb = vec3( depthValue, depthValue, depthValue );
imageStore( colorImage, uv, color );
} }

View File

@ -0,0 +1,54 @@
using Godot;
using Godot.Collections;
using System.Collections.Generic;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class NormalViewEffect:SingleShaderCompositorEffect
{
public static readonly string shaderPath = Path( "DepthView/NormalViewShader.glsl" );
RDSampler sampler;
[Export( PropertyHint.Range, "0,1") ]
public float normalsAmount = 1;
[Export( PropertyHint.Range, "0,1") ]
public float grayAmount = 0f;
protected override void OnConfigure()
{
EffectCallbackType = EffectCallbackTypeEnum.PostTransparent;
_shaderPath = shaderPath;
_groupSize = 8;
}
protected override void OnInitialize()
{
base.OnInitialize();
sampler = context.Sampler( RenderingDevice.SamplerFilter.Nearest, RenderingDevice.SamplerRepeatMode.ClampToEdge );
}
protected override void SetConstants()
{
constants.Set(
normalsAmount,
grayAmount
);
}
protected override void RenderView()
{
context.AssignScreenColorTexture();
context.pushConstants = constants;
context.ProcessComputeProgram();
}
}
}

View File

@ -0,0 +1 @@
uid://b04udly3ubuf2

View File

@ -0,0 +1,49 @@
#[compute]
#version 450
layout( local_size_x = 8, local_size_y = 8, local_size_z = 1 ) in;
layout( rgba16f, set = 0, binding = 0)
uniform image2D colorImage;
layout( set = 1, binding = 0)
uniform sampler2D normalSampler;
layout( push_constant, std430 )
uniform Parameters
{
float normalsAmount;
float grayAmount;
} parameters;
vec3 sampleNormal( ivec2 coord, ivec2 size )
{
coord = clamp( coord, ivec2( 0 ), size - ivec2( 1 ) );
vec2 uv = ( vec2( coord ) + 0.5 ) / size;
return texture( normalSampler, uv ).xyz;
}
void main()
{
ivec2 uv = ivec2( gl_GlobalInvocationID.xy );
ivec2 size = imageSize( colorImage );
if ( uv.x >= size.x || uv.y >= size.y )
{
return;
}
vec4 color = imageLoad( colorImage, uv );
vec3 normal = sampleNormal( uv, size );
float gray = color.r * 0.2 + color.g * 0.7 + color.b * 0.1;
normal = mix( normal, normal * gray, parameters.grayAmount );
color.rgb = normal;
imageStore( colorImage, uv, color );
}

View File

@ -0,0 +1,14 @@
[remap]
importer="glsl"
type="RDShaderFile"
uid="uid://bcdpc2kr1ico"
path="res://.godot/imported/NormalViewShader.glsl-8808b7c889cc126ae77b26b3c812033a.res"
[deps]
source_file="res://addons/rokojori_action_library/Runtime/Rendering/Compositor/CompositorEffects/NormalView/NormalViewShader.glsl"
dest_files=["res://.godot/imported/NormalViewShader.glsl-8808b7c889cc126ae77b26b3c812033a.res"]
[params]

View File

@ -69,6 +69,12 @@ namespace Rokojori
return RDTexture.Depth( this ); return RDTexture.Depth( this );
} }
public RDTexture GetScreenNormalRoughnessTexture()
{
return RDTexture.NormalRoughness( this );
}
public void SetProgram( RDProgram p ) public void SetProgram( RDProgram p )
{ {
SetShaderAndPipeline( p.shader, p.pipeline ); SetShaderAndPipeline( p.shader, p.pipeline );
@ -107,6 +113,11 @@ namespace Rokojori
AssignTexture( GetScreenDepthTexture(), sampler, setIndex ); AssignTexture( GetScreenDepthTexture(), sampler, setIndex );
} }
public void AssignScreenNormalRoughnessTexture( RDSampler sampler = null, int setIndex = -1 )
{
AssignTexture( GetScreenNormalRoughnessTexture(), sampler, setIndex );
}
RDTexture _missingTexture = null; RDTexture _missingTexture = null;
Vector2I _missingTextureSize = new Vector2I( 64, 64 ); Vector2I _missingTextureSize = new Vector2I( 64, 64 );

View File

@ -14,18 +14,26 @@ namespace Rokojori
public static RDTexture Color( RDContext context ) public static RDTexture Color( RDContext context )
{ {
var rid = context.sceneBuffers.GetColorLayer( (uint) context.view ); // var rid = context.sceneBuffers.GetColorLayer( (uint) context.view );
var rid = context.sceneBuffers.GetTextureSlice( "render_buffers", "color", (uint) context.view, 0, 1, 1 );
return new RDTexture( context, rid ); return new RDTexture( context, rid );
} }
public static RDTexture Depth( RDContext context ) public static RDTexture Depth( RDContext context )
{ {
var rid = context.sceneBuffers.GetDepthLayer( (uint) context.view ); // var rid = context.sceneBuffers.GetDepthLayer( (uint) context.view );
var rid = context.sceneBuffers.GetTextureSlice( "render_buffers", "depth", (uint) context.view, 0, 1, 1 );
return new RDTexture( context, rid ); return new RDTexture( context, rid );
} }
public static RDTexture NormalRoughness( RDContext context )
{
// var rid = context.sceneBuffers.GetDepthLayer( (uint) context.view );
var rid = context.sceneBuffers.GetTextureSlice( "forward_clustered", "normal_roughness", (uint) context.view, 0, 1, 1 );
return new RDTexture( context, rid );
}
public void SetData( byte[] data, int layer = 0 ) public void SetData( byte[] data, int layer = 0 )
{ {
var error = context.renderingDevice.TextureUpdate( rid, (uint) layer, data ); var error = context.renderingDevice.TextureUpdate( rid, (uint) layer, data );

View File

@ -186,4 +186,14 @@ vec4 mixThreeColors( vec4 a, vec4 b, vec4 c, float t )
float wc = mapClamped( t, 0.5, 1, 0.0, 1.0 ); float wc = mapClamped( t, 0.5, 1, 0.0, 1.0 );
return a * wa + b * wb + c * wc; return a * wa + b * wb + c * wc;
}
vec3 gamma( vec3 color, float gamma )
{
color.r = pow( color.r, gamma );
color.g = pow( color.g, gamma );
color.b = pow( color.b, gamma );
return color;
} }

View File

@ -53,4 +53,21 @@ float triangle( float value )
vec2 onCircle( float angle ) vec2 onCircle( float angle )
{ {
return vec2( cos( angle ), sin( angle ) ); return vec2( cos( angle ), sin( angle ) );
}
float normalizeAngle( float degrees )
{
while ( degrees < 0.0 )
{
degrees += 360.0;
}
return degrees;
}
float angleDelta( float degreesA, float degreesB )
{
float angleDelta = degreesB - degreesA;
angleDelta = mod( angleDelta + 180.0, 360.0 ) - 180.0;
return angleDelta;
} }

View File

@ -15,6 +15,11 @@ vec3 applyMatrixWithoutTranslation( vec3 v, mat4 m )
return ( mw * vec4( v, 1.0 ) ).xyz; return ( mw * vec4( v, 1.0 ) ).xyz;
} }
vec3 applyMatrix( vec3 v, mat3 m )
{
return ( m * v ).xyz;
}
// L W V // L W V
// L // L
// W // W
@ -25,12 +30,12 @@ vec3 applyMatrixWithoutTranslation( vec3 v, mat4 m )
// WD // WD
// VD // VD
vec3 localToWorld( vec3 _VERTEX, mat4 _MODEL_MATRIX ) vec3 localToWorld( vec3 local, mat4 _MODEL_MATRIX )
{ {
return ( _MODEL_MATRIX * vec4( _VERTEX, 1.0 ) ).xyz; return ( _MODEL_MATRIX * vec4( local, 1.0 ) ).xyz;
} }
vec3 localToWorldDirection( vec3 _VERTEX, mat4 _MODEL_MATRIX ) vec3 localToWorldDirection( vec3 local, mat4 _MODEL_MATRIX )
{ {
mat4 mw = _MODEL_MATRIX; mat4 mw = _MODEL_MATRIX;
mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 0 ] = 0.0;
@ -38,20 +43,30 @@ vec3 localToWorldDirection( vec3 _VERTEX, mat4 _MODEL_MATRIX )
mw[ 3 ][ 2 ] = 0.0; mw[ 3 ][ 2 ] = 0.0;
mw[ 3 ][ 3 ] = 1.0; mw[ 3 ][ 3 ] = 1.0;
return ( mw * vec4( _VERTEX, 1.0 ) ).xyz; return ( mw * vec4( local, 1.0 ) ).xyz;
} }
vec3 localToView( vec3 _VERTEX, mat4 _MODELVIEW_MATRIX ) vec3 localToView( vec3 local, mat4 _MODELVIEW_MATRIX )
{ {
return ( _MODELVIEW_MATRIX * vec4( _VERTEX, 1.0 ) ).xyz; return ( _MODELVIEW_MATRIX * vec4( local, 1.0 ) ).xyz;
} }
vec3 worldToLocal( vec3 _VERTEX, mat4 _MODEL_MATRIX ) vec3 localToViewDirection( vec3 local, mat4 _MODELVIEW_MATRIX )
{ {
return ( inverse( _MODEL_MATRIX ) * vec4( _VERTEX, 1.0 ) ).xyz; return applyMatrixWithoutTranslation( local, _MODELVIEW_MATRIX );
} }
vec3 worldToLocalDirection( vec3 _VERTEX, mat4 _MODEL_MATRIX ) vec3 localToViewDirection( vec3 local, mat3 _MODELVIEW_NORMAL_MATRIX )
{
return applyMatrix( local, _MODELVIEW_NORMAL_MATRIX );
}
vec3 worldToLocal( vec3 world, mat4 _MODEL_MATRIX )
{
return ( inverse( _MODEL_MATRIX ) * vec4( world, 1.0 ) ).xyz;
}
vec3 worldToLocalDirection( vec3 world, mat4 _MODEL_MATRIX )
{ {
mat4 mw = inverse( _MODEL_MATRIX ); mat4 mw = inverse( _MODEL_MATRIX );
mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 0 ] = 0.0;
@ -59,7 +74,7 @@ vec3 worldToLocalDirection( vec3 _VERTEX, mat4 _MODEL_MATRIX )
mw[ 3 ][ 2 ] = 0.0; mw[ 3 ][ 2 ] = 0.0;
mw[ 3 ][ 3 ] = 1.0; mw[ 3 ][ 3 ] = 1.0;
return ( mw * vec4( _VERTEX, 1.0 ) ).xyz; return ( mw * vec4( world, 1.0 ) ).xyz;
} }
@ -68,7 +83,7 @@ vec3 worldToView( vec3 world, mat4 _VIEW_MATRIX )
return ( _VIEW_MATRIX * vec4( world, 1.0 ) ).xyz; return ( _VIEW_MATRIX * vec4( world, 1.0 ) ).xyz;
} }
vec3 worldToViewDirection( vec3 direction, mat4 _VIEW_MATRIX ) vec3 worldToViewDirection( vec3 worldDirection, mat4 _VIEW_MATRIX )
{ {
mat4 mw = _VIEW_MATRIX; mat4 mw = _VIEW_MATRIX;
mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 0 ] = 0.0;
@ -76,7 +91,7 @@ vec3 worldToViewDirection( vec3 direction, mat4 _VIEW_MATRIX )
mw[ 3 ][ 2 ] = 0.0; mw[ 3 ][ 2 ] = 0.0;
mw[ 3 ][ 3 ] = 1.0; mw[ 3 ][ 3 ] = 1.0;
return ( mw * vec4( direction, 1.0 ) ).xyz; return ( mw * vec4( worldDirection, 1.0 ) ).xyz;
} }
vec3 viewToWorld( vec3 view, mat4 _INV_VIEW_MATRIX ) vec3 viewToWorld( vec3 view, mat4 _INV_VIEW_MATRIX )
@ -84,7 +99,7 @@ vec3 viewToWorld( vec3 view, mat4 _INV_VIEW_MATRIX )
return applyMatrix( view, _INV_VIEW_MATRIX ); return applyMatrix( view, _INV_VIEW_MATRIX );
} }
vec3 viewToWorldDirection( vec3 view, mat4 _INV_VIEW_MATRIX ) vec3 viewToWorldDirection( vec3 viewDirection, mat4 _INV_VIEW_MATRIX )
{ {
mat4 mw = _INV_VIEW_MATRIX; mat4 mw = _INV_VIEW_MATRIX;
mw[ 3 ][ 0 ] = 0.0; mw[ 3 ][ 0 ] = 0.0;
@ -93,7 +108,7 @@ vec3 viewToWorldDirection( vec3 view, mat4 _INV_VIEW_MATRIX )
mw[ 3 ][ 3 ] = 1.0; mw[ 3 ][ 3 ] = 1.0;
return applyMatrix( view, mw ); return applyMatrix( viewDirection, mw );
} }
vec3 viewToLocal( vec3 view, mat4 _INV_VIEW_MATRIX, mat4 _MODEL_MATRIX ) vec3 viewToLocal( vec3 view, mat4 _INV_VIEW_MATRIX, mat4 _MODEL_MATRIX )

View File

@ -43,6 +43,13 @@ namespace Rokojori
{ {
return material; return material;
} }
var mesh = mi.Mesh;
if ( mesh != null && mesh.SurfaceGetMaterial( 0 ) != null )
{
return (M) mesh.SurfaceGetMaterial( 0 );
}
} }
else if ( node is CsgPrimitive3D ) else if ( node is CsgPrimitive3D )
{ {
@ -87,6 +94,8 @@ namespace Rokojori
{ {
if ( node is MeshInstance3D mi) if ( node is MeshInstance3D mi)
{ {
var mesh = mi.Mesh;
mi.SetSurfaceOverrideMaterial( index, material ); mi.SetSurfaceOverrideMaterial( index, material );
if ( index == 0 && mi.MaterialOverride != null ) if ( index == 0 && mi.MaterialOverride != null )

View File

@ -0,0 +1,47 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, unshaded;
#include "res://addons/rokojori_action_library/Runtime/Shading/Library/Colors.gdshaderinc"
uniform float gammaA = 1.0;
uniform sampler2D channelTextureA : hint_default_white, filter_linear_mipmap, repeat_enable;
uniform float gammaB = 1.0;
uniform sampler2D channelTextureB : hint_default_white, filter_linear_mipmap, repeat_enable;
uniform float gammaC = 1.0;
uniform sampler2D channelTextureC : hint_default_black, filter_linear_mipmap, repeat_enable;
uniform vec3 uv1_scale = vec3( 1, 1, 1 );
uniform vec3 uv1_offset = vec3( 0, 0, 0 );
void vertex()
{
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
vec4 getColor( vec2 uv, sampler2D channelTexture, int index, float gammaPower )
{
vec4 color = texture( channelTexture, uv );
vec4 outputColor = index == 0 ? vec4( color.r, 0, 0, 1 ) :
index == 1 ? vec4( 0, color.g, 0, 1 ) :
vec4( 0, 0, color.b, 1 );
outputColor.rgb = gamma( outputColor.rgb, gammaPower );
return outputColor;
}
void fragment()
{
vec4 colorA = getColor( UV, channelTextureA, 0, gammaA );
vec4 colorB = getColor( UV, channelTextureB, 1, gammaB );
vec4 colorC = getColor( UV, channelTextureC, 2, gammaC );
ALBEDO = colorA.rgb + colorB.rgb + colorC.rgb;
}

View File

@ -0,0 +1 @@
uid://drcoijnirdo13

View File

@ -0,0 +1,17 @@
shader_type spatial;
render_mode blend_mix, unshaded, alpha_to_coverage;
uniform sampler2D screenMap: hint_screen_texture, repeat_disable, filter_nearest;
uniform sampler2D normalMap: hint_normal_roughness_texture, repeat_disable, filter_nearest;
void vertex()
{
POSITION = vec4( VERTEX.xy, 0.1, 1.0 );
}
void fragment()
{
ALBEDO = textureLod( normalMap, UV, 0 ).rgb;
ALPHA = textureLod( screenMap, UV, 0 ).w;
}

View File

@ -0,0 +1 @@
uid://d2xw77vdetaln

View File

@ -0,0 +1,48 @@
shader_type spatial;
render_mode blend_mix,depth_draw_opaque,cull_disabled, unshaded;
uniform vec4 albedo_color : source_color;
uniform sampler2D albedo_texture : source_color;
uniform sampler2D normal_texture : source_color;
uniform bool use_normalmap = false;
uniform bool use_alpha_texture = false;
uniform float alpha_scissor_threshold : hint_range(0,1);
uniform float normal_scale : hint_range(-5,5) = 1.0;
uniform vec3 uv1_scale;
uniform vec3 uv1_offset;
void vertex()
{
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
void fragment()
{
vec2 base_uv = UV;
vec4 albedo = texture( albedo_texture, base_uv ) * albedo_color;
vec4 normal_tex = texture( normal_texture, base_uv );
// 0.5 + -1.0 == -1.0 + 0.5
//ALBEDO = vec3(1.0 - NORMAL.y, 1.0 - NORMAL.x, - NORMAL.z)* 0.5;
if ( use_normalmap )
{
vec3 normalmap;
normalmap.xy = normal_tex.xy * 2.0 - 1.0;
normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy)));
NORMAL = normalize(mix(NORMAL, TANGENT * normalmap.x + BINORMAL * normalmap.y + NORMAL * normalmap.z, normal_scale));
}
ALBEDO = vec3( -NORMAL.x, NORMAL.y, -NORMAL.z) * 0.5 + 0.5;
if ( use_alpha_texture )
{
ALPHA = albedo.a;
ALPHA_SCISSOR_THRESHOLD = alpha_scissor_threshold;
}
}

View File

@ -0,0 +1 @@
uid://xcerdccafolw

View File

@ -0,0 +1,20 @@
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, unshaded;
uniform vec3 uv1_scale = vec3( 1, 1, 0 );
uniform vec3 uv1_offset = vec3( 0, 0, 0 );
void vertex()
{
UV = UV * uv1_scale.xy + uv1_offset.xy;
}
void fragment()
{
ALBEDO = vec3( UV.x, UV.y, 0.0 );
}

View File

@ -0,0 +1 @@
uid://c7drksm444hh8