/// <summary> /// This sets a texture ONLY if it has changed (i.e. not the same or content is dirty) /// </summary> /// <param name="_Name"></param> /// <param name="_Value"></param> /// <param name="_bClearDirtyFlag">True to mark the texture as "clean" once assigned</param> public static void SetGlobalTexture( string _Name, NuajTexture2D _Value, bool _bClearDirtyFlag ) { NuajTexture2D CurrentTexture = ms_GlobalParamName2Texture.ContainsKey( _Name ) ? ms_GlobalParamName2Texture[_Name] : null; if ( _Value == CurrentTexture && _Value != null && !_Value.IsDirty ) return; // No change in texture or content... ms_GlobalParamName2Texture[_Name] = _Value; // Update to new texture // Upload... Shader.SetGlobalTexture( _Name, _Value != null ? _Value.Texture : null ); if ( _bClearDirtyFlag && _Value != null ) _Value.IsDirty = false; // This texture has been uploaded so it's not dirty anymore... // Notify Help.LogDebugWarning( "Texture \"" + (_Value != null && _Value.Texture ? _Value.Texture.name : "null") + "\" has been uploaded as GLOBAL \"" + _Name + "\"" ); }
/// <summary> /// Builds the table containing the Mie phase function /// </summary> protected void BuildPhaseFunction( double[] _PhaseFunction ) { // Compute MIN/MAX indices of the phase function int MinIndex = Mathf.FloorToInt( _PhaseFunction.Length * PHASE_START_ANGLE / Mathf.PI ); int MaxIndex = Mathf.FloorToInt( (_PhaseFunction.Length-1) * PHASE_END_ANGLE / Mathf.PI ); // Compute integral of provided function double fIntegral = 0.0; for ( int Index=0; Index < PHASE_TEXTURE_SIZE; Index++ ) { int OriginalPhaseIndex = MinIndex + (MaxIndex - MinIndex) * Index / (PHASE_TEXTURE_SIZE-1); fIntegral += _PhaseFunction[OriginalPhaseIndex]; } fIntegral *= Math.PI / PHASE_TEXTURE_SIZE; // * dTheta fIntegral *= 2.0 * Math.PI; fIntegral = 1.0 / fIntegral; // Copy source function into collapsed table float[] PhaseFactors = new float[PHASE_TEXTURE_SIZE]; double IntegralCheck = 0.0; for ( int Index=0; Index < PHASE_TEXTURE_SIZE; Index++ ) { int OriginalPhaseIndex = MinIndex + (MaxIndex - MinIndex) * Index / PHASE_TEXTURE_SIZE; PhaseFactors[Index] = (float) (_PhaseFunction[OriginalPhaseIndex] * fIntegral); IntegralCheck += PhaseFactors[Index]; } IntegralCheck *= Math.PI / PHASE_TEXTURE_SIZE; // * dTheta IntegralCheck *= 2.0 * Math.PI; // Create phase function for 0- and single-scattering Color[] Pixels = new Color[PHASE_TEXTURE_SIZE]; for ( int i=0; i < PHASE_TEXTURE_SIZE; i++ ) { float Value = PhaseFactors[i] * 256.0f; float R = Mathf.Floor( Value ); float G = Value - R; Pixels[i] = new Color( R / 256.0f, G, 0.0f, 0.0f ); } // Build the convolved phase function for double-scattering double[] PhaseConvolved = new double[PHASE_TEXTURE_SIZE]; double DeltaAngle = Math.PI / PHASE_TEXTURE_SIZE; for ( int AngleIndex0=0; AngleIndex0 < PHASE_TEXTURE_SIZE; AngleIndex0++ ) { double Phase0 = PhaseFactors[AngleIndex0]; double Convolution = 0.0; for ( int AngleIndex1=0; AngleIndex1 < PHASE_TEXTURE_SIZE; AngleIndex1++ ) Convolution += Phase0 * PhaseFactors[(PHASE_TEXTURE_SIZE + AngleIndex0 - AngleIndex1) % PHASE_TEXTURE_SIZE]; PhaseConvolved[AngleIndex0] = (float) (DeltaAngle * Convolution); } for ( int i=0; i < PHASE_TEXTURE_SIZE; i++ ) { float Value = (float) (PhaseConvolved[i] * 256.0); float B = Mathf.Floor( Value ); float A = Value - B; Pixels[i].b = B / 256.0f; Pixels[i].a = A; } // Build texture m_TexturePhase = Help.CreateTexture( "Layered Clouds Phase Function", PHASE_TEXTURE_SIZE, 1, TextureFormat.ARGB32, false, FilterMode.Bilinear, TextureWrapMode.Clamp ); m_TexturePhase.SetPixels( 0, 0, PHASE_TEXTURE_SIZE, 1, Pixels, 0 ); m_TexturePhase.Apply(); }