1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
|
// Amplify Shader Editor - Visual Shader Editing Tool
// Copyright (c) Amplify Creations, Lda <info@amplify.pt>
using UnityEngine;
using UnityEditor;
using System;
namespace AmplifyShaderEditor
{
enum POMTexTypes
{
Texture2D,
Texture3D,
TextureArray
};
[Serializable]
[NodeAttributes( "Parallax Occlusion Mapping", "UV Coordinates", "Calculates offseted UVs for parallax occlusion mapping" )]
public sealed class ParallaxOcclusionMappingNode : ParentNode
{
private const string ArrayIndexStr = "Array Index";
private const string Tex3DSliceStr = "Tex3D Slice";
private readonly string[] m_channelTypeStr = { "Red Channel", "Green Channel", "Blue Channel", "Alpha Channel" };
private readonly string[] m_channelTypeVal = { "r", "g", "b", "a" };
[SerializeField]
private int m_selectedChannelInt = 0;
//[SerializeField]
//private int m_minSamples = 8;
//[SerializeField]
//private int m_maxSamples = 16;
[SerializeField]
private InlineProperty m_inlineMinSamples = new InlineProperty( 8 );
[SerializeField]
private InlineProperty m_inlineMaxSamples = new InlineProperty( 16 );
[ SerializeField]
private int m_sidewallSteps = 2;
[SerializeField]
private float m_defaultScale = 0.02f;
[SerializeField]
private float m_defaultRefPlane = 0f;
[SerializeField]
private bool m_clipEnds = false;
[SerializeField]
private Vector2 m_tilling = new Vector2( 1, 1 );
[SerializeField]
private bool m_useCurvature = false;
//[SerializeField]
//private bool m_useTextureArray = false;
[SerializeField]
private POMTexTypes m_pomTexType = POMTexTypes.Texture2D;
//[SerializeField]
//private bool m_useCurvature = false;
[SerializeField]
private Vector2 m_CurvatureVector = new Vector2( 0, 0 );
private string m_functionHeader = "POM( {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13} )";
private string m_functionBody = string.Empty;
//private const string WorldDirVarStr = "worldViewDir";
private InputPort m_uvPort;
private InputPort m_texPort;
private InputPort m_scalePort;
private InputPort m_viewdirTanPort;
private InputPort m_refPlanePort;
private InputPort m_curvaturePort;
private InputPort m_arrayIndexPort;
private OutputPort m_pomUVPort;
private Vector4Node m_texCoordsHelper;
protected override void CommonInit( int uniqueId )
{
base.CommonInit( uniqueId );
AddInputPort( WirePortDataType.FLOAT2, false, "UV" );
AddInputPort( WirePortDataType.SAMPLER2D, false, "Tex" );
AddInputPort( WirePortDataType.FLOAT, false, "Scale" );
AddInputPort( WirePortDataType.FLOAT3, false, "ViewDir (tan)" );
AddInputPort( WirePortDataType.FLOAT, false, "Ref Plane" );
AddInputPort( WirePortDataType.FLOAT2, false, "Curvature" );
AddInputPort( WirePortDataType.FLOAT, false, ArrayIndexStr );
AddOutputPort( WirePortDataType.FLOAT2, "Out" );
m_uvPort = m_inputPorts[ 0 ];
m_texPort = m_inputPorts[ 1 ];
m_scalePort = m_inputPorts[ 2 ];
m_viewdirTanPort = m_inputPorts[ 3 ];
m_refPlanePort = m_inputPorts[ 4 ];
m_pomUVPort = m_outputPorts[ 0 ];
m_curvaturePort = m_inputPorts[ 5 ];
m_arrayIndexPort = m_inputPorts[ 6 ];
m_scalePort.FloatInternalData = 0.02f;
m_useInternalPortData = false;
m_textLabelWidth = 130;
m_autoWrapProperties = true;
m_curvaturePort.Visible = false;
m_arrayIndexPort.Visible = false;
UpdateSampler();
}
public override void DrawProperties()
{
base.DrawProperties();
EditorGUI.BeginChangeCheck();
m_selectedChannelInt = EditorGUILayoutPopup( "Channel", m_selectedChannelInt, m_channelTypeStr );
if ( EditorGUI.EndChangeCheck() )
{
UpdateSampler();
GeneratePOMfunction();
}
EditorGUIUtility.labelWidth = 105;
//m_minSamples = EditorGUILayoutIntSlider( "Min Samples", m_minSamples, 1, 128 );
UndoParentNode inst = this;
m_inlineMinSamples.CustomDrawer( ref inst, ( x ) => { m_inlineMinSamples.IntValue = EditorGUILayoutIntSlider( "Min Samples", m_inlineMinSamples.IntValue, 1, 128 ); }, "Min Samples" );
//m_maxSamples = EditorGUILayoutIntSlider( "Max Samples", m_maxSamples, 1, 128 );
m_inlineMaxSamples.CustomDrawer( ref inst, ( x ) => { m_inlineMaxSamples.IntValue = EditorGUILayoutIntSlider( "Max Samples", m_inlineMaxSamples.IntValue, 1, 128 ); }, "Max Samples" );
EditorGUI.BeginChangeCheck();
m_sidewallSteps = EditorGUILayoutIntSlider( "Sidewall Steps", m_sidewallSteps, 0, 10 );
if ( EditorGUI.EndChangeCheck() )
{
GeneratePOMfunction();
}
EditorGUI.BeginDisabledGroup(m_scalePort.IsConnected );
m_defaultScale = EditorGUILayoutSlider( "Default Scale", m_defaultScale, 0, 1 );
EditorGUI.EndDisabledGroup();
EditorGUI.BeginDisabledGroup( m_refPlanePort.IsConnected );
m_defaultRefPlane = EditorGUILayoutSlider( "Default Ref Plane", m_defaultRefPlane, 0, 1 );
EditorGUI.EndDisabledGroup();
EditorGUIUtility.labelWidth = m_textLabelWidth;
EditorGUI.BeginChangeCheck();
//m_useTextureArray = EditorGUILayoutToggle( "Use Texture Array", m_useTextureArray );
m_pomTexType = (POMTexTypes)EditorGUILayoutEnumPopup( "Texture Type", m_pomTexType );
if( EditorGUI.EndChangeCheck() )
{
UpdateIndexPort();
m_sizeIsDirty = true;
GeneratePOMfunction();
//UpdateCurvaturePort();
}
if( m_arrayIndexPort.Visible && !m_arrayIndexPort.IsConnected )
{
m_arrayIndexPort.FloatInternalData = EditorGUILayoutFloatField( "Array Index", m_arrayIndexPort.FloatInternalData );
}
//float cached = EditorGUIUtility.labelWidth;
//EditorGUIUtility.labelWidth = 70;
m_clipEnds = EditorGUILayoutToggle( "Clip Edges", m_clipEnds );
//EditorGUIUtility.labelWidth = -1;
//EditorGUIUtility.labelWidth = 100;
//EditorGUILayout.BeginHorizontal();
//EditorGUI.BeginDisabledGroup( !m_clipEnds );
//m_tilling = EditorGUILayout.Vector2Field( string.Empty, m_tilling );
//EditorGUI.EndDisabledGroup();
//EditorGUILayout.EndHorizontal();
//EditorGUIUtility.labelWidth = cached;
EditorGUI.BeginChangeCheck();
m_useCurvature = EditorGUILayoutToggle( "Clip Silhouette", m_useCurvature );
if ( EditorGUI.EndChangeCheck() )
{
GeneratePOMfunction();
UpdateCurvaturePort();
}
EditorGUI.BeginDisabledGroup( !(m_useCurvature && !m_curvaturePort.IsConnected) );
m_CurvatureVector = EditorGUILayoutVector2Field( string.Empty, m_CurvatureVector );
EditorGUI.EndDisabledGroup();
EditorGUILayout.HelpBox( "WARNING:\nTex must be connected to a Texture Object for this node to work\n\nMin and Max samples:\nControl the minimum and maximum number of layers extruded\n\nSidewall Steps:\nThe number of interpolations done to smooth the extrusion result on the side of the layer extrusions, min is used at steep angles while max is used at orthogonal angles\n\n"+
"Ref Plane:\nReference plane lets you adjust the starting reference height, 0 = deepen ground, 1 = raise ground, any value above 0 might cause distortions at higher angles\n\n"+
"Clip Edges:\nThis will clip the ends of your uvs to give a more 3D look at the edges. It'll use the tilling given by your Heightmap input.\n\n"+
"Clip Silhouette:\nTurning this on allows you to use the UV coordinates to clip the effect curvature in U or V axis, useful for cylinders, works best with 'Clip Edges' turned OFF", MessageType.None );
}
private void UpdateIndexPort()
{
m_arrayIndexPort.Visible = m_pomTexType != POMTexTypes.Texture2D;
if( m_arrayIndexPort.Visible )
{
m_arrayIndexPort.Name = m_pomTexType == POMTexTypes.Texture3D ? Tex3DSliceStr : ArrayIndexStr;
}
}
private void UpdateSampler()
{
m_texPort.Name = "Tex (" + m_channelTypeVal[ m_selectedChannelInt ].ToUpper() + ")";
}
private void UpdateCurvaturePort()
{
if ( m_useCurvature )
m_curvaturePort.Visible = true;
else
m_curvaturePort.Visible = false;
m_sizeIsDirty = true;
}
public override string GenerateShaderForOutput( int outputId, ref MasterNodeDataCollector dataCollector, bool ignoreLocalvar )
{
if( !m_texPort.IsConnected )
{
UIUtils.ShowMessage( UniqueId, "Parallax Occlusion Mapping node only works if a Texture Object is connected to its Tex (R) port" );
return "0";
}
base.GenerateShaderForOutput( outputId, ref dataCollector, ignoreLocalvar );
WirePortDataType texType = ( m_pomTexType == POMTexTypes.Texture3D )?WirePortDataType.SAMPLER3D: WirePortDataType.SAMPLER2D;
GeneratePOMfunction();
string arrayIndex = m_arrayIndexPort.Visible?m_arrayIndexPort.GeneratePortInstructions( ref dataCollector ):"0";
string textcoords = m_uvPort.GeneratePortInstructions( ref dataCollector );
if( m_pomTexType == POMTexTypes.Texture3D )
{
string texName = "pomTexCoord" + OutputId;
dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, WirePortDataType.FLOAT3, texName, string.Format( "float3({0},{1})", textcoords, arrayIndex ) );
textcoords = texName;
}
string texture = m_texPort.GenerateShaderForOutput( ref dataCollector, texType,false,true );
string scale = m_defaultScale.ToString();
if( m_scalePort.IsConnected )
scale = m_scalePort.GeneratePortInstructions( ref dataCollector );
string viewDirTan = "";
if ( !m_viewdirTanPort.IsConnected )
{
if ( !dataCollector.DirtyNormal )
dataCollector.ForceNormal = true;
if ( dataCollector.IsTemplate )
{
viewDirTan = dataCollector.TemplateDataCollectorInstance.GetTangentViewDir( CurrentPrecisionType );
}
else
{
viewDirTan = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.Tangent );
//dataCollector.AddToInput( UniqueId, SurfaceInputs.VIEW_DIR, m_currentPrecisionType );
//viewDirTan = Constants.InputVarStr + "." + UIUtils.GetInputValueFromType( SurfaceInputs.VIEW_DIR );
}
}
else
{
viewDirTan = m_viewdirTanPort.GeneratePortInstructions( ref dataCollector );
}
//generate world normal
string normalWorld = string.Empty;
if ( dataCollector.IsTemplate )
{
normalWorld = dataCollector.TemplateDataCollectorInstance.GetWorldNormal( CurrentPrecisionType );
}
else
{
dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_NORMAL, CurrentPrecisionType );
dataCollector.AddToInput( UniqueId, SurfaceInputs.INTERNALDATA, addSemiColon: false );
normalWorld = GeneratorUtils.GenerateWorldNormal( ref dataCollector, UniqueId );
}
//string normalWorld = "WorldNormalVector( " + Constants.InputVarStr + ", float3( 0, 0, 1 ) )";
//generate viewDir in world space
//string worldPos = string.Empty;
//if( dataCollector.IsTemplate )
//{
// worldPos = dataCollector.TemplateDataCollectorInstance.GetWorldPos();
//}
//else
//{
// dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS );
// worldPos = Constants.InputVarStr + ".worldPos";
//}
//if( !dataCollector.IsTemplate )
// dataCollector.AddToInput( UniqueId, SurfaceInputs.WORLD_POS );
string worldViewDir = GeneratorUtils.GenerateViewDirection( ref dataCollector, UniqueId, ViewSpace.World );
//dataCollector.AddToLocalVariables( UniqueId, m_currentPrecisionType, WirePortDataType.FLOAT3, WorldDirVarStr, TemplateHelperFunctions.WorldSpaceViewDir( dataCollector, worldPos, true ) );
string dx = "ddx("+ textcoords + ")";
string dy = "ddy(" + textcoords + ")";
string refPlane = m_defaultRefPlane.ToString();
if ( m_refPlanePort.IsConnected )
refPlane = m_refPlanePort.GeneratePortInstructions( ref dataCollector );
string curvature = "float2("+ m_CurvatureVector.x + "," + m_CurvatureVector.y + ")";
if ( m_useCurvature )
{
dataCollector.AddToProperties( UniqueId, "[Header(Parallax Occlusion Mapping)]", 300 );
dataCollector.AddToProperties( UniqueId, "_CurvFix(\"Curvature Bias\", Range( 0 , 1)) = 1", 301 );
dataCollector.AddToUniforms( UniqueId, "uniform float _CurvFix;" );
if ( m_curvaturePort.IsConnected )
curvature = m_curvaturePort.GeneratePortInstructions( ref dataCollector );
}
string localVarName = "OffsetPOM" + OutputId;
string textCoordsST = string.Empty;
//string textureSTType = dataCollector.IsSRP ? "float4 " : "uniform float4 ";
//dataCollector.AddToUniforms( UniqueId, textureSTType + texture +"_ST;");
if( m_texCoordsHelper == null )
{
m_texCoordsHelper = CreateInstance<Vector4Node>();
m_texCoordsHelper.ContainerGraph = ContainerGraph;
m_texCoordsHelper.SetBaseUniqueId( UniqueId, true );
m_texCoordsHelper.RegisterPropertyOnInstancing = false;
m_texCoordsHelper.AddGlobalToSRPBatcher = true;
}
if( UIUtils.CurrentWindow.OutsideGraph.IsInstancedShader )
{
m_texCoordsHelper.CurrentParameterType = PropertyType.InstancedProperty;
}
else
{
m_texCoordsHelper.CurrentParameterType = PropertyType.Global;
}
m_texCoordsHelper.ResetOutputLocals();
m_texCoordsHelper.SetRawPropertyName( texture + "_ST" );
textCoordsST = m_texCoordsHelper.GenerateShaderForOutput( 0, ref dataCollector, false );
//////
if( m_pomTexType == POMTexTypes.TextureArray )
dataCollector.UsingArrayDerivatives = true;
string textureArgs = string.Empty;
if( m_pomTexType == POMTexTypes.TextureArray )
{
if( UIUtils.CurrentWindow.OutsideGraph.IsSRP )
{
textureArgs = "TEXTURE2D_ARRAY_ARGS( " + texture + ", sampler" + texture + ")";
}
else
{
textureArgs = "UNITY_PASS_TEX2DARRAY(" + texture + ")";
}
}
else
{
bool sampleThroughMacros = UIUtils.CurrentWindow.OutsideGraph.SamplingThroughMacros;
if( sampleThroughMacros )
{
dataCollector.AddToUniforms( UniqueId, string.Format( Constants.SamplerDeclarationSRPMacros[ TextureType.Texture2D ], texture ) );
textureArgs = string.Format( "{0},sampler{0}", texture );
}
else
{
textureArgs = texture;
}
}
//string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, ( (m_pomTexType == POMTexTypes.TextureArray) ? "UNITY_PASS_TEX2DARRAY(" + texture + ")": texture), textcoords, dx, dy, normalWorld, worldViewDir, viewDirTan, m_minSamples, m_maxSamples, scale, refPlane, texture+"_ST.xy", curvature, arrayIndex );
string functionResult = dataCollector.AddFunctions( m_functionHeader, m_functionBody, textureArgs, textcoords, dx, dy, normalWorld, worldViewDir, viewDirTan, m_inlineMinSamples.GetValueOrProperty(false), m_inlineMinSamples.GetValueOrProperty(false), scale, refPlane, textCoordsST + ".xy", curvature, arrayIndex );
dataCollector.AddLocalVariable( UniqueId, CurrentPrecisionType, m_pomUVPort.DataType, localVarName, functionResult );
return GetOutputVectorItem( 0, outputId, localVarName );
}
private void GeneratePOMfunction()
{
bool sampleThroughMacros = UIUtils.CurrentWindow.OutsideGraph.SamplingThroughMacros;
m_functionBody = string.Empty;
switch( m_pomTexType )
{
default:
case POMTexTypes.Texture2D:
{
string sampleParam = sampleThroughMacros ? "TEXTURE2D_PARAM(heightMap,samplerheightMap)" : "sampler2D heightMap";
IOUtils.AddFunctionHeader( ref m_functionBody, string.Format("inline float2 POM( {0}, float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )", sampleParam ));
}
break;
case POMTexTypes.Texture3D:
{
string sampleParam = sampleThroughMacros ? "TEXTURE3D_PARAM( heightMap,samplerheightMap) " : "sampler3D heightMap";
IOUtils.AddFunctionHeader( ref m_functionBody, string.Format("inline float2 POM( {0}, float3 uvs, float3 dx, float3 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )", sampleParam ) );
}
break;
case POMTexTypes.TextureArray:
if( UIUtils.CurrentWindow.OutsideGraph.IsSRP )
IOUtils.AddFunctionHeader( ref m_functionBody, "inline float2 POM( TEXTURE2D_ARRAY_PARAM(heightMap,samplerheightMap), float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )" );
else
IOUtils.AddFunctionHeader( ref m_functionBody, "inline float2 POM( UNITY_ARGS_TEX2DARRAY(heightMap), float2 uvs, float2 dx, float2 dy, float3 normalWorld, float3 viewWorld, float3 viewDirTan, int minSamples, int maxSamples, float parallax, float refPlane, float2 tilling, float2 curv, int index )" );
break;
}
IOUtils.AddFunctionLine( ref m_functionBody, "float3 result = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "int stepIndex = 0;" );
//IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )( minSamples + dot( viewWorld, normalWorld ) * ( maxSamples - minSamples ) );" );
//IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )lerp( maxSamples, minSamples, length( fwidth( uvs ) ) * 10 );" );
IOUtils.AddFunctionLine( ref m_functionBody, "int numSteps = ( int )lerp( (float)maxSamples, (float)minSamples, saturate( dot( normalWorld, viewWorld ) ) );" );
IOUtils.AddFunctionLine( ref m_functionBody, "float layerHeight = 1.0 / numSteps;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float2 plane = parallax * ( viewDirTan.xy / viewDirTan.z );" );
switch( m_pomTexType )
{
default:
case POMTexTypes.Texture2D:
IOUtils.AddFunctionLine( ref m_functionBody, "uvs += refPlane * plane;" );
break;
case POMTexTypes.Texture3D:
IOUtils.AddFunctionLine( ref m_functionBody, "uvs.xy += refPlane * plane;" );
break;
case POMTexTypes.TextureArray:
IOUtils.AddFunctionLine( ref m_functionBody, "uvs += refPlane * plane;" );
break;
}
IOUtils.AddFunctionLine( ref m_functionBody, "float2 deltaTex = -plane * layerHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float2 prevTexOffset = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float prevRayZ = 1.0f;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float prevHeight = 0.0f;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float2 currTexOffset = deltaTex;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float currRayZ = 1.0f - layerHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float currHeight = 0.0f;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float intersection = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float2 finalTexOffset = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "while ( stepIndex < numSteps + 1 )" );
IOUtils.AddFunctionLine( ref m_functionBody, "{" );
if( m_useCurvature )
{
IOUtils.AddFunctionLine( ref m_functionBody, " result.z = dot( curv, currTexOffset * currTexOffset );" );
switch( m_pomTexType )
{
default:
case POMTexTypes.Texture2D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_GRAD( heightMap, samplerheightMap, uvs + currTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = tex2Dgrad( heightMap, uvs + currTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
}
}
break;
case POMTexTypes.Texture3D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_GRAD( heightMap, samplerheightMap, uvs + float3(currTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = tex3Dgrad( heightMap, uvs + float3(currTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
}
}
break;
case POMTexTypes.TextureArray:
if( UIUtils.CurrentWindow.OutsideGraph.IsSRP )
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_ARRAY_GRAD( heightMap,samplerheightMap, uvs + currTexOffset,index, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
else
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = ASE_SAMPLE_TEX2DARRAY_GRAD( heightMap, float3(uvs + currTexOffset,index), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + " * ( 1 - result.z );" );
break;
}
}
else
{
switch( m_pomTexType )
{
default:
case POMTexTypes.Texture2D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_GRAD( heightMap,samplerheightMap, uvs + currTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = tex2Dgrad( heightMap, uvs + currTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
}
break;
case POMTexTypes.Texture3D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_GRAD( heightMap, samplerheightMap, uvs + float3(currTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = tex3Dgrad( heightMap, uvs + float3(currTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
}
break;
case POMTexTypes.TextureArray:
if( UIUtils.CurrentWindow.OutsideGraph.IsSRP )
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = SAMPLE_TEXTURE2D_ARRAY_GRAD( heightMap, samplerheightMap, uvs + currTexOffset,index, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
else
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = ASE_SAMPLE_TEX2DARRAY_GRAD( heightMap, float3(uvs + currTexOffset,index), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
break;
}
}
IOUtils.AddFunctionLine( ref m_functionBody, " if ( currHeight > currRayZ )" );
IOUtils.AddFunctionLine( ref m_functionBody, " {" );
IOUtils.AddFunctionLine( ref m_functionBody, " stepIndex = numSteps + 1;" );
IOUtils.AddFunctionLine( ref m_functionBody, " }" );
IOUtils.AddFunctionLine( ref m_functionBody, " else" );
IOUtils.AddFunctionLine( ref m_functionBody, " {" );
IOUtils.AddFunctionLine( ref m_functionBody, " stepIndex++;" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevTexOffset = currTexOffset;" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevRayZ = currRayZ;" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevHeight = currHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " currTexOffset += deltaTex;" );
if ( m_useCurvature )
IOUtils.AddFunctionLine( ref m_functionBody, " currRayZ -= layerHeight * ( 1 - result.z ) * (1+_CurvFix);" );
else
IOUtils.AddFunctionLine( ref m_functionBody, " currRayZ -= layerHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " }" );
IOUtils.AddFunctionLine( ref m_functionBody, "}" );
if ( m_sidewallSteps > 0 )
{
IOUtils.AddFunctionLine( ref m_functionBody, "int sectionSteps = " + m_sidewallSteps + ";" );
IOUtils.AddFunctionLine( ref m_functionBody, "int sectionIndex = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float newZ = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "float newHeight = 0;" );
IOUtils.AddFunctionLine( ref m_functionBody, "while ( sectionIndex < sectionSteps )" );
IOUtils.AddFunctionLine( ref m_functionBody, "{" );
IOUtils.AddFunctionLine( ref m_functionBody, " intersection = ( prevHeight - prevRayZ ) / ( prevHeight - currHeight + currRayZ - prevRayZ );" );
IOUtils.AddFunctionLine( ref m_functionBody, " finalTexOffset = prevTexOffset + intersection * deltaTex;" );
IOUtils.AddFunctionLine( ref m_functionBody, " newZ = prevRayZ - intersection * layerHeight;" );
switch( m_pomTexType )
{
default:
case POMTexTypes.Texture2D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = SAMPLE_TEXTURE2D_GRAD( heightMap, samplerheightMap, uvs + finalTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = tex2Dgrad( heightMap, uvs + finalTexOffset, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
}
break;
case POMTexTypes.Texture3D:
{
if( sampleThroughMacros )
{
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = SAMPLE_TEXTURE2D_GRAD( heightMap, samplerheightMap, uvs + float3(finalTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = tex3Dgrad( heightMap, uvs + float3(finalTexOffset,0), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
}
}
break;
case POMTexTypes.TextureArray:
if( UIUtils.CurrentWindow.OutsideGraph.IsSRP )
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = SAMPLE_TEXTURE2D_ARRAY_GRAD( heightMap, samplerheightMap, uvs + finalTexOffset,index, dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
else
IOUtils.AddFunctionLine( ref m_functionBody, " newHeight = ASE_SAMPLE_TEX2DARRAY_GRAD( heightMap, float3(uvs + finalTexOffset,index), dx, dy )." + m_channelTypeVal[ m_selectedChannelInt ] + ";" );
break;
}
IOUtils.AddFunctionLine( ref m_functionBody, " if ( newHeight > newZ )" );
IOUtils.AddFunctionLine( ref m_functionBody, " {" );
IOUtils.AddFunctionLine( ref m_functionBody, " currTexOffset = finalTexOffset;" );
IOUtils.AddFunctionLine( ref m_functionBody, " currHeight = newHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " currRayZ = newZ;" );
IOUtils.AddFunctionLine( ref m_functionBody, " deltaTex = intersection * deltaTex;" );
IOUtils.AddFunctionLine( ref m_functionBody, " layerHeight = intersection * layerHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " }" );
IOUtils.AddFunctionLine( ref m_functionBody, " else" );
IOUtils.AddFunctionLine( ref m_functionBody, " {" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevTexOffset = finalTexOffset;" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevHeight = newHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " prevRayZ = newZ;" );
IOUtils.AddFunctionLine( ref m_functionBody, " deltaTex = ( 1 - intersection ) * deltaTex;" );
IOUtils.AddFunctionLine( ref m_functionBody, " layerHeight = ( 1 - intersection ) * layerHeight;" );
IOUtils.AddFunctionLine( ref m_functionBody, " }" );
IOUtils.AddFunctionLine( ref m_functionBody, " sectionIndex++;" );
IOUtils.AddFunctionLine( ref m_functionBody, "}" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, "finalTexOffset = currTexOffset;" );
}
if ( m_useCurvature )
{
IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" );
IOUtils.AddFunctionLine( ref m_functionBody, "if ( unity_LightShadowBias.z == 0.0 )" );
IOUtils.AddFunctionLine( ref m_functionBody, "{" );
IOUtils.AddFunctionLine( ref m_functionBody, "#endif" );
IOUtils.AddFunctionLine( ref m_functionBody, " if ( result.z > 1 )" );
IOUtils.AddFunctionLine( ref m_functionBody, " clip( -1 );" );
IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" );
IOUtils.AddFunctionLine( ref m_functionBody, "}" );
IOUtils.AddFunctionLine( ref m_functionBody, "#endif" );
}
if ( m_clipEnds )
{
IOUtils.AddFunctionLine( ref m_functionBody, "result.xy = uvs + finalTexOffset;" );
IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" );
IOUtils.AddFunctionLine( ref m_functionBody, "if ( unity_LightShadowBias.z == 0.0 )" );
IOUtils.AddFunctionLine( ref m_functionBody, "{" );
IOUtils.AddFunctionLine( ref m_functionBody, "#endif" );
IOUtils.AddFunctionLine( ref m_functionBody, " if ( result.x < 0 )" );
IOUtils.AddFunctionLine( ref m_functionBody, " clip( -1 );" );
IOUtils.AddFunctionLine( ref m_functionBody, " if ( result.x > tilling.x )" );
IOUtils.AddFunctionLine( ref m_functionBody, " clip( -1 );" );
IOUtils.AddFunctionLine( ref m_functionBody, " if ( result.y < 0 )" );
IOUtils.AddFunctionLine( ref m_functionBody, " clip( -1 );" );
IOUtils.AddFunctionLine( ref m_functionBody, " if ( result.y > tilling.y )" );
IOUtils.AddFunctionLine( ref m_functionBody, " clip( -1 );" );
IOUtils.AddFunctionLine( ref m_functionBody, "#ifdef UNITY_PASS_SHADOWCASTER" );
IOUtils.AddFunctionLine( ref m_functionBody, "}" );
IOUtils.AddFunctionLine( ref m_functionBody, "#endif" );
IOUtils.AddFunctionLine( ref m_functionBody, "return result.xy;" );
}
else
{
IOUtils.AddFunctionLine( ref m_functionBody, "return uvs + finalTexOffset;" );
}
IOUtils.CloseFunctionBody( ref m_functionBody );
}
public override void ReadFromString( ref string[] nodeParams )
{
base.ReadFromString( ref nodeParams );
m_selectedChannelInt = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
//m_minSamples = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
//m_maxSamples = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
if( UIUtils.CurrentShaderVersion() < 15406 )
{
m_inlineMinSamples.IntValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
m_inlineMaxSamples.IntValue = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
}
else
{
m_inlineMinSamples.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
m_inlineMaxSamples.ReadFromString( ref m_currentReadParamIdx, ref nodeParams );
}
m_sidewallSteps = Convert.ToInt32( GetCurrentParam( ref nodeParams ) );
m_defaultScale = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
m_defaultRefPlane = Convert.ToSingle( GetCurrentParam( ref nodeParams ) );
if ( UIUtils.CurrentShaderVersion() > 3001 )
{
m_clipEnds = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
string[] vector2Component = GetCurrentParam( ref nodeParams ).Split( IOUtils.VECTOR_SEPARATOR );
if ( vector2Component.Length == 2 )
{
m_tilling.x = Convert.ToSingle( vector2Component[ 0 ] );
m_tilling.y = Convert.ToSingle( vector2Component[ 1 ] );
}
}
if ( UIUtils.CurrentShaderVersion() > 5005 )
{
m_useCurvature = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
m_CurvatureVector = IOUtils.StringToVector2( GetCurrentParam( ref nodeParams ) );
}
if( UIUtils.CurrentShaderVersion() > 13103 )
{
if( UIUtils.CurrentShaderVersion() < 15307 )
{
bool arrayIndexVisible = false;
arrayIndexVisible = Convert.ToBoolean( GetCurrentParam( ref nodeParams ) );
m_pomTexType = arrayIndexVisible ? POMTexTypes.TextureArray : POMTexTypes.Texture2D;
}
else
{
m_pomTexType = (POMTexTypes)Enum.Parse( typeof(POMTexTypes), GetCurrentParam( ref nodeParams ) );
}
UpdateIndexPort();
}
UpdateSampler();
GeneratePOMfunction();
UpdateCurvaturePort();
}
public override void WriteToString( ref string nodeInfo, ref string connectionsInfo )
{
base.WriteToString( ref nodeInfo, ref connectionsInfo );
IOUtils.AddFieldValueToString( ref nodeInfo, m_selectedChannelInt );
//IOUtils.AddFieldValueToString( ref nodeInfo, m_minSamples );
//IOUtils.AddFieldValueToString( ref nodeInfo, m_maxSamples );
m_inlineMinSamples.WriteToString( ref nodeInfo );
m_inlineMaxSamples.WriteToString( ref nodeInfo );
IOUtils.AddFieldValueToString( ref nodeInfo, m_sidewallSteps );
IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultScale );
IOUtils.AddFieldValueToString( ref nodeInfo, m_defaultRefPlane );
IOUtils.AddFieldValueToString( ref nodeInfo, m_clipEnds );
IOUtils.AddFieldValueToString( ref nodeInfo, m_tilling.x.ToString() + IOUtils.VECTOR_SEPARATOR + m_tilling.y.ToString() );
IOUtils.AddFieldValueToString( ref nodeInfo, m_useCurvature );
IOUtils.AddFieldValueToString( ref nodeInfo, IOUtils.Vector2ToString( m_CurvatureVector ) );
//IOUtils.AddFieldValueToString( ref nodeInfo, m_useTextureArray );
IOUtils.AddFieldValueToString( ref nodeInfo, m_pomTexType);
}
public override void Destroy()
{
base.Destroy();
//Not calling m_texCoordsHelper.Destroy() on purpose so UIUtils does not incorrectly unregister stuff
if( m_texCoordsHelper != null )
{
DestroyImmediate( m_texCoordsHelper );
m_texCoordsHelper = null;
}
m_uvPort = null;
m_texPort = null;
m_scalePort = null;
m_viewdirTanPort = null;
m_pomUVPort = null;
}
}
}
|