//---------------------------------------------------------------------------- Fluid2UpdateState::Fluid2UpdateState(int xSize, int ySize, int numXThreads, int numYThreads, std::shared_ptr<ConstantBuffer> const& parameters) : mNumXGroups(xSize/numXThreads), mNumYGroups(ySize/numYThreads) { HLSLDefiner definer; definer.SetInt("NUM_X_THREADS", numXThreads); definer.SetInt("NUM_Y_THREADS", numYThreads); // Create the shader for generating velocity from vortices. mComputeUpdateState.reset(ShaderFactory::CreateCompute("UpdateState", msHLSLUpdateStateString, definer)); LogAssert(mComputeUpdateState != nullptr, "Cannot create compute shader."); mUpdateState.reset(new Texture2(DF_R32G32B32A32_FLOAT, xSize, ySize)); mUpdateState->SetUsage(Resource::SHADER_OUTPUT); mAdvectionSampler.reset(new SamplerState()); mAdvectionSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P; mAdvectionSampler->mode[0] = SamplerState::CLAMP; mAdvectionSampler->mode[1] = SamplerState::CLAMP; mComputeUpdateState->Set("Parameters", parameters); mComputeUpdateState->Set("advectionSampler", mAdvectionSampler); mComputeUpdateState->Set("updateState", mUpdateState); }
//---------------------------------------------------------------------------- void PerformanceAMDWindow::CreateTextureGenerator() { // Load the texture. std::string path = mEnvironment.GetPath("MedicineBag.jpg"); mOriginalTexture.reset(WICFileIO::Load(path, false)); // Create a texture that will be generated by a compute shader from the // original texture. unsigned int const width = mOriginalTexture->GetWidth(); unsigned int const height = mOriginalTexture->GetHeight(); mBlurredTexture.reset(new Texture2(DF_R8G8B8A8_UNORM, width, height)); mBlurredTexture->SetUsage(Resource::SHADER_OUTPUT); // Create the compute shader for blurring the original texture. unsigned int const numThreads = 8; HLSLDefiner definer; definer.SetInt("DELTA", 3); definer.SetUnsignedInt("NUM_X_THREADS", numThreads); definer.SetUnsignedInt("NUM_Y_THREADS", numThreads); mNumXGroups = width / numThreads; mNumYGroups = height / numThreads; mGenerateTexture.reset(ShaderFactory::CreateCompute( mEnvironment.GetPath("GenerateTexture.hlsl"), definer)); mGenerateTexture->Set("input", mOriginalTexture); mGenerateTexture->Set("output", mBlurredTexture); }
//---------------------------------------------------------------------------- Fluid3InitializeSource::Fluid3InitializeSource(int xSize, int ySize, int zSize, int numXThreads, int numYThreads, int numZThreads, std::shared_ptr<ConstantBuffer> const& parameters) : mNumXGroups(xSize/numXThreads), mNumYGroups(ySize/numYThreads), mNumZGroups(zSize/numZThreads) { // Create the resources for generating velocity from vortices. mVortex.reset(new ConstantBuffer(sizeof(Vortex), true)); mVelocity0.reset(new Texture3(DF_R32G32B32A32_FLOAT, xSize, ySize, zSize)); mVelocity0->SetUsage(Resource::SHADER_OUTPUT); mVelocity1.reset(new Texture3(DF_R32G32B32A32_FLOAT, xSize, ySize, zSize)); mVelocity1->SetUsage(Resource::SHADER_OUTPUT); // Create the resources for generating velocity from wind and gravity. mExternal.reset(new ConstantBuffer(sizeof(External), false)); External& e = *mExternal->Get<External>(); e.densityProducer = { 0.5f, 0.5f, 0.5f, 0.0f }; e.densityPData = { 0.01f, 16.0f, 0.0f, 0.0f }; e.densityConsumer = { 0.75f, 0.75f, 0.75f, 0.0f }; e.densityCData = { 0.01f, 0.0f, 0.0f, 0.0f }; e.gravity = { 0.0f, 0.0f, 0.0f, 0.0f }; e.windData = { 0.001f, 0.0f, 0.0f, 0.0f }; mSource.reset(new Texture3(DF_R32G32B32A32_FLOAT, xSize, ySize, zSize)); mSource->SetUsage(Resource::SHADER_OUTPUT); // Create the shader for generating velocity from vortices. HLSLDefiner definer; definer.SetInt("NUM_X_THREADS", numXThreads); definer.SetInt("NUM_Y_THREADS", numYThreads); definer.SetInt("NUM_Z_THREADS", numZThreads); mGenerateVortex.reset(ShaderFactory::CreateCompute("GenerateVortex", msHLSLGenerateVortexString, definer)); LogAssert(mGenerateVortex != nullptr, "Cannot create compute shader."); mGenerateVortex->Set("Parameters", parameters); mGenerateVortex->Set("Vortex", mVortex); mGenerateVortex->Set("inVelocity", mVelocity0); mGenerateVortex->Set("outVelocity", mVelocity1); // Create the shader for generating the sources to the fluid simulation. mInitializeSource.reset(ShaderFactory::CreateCompute("InitializeSource", msHLSLInitializeSourceString, definer)); LogAssert(mInitializeSource != nullptr, "Cannot create compute shader."); mInitializeSource->Set("Parameters", parameters); mInitializeSource->Set("External", mExternal); mInitializeSource->Set("source", mSource); }
//---------------------------------------------------------------------------- Fluid2AdjustVelocity::Fluid2AdjustVelocity(int xSize, int ySize, int numXThreads, int numYThreads, std::shared_ptr<ConstantBuffer> const& parameters) : mNumXGroups(xSize/numXThreads), mNumYGroups(ySize/numYThreads) { HLSLDefiner definer; definer.SetInt("NUM_X_THREADS", numXThreads); definer.SetInt("NUM_Y_THREADS", numYThreads); mAdjustVelocity.reset(ShaderFactory::CreateCompute("AdjustVelocity", msHLSLAdjustVelocityString, definer)); LogAssert(mAdjustVelocity != nullptr, "Cannot create compute shader."); mAdjustVelocity->Set("Parameters", parameters); }
//---------------------------------------------------------------------------- Fluid2InitializeState::Fluid2InitializeState(int xSize, int ySize, int numXThreads, int numYThreads) : mNumXGroups(xSize/numXThreads), mNumYGroups(ySize/numYThreads) { // Use a Mersenne twister engine for random numbers. std::mt19937 mte; std::uniform_real_distribution<float> unirnd(0.0f, 1.0f); // Initial density values are randomly generated. mDensity.reset(new Texture2(DF_R32_FLOAT, xSize, ySize)); float* data = mDensity->Get<float>(); for (unsigned int i = 0; i < mDensity->GetNumElements(); ++i, ++data) { *data = unirnd(mte); } // Initial velocity values are zero. mVelocity.reset(new Texture2(DF_R32G32_FLOAT, xSize, ySize)); memset(mVelocity->GetData(), 0, mVelocity->GetNumBytes()); // The states at time 0 and time -dt are initialized by a compute shader. mStateTm1.reset(new Texture2(DF_R32G32B32A32_FLOAT, xSize, ySize)); mStateTm1->SetUsage(Resource::SHADER_OUTPUT); mStateT.reset(new Texture2(DF_R32G32B32A32_FLOAT, xSize, ySize)); mStateT->SetUsage(Resource::SHADER_OUTPUT); // Create the shader for initializing velocity and density. HLSLDefiner definer; definer.SetInt("NUM_X_THREADS", numXThreads); definer.SetInt("NUM_Y_THREADS", numYThreads); mInitializeState.reset(ShaderFactory::CreateCompute("InitializeState", msHLSLInitializeStateString, definer)); LogAssert(mInitializeState != nullptr, "Cannot create compute shader."); mInitializeState->Set("density", mDensity); mInitializeState->Set("velocity", mVelocity); mInitializeState->Set("stateTm1", mStateTm1); mInitializeState->Set("stateT", mStateT); }
//---------------------------------------------------------------------------- Fluid2ComputeDivergence::Fluid2ComputeDivergence(int xSize, int ySize, int numXThreads, int numYThreads, std::shared_ptr<ConstantBuffer> const& parameters) : mNumXGroups(xSize/numXThreads), mNumYGroups(ySize/numYThreads) { HLSLDefiner definer; definer.SetInt("NUM_X_THREADS", numXThreads); definer.SetInt("NUM_Y_THREADS", numYThreads); // Create the shader for computing the divergence of the velocity. mComputeDivergence.reset(ShaderFactory::CreateCompute("ComputeDivergence", msHLSLComputeDivergenceString, definer)); LogAssert(mComputeDivergence != nullptr, "Cannot create compute shader."); mDivergence.reset(new Texture2(DF_R32_FLOAT, xSize, ySize)); mDivergence->SetUsage(Resource::SHADER_OUTPUT); mComputeDivergence->Set("Parameters", parameters); mComputeDivergence->Set("divergence", mDivergence); }
//---------------------------------------------------------------------------- bool StructuredBuffersWindow::CreateScene() { // Create the shaders and associated resources HLSLDefiner definer; definer.SetInt("WINDOW_WIDTH", mXSize); std::shared_ptr<VertexShader> vshader(ShaderFactory::CreateVertex( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!vshader) { return false; } std::shared_ptr<PixelShader> pshader(ShaderFactory::CreatePixel( mEnvironment.GetPath("StructuredBuffers.hlsl"), definer)); if (!pshader) { return false; } std::shared_ptr<ConstantBuffer> cbuffer(new ConstantBuffer( sizeof(Matrix4x4<float>), true)); vshader->Set("PVWMatrix", cbuffer); // Create the pixel shader and associated resources. std::string path = mEnvironment.GetPath("StoneWall.png"); std::shared_ptr<Texture2> baseTexture(WICFileIO::Load(path, false)); pshader->Set("baseTexture", baseTexture); std::shared_ptr<SamplerState> baseSampler(new SamplerState()); baseSampler->filter = SamplerState::MIN_L_MAG_L_MIP_P; baseSampler->mode[0] = SamplerState::CLAMP; baseSampler->mode[1] = SamplerState::CLAMP; pshader->Set("baseSampler", baseSampler); mDrawnPixels.reset(new StructuredBuffer(mXSize*mYSize, sizeof(Vector4<float>))); mDrawnPixels->SetUsage(Resource::SHADER_OUTPUT); mDrawnPixels->SetCopyType(Resource::COPY_BIDIRECTIONAL); memset(mDrawnPixels->GetData(), 0, mDrawnPixels->GetNumBytes()); pshader->Set("drawnPixels", mDrawnPixels); // Create the visual effect for the square. std::shared_ptr<VisualEffect> effect(new VisualEffect(vshader, pshader)); // Create a vertex buffer for a single triangle. The PNG is stored in // left-handed coordinates. The texture coordinates are chosen to reflect // the texture in the y-direction. struct Vertex { Vector3<float> position; Vector2<float> tcoord; }; VertexFormat vformat; vformat.Bind(VA_POSITION, DF_R32G32B32_FLOAT, 0); vformat.Bind(VA_TEXCOORD, DF_R32G32_FLOAT, 0); std::shared_ptr<VertexBuffer> vbuffer(new VertexBuffer(vformat, 4)); Vertex* vertex = vbuffer->Get<Vertex>(); vertex[0].position = Vector3<float>(0.0f, 0.0f, 0.0f); vertex[0].tcoord = Vector2<float>(0.0f, 1.0f); vertex[1].position = Vector3<float>(1.0f, 0.0f, 0.0f); vertex[1].tcoord = Vector2<float>(1.0f, 1.0f); vertex[2].position = Vector3<float>(0.0f, 1.0f, 0.0f); vertex[2].tcoord = Vector2<float>(0.0f, 0.0f); vertex[3].position = Vector3<float>(1.0f, 1.0f, 0.0f); vertex[3].tcoord = Vector2<float>(1.0f, 0.0f); // Create an indexless buffer for a triangle mesh with two triangles. std::shared_ptr<IndexBuffer> ibuffer(new IndexBuffer(IP_TRISTRIP, 2)); // Create the geometric object for drawing. Translate it so that its // center of mass is at the origin. This supports virtual trackball // motion about the object "center". mSquare.reset(new Visual(vbuffer, ibuffer, effect)); mSquare->localTransform.SetTranslation(-0.5f, -0.5f, 0.0f); mSquare->Update(); // Enable automatic updates of pvw-matrices and w-matrices. SubscribeCW(mSquare, cbuffer); // The structured buffer is written in the pixel shader. This texture // will receive a copy of it so that we can write the results to disk // as a PNG file. mDrawnPixelsTexture = new Texture2(DF_R8G8B8A8_UNORM, mXSize, mYSize); return true; }