Simul Support ExchangeCategory: CloudsGetting wind in TrueSky sample
Micael asked 2 years ago

I am trying to reproduce the wind effect on clouds (as seen in this tutorial) using Standalone SDK (v4.3) and “SimulDirectX11Sample_MD”.
Whatever the value set in “WindSpeedMS” (in TrueSkySample.cpp), the clouds stay motionless.
What do we need to change to make the clouds move with the wind?

2 Answers
James - Simul Support Staff answered 2 years ago

You will either need to progress the current time in the scene, or set weatherRenderer->SetRealTimeWind to true, which will result in weather effects being independent to the simulation.

Micael answered 2 years ago

Thanks for your answer.
I have done the following changes:

  • cloudOpt.WindSpeedMS = vec3(20.01f,0.0f,0.0f);
  • weatherRenderer->GetSkyKeyframer()->SetTime(real_time / 3)

The time runs and the rain is moving according wind but the clouds stay motionless.
Do I forgot something else ?
Here is the complete “TrueSkySample.cpp” modified code I use.

Start your code here

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
//#define SHOW_OVERLAYS
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include “Platform/Core/EnvironmentVariables.h”
#include “Simul/Clouds/TrueSkyRenderer.h”
#ifdef SAMPLE_USE_D3D12
#include “Platform/DirectX12/RenderPlatform.h”
#include “Platform/DirectX12/DeviceManager.h”
#include “Platform/DirectX12/Texture.h”
#endif
#ifdef SAMPLE_USE_D3D11
#include “Platform/DirectX11/RenderPlatform.h”
#include “Platform/DirectX11/DeviceManager.h”
#include “Platform/DirectX11/Texture.h”
#endif
#ifdef SAMPLE_USE_VULKAN
#include “Platform/Vulkan/RenderPlatform.h”
#include “Platform/Vulkan/DeviceManager.h”
#include “Platform/Vulkan/Texture.h”
#endif
#ifdef SAMPLE_USE_OPENGL
#include “Platform/OpenGL/RenderPlatform.h”
#include “Platform/OpenGL/DeviceManager.h”
#include “Platform/OpenGL/Texture.h”
#endif
#include “Simul/Clouds/BaseWeatherRenderer.h”
#include “Simul/Clouds/CloudRenderer.h”
#include “Simul/Sky/BaseSkyRenderer.h”
#include “Platform/CrossPlatform/HDRRenderer.h”
#include “Platform/CrossPlatform/View.h”
#include “Platform/CrossPlatform/Mesh.h”
#include “Platform/CrossPlatform/GpuProfiler.h”
#include “Simul/Terrain/BaseTerrainRenderer.h”
#include “Platform/CrossPlatform/Camera.h”
#include “Simul/Clouds/Skylight.h”
#include “Platform/CrossPlatform/DeviceContext.h”
#include “Platform/Core/CommandLineParams.h”
#include “Platform/CrossPlatform/DisplaySurfaceManager.h”
#ifdef _MSC_VER
#include “Platform/Windows/VisualStudioDebugOutput.h”
#include “Simul/Shaders/SL/sky_constants.sl”
#include “Simul/Clouds/BaseWeatherRenderer.h”
VisualStudioDebugOutput debug_buffer(true,NULL,128);
#endif
#include <SDKDDKVer.h>
#include <shellapi.h>

int kOverrideWidth = 1440;
int kOverrideHeight = 900;
HWND hWnd = nullptr;
using namespace simul;
clouds::Skylight testSkyLight;
//! This class manages the Device object, and makes the connection between Windows HWND’s and swapchains.
//! In practice you will have your own method to do this.
#ifdef SAMPLE_USE_VULKAN
vulkan::DeviceManager deviceManager;
crossplatform::GraphicsDeviceInterface *graphicsDeviceInterface=&deviceManager;
#endif
#ifdef SAMPLE_USE_D3D12
dx12::DeviceManager deviceManager;
crossplatform::GraphicsDeviceInterface *graphicsDeviceInterface=&deviceManager;
#endif
#ifdef SAMPLE_USE_D3D11
dx11::DeviceManager deviceManager;
crossplatform::GraphicsDeviceInterface *graphicsDeviceInterface=&deviceManager;
#endif
#ifdef SAMPLE_USE_OPENGL
#include “OpenGL.h”
opengl::DeviceManager deviceManager;
crossplatform::GraphicsDeviceInterface *graphicsDeviceInterface=&deviceManager;

