Пример #1
0
void OptiXRenderer::convertToOptiXScene(optix::Context context, int width, int height, float film_location) {
	// Setup lighting
	// TODO For now, we assume just one light
	context->setEntryPointCount( 1 );
	context->setRayGenerationProgram( 0, mScene->mLights[0]->getOptiXLight(context) );

	// Exception program
	context->setExceptionProgram( 0, context->createProgramFromPTXFile( "ptx/PhotonTracer.ptx", "exception" ) );

	// Miss program
	context->setMissProgram( 0, context->createProgramFromPTXFile( "ptx/PhotonTracer.ptx", "miss" ) );

	// Geometry group
	optix::GeometryGroup geometrygroup = context->createGeometryGroup();
	geometrygroup->setChildCount( mScene->mObjects.size() + 1 );
	geometrygroup->setAcceleration( context->createAcceleration("Bvh","Bvh") );

	// Add objects
	for(std::vector<RenderObject*>::size_type i = 0; i != mScene->mObjects.size(); i++) {
		optix::GeometryInstance gi = context->createGeometryInstance();
		// TODO we only support 1 material type per object
		gi->setMaterialCount(1);
		gi->setGeometry(   mScene->mObjects[i]->getOptiXGeometry(context));
		gi->setMaterial(0, mScene->mObjects[i]->getOptiXMaterial(context));
		geometrygroup->setChild(i, gi);
	}

	// Create Camera
	//
	mCameraMat = new CameraMaterial(width, height, 1);
	PlaneObject* plane = new PlaneObject(mCameraMat);
	plane->setPosition(0, 0, film_location); //-65
	mCameraObject = plane;
	// Convert to OptiX
	optix::GeometryInstance gi = context->createGeometryInstance();
	gi->setMaterialCount(1);
	gi->setGeometry(   mCameraObject->getOptiXGeometry(context));
	mCameraMatOptiX = mCameraObject->getOptiXMaterial(context);
	mCameraMatOptiX["width"]->setInt(width);
	mCameraMatOptiX["height"]->setInt(height);
	gi->setMaterial(0, mCameraMatOptiX);
	geometrygroup->setChild(mScene->mObjects.size(), gi);

	context["top_object"]->set(geometrygroup);
}
Пример #2
0
void Material::registerMaterialWithShadowProgram( optix::Context & context, optix::Material & material )
{
    if(!m_hasLoadedOptixAnyHitProgram)
    {
        m_optixAnyHitProgram = context->createProgramFromPTXFile( "DirectRadianceEstimation.cu.ptx", "gatherAnyHitOnNonEmitter");
        m_hasLoadedOptixAnyHitProgram = true;
    }
    material->setAnyHitProgram(RayType::SHADOW, m_optixAnyHitProgram);
}
Пример #3
0
optix::Geometry PlaneObject::getOptiXGeometry(optix::Context context) {
	optix::Geometry parallelogram = context->createGeometry();
	parallelogram->setPrimitiveCount( 1u );
	parallelogram->setBoundingBoxProgram( context->createProgramFromPTXFile("ptx/PlaneObject.ptx", "bounds" ) );
	parallelogram->setIntersectionProgram( context->createProgramFromPTXFile("ptx/PlaneObject.ptx", "intersect" ) );
	parallelogram["plane"]->setFloat(    normal->x,       normal->y,       normal->z, normal->dotProduct(position));
	// Move the anchor point
	Vector3D anchor = *position;
	anchor = anchor + (*up)*(-height/2);
	anchor = anchor + (*right)*(-width/2);
	parallelogram["anchor"]->setFloat( anchor.x,     anchor.y,     anchor.z );
	Vector3D v1 = *up*width;
	Vector3D v2 = *right*height;
	v1 = v1 * (1/(v1.dotProduct(&v1)));
	v2 = v2 * (1/(v2.dotProduct(&v2)));
	parallelogram["v1"]->setFloat(v1.x, v1.y, v1.z );
	parallelogram["v2"]->setFloat(v2.x, v2.y, v2.z );
	return parallelogram;
}
optix::Material ColourMaterial::getOptiXMaterial(optix::Context context) {
	optix::Program chp = context->createProgramFromPTXFile( "ptx/ColourMaterial.ptx", "closest_hit" );
	optix::Material mat = context->createMaterial();
	mat->setClosestHitProgram(0, chp);
	mat["max_wavelength"]->setFloat(mColourWavelengthMax);
	mat["min_wavelength"]->setFloat(mColourWavelengthMin);
	mat["standard_deviation"]->setFloat(std);
	mat["ideal_range"]->setFloat(ideal_range);
	return mat;
}
Пример #5
0
optix::Geometry AABInstance::getOptixGeometry( optix::Context & context)
{
    if(m_hasLoadedOptixPrograms == false)
    {
        m_programBoundingBox = context->createProgramFromPTXFile("AAB.cu.ptx", "boundingBox");
        m_programIntersection = context->createProgramFromPTXFile("AAB.cu.ptx", "intersect");
        m_hasLoadedOptixPrograms = true;
    }
    
    optix::Geometry geometry = context->createGeometry();
    geometry->setPrimitiveCount(1u);
    geometry->setBoundingBoxProgram(m_programBoundingBox);
    geometry->setIntersectionProgram(m_programIntersection);

    geometry["cuboidMin"]->setFloat( this->m_aab.min );
    geometry["cuboidMax"]->setFloat( this->m_aab.max );

    return geometry;
}
Пример #6
0
optix::Geometry SphereInstance::getOptixGeometry( optix::Context & context)
{
    if(m_hasLoadedOptixPrograms == false)
    {
        m_programBoundingBox = context->createProgramFromPTXFile("Sphere.cu.ptx", "boundingBox");
        m_programIntersection = context->createProgramFromPTXFile("Sphere.cu.ptx", "intersect");
        m_hasLoadedOptixPrograms = true;
    }

    optix::Geometry sphere = context->createGeometry();
    sphere->setPrimitiveCount(1);
    sphere->setIntersectionProgram( m_programIntersection );
    sphere->setBoundingBoxProgram( m_programBoundingBox );

    sphere["radius"]->setFloat( this->m_sphere.radius );
    sphere["center"]->setFloat( this->m_sphere.center );

    return sphere;
}
optix::Material CameraMaterial::getOptiXMaterial(optix::Context context) {
	optix::Program chp = context->createProgramFromPTXFile( "ptx/CameraMaterial.ptx", "closest_hit" );
	optix::Material mat = context->createMaterial();
	mat->setClosestHitProgram(0, chp);
	mat["camera_size"]->setFloat(actualWidth, actualHeight);
	mat["image_size"]->setInt(imageWidth, imageHeight);
	mat["max_intensity"]->setInt(1);
	mat["camera_gamma"]->setFloat(1.0f);
	return mat;
}
Пример #8
0
optix::Material Glass::getOptixMaterial(optix::Context & context)
{
    if(!m_optixMaterialIsCreated)
    {
        m_optixMaterial = context->createMaterial();
        optix::Program radianceClosestProgram = context->createProgramFromPTXFile( "Glass.cu.ptx", "closestHitRadiance");
        optix::Program radianceAnyHitProgram = context->createProgramFromPTXFile( "Glass.cu.ptx", "anyHitRadiance");
        optix::Program photonClosestProgram = context->createProgramFromPTXFile( "Glass.cu.ptx", "closestHitPhoton");
        optix::Program photonAnyHitProgram = context->createProgramFromPTXFile( "Glass.cu.ptx", "anyHitPhoton");

        //vcmClosestHitLight

        m_optixMaterial->setClosestHitProgram(RayType::RADIANCE, radianceClosestProgram);
        //m_optixMaterial->setAnyHitProgram(RayType::RADIANCE, radianceAnyHitProgram );
        m_optixMaterial->setClosestHitProgram(RayType::RADIANCE_IN_PARTICIPATING_MEDIUM, radianceClosestProgram);
        //m_optixMaterial->setAnyHitProgram(RayType::RADIANCE_IN_PARTICIPATING_MEDIUM, radianceAnyHitProgram);
        
        m_optixMaterial->setClosestHitProgram(RayType::PHOTON, photonClosestProgram);
        //m_optixMaterial->setAnyHitProgram(RayType::PHOTON, photonAnyHitProgram);
        m_optixMaterial->setClosestHitProgram(RayType::PHOTON_IN_PARTICIPATING_MEDIUM, photonClosestProgram);
       // m_optixMaterial->setAnyHitProgram(RayType::PHOTON_IN_PARTICIPATING_MEDIUM, photonAnyHitProgram);

        m_optixMaterial->setClosestHitProgram(RayType::LIGHT_VCM, context->createProgramFromPTXFile( "Glass.cu.ptx", "vcmClosestHitLight"));
        m_optixMaterial->setClosestHitProgram(RayType::CAMERA_VCM, context->createProgramFromPTXFile( "Glass.cu.ptx", "vcmClosestHitCamera"));

        this->registerMaterialWithShadowProgram(context, m_optixMaterial);
        m_optixMaterialIsCreated = true;
    }
    
    return m_optixMaterial;
}
Пример #9
0
optix::Material Texture::getOptixMaterial(optix::Context & context)
{
    if(!m_optixMaterialIsCreated)
    {
        m_optixMaterial = context->createMaterial();
        optix::Program radianceProgram = context->createProgramFromPTXFile( "Texture.cu.ptx", "closestHitRadiance");
        optix::Program photonProgram = context->createProgramFromPTXFile( "Texture.cu.ptx", "closestHitPhoton");

        m_optixMaterial->setClosestHitProgram(RayType::RADIANCE, radianceProgram);
        m_optixMaterial->setClosestHitProgram(RayType::RADIANCE_IN_PARTICIPATING_MEDIUM, radianceProgram);
        m_optixMaterial->setClosestHitProgram(RayType::PHOTON, photonProgram);
        m_optixMaterial->setClosestHitProgram(RayType::PHOTON_IN_PARTICIPATING_MEDIUM, photonProgram);
        m_optixMaterial->setClosestHitProgram(RayType::LIGHT_VCM, context->createProgramFromPTXFile( "Texture.cu.ptx", "vcmClosestHitLight"));
        m_optixMaterial->setClosestHitProgram(RayType::CAMERA_VCM, context->createProgramFromPTXFile( "Texture.cu.ptx", "vcmClosestHitCamera"));
        m_optixMaterial->validate();
        this->registerMaterialWithShadowProgram(context, m_optixMaterial);
        m_optixMaterialIsCreated = true;
    }
    
    // Diffuse buffer

    optix::Buffer buffer = createBufferFromImage(context, *m_diffuseImage);
    m_diffuseSampler = createTextureSamplerFromBuffer(context, buffer);

    optix::Buffer normalsBuffer;
    if(m_normalMapImage != NULL)
    {
        normalsBuffer = createBufferFromImage(context, *m_normalMapImage);
    }
    else
    {
        normalsBuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_BYTE4, 0, 0);
    }

    m_normalMapSampler = createTextureSamplerFromBuffer(context, normalsBuffer);
    return m_optixMaterial;
}
Пример #10
0
void PolygonMesh::initialise(optix::Context c) {
	string mesh_ptx_path = ptxpath("path_tracer", "PolygonMesh.cu");
	bounding_box = c->createProgramFromPTXFile(mesh_ptx_path, "mesh_bounds");
	intersection = c->createProgramFromPTXFile(mesh_ptx_path, "mesh_intersect");
	initialised = true;
}
Пример #11
0
void TriangleMesh::optixInit(optix::Context context) {

	try {

		static optix::Program intersectProgram = context->createProgramFromPTXFile("ptx/triangle_mesh_program.cu.ptx", "intersect");
		static optix::Program boundsProgram = context->createProgramFromPTXFile("ptx/triangle_mesh_program.cu.ptx", "bounds");

#if OPTIX_USE_GEOMETRY_VBO
		// Bind vertex VBO
		Optix.posBuffer = context->createBufferFromGLBO(RT_BUFFER_INPUT, vboPos);
		Optix.posBuffer->setFormat(RT_FORMAT_FLOAT3);
		Optix.posBuffer->setSize(posData.size());

		// Bind normal VBO
		Optix.normalBuffer = context->createBufferFromGLBO(RT_BUFFER_INPUT, vboNormal);
		Optix.normalBuffer->setFormat(RT_FORMAT_FLOAT3);
		Optix.normalBuffer->setSize(normalData.size());

		// Bind texture VBO
		Optix.texCoordBuffer = context->createBufferFromGLBO(RT_BUFFER_INPUT, vboTexCoord);
		Optix.texCoordBuffer->setFormat(RT_FORMAT_FLOAT2);
		Optix.texCoordBuffer->setSize(texCoordData.size());

		// Bind index IBO
		Optix.indexBuffer = context->createBufferFromGLBO(RT_BUFFER_INPUT, ibo);
		Optix.indexBuffer->setFormat(RT_FORMAT_UNSIGNED_INT);
		Optix.indexBuffer->setSize(indexData.size());
#else
		// Copy position buffer
		Optix.posBuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, posData.size());
		memcpy(Optix.posBuffer->map(), &posData[0], posData.size() * sizeof(Vec3));
		Optix.posBuffer->unmap();

		// Copy normal buffer
		Optix.normalBuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, normalData.size());
		memcpy(Optix.normalBuffer->map(), &normalData[0], normalData.size() * sizeof(Vec3));
		Optix.normalBuffer->unmap();

		// Copy texture buffer
		Optix.texCoordBuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, texCoordData.size());
		memcpy(Optix.texCoordBuffer->map(), &texCoordData[0], texCoordData.size() * sizeof(Vec2));
		Optix.texCoordBuffer->unmap();

		// Copy index buffer
		Optix.indexBuffer = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT3, indexData.size());
		memcpy(Optix.indexBuffer->map(), &indexData[0], indexData.size() * sizeof(TrianglePrimitive));
		Optix.indexBuffer->unmap();
