Efficient way to add noise on a gradient sky?

All topics about ZGameEditor goes here.

Moderator: Moderators

Post Reply
User avatar
Ats
Posts: 268
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Efficient way to add noise on a gradient sky?

Post by Ats » Thu May 21, 2020 7:04 pm

Hello. Today I'm trying to add a noise gradient to make a nice sky.
Something a bit like that: https://blenderartists.org/t/grainy-noi ... nt/1229520

So I put together a working example, but I'm not happy at the generating speed of it... I tried to optimize the number of pixels to produce by playing with the width/height of the bitmap, and the repetition of the texture on the X axis. But still, there's a pause each time the texture is regenerated.
And right now, the bitmap size don't even match the resolution of the full screen (F9), so the noise is quite big and blurry...
Is there an efficient way to achieve that?

I'd like to get what we see on the rotating cube, but on the sky behind.

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" FullScreen="255" ScreenMode="0" ClipFar="200" FileVersion="2">
  <OnUpdate>
    <ZExpression>
      <Expression>
<![CDATA[Timer -= App.DeltaTime;
if (Timer <= 0)
{
  Timer = 2;
  SkyColorBottom.X = 0.4 * rnd();
  SkyColorBottom.Y = 0.4 * rnd();
  SkyColorBottom.Z = 0.4 * rnd();
  SkyColorTop.X = 1 - 0.4 * rnd();
  SkyColorTop.Y = 1 - 0.4 * rnd();
  SkyColorTop.Z = 1 - 0.4 * rnd();
  @RefreshContent(Component: SkyBitmap);
}

rotateCube.Rotate.X+=.2*App.DeltaTime;
rotateCube.Rotate.Y+=.2*App.DeltaTime;]]>
      </Expression>
    </ZExpression>
  </OnUpdate>
  <OnRender>
    <RenderTransformGroup Scale="8 8 0">
      <Children>
        <UseMaterial Material="SkyMaterial"/>
        <RenderMesh Mesh="CubeMesh"/>
      </Children>
    </RenderTransformGroup>
    <RenderTransformGroup Name="rotateCube" Rotate="246.1398 242.6618 0">
      <Children>
        <RenderMesh Mesh="CubeMesh"/>
      </Children>
    </RenderTransformGroup>
  </OnRender>
  <Content>
    <Bitmap Name="SkyBitmap" Width="256" Height="768">
      <Producers>
        <BitmapExpression Name="SkyColorBitmap">
          <Expression>
<![CDATA[// Noise
float n = rnd()*.4;
// Color
float r = SkyColorTop.X*Y + SkyColorBottom.X*(1-Y*.7);
float g = SkyColorTop.Y*Y + SkyColorBottom.Y*(1-Y*.7);
float b = SkyColorTop.Z*Y + SkyColorBottom.Z*(1-Y*.7);
// https://en.wikipedia.org/wiki/Blend_modes#Soft_Light
//if (n < 0.5)
//{
  Pixel.R = 2*r*n + r*r*(1-2*n);
  Pixel.G = 2*g*n + g*g*(1-2*n);
  Pixel.B = 2*b*n + b*b*(1-2*n);
/*
}
else
{
  Pixel.R = 2*r*(1-n) + sqrt(r)*(2*n-1);
  Pixel.G = 2*g*(1-n) + sqrt(g)*(2*n-1);
  Pixel.B = 2*b*(1-n) + sqrt(b)*(2*n-1);
}
*/
Pixel.A = 1;]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Material Name="SkyMaterial" Shading="1" Light="0" Blend="1" ZBuffer="0">
      <Textures>
        <MaterialTexture Texture="SkyBitmap" TextureScale="4 1 1" TextureWrapMode="1" TexCoords="1" Origin="0 0 0"/>
      </Textures>
    </Material>
    <Mesh Name="CubeMesh">
      <Producers>
        <MeshBox/>
      </Producers>
    </Mesh>
    <Variable Name="SkyColorBottom" Type="7"/>
    <Variable Name="SkyColorTop" Type="7"/>
    <Variable Name="Timer"/>
  </Content>
</ZApplication>
Oh, by the way, the purpose is to generate sky gradients on the fly, the sky gradient could be a 64x64 bitmap with a 4096*4096 noise generated only once and blended into i,t if that could help for the speed. But is it possible to blend two materialTextures of different sizes inside a material? Or blend two materials?

User avatar
Kjell
Posts: 1724
Joined: Sat Feb 23, 2008 11:15 pm

Re: Efficient way to add noise on a gradient sky?

Post by Kjell » Thu May 21, 2020 8:34 pm

Hi Ats,
Ats wrote:
Thu May 21, 2020 7:04 pm
Oh, by the way, the purpose is to generate sky gradients on the fly, the sky gradient could be a 64x64 bitmap with a 4096*4096 noise generated only once and blended into i,t if that could help for the speed. But is it possible to blend two materialTextures of different sizes inside a material?
Sure :) here's a simple example ..

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" ScreenMode="0" ViewportRatio="3" RenderOrder="1" FileVersion="2">
  <OnLoaded>
    <SpawnModel Model="Box"/>
    <CallComponent Component="GradientRefresh"/>
  </OnLoaded>
  <OnUpdate>
    <Timer Interval="2">
      <OnTimer>
        <CallComponent Component="GradientRefresh"/>
      </OnTimer>
    </Timer>
  </OnUpdate>
  <OnRender>
    <UseMaterial Material="SkyMaterial"/>
    <RenderMesh Mesh="SkyMesh"/>
  </OnRender>
  <Content>
    <Bitmap Name="NoiseBitmap" Width="256" Height="256">
      <Producers>
        <BitmapExpression>
          <Expression>