void GlfwErrorCallback(int errcode, const char* info)
{
std::cout << “[GLFW ERROR] ” << info << std::endl;
}
#endif
crossplatform::DisplaySurfaceManager displaySurfaceManager;
platform::core::CommandLineParams commandLineParams;
//! An example of how to use simul::dx11::SimulWeatherRendererDX12 in context.
class PlatformRenderer:public crossplatform::PlatformRendererInterface
{
//! It is better to use a reversed depth buffer format, i.e. the near plane is z=1 and the far plane is z=0. This
//! distributes numerical precision to where it is better used.
static const bool reverseDepth=true;
//! An instance of the weather renderer class for dx12.
clouds::BaseWeatherRenderer *weatherRenderer;
//! A terrain renderer is included in order to generate example depth information for the compositor.
terrain::BaseTerrainRenderer *terrainRenderer;
//! A framebuffer to store the colour and depth textures for the view.
crossplatform::BaseFramebuffer *hdrFramebuffer;
//! An HDR Renderer to put the contents of hdrFramebuffer to the screen. In practice you will probably have your own method for this.
crossplatform::HdrRenderer *hDRRenderer;

// A simple example mesh to draw as transparent
//crossplatform::Mesh *transparentMesh;
crossplatform::Effect *transparentEffect;
crossplatform::ConstantBuffer<SolidConstants> solidConstants;
//! A camera instance to generate view and proj matrices and handle mouse control.
//! In practice you will have your own solution for this.
crossplatform::Camera camera;
crossplatform::MouseCameraState mouseCameraState;
crossplatform::MouseCameraInput mouseCameraInput;
bool keydown[256];
crossplatform::Texture *depthTexture;
public:
int framenumber;
//! The render platform implements the cross-platform Simul graphics API for a specific target API,
simul::crossplatform::RenderPlatform *renderPlatform;
PlatformRenderer(simul::clouds::Environment *env):
weatherRenderer(NULL)
,terrainRenderer(NULL)
,hdrFramebuffer(NULL)
,hDRRenderer(NULL)
,transparentEffect(NULL)
,framenumber(0)
,renderPlatform(nullptr)
{
#ifdef SAMPLE_USE_D3D12
renderPlatform =new dx12::RenderPlatform();
#endif
#ifdef SAMPLE_USE_D3D11
renderPlatform =new dx11::RenderPlatform();
#endif
#ifdef SAMPLE_USE_VULKAN
renderPlatform =new vulkan::RenderPlatform();
#endif
#ifdef SAMPLE_USE_OPENGL
renderPlatform =new opengl::RenderPlatform();
#endif
depthTexture=renderPlatform->CreateTexture();
weatherRenderer =new clouds::BaseWeatherRenderer(env,NULL);
hDRRenderer =new crossplatform::HdrRenderer();
terrainRenderer =new terrain::BaseTerrainRenderer(NULL);
terrainRenderer->SetBaseSkyInterface(env->skyKeyframer);
hdrFramebuffer=renderPlatform->CreateFramebuffer(“HDR FrameBuffer”);
hdrFramebuffer->SetFormat(crossplatform::RGBA_16_FLOAT);
hdrFramebuffer->SetDepthFormat(crossplatform::D_32_FLOAT);
hdrFramebuffer->SetAntialiasing(8); // Set the AntiAliasing beforehand -AJR.
// We should provide default clear values and then stick to those
hdrFramebuffer->DefaultClearColour = vec4(0.0f, 0.0f, 0.0f, 1.0f);
hdrFramebuffer->DefaultClearDepth = reverseDepth ? 0.0f : 1.0f;
hdrFramebuffer->DefaultClearStencil = 0;
camera.SetPositionAsXYZ(0.0f,0,650.f);
float look[]={0.f,1.f,0.f},up[]={0.f,0.f,1.f};
camera.LookInDirection(look,up);
camera.SetHorizontalFieldOfViewDegrees(90.f);
// Automatic vertical fov – depends on window shape:
camera.SetVerticalFieldOfViewDegrees(0.f);
crossplatform::CameraViewStruct vs;
vs.exposure = 1.f;
vs.farZ = 300000.f;
vs.nearZ = 1.f;
vs.gamma = 0.44f;
vs.InfiniteFarPlane = false;
vs.projection = crossplatform::FORWARD;
// We can leave the default camera setup in place, or change it:
#if 0
camera.SetCameraViewStruct(vs);
#endif
memset(keydown,0,sizeof(keydown));
// Whether run from the project directory or from the executable location, we want to be
// able to find the shaders and textures:
renderPlatform->PushTexturePath(“”);
renderPlatform->PushTexturePath(“../../../../Media/Textures”);
renderPlatform->PushTexturePath(“../../Media/Textures”);
// Or from the Simul directory -e.g. by automatic builds:
#ifdef SAMPLE_USE_D3D12
renderPlatform->PushShaderPath(“Platform/DirectX12/HLSL/”);
renderPlatform->PushShaderPath(“../../../../Platform/DirectX12/HLSL”);
renderPlatform->PushShaderPath(“../../Platform/DirectX12/HLSL”);
#endif
renderPlatform->PushShaderPath(“Platform/Shaders/SFX/”);
renderPlatform->PushTexturePath(“Media/Textures”);
renderPlatform->PushShaderPath(“../../../../Platform/CrossPlatform/SFX”);
renderPlatform->PushShaderPath(“../../Platform/CrossPlatform/SFX”);
renderPlatform->PushShaderPath(“../../../../Shaders/SFX/”);
renderPlatform->PushShaderPath(“../../../../Shaders/SL/”);
renderPlatform->PushShaderPath(“../../Shaders/SFX/”);
renderPlatform->PushShaderPath(“../../Shaders/SL/”);
// Shader binaries: we want to use a shared common directory under Simul/Media. But if we’re running from some other place, we’ll just create a “shaderbin” directory.
std::string simul_env=simul::base::EnvironmentVariables::GetSimulEnvironmentVariable(“SIMUL”);
std::vector<std::string> simuls;
if(simul_env.length())
simuls.push_back(simul_env);
simuls.push_back(“../..”);
simuls.push_back(“../../..”);
for(auto simul: simuls)
{
std::string platform_build_path=((simul +”/build/Platform/”)+renderPlatform->GetPathName());
renderPlatform->PushShaderBinaryPath((platform_build_path+”/shaderbin”).c_str());
renderPlatform->PushTexturePath((simul +”/Media/Textures”).c_str());
}
renderPlatform->PushShaderBinaryPath(“shaderbin”);
}
~PlatformRenderer()
{
OnLostDevice();
del(weatherRenderer,NULL);
del(hDRRenderer,NULL);
del(terrainRenderer,NULL);
del(hdrFramebuffer,NULL);
delete depthTexture;
delete renderPlatform;
}
// This allows live-recompile of shaders.
void RecompileShaders()
{
renderPlatform->RecompileShaders();
weatherRenderer->RecompileShaders();
hDRRenderer->RecompileShaders();
terrainRenderer->RecompileShaders();
}
bool IsEnabled() const
{
return true;
}
void OnCreateDevice(void* pd3dDevice)
{
#ifdef SAMPLE_USE_D3D12
// We will provide a command list so initialization of following resource can take place
((dx12::RenderPlatform*)renderPlatform)->SetImmediateContext((dx12::ImmediateContext*)deviceManager.GetImmediateContext());
#endif
// Use these in practice:
renderPlatform->RestoreDeviceObjects(pd3dDevice);
weatherRenderer->RestoreDeviceObjects(renderPlatform);
// These are for example:
hDRRenderer->RestoreDeviceObjects(renderPlatform);
hdrFramebuffer->RestoreDeviceObjects(renderPlatform);
terrainRenderer->RestoreDeviceObjects(renderPlatform);
transparentEffect=renderPlatform->CreateEffect();
transparentEffect->Load(renderPlatform,”solid”);
solidConstants.RestoreDeviceObjects(renderPlatform);
solidConstants.LinkToEffect(transparentEffect,”SolidConstants”);
testSkyLight.RestoreDeviceObjects(renderPlatform);
#ifdef SAMPLE_USE_D3D12
deviceManager.FlushImmediateCommandList();
#endif
}
// We only ever create one view in this example, but in general, this should return a new value each time it’s called.
int AddView()
{
static int last_view_id=0;
// We override external_framebuffer here and pass “true” to demonstrate how external depth buffers are used.
// In this case, we use hdrFramebuffer’s depth buffer.
return last_view_id++;
}
void ResizeView(int view_id,int W,int H)
{
kOverrideWidth = W;
kOverrideHeight = H;
hDRRenderer->SetBufferSize(W,H);
hdrFramebuffer->SetWidthAndHeight(W,H);
hdrFramebuffer->SetAntialiasing(8);
}

void RenderTransparentTest(crossplatform::DeviceContext &deviceContext)
{
}
void Render(int view_id, void* context,void* colorBuffer, int w, int h, long long frame, void* context_allocator = nullptr) override
{
auto cloudOpt = weatherRenderer->GetCloudRenderer()->GetCloudRenderingOptions();
cloudOpt.MaximumCubemapResolution = 512;
cloudOpt.RaytraceMode = clouds::STANDARD_RENDERING;
cloudOpt.WindSpeedMS = vec3(20.01f,0.0f,0.0f);
cloudOpt.DefaultAmortization = 0;
weatherRenderer->GetCloudRenderer()->SetCloudRenderingOptions(cloudOpt);
#if 0//def SAMPLE_USE_D3D12
simul::crossplatform::DeviceContext computeContext;
deviceManager.GetNextComputeContext(computeContext);
weatherRenderer->AsynchronousUpdate(computeContext,0.0);
deviceManager.EndAsynchronousFrame();
#endif
// Device context structure
simul::crossplatform::GraphicsDeviceContext deviceContext;
// Store back buffer, depth buffer and viewport information
deviceContext.defaultTargetsAndViewport.num = 1;
deviceContext.defaultTargetsAndViewport.m_rt[0] = colorBuffer;
deviceContext.defaultTargetsAndViewport.rtFormats[0] = crossplatform::UNKNOWN; //To be later defined in the pipeline
deviceContext.defaultTargetsAndViewport.m_dt = nullptr;
deviceContext.defaultTargetsAndViewport.depthFormat = crossplatform::UNKNOWN;
deviceContext.defaultTargetsAndViewport.viewport = { 0,0,kOverrideWidth,kOverrideHeight };
deviceContext.frame_number = framenumber;
deviceContext.platform_context = context;
deviceContext.renderPlatform = renderPlatform;
deviceContext.viewStruct.view_id = view_id;
deviceContext.viewStruct.depthTextureStyle = crossplatform::PROJECTION;
{
deviceContext.viewStruct.view = camera.MakeViewMatrix();
float aspect = (float)kOverrideWidth/ (float)kOverrideHeight;
if (reverseDepth)
{
deviceContext.viewStruct.proj = camera.MakeDepthReversedProjectionMatrix(aspect);
}
else
{
deviceContext.viewStruct.proj = camera.MakeProjectionMatrix(aspect);
}
deviceContext.viewStruct.Init();
}
renderPlatform->BeginFrame(deviceContext);
// Profiling
#ifdef DO_PROFILING
simul::crossplatform::SetGpuProfilingInterface(deviceContext, renderPlatform->GetGpuProfiler());
renderPlatform->GetGpuProfiler()->SetMaxLevel(9);
renderPlatform->GetGpuProfiler()->StartFrame(deviceContext);
#endif
hdrFramebuffer->SetWidthAndHeight(w, h);
hdrFramebuffer->Activate(deviceContext);
hdrFramebuffer->Clear(deviceContext, 0.0f, 0.0f, 0.0f, 1.0f, reverseDepth ? 0.0f : 1.0f);
{
// Pre-Render Update
static platform::core::Timer timer;
float real_time = timer.UpdateTimeSum() / 1000.0f;
//env->skyKeyframer->SetTime(0.0f);
weatherRenderer->GetSkyKeyframer()->SetTime(real_time / 3);
//weatherRenderer->GetSkyKeyframer()->SetTime(0.35f + (real_time * 0.01f));
weatherRenderer->PreRenderUpdate(deviceContext, real_time);
testSkyLight.Update(deviceContext, weatherRenderer);
#if PLATFORM_DEBUG_DISABLE<1
// Render terrain
bool doTerrain = true;
if(doTerrain)
{
if (weatherRenderer&&weatherRenderer->GetCloudRenderer())
terrainRenderer->SetCloudShadowTexture(weatherRenderer->GetCloudRenderer()->GetCloudShadowData());
LightingQueryResult res = weatherRenderer->GetBaseSkyRenderer()->GetLightingQuery
(
0x913563A,
crossplatform::GetCameraPosVector(deviceContext.viewStruct.view)
);
terrainRenderer->SetLighting((const float*)res.sunlight, (const float*)res.moonlight, (const float*)res.ambient);
terrainRenderer->Render(deviceContext, 1.0f);
}

// Render
bool doWeather = true;
if (doWeather)
{
hdrFramebuffer->DeactivateDepth(deviceContext);
#ifdef SAMPLE_USE_D3D12
depthTexture->InitFromExternalTexture2D(renderPlatform, hdrFramebuffer->GetDepthTexture()->AsD3D12Resource(), hdrFramebuffer->GetDepthTexture()->AsD3D12ShaderResourceView(deviceContext));
#endif
#ifdef SAMPLE_USE_D3D11
depthTexture->InitFromExternalTexture2D(renderPlatform,hdrFramebuffer->GetDepthTexture()->AsD3D11Texture2D(),nullptr,w,h,hdrFramebuffer->GetDepthFormat());
#endif
weatherRenderer->Render(deviceContext,deviceContext.viewStruct, clouds::TrueSkyRenderMode::STANDARD, 1.0f, 1.0f, depthTexture, testSkyLight.frameBuffer->GetTexture(), &renderPlatform->GetViewport(deviceContext, 0));
weatherRenderer->Render(deviceContext, deviceContext.viewStruct, clouds::TrueSkyRenderMode::TRANSLUCENT, 1.0f, 1.0f, depthTexture, testSkyLight.frameBuffer->GetTexture(), &renderPlatform->GetViewport(deviceContext, 0));
}
#endif
}
hdrFramebuffer->Deactivate(deviceContext);
hDRRenderer->Render(deviceContext, hdrFramebuffer->GetTexture(),1.0f, 0.44f);
//renderPlatform->DrawCubemap(deviceContext, testSkyLight.frameBuffer->GetTexture(),0,0,0.1f,1.f,1.f);
//weatherRenderer->GetBaseSkyRenderer()->RenderFades(deviceContext, 0, 0, 0, kOverrideWidth, kOverrideHeight);
//weatherRenderer->GetCloudRenderer()->RenderCrossSections(deviceContext);
#ifdef DO_PROFILING
renderPlatform->GetGpuProfiler()->EndFrame(deviceContext);
renderPlatform->LinePrint(deviceContext,renderPlatform->GetGpuProfiler()->GetDebugText());
#endif
framenumber++;
}
void OnLostDevice()
{
if(transparentEffect)
{
transparentEffect->InvalidateDeviceObjects();
delete transparentEffect;
transparentEffect=nullptr;
}
solidConstants.InvalidateDeviceObjects();
weatherRenderer->InvalidateDeviceObjects();
hDRRenderer->InvalidateDeviceObjects();
terrainRenderer->InvalidateDeviceObjects();
renderPlatform->InvalidateDeviceObjects();
hdrFramebuffer->InvalidateDeviceObjects();
}
void OnDestroyDevice()
{
OnLostDevice();
}
void RemoveView(int)
{
}
bool OnDeviceRemoved()
{
OnLostDevice();
return true;
}
void OnFrameMove(double fTime,float time_step)
{
mouseCameraInput.forward_back_input =(float)keydown[‘w’]-(float)keydown[‘s’];
mouseCameraInput.right_left_input =(float)keydown[‘d’]-(float)keydown[‘a’];
mouseCameraInput.up_down_input =(float)keydown[‘t’]-(float)keydown[‘g’];
crossplatform::UpdateMouseCamera
(
&camera
,time_step
,4000.f
,mouseCameraState
,mouseCameraInput
,14000.f
);
}
void OnMouse(bool bLeftButtonDown
,bool bRightButtonDown
,bool bMiddleButtonDown
,int nMouseWheelDelta
,int xPos
,int yPos )
{
mouseCameraInput.MouseButtons
=(bLeftButtonDown?crossplatform::MouseCameraInput::LEFT_BUTTON:0)
|(bRightButtonDown?crossplatform::MouseCameraInput::RIGHT_BUTTON:0)
|(bMiddleButtonDown?crossplatform::MouseCameraInput::MIDDLE_BUTTON:0);
mouseCameraInput.MouseX=xPos;
mouseCameraInput.MouseY=yPos;
}

void OnKeyboard(unsigned wParam,bool bKeyDown)
{
switch (wParam)
{
case VK_LEFT:
case VK_RIGHT:
case VK_UP:
case VK_DOWN:
break;
case ‘R’:
RecompileShaders();
break;
default:
int k=tolower(wParam);
if(k>255)
return;
keydown[k]=bKeyDown?1:0;
break;
}
}
};
// Global Variables:
simul::clouds::Environment* env = nullptr;
PlatformRenderer* renderer = nullptr;
HINSTANCE hInst; // current instance
wchar_t wszWindowClass[] = L”SampleDX12″; // the main window class name
// from #include <Windowsx.h>
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
#define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
switch (message)
{
case WM_MOUSEWHEEL:
if(renderer)
{
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
renderer->OnMouse((wParam&MK_LBUTTON)!=0
,(wParam&MK_RBUTTON)!=0
,(wParam&MK_MBUTTON)!=0
,0,xPos,yPos);
}
break;
case WM_MOUSEMOVE:
if(renderer)
{
int xPos = GET_X_LPARAM(lParam);
int yPos = GET_Y_LPARAM(lParam);
renderer->OnMouse((wParam&MK_LBUTTON)!=0
,(wParam&MK_RBUTTON)!=0
,(wParam&MK_MBUTTON)!=0
,0,xPos,yPos);
}
break;
case WM_KEYDOWN:
if(renderer)
renderer->OnKeyboard((unsigned)wParam,true);
break;
case WM_KEYUP:
if(renderer)
renderer->OnKeyboard((unsigned)wParam,false);
break;
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
//switch (wmId)
return DefWindowProc(hWnd, message, wParam, lParam);
break;
case WM_SIZE:
if(renderer)
{
INT Width = LOWORD(lParam);
INT Height = HIWORD(lParam);
if(Width>8192||Height>8192||Width<0||Height<0)
break;
displaySurfaceManager.ResizeSwapChain(hWnd);
}
break;
case WM_PAINT:
if(renderer)
{
double fTime=0.0;
float time_step=0.01f;
renderer->OnFrameMove(fTime,time_step);
env->Update();
displaySurfaceManager.Render(hWnd);
displaySurfaceManager.EndFrame();
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
//Sleep(10000);
wchar_t **szArgList;
int argCount;
szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount);
#if 1
#ifdef _MSC_VER
// The following disables error dialogues in the case of a crash, this is so automated testing will not hang. See http://blogs.msdn.com/b/oldnewthing/archive/2004/07/27/198410.aspx
SetErrorMode(SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS);
// But that doesn’t work sometimes, so:
_set_abort_behavior(0,_WRITE_ABORT_MSG);
_set_abort_behavior(0,_CALL_REPORTFAULT);
// And still we might get “debug assertion failed” boxes. So we do this as well:
_set_error_mode(_OUT_TO_STDERR);
#endif

platform::core::GetCommandLineParams(commandLineParams,argCount,(const wchar_t **)szArgList);
if(commandLineParams.logfile_utf8.length())
debug_buffer.setLogFile(commandLineParams.logfile_utf8.c_str());
// Initialize the Window class:
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEXW);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = 0;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = NULL;
wcex.lpszMenuName = 0;
wcex.lpszClassName = wszWindowClass;
wcex.hIconSm = 0;
RegisterClassExW(&wcex);
}
// Create the window:
{
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindowW(wszWindowClass,L”Sample”, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, 0, kOverrideWidth/*commandLineParams.win_w*/, kOverrideHeight/*commandLineParams.win_h*/, NULL, NULL, hInstance, NULL);
if (!hWnd)
return 0;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
}
#endif
// Pass “true” to graphicsDeviceInterface to use d3d debugging etc:
graphicsDeviceInterface->Initialize(true,false,false);
env =new simul::clouds::Environment();
renderer =new PlatformRenderer(env);
displaySurfaceManager.Initialize(renderer->renderPlatform);
// Did we specify a file to load on the command line?
bool loaded_file=false;
//if(!commandLineParams.sq_filename_utf8.length())
// commandLineParams.sq_filename_utf8=”three_layers.sq”;
if(commandLineParams.sq_filename_utf8.length())
{
simul::crossplatform::TextFileInput ifs;
ifs.Load(commandLineParams.sq_filename_utf8.c_str());
if(ifs.Good())
{
env->LoadFromText(ifs);
loaded_file=true;
}
}
// Default sky has no clouds. That’s boring, so we’ll insert a keyframe:
if(!loaded_file)
{
clouds::CloudKeyframer *ck1=env->CreateCloudKeyframer(nullptr,false,1);
clouds::CloudKeyframe *K1 = ck1->InsertKeyframe(0.25);
K1->cloudiness = 0.5f;
K1->precipitation=1.0f;
//ck1->SetOverrideWind(true);
//#if 0
K1->cloud_base_km = 1.8f;
K1->cloud_height_km = 7.0f;
//K1->max_density_gm3 = 1.0f;
K1->distribution_base_layer = 0.5f;
K1->distribution_transition = 0.5f;
K1->worley_noise = 0.35f;
K1->worley_scale = 4.0;
K1->diffusivity = 0.6f;
K1->persistence = 0.1f;
K1->octaves = 3;
K1->upper_density = 0.5f;
K1->simulation = 0.0f;
K1->base_noise_factor = 0.4f;
K1->edge_worley_noise = 0.2f;
K1->fractal_amplitude = 1.5f;
K1->edge_sharpness = 0.2f;
K1->churn = 1;
//#endif
}
// Create an instance of our simple renderer class defined above:
renderer->OnCreateDevice(graphicsDeviceInterface->GetDevice());
//displaySurfaceManager.AddWindow(hWnd);
displaySurfaceManager.SetRenderer(hWnd,renderer,-1);
#ifdef SAMPLE_USE_D3D12
// deviceManager.FlushImmediateCommandList();
#endif
// Main message loop:
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
InvalidateRect(hWnd, NULL, TRUE);
if(commandLineParams.quitafterframe>0&& renderer->framenumber>=commandLineParams.quitafterframe)
break;
}
renderer->OnDeviceRemoved();
displaySurfaceManager.RemoveWindow(hWnd);
// Because this object is on the stack, we must free up its GPU objects explicitly before shutting down the RenderPlatform.
testSkyLight.InvalidateDeviceObjects();
delete renderer;
displaySurfaceManager.Shutdown();

graphicsDeviceInterface->Shutdown();
delete env;
return (int)0;// msg.wParam;
}

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
return WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
}