#endif

		// Make geometry
		Optix.geometry = context->createGeometry();
		Optix.geometry->setIntersectionProgram(intersectProgram);
		Optix.geometry->setBoundingBoxProgram(boundsProgram);
		Optix.geometry->setPrimitiveCount(indexData.size());
		Optix.geometry["posData"]->setBuffer(Optix.posBuffer);
		Optix.geometry["normalData"]->setBuffer(Optix.normalBuffer);
		Optix.geometry["texCoordData"]->setBuffer(Optix.texCoordBuffer);
		Optix.geometry["indexData"]->setBuffer(Optix.indexBuffer);

		// Make instance
		if (!material->Optix.material) {
			
#if OPTIX_USE_OPENGL_TEXTURE
			material->Optix.sampler = context->createTextureSamplerFromGLImage(material->image->texture, RT_TARGET_GL_TEXTURE_2D);
#else
			optix::Buffer buf = context->createBuffer(RT_BUFFER_INPUT, RT_FORMAT_FLOAT4, material->image->width, material->image->height);
			memcpy(buf->map(), material->image->pixels, material->image->width * material->image->height * sizeof(Color));
			buf->unmap();
			material->Optix.sampler = context->createTextureSampler();
			material->Optix.sampler->setArraySize(1);
			material->Optix.sampler->setMipLevelCount(1);
			material->Optix.sampler->setBuffer(0, 0, buf);
#endif
			material->Optix.sampler->setWrapMode(0, RT_WRAP_REPEAT);
			material->Optix.sampler->setWrapMode(1, RT_WRAP_REPEAT);
			material->Optix.sampler->setIndexingMode(RT_TEXTURE_INDEX_NORMALIZED_COORDINATES);
			material->Optix.sampler->setReadMode(RT_TEXTURE_READ_NORMALIZED_FLOAT);
			material->Optix.sampler->setMaxAnisotropy(1.f);
			RTfiltermode filter = (material->image->filter == GL_NEAREST) ? RT_FILTER_NEAREST : RT_FILTER_LINEAR;
			material->Optix.sampler->setFilteringModes(filter, filter, RT_FILTER_NONE);
			
			material->Optix.material = context->createMaterial();
			material->Optix.material->setClosestHitProgram(0, materialClosestHitProgram);
			material->Optix.material->setAnyHitProgram(1, materialAnyHitProgram);
			material->Optix.material["sampler"]->setTextureSampler(material->Optix.sampler);
			material->Optix.material["ambient"]->setFloat(material->ambient.r(), material->ambient.g(), material->ambient.b(), material->ambient.a());
			material->Optix.material["specular"]->setFloat(material->specular.r(), material->specular.g(), material->specular.b(), material->specular.a());
			material->Optix.material["diffuse"]->setFloat(material->diffuse.r(), material->diffuse.g(), material->diffuse.b(), material->diffuse.a());
			material->Optix.material["shineExponent"]->setFloat(material->shineExponent);
			material->Optix.material["reflectIntensity"]->setFloat(material->reflectIntensity);
			material->Optix.material["refractIndex"]->setFloat(material->refractIndex);

		}

		Optix.geometryInstance = context->createGeometryInstance();
		Optix.geometryInstance->setGeometry(Optix.geometry);
		Optix.geometryInstance->addMaterial(material->Optix.material);

	} catch (optix::Exception e) {
		printException(e);
	}

}
Пример #12
0
optix::Group CornellSmall::getSceneRootGroup(optix::Context & context)
{
    m_pgram_bounding_box = context->createProgramFromPTXFile( "parallelogram.cu.ptx", "bounds" );
    m_pgram_intersection = context->createProgramFromPTXFile( "parallelogram.cu.ptx", "intersect" );

    // create geometry instances
    QVector<optix::GeometryInstance> gis;

    Diffuse diffuseWhite = Diffuse(optix::make_float3( 0.8f ));
    Diffuse diffuseGreen = Diffuse(optix::make_float3( 0.05f, 0.8f, 0.05f ));
    Diffuse diffuseRed = Diffuse(optix::make_float3( 1.f, 0.05f, 0.05f ));

    // colors as in SmallVCM
    if ((m_config & CornellSmall::SmallVCMColors) != 0)
    {
        diffuseWhite = Diffuse(optix::make_float3( 0.803922f, 0.803922f, 0.803922f ));
        diffuseGreen = Diffuse(optix::make_float3( 0.156863f, 0.803922f, 0.172549f ));
        diffuseRed = Diffuse(optix::make_float3( 0.803922f, 0.152941f, 0.152941f ));
    }
    Diffuse diffuseBlue = Diffuse(optix::make_float3( 0.156863f, 0.172549f, 0.803922f ));

    Mirror mirror = Mirror(optix::make_float3(1.f,1.f,1.f));
    Glossy glossyWhite = Glossy(optix::make_float3(.1f,.1f,.1f), optix::make_float3(.7f,.7f,.7f), 90.f);
    Glass glass = Glass(1.6, optix::make_float3(1.f,1.f,1.f), optix::make_float3(1.f,1.f,1.f) );
    DiffuseEmitter emitter = DiffuseEmitter(m_sceneLights[0].power, Vector3(1));

    // Set up materials
    // Floor
    Material *matFloor = &diffuseWhite;
    if ((m_config & Config::FloorMirror) != 0)
    {
        matFloor = &mirror;
    }
    else if ((m_config & Config::FloorGlossy) != 0)
    {
        matFloor = &glossyWhite;
    }

    // Ceiling
    Material *matCeiling = &diffuseWhite;

    // Back wall
    Material *matBackWall = &diffuseWhite;
    if ((m_config & Config::BackwallBlue) != 0)
    {
        matBackWall = &diffuseBlue;
    }

    // Right wall
    Material *matRightWall = &diffuseGreen;
    if ((m_config & CornellSmall::SmallVCMColors) != 0)
        matRightWall = &diffuseRed;

    // Left wall
    Material *matLeftWall = &diffuseRed;
    if ((m_config & CornellSmall::SmallVCMColors) != 0)
        matLeftWall = &diffuseGreen;

    // Short block
    Material *matShortBlock = &diffuseWhite;

    // Tall block
    Material *matTallBlock = &diffuseWhite;


    // Set geometry - Cornell box size in SmallVCM 2.56004, here rounded up slightly
    // Floor    
    gis.push_back( createParallelogram(0, context, optix::make_float3( 0.0f, 0.0f, 0.0f ),
        optix::make_float3( 0.0f, 0.0f, 2.5f ),
        optix::make_float3( 2.5f, 0.0f, 0.0f ),
        *matFloor ) );

    // Ceiling
    if ((m_config & Config::LightPointDistant) == 0)
    {
        gis.push_back( createParallelogram(1, context, optix::make_float3( 0.0f, 2.5f, 0.0f ),
            optix::make_float3( 2.5f, 0.0f, 0.0f ),
            optix::make_float3( 0.0f, 0.0f, 2.5f ),
            *matCeiling ) );
    }

    // Back wall
    gis.push_back( createParallelogram(2, context,optix::make_float3( 0.0f, 0.0f, 2.5f),
        optix::make_float3( 0.0f, 2.5f, 0.0f),
        optix::make_float3( 2.5f, 0.0f, 0.0f),
        *matBackWall));

    // Right wall
    gis.push_back( createParallelogram(3, context, optix::make_float3( 0.0f, 0.0f, 0.0f ),
        optix::make_float3( 0.0f, 2.5f, 0.0f ),
        optix::make_float3( 0.0f, 0.0f, 2.5f ),
        *matRightWall ) );

    // Left wall
    gis.push_back( createParallelogram(4, context, optix::make_float3( 2.5f, 0.0f, 0.0f ),
        optix::make_float3( 0.0f, 0.0f, 2.5f ),
        optix::make_float3( 0.0f, 2.5f, 0.0f ),
        *matLeftWall ) );


    if ((m_config & Config::Blocks) != 0)
    {
        // Short block
        gis.push_back( createParallelogram(5, context, 
            optix::make_float3( 130.0f, 165.0f, 65.0f) / 220.f,
            optix::make_float3( -48.0f, 0.0f, 160.0f) / 220.f,
            optix::make_float3( 160.0f, 0.0f, 49.0f) / 220.f,
            *matShortBlock ) );
        gis.push_back( createParallelogram(6, context, 
            optix::make_float3( 290.0f, 0.0f, 114.0f) / 220.f,
            optix::make_float3( 0.0f, 165.0f, 0.0f) / 220.f,
            optix::make_float3( -50.0f, 0.0f, 158.0f) / 220.f,
            *matShortBlock ) );
        gis.push_back( createParallelogram(7, context, 
            optix::make_float3( 130.0f, 0.0f, 65.0f) / 220.f,
            optix::make_float3( 0.0f, 165.0f, 0.0f) / 220.f,
            optix::make_float3( 160.0f, 0.0f, 49.0f) / 220.f,
            *matShortBlock ) );
        gis.push_back( createParallelogram(8, context, 
            optix::make_float3( 82.0f, 0.0f, 225.0f) / 220.f,
            optix::make_float3( 0.0f, 165.0f, 0.0f) / 220.f,
            optix::make_float3( 48.0f, 0.0f, -160.0f) / 220.f,
            *matShortBlock ) );
        gis.push_back( createParallelogram(9, context,
            optix::make_float3( 240.0f, 0.0f, 272.0f) / 220.f,
            optix::make_float3( 0.0f, 165.0f, 0.0f) / 220.f,
            optix::make_float3( -158.0f, 0.0f, -47.0f) / 220.f,
            *matShortBlock));
        
        // Tall block
        gis.push_back( createParallelogram(10, context, 
            optix::make_float3( 423.0f, 340.0f, 247.0f) / 220.f,
            optix::make_float3( -158.0f, 0.0f, 49.0f) / 220.f,
            optix::make_float3( 49.0f, 0.0f, 159.0f) / 220.f,
            *matTallBlock ) );
        gis.push_back( createParallelogram(11, context, 
            optix::make_float3( 423.0f, 0.0f, 247.0f) / 220.f,
            optix::make_float3( 0.0f, 340.0f, 0.0f) / 220.f,
            optix::make_float3( 49.0f, 0.0f, 159.0f) / 220.f,
            *matTallBlock ) );
        gis.push_back( createParallelogram(12, context, 
            optix::make_float3( 472.0f, 0.0f, 406.0f) / 220.f,
            optix::make_float3( 0.0f, 340.0f, 0.0f) / 220.f,
            optix::make_float3( -158.0f, 0.0f, 50.0f) / 220.f,
            *matTallBlock ) );
        gis.push_back( createParallelogram(13, context, 
            optix::make_float3( 314.0f, 0.0f, 456.0f) / 220.f,
            optix::make_float3( 0.0f, 340.0f, 0.0f) / 220.f,
            optix::make_float3( -49.0f, 0.0f, -160.0f) / 220.f,
            *matTallBlock ) );
        gis.push_back( createParallelogram(14, context, 
            optix::make_float3( 265.0f, 0.0f, 296.0f) / 220.f,
            optix::make_float3( 0.0f, 340.1f, 0.0f) / 220.f,
            optix::make_float3( 158.0f, 0.0f, -49.0f) / 220.f,
            *matTallBlock ) );
    }

    // Area light
    if ( ((m_config & Config::LightArea) != 0) || 
         ((m_config & Config::LightAreaUpwards) != 0) )
    {
        emitter.setInverseArea(m_sceneLights[0].inverseArea);
        for(int i = 0; i < m_sceneLights.size(); i++)
        {
            gis.push_back(createParallelogram(15 + i, context, m_sceneLights[i].position, 
                m_sceneLights[i].v1, m_sceneLights[i].v2, emitter));
        }
    }    


    // Large sphere
    if ((m_config & Config::LargeMirrorSphere) != 0 || (m_config & Config::LargeGlassSphere) != 0)
    {
        Material *matLargeSphere = &mirror;
        if ((m_config & Config::LargeGlassSphere) != 0)
            matLargeSphere = &glass;

        float radius = 0.8;
        SphereInstance sphere = SphereInstance(*matLargeSphere, Sphere(Vector3(1.25f, radius, 1.25f), radius));
        gis.push_back(sphere.getOptixGeometryInstance(context));
    }
    
    // Small glass sphere right
    if ((m_config & Config::SmallGlassSphere))
    {
        float radius = 0.5;
        SphereInstance sphere = SphereInstance(glass, Sphere(Vector3(1.25f - 0.535714269f, radius, 1.25f), radius));
        gis.push_back(sphere.getOptixGeometryInstance(context));
    }

    // Small mirror sphere left
    if ((m_config & Config::SmallMirrorSphere))
    {
        float radius = 0.5;
        SphereInstance sphere = SphereInstance(mirror, Sphere(Vector3(1.25f + 0.535714269f, radius, 1.25f), radius));
        gis.push_back(sphere.getOptixGeometryInstance(context));
    }

    // Create geometry group
    optix::GeometryGroup geometry_group = context->createGeometryGroup();
    geometry_group->setChildCount( static_cast<unsigned int>( gis.size() ) );
    for (int i = 0; i < gis.size(); ++i )
        geometry_group->setChild( i, gis[i] );

    geometry_group->setAcceleration(context->createAcceleration("NoAccel", "NoAccel")); // Bvh Sbvh Trbvh NoAccel // Bvh BvhCompact NoAccel

    optix::Group gro = context->createGroup();
    gro->setChildCount(1);
    gro->setChild(0, geometry_group);
    optix::Acceleration acceleration = context->createAcceleration("NoAccel", "NoAccel"); 
    gro->setAcceleration(acceleration);

    return gro;
}