<![CDATA[//

float s = random(0.8, 0.2);

//

Pixel.R = s;
Pixel.G = s;
Pixel.B = s;]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Bitmap Name="GradientBitmap" Width="2" Height="2">
      <Producers>
        <BitmapExpression>
          <Expression>
<![CDATA[//

if(Y)
{
  Pixel.R = GradientData[3];
  Pixel.G = GradientData[4];
  Pixel.B = GradientData[5];
}
else
{
  Pixel.R = GradientData[0];
  Pixel.G = GradientData[1];
  Pixel.B = GradientData[2];
}]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Array Name="GradientData" SizeDim1="6"/>
    <ZExpression Name="GradientRefresh">
      <Expression>
<![CDATA[//

GradientData[0] = random(0.2, 0.2);
GradientData[1] = random(0.2, 0.2);
GradientData[2] = random(0.2, 0.2);

GradientData[3] = random(0.8, 0.2);
GradientData[4] = random(0.8, 0.2);
GradientData[5] = random(0.8, 0.2);

//

@RefreshContent(Component: GradientBitmap);]]>
      </Expression>
    </ZExpression>
    <Model Name="Box" RotationVelocity="0.2 0.2 0">
      <OnRender>
        <UseMaterial Material="BoxMaterial"/>
        <RenderMesh Mesh="BoxMesh"/>
      </OnRender>
    </Model>
    <Mesh Name="BoxMesh">
      <Producers>
        <MeshBox/>
      </Producers>
    </Mesh>
    <Material Name="BoxMaterial">
      <Textures>
        <MaterialTexture Texture="GradientBitmap" TextureScale="1 0.25 1" TextureY="0.125" TextureWrapMode="2"/>
        <MaterialTexture Texture="NoiseBitmap" TextureWrapMode="1" TexCoords="1"/>
      </Textures>
    </Material>
    <Mesh Name="SkyMesh">
      <Producers>
        <MeshBox Scale="8 4.5 1" Grid2DOnly="255"/>
      </Producers>
    </Mesh>
    <Material Name="SkyMaterial" ZBuffer="0">
      <Textures>
        <MaterialTexture Texture="GradientBitmap" TextureScale="1 0.5 1" TexCoords="1"/>
        <MaterialTexture Texture="NoiseBitmap" TextureScale="5 2.8125 1" TextureWrapMode="1" TexCoords="1"/>
      </Textures>
    </Material>
  </Content>
</ZApplication>
K

User avatar
Ats
Posts: 268
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: Efficient way to add noise on a gradient sky?

Post by Ats » Fri May 22, 2020 8:59 am

Thanks, Kjell. As always, I'm amazed by the simplicity of your examples. I didn't even know that a 2x2 bitmap would suffice to make a beautiful gradient and that the linear filter would do the trick :D

Post Reply