void setupScene() { m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); LightPtr light(new Light); light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5))); light->setPosition(glm::vec3(0, 0.5, 0) + light->getDirection() * -10.0f); m_visSystem->addLight(light); // Volume std::vector<std::string> gridNames; gridNames.push_back(m_config.densityGridName); if (!m_config.temperatureGridName.empty()) { gridNames.push_back(m_config.temperatureGridName); } std::vector<openvdb::GridBase::Ptr> baseGrids = loadGridsFromFile(m_config.vdbVilename, gridNames); openvdb::FloatGrid::Ptr densityGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[0]); openvdb::FloatGrid::Ptr temperatureGrid; if (!m_config.temperatureGridName.empty()) { temperatureGrid = openvdb::gridPtrCast<openvdb::FloatGrid>(baseGrids[1]); // Rescale temperature field to between 0 and 1 { float minValue = 99999999999999; float maxValue = -99999999999999; for (openvdb::FloatGrid::ValueOnCIter iter = temperatureGrid->cbeginValueOn(); iter.test(); ++iter) { float value = *iter; minValue = std::min(minValue, value); maxValue = std::max(maxValue, value); } float scale = 1.0 / (maxValue - minValue); for (openvdb::FloatGrid::ValueOnIter iter = temperatureGrid->beginValueOn(); iter.test(); ++iter) { float value = *iter; value = (value - minValue) * scale; iter.setValue(value); } } // Ensure both grids have the same hierarchy { openvdb::FloatGrid::Ptr resultGrid = openvdb::FloatGrid::create(); resultGrid->tree().combine2(densityGrid->tree(), temperatureGrid->tree(), CopyBIntoA()); temperatureGrid->tree().combine(densityGrid->tree(), CopyBIntoA()); densityGrid = resultGrid; } } std::vector<GridPtr> grids; GridTextureRolesMap gridTextureRoles; grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(densityGrid, 1))); gridTextureRoles[GridTextureRole_Diffuse] = grids.back(); if (m_config.generateNormals) { Vec3UByteGrid::Ptr normalGrid = createNormalGrid(*densityGrid); grids.push_back(GridPtr(new VdbGrid<Vec3UByteGrid>(normalGrid, 3))); gridTextureRoles[GridTextureRole_Normal] = grids.back(); } if (temperatureGrid) { grids.push_back(GridPtr(new VdbGrid<openvdb::FloatGrid>(temperatureGrid, 1))); gridTextureRoles[GridTextureRole_Temperature] = grids.back(); } openvdb::CoordBBox bbox; densityGrid->constTree().evalLeafBoundingBox(bbox); float scale = 1.0f / (float)bbox.extents().asVec3s().length(); glm::vec3 center = toVec3(bbox.getCenter() * scale); std::ostringstream ss; ss << "Grid extents: " << bbox.extents().x() << ", " << bbox.extents().y() << ", " << bbox.extents().z(); defaultLogger()->logLine(ss.str()); int renderQueueId; if (m_config.renderToLowResTarget) { renderQueueId = RenderQueueId_OffscreenTransparentObjects; } else { renderQueueId = getDefaultRenderQueueId(); } RenderableVolumeConfig config; config.grids = grids; config.materialFactory.reset(new SparseVolumeMaterialFactoryI(gridTextureRoles, m_config.transparent, m_config.opacityMultiplier)); config.scale = scale; config.batchBoxes = !m_config.transparent; // don't batch if we have transparency so we can sort RenderableVolumePtr volume = RenderableVolumeFactory::createRenderableVolume(config); BOOST_FOREACH(const GVis::RenderableNodePtr& node, volume->nodes) { node->translate(-center); m_visSystem->addRenderableNode(node, renderQueueId); } if (m_config.transparent) { RenderQueuePtr renderQueue = m_visSystem->getRenderQueue(renderQueueId); if (renderQueue) renderQueue->setSortingMode(RenderSortingMode_BackToFront); } if (m_config.renderToLowResTarget) { int volumeTargetWidth = m_window->getWidth() / 2; int volumeTargetHeight = m_window->getHeight() / 2; TexturePtr offscreenTransparentObjectsTexture; // Create offscreen transparent objects target { ImageTextureConfig config = ImageTextureConfig::createDefault(); config.width = volumeTargetWidth; config.height = volumeTargetHeight; config.textureAddressMode = TextureAddressMode_Clamp; offscreenTransparentObjectsTexture.reset(new Texture(config)); { RenderTextureTargetConfig config; config.texture = offscreenTransparentObjectsTexture; config.attachment = FrameBufferAttachment_Color; RenderTextureTargetPtr target(new RenderTextureTarget(config)); { ViewportPtr viewport = target->addDefaultViewport(m_camera); viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects); viewport->setBackgroundColor(glm::vec4(0,0,0,0)); } m_window->addRenderTarget(target); } } // Composite offscreen particles { TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler"); ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag")); TechniquePtr technique(new Technique(shader)); technique->addTextureUnit(textureUnit); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); MaterialPtr material(new Material); material->setTechnique(technique); { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects); } } } if (m_config.orbitCam) { centerNode.reset(new SceneNode); centerNode->addChild(m_camera); m_cameraInputEnabled = false; } m_camera->setPosition_parentSpace(glm::vec3(0,0,1.4)); }
void setupScene() { // Must create ClSystem before OpenGL textures. FIXME: this constraint should be more explicit m_clSystem.reset(new ClSystem); m_window->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); LightPtr light(new Light); light->setDirection(glm::normalize(glm::vec3(1.5, -1, -0.5))); light->setPosition(glm::vec3(0, 1.0, 0) + light->getDirection() * -10.0f); m_visSystem->addLight(light); { ShadowProjectorConfig config = ShadowProjectorConfig::createDefault(); config.sceneHeight = config.sceneWidth = 2; config.shadowFormat = ShadowFormat_RGB32F; m_shadowProjector.reset(new ShadowProjector(config)); m_shadowProjector->setLight(light); m_window->addRenderTarget(m_shadowProjector->getRenderTextureTarget()); } RenderTextureTargetPtr sceneDepthTarget = createDepthTarget(m_camera, m_window->getWidth(), m_window->getHeight()); sceneDepthTarget->getViewports().front()->setRenderQueueIdMask(~RenderQueueId_OffscreenTransparentObjects); TexturePtr sceneDepthTexture = sceneDepthTarget->getTexture(); // Volume { int width = 64; int height = 128; int depth = 128; int size = width * height * depth * 4; m_imageData.reset(new unsigned char[size]); memset(m_imageData.get(), 0, size); // Density texture m_textureConfig = ImageTextureConfig::createDefault(); m_textureConfig.width = width; m_textureConfig.height = height; m_textureConfig.depth = depth; m_textureConfig.is3d = true; m_textureConfig.format = PixelFormat_RGBA8; m_textureConfig.textureAddressMode = TextureAddressMode_Clamp; m_textureConfig.data = m_imageData.get(); m_fluidStateTexture.reset(new Texture(m_textureConfig)); // Normal texture { ImageTextureConfig normalTextureConfig = m_textureConfig; normalTextureConfig.width /= 2; normalTextureConfig.height /= 2; normalTextureConfig.depth /= 2; normalTextureConfig.data = 0; m_normalTexture.reset(new Texture(normalTextureConfig)); } glm::vec3 boxSize(0.5, 1, 1); glm::vec3 volumeTextureSize(m_textureConfig.width, m_textureConfig.height, m_textureConfig.depth); MaterialPtr material(new Material); // Main technique { ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumetricSmoke.frag")); TechniquePtr technique(new Technique(shader)); { Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize)); technique->addCustomShaderParameter(boxModelSizeParameter); Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize)); technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter); technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 30.0))); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); { TextureUnit unit(m_fluidStateTexture, "albedoSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(sceneDepthTexture, "sceneDepthSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(m_shadowProjector->getShadowTexture(), "shadowSampler"); technique->addTextureUnit(unit); } { TextureUnit unit(m_normalTexture, "normalSampler"); technique->addTextureUnit(unit); } } material->setTechnique(technique); } // Deep shadow caster technique { ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Volume/RaymarchedVolume.vert", "Shaders/Volume/VolumeShadowCaster.frag")); TechniquePtr technique(new Technique(shader)); { Vec3ShaderParameterPtr boxModelSizeParameter(new Vec3ShaderParameter("volumeSize_modelSpace", boxSize)); technique->addCustomShaderParameter(boxModelSizeParameter); Vec3ShaderParameterPtr oneOnVolumeTextureSizeParameter(new Vec3ShaderParameter("oneOnVolumeTextureSize", 1.0f / volumeTextureSize)); technique->addCustomShaderParameter(oneOnVolumeTextureSizeParameter); technique->addCustomShaderParameter(ShaderParameterPtr(new FloatShaderParameter("opacityMultiplier", 0.8))); { TextureUnit unit(m_fluidStateTexture, "albedoSampler"); technique->addTextureUnit(unit); } } material->setTechnique(technique, TechniqueCategory_DepthRtt); } { BoxConfig config; config.size = boxSize; MeshPtr mesh = BoxMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode(new RenderableNode); renderableNode->addRenderable(geo); renderableNode->setPosition(glm::vec3(0, 0.5, 0)); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_OffscreenTransparentObjects); } } // Scene geo { ShadowedMaterialFactory materialFactory(m_shadowProjector->getShadowTexture()); // Ground plane { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(5, 5)); config.orientation = glm::angleAxis(halfPi(), glm::vec3(-1, 0, 0)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, materialFactory.createMaterial(TextureRoles()))); RenderableNodePtr renderableNode = RenderableNode::createWithSingleGeo(geo); m_visSystem->addRenderableNode(renderableNode); } } int volumeTargetWidth = m_window->getWidth() / 2; int volumeTargetHeight = m_window->getHeight() / 2; TexturePtr offscreenTransparentObjectsTexture; // Create offscreen transparent objects target { ImageTextureConfig config = ImageTextureConfig::createDefault(); config.width = volumeTargetWidth; config.height = volumeTargetHeight; config.textureAddressMode = TextureAddressMode_Clamp; offscreenTransparentObjectsTexture.reset(new Texture(config)); { RenderTextureTargetConfig config; config.texture = offscreenTransparentObjectsTexture; config.attachment = FrameBufferAttachment_Color; RenderTextureTargetPtr target(new RenderTextureTarget(config)); { ViewportPtr viewport = target->addDefaultViewport(m_camera); viewport->setRenderQueueIdMask(RenderQueueId_OffscreenTransparentObjects); viewport->setBackgroundColor(glm::vec4(0,0,0,0)); } m_window->addRenderTarget(target); } } // Composite offscreen particles { TextureUnit textureUnit(offscreenTransparentObjectsTexture, "albedoSampler"); ShaderProgramPtr shader = ShaderProgram::createShaderProgram(ShaderProgramConfig("Shaders/Common/ScreenQuad.vert", "Shaders/Common/SimpleTextured.frag")); TechniquePtr technique(new Technique(shader)); technique->addTextureUnit(textureUnit); technique->setAlphaBlendingMode(AlphaBlendingMode_PreMultiplied); MaterialPtr material(new Material); material->setTechnique(technique); { RectangleConfig config = RectangleConfig::defaultWithSize(glm::vec2(2, 2)); MeshPtr mesh = RectangleMeshFactory::createMesh(config); GeoPtr geo(new Geo(mesh, material)); RenderableNodePtr renderableNode(new RenderableNode); renderableNode->addRenderable(geo); m_visSystem->addRenderableNode(renderableNode, RenderQueueId_CompositeOffscreenTransparentObjects); } } int tempBufferElementCount = m_textureConfig.width * m_textureConfig.height * m_textureConfig.depth; std::string fluidKernelsDir = "Kernels/Fluid"; TempBufferPoolPtr tempBufferPool(new TempBufferPool(*m_clSystem, tempBufferElementCount)); m_solver = createFluidSolver(*m_clSystem, getGlTexture(m_fluidStateTexture), tempBufferPool, fluidKernelsDir); FluidSolverParamsPtr params = m_solver->getParams(); params->temperatureBuoyancy = 15; params->densityWeight = 2.0; params->drag = 0.05; m_isosurfaceNormalCalculator = createIsosurfaceNormalCalculator(*m_clSystem, getGlTexture(m_normalTexture), m_solver, tempBufferPool, fluidKernelsDir); m_camera->setPosition(glm::vec3(2.2, 0.5, 0.7)); m_cameraController->rotate(1.2, -0.05); }