Esempio n. 1
0
void WaterRenderer::Draw() {
	ShaderSet* currentShaderSet = FRAMEWORK->GetOpenGLWrapper()->GetCurrentShaderSet();
	if (currentShaderSet->HasHandle(SHADER_VARIABLE_VARIABLENAME_scrolling_uv_offset)) {
		GLint scrolling_uv_offset_handle = currentShaderSet->GetHandle(SHADER_VARIABLE_VARIABLENAME_scrolling_uv_offset);
		GLCALL(glUniform1f, scrolling_uv_offset_handle, this->scrollingUVsOffset);
	}

	if (this->secondaryTexture) {
		this->secondaryTexture->Draw(2);
	}

	MeshRenderer::Draw();

}
Esempio n. 2
0
// SDL wants main() to have this exact signature
extern "C" int main(int argc, char* argv[])
{
    // Initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr, "SDL_Init: %s\n", SDL_GetError());
        return 1;
    }

    // Plain 32-bit RGBA8 pixel format
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);

    // Don't need built-in depth buffer, we use our own.
    //SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);

    // Select OpenGL version
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

#ifdef _DEBUG
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
#endif

    // Create the window
	SDL_Window* window = SDL_CreateWindow("OpenGL", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL);
    if (!window)
    {
        fprintf(stderr, "SDL_CreateWindow: %s\n", SDL_GetError());
        return 1;
    }

    // Create the OpenGL context
    SDL_GLContext context = SDL_GL_CreateContext(window);
    if (!context)
    {
        fprintf(stderr, "SDL_GL_CreateContext: %s\n", SDL_GetError());
        return 1;
    }

    // Initialize OpenGL (must be called before calling any OpenGL functions)
    OpenGL_Init();	

	// DEBUG: print OpenGL version
	const GLubyte* version = glGetString(GL_VERSION);
	fprintf(stdout, "OpenGL Version: %s\n", version);	

	//======================== VAO ===============================
	// Hook up the vertex and index buffers to a "vertex array object" (VAO)
	// VAOs are the closest thing OpenGL has to a "mesh" object.
	// VAOs are used to feed data from buffers to thgle inputs of a vertex shader.
	//============================================================	

	//===================== VBO/EBO ===============================
	Skybox skyBox = Skybox();
	skyBox.load();

	TerrainMesh terrainMesh = TerrainMesh(64, 64, 0.0);
	terrainMesh.load();

	
	//============================================================

	//===================== TEXTURES =============================
	
	//============================================================

	//======================= SHADERS ============================
	// init terrain shader
	ShaderSet terrainShaderSet;
	terrainShaderSet.SetVersion("330");

	// set uniforms (use preambles here or define them in the shader file, but NOT both)
	terrainShaderSet.SetPreamble(
		"uniform mat4 iModelViewProjection;\n"
		"uniform mat4 iModel;\n"
		"uniform mat4 iView;\n"
		"uniform vec3 iLightPosition_worldspace;\n"
		"uniform sampler2DArray iTextureArray;\n"
	);
	GLuint* terrainShaderId = terrainShaderSet.AddProgramFromExts({ "a3.vert", "a3.frag" });


	// init skybox shader
	ShaderSet skyboxShaderSet;
	skyboxShaderSet.SetVersion("330");

	// set uniforms (use preambles here or define them in the shader file, but NOT both)
	skyboxShaderSet.SetPreamble(
		"uniform mat4 iProjection;\n"
		"uniform mat4 iView;\n"
		"uniform samplerCube iSkyBoxCubeTexture;\n"
	);
	GLuint* skyboxShaderId = skyboxShaderSet.AddProgramFromExts({ "skybox.vert", "skybox.frag" });
	//============================================================

	//======================== LIGHTS ============================
	glm::vec3 light = glm::vec3(4, 40, 4);
	//============================================================

	//================== BEZIER CURVES ===========================
	glm::vec3 xzLength = glm::vec3(32.0, 0.0, 32.0);
	glm::vec3 yPull = glm::vec3(0.0, 20.0, 0.0);
	glm::vec3 xPull = glm::vec3(20.0, 0.0, 0.0);

	CubicBezierCurve bezierCurve1 = CubicBezierCurve(light, xzLength, yPull, yPull);
	CubicBezierCurve bezierCurve2 = CubicBezierCurve(bezierCurve1.p3, xzLength, -yPull, -yPull);
	CubicBezierCurve bezierCurve3 = CubicBezierCurve(bezierCurve2.p3, -xzLength, xPull, xPull);
	CubicBezierCurve bezierCurve4 = CubicBezierCurve(bezierCurve3.p3, -xzLength, -xPull, -xPull);
	
	BezierPath bezierPath = BezierPath(std::vector<CubicBezierCurve>{ bezierCurve1, bezierCurve2, bezierCurve3, bezierCurve4 });
	//============================================================
	
    // Begin main loop
	double lastTime = 0;
	InputHandler inputHandler = InputHandler(window);
	Camera camera = Camera(4, 40, 4);
	float bezierTime = 0.0;
	const float bezierSpeed = 0.001;
    while (1)
    {			
		//================= UPDATE USER INPUT ========================
		double currentTime = SDL_GetTicks() / 1000.0;		
		float deltaTime = float(currentTime - lastTime);
		
		if (inputHandler.updateInput(deltaTime) == -1)
		{
			goto quit;
		}
		camera.update(inputHandler.getInputData(), deltaTime);

		lastTime = currentTime;
		//============================================================

		//================= COMPUTE MATRICES =========================
		// move camera position along bezier curve		
		glm::vec3 bezPos = bezierPath.getPointAt(bezierTime);
		bezierTime += bezierSpeed;
		bezierTime = (bezierTime > 1.0) ? 0.0 : bezierTime;
		camera.position = bezPos;

		// Projection matrix
		glm::mat4 Projection = glm::perspective(
			camera.FoV,
			camera.aspectRatio,
			camera.nearClip,
			camera.farClip
		);

		// Or, for an ortho camera :
		//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates

		// Camera matrix
		glm::mat4 View = glm::lookAt(
			camera.position,
			camera.position + camera.direction,
			camera.up
		);

		// Model matrix : an identity matrix (model will be at the origin)
		glm::mat4 Model = glm::mat4(1.0f);
		// Our ModelViewProjection : multiplication of our 3 matrices
		glm::mat4 ModelViewProjection = Projection * View * Model; // Remember, matrix multiplication is the other way around
		//glm::mat4 ModelViewProjection = MVP;
		//============================================================		

		//================== UPDATE SHADERS ==========================
		// Set the color to clear with
		//glClearColor(100.0f / 255.0f, 149.0f / 255.0f, 237.0f / 255.0f, 1.0f);
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

		// Clear the screen
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		//===================== Z-BUFFER =============================
		// Enable depth test
		glEnable(GL_DEPTH_TEST);
		// Accept fragment if it closer to the camera than the former one
		glDepthFunc(GL_LESS);


		// TERRAIN ======================================================
		// Recompile/relink any programs that changed (must be called)
		terrainShaderSet.UpdatePrograms();

		// set OpenGL's shader program (must be called in loop)
		glUseProgram(*terrainShaderId);

		// get uniform handles
		GLuint iModelViewProjectionLoc = glGetUniformLocation(*terrainShaderId, "iModelViewProjection");
		GLuint iModelLoc = glGetUniformLocation(*terrainShaderId, "iModel");
		GLuint iViewLoc = glGetUniformLocation(*terrainShaderId, "iView");
		GLuint iLightPosition_worldspaceLoc = glGetUniformLocation(*terrainShaderId, "iLightPosition_worldspace");

		// send matrix uniforms to shader
		if (iModelViewProjectionLoc != -1)
		{
			glUniformMatrix4fv(iModelViewProjectionLoc, 1, GL_FALSE, &ModelViewProjection[0][0]);
		}

		if (iModelLoc != -1)
		{
			glUniformMatrix4fv(iModelLoc, 1, GL_FALSE, &Model[0][0]);
		}
		if (iViewLoc != -1)
		{
			glUniformMatrix4fv(iViewLoc, 1, GL_FALSE, &View[0][0]);
		}						

		// pass light position uniform to shader
		if (iLightPosition_worldspaceLoc != -1) 
		{
			glUniform3f(iLightPosition_worldspaceLoc, light.x, light.y, light.z);
		}				

		terrainMesh.generateTextureUniform(terrainShaderId, "iTextureArray");

		terrainMesh.attachToVAO(0, 1, 2, 3);

		terrainMesh.draw();



		// SKYBOX ========================================================
		// Recompile/relink any programs that changed (must be called)
		skyboxShaderSet.UpdatePrograms();

		// set OpenGL's shader program (must be called in loop)
		glUseProgram(*skyboxShaderId);

		// get skybox shader uniform handles
		GLuint iSkyBoxViewLoc = glGetUniformLocation(*skyboxShaderId, "iView");
		GLuint iSkyBoxProjectionLoc = glGetUniformLocation(*skyboxShaderId, "iProjection");
		if (iSkyBoxViewLoc != -1)
		{
			// remove the translation component of the view matrix
			// to make sure the skybox's origin is always at the camera
			glm::mat4 newView = glm::mat4(glm::mat3(View));
			glUniformMatrix4fv(iSkyBoxViewLoc, 1, GL_FALSE, &newView[0][0]);
		}
		if (iSkyBoxProjectionLoc != -1)
		{
			glUniformMatrix4fv(iSkyBoxProjectionLoc, 1, GL_FALSE, &Projection[0][0]);
		}

		// generate uniforms for object textures		
		skyBox.generateTextureUniform(skyboxShaderId, "iSkyBoxCubeTexture");

		skyBox.attachToVAO(4);

		skyBox.draw();


		// draw wireframe of mesh
		//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);		
		

		// check for errors
		GLenum err2;
		while ((err2 = glGetError()) != GL_NO_ERROR) {
			std::cerr << "OpenGL error: " << err2 << std::endl;
		}

		// disable the depth buffer
		glDisable(GL_DEPTH_TEST);

        // SDL docs: "On Mac OS X make sure you bind 0 to the draw framebuffer before swapping the window, otherwise nothing will happen."
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
        
        // Display the frame of rendering to the window
        SDL_GL_SwapWindow(window);		
    }

quit:
    SDL_Quit();
    return 0;
}
Esempio n. 3
0
int main(int argc, char** argv)
{
    Display d;
	
    d.Initialize(800, 600, 24, "Sample 03");
	
    if( d.Show() == false )
    {
        std::cout << "Failed to open window, exiting." << std::endl;
        return 1;
    }
	
    d.ClearColor( Color::White() );
	
	
    VertexBuffer<VertexColor> vbo(3);
	
    vbo.AddElement( VertexColor( Vector3(0.0f, 0.5f, -2.0f),
                                Color::Red()));
    vbo.AddElement( VertexColor( Vector3(0.5f, -0.5f, -2.0f),
                                Color::Green()));
    vbo.AddElement( VertexColor( Vector3(-0.5f, -0.5f, -2.0f),
                                Color::Blue()));
    
    vbo.Generate();
	
	
	//load shaders
	ShaderSet* ss = new ShaderSet();
	Shader* vert = new Shader("../../data/Shader.vert", shader::Vertex);
	Shader* frag = new Shader("../../data/Shader.frag", shader::Fragment);
	
	ss->AddShader(vert);
	ss->AddShader(frag);
	
	ss->Finalize();
	
	GLint uniformId = ss->GetUniformId("translate");
	float transY = 0.0f;
	
	uint time = Timer::GetCurrentGameTime();
	
    while(d.Listener()->Update())
    {
        d.ClearScreen();
		
        d.SetupPerspective(45.0f, 0.1f, 100.0f);
        
		ss->Bind();
		
		// update the shader translation
		transY += ((float)(Timer::GetCurrentGameTime() - time)) / 200.0f;
		time = Timer::GetCurrentGameTime();
		glUniform1f(uniformId, transY);

		
        vbo.Bind();
        glDrawArrays(GL_TRIANGLES, 0, 3);
        vbo.Unbind();
		
		ss->Unbind();
		
        d.SwapBuffers();
    }
	
    return 0;
}
int Init()
{
	ovr_Initialize();
	HMD = ovrHmd_Create(0);
	if (!HMD)
	{
		MessageBox(NULL, "Oculus Rift not detected.", "", MB_OK);
		return 1;
	}
	if (HMD->ProductName[0] == '\0')
	{
		MessageBox(NULL, "Rift detected, display not enabled.", "", MB_OK);
	}

	//Setup Window and Graphics - use window frame if relying on Oculus driver
	const int backBufferMultisample = 1;
	bool UseAppWindowFrame = true;
	HWND window = Util_InitWindowAndGraphics(Recti(HMD->WindowsPos, HMD->Resolution), 
		FullScreen, backBufferMultisample, UseAppWindowFrame, &pRender);
	if (!window) return 1;
	ovrHmd_AttachToWindow(HMD, window, NULL, NULL);

	Sizei recommenedTex0Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Left, HMD->DefaultEyeFov[0], 1.0f);
	Sizei recommenedTex1Size = ovrHmd_GetFovTextureSize(HMD, ovrEye_Right, HMD->DefaultEyeFov[1], 1.0f);
	Sizei RenderTargetSize;
	RenderTargetSize.w = recommenedTex0Size.w + recommenedTex1Size.w;
	RenderTargetSize.h = max(recommenedTex0Size.h, recommenedTex1Size.h);

	RenderTargetSize.w = HMD->Resolution.w;
	RenderTargetSize.h = HMD->Resolution.h;

	//const int eyeRenderMultisample = 1;
	pRendertargetTexture = pRender->CreateRenderTarget(RenderTargetSize.w/2, RenderTargetSize.h/2);
	//pRendertargetTexture = pRender->CreateRenderTarget(512, 512);
	RenderTargetSize.w = pRendertargetTexture->Width;
	RenderTargetSize.h = pRendertargetTexture->Height;

	IDirect3DSurface9 *zb = 0;
	pRender->Device->GetDepthStencilSurface(&zb);
	D3DSURFACE_DESC d;
	zb->GetDesc(&d);

	// Initialize eye rendering information.
	// The viewport sizes are re-computed in case RenderTargetSize due to HW limitations.
	ovrFovPort eyeFov[2] = { HMD->DefaultEyeFov[0], HMD->DefaultEyeFov[1] };

	EyeRenderViewport[0].Pos  = Vector2i(0, 0);
	EyeRenderViewport[0].Size = Sizei(RenderTargetSize.w / 2, RenderTargetSize.h);
	EyeRenderViewport[1].Pos  = Vector2i((RenderTargetSize.w + 1) / 2, 0);
	EyeRenderViewport[1].Size = EyeRenderViewport[0].Size;

	// ---------------------

	DistortionShaders = pRender->CreateShaderSet();
	DistortionShaders->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_Distortion));
	DistortionShaders->SetShader(pRender->LoadBuiltinShader(Shader_Pixel, PShader_Distortion));
	DistortionDecl = VertexDecl::GetDecl(VertexType_Distortion);

	for (int eyeNum = 0; eyeNum < 2; ++eyeNum)
	{
		ovrDistortionMesh meshData;
		ovrHmd_CreateDistortionMesh(HMD, (ovrEyeType)eyeNum, eyeFov[eyeNum],
			ovrDistortionCap_Chromatic | ovrDistortionCap_TimeWarp, &meshData);
		MeshVBs[eyeNum] = pRender->CreateVertexBuffer();
		MeshVBs[eyeNum]->Data(meshData.pVertexData, sizeof(ovrDistortionVertex)*meshData.VertexCount);
		MeshIBs[eyeNum] = pRender->CreateIndexBuffer();
		MeshIBs[eyeNum]->Data(meshData.pIndexData, sizeof(unsigned short)*meshData.IndexCount);

		MeshVBCnts[eyeNum] = meshData.VertexCount;
		MeshIBCnts[eyeNum] = meshData.IndexCount;
		ovrHmd_DestroyDistortionMesh(&meshData);

		EyeRenderDesc[eyeNum] = ovrHmd_GetRenderDesc(HMD, (ovrEyeType)eyeNum, eyeFov[eyeNum]);

		ovrHmd_GetRenderScaleAndOffset(eyeFov[eyeNum], RenderTargetSize, EyeRenderViewport[eyeNum], UVScaleOffset[eyeNum]);
	}

	ovrHmd_SetEnabledCaps(HMD, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);

	ovrHmd_ConfigureTracking(HMD,
		ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection | ovrTrackingCap_Position, 0);

	// ---------------------

	pRoomScene = new Scene;
	PopulateRoomScene(pRoomScene, pRender);

	// texture model
	ShaderSet* ss = pRender->CreateShaderSet();
	ss->SetShader(pRender->LoadBuiltinShader(Shader_Vertex, VShader_MVP_UV));
	ss->SetShader(pRender->LoadBuiltinShader(Shader_Pixel, PShader_UV));

	Model<VertexXYZUV> *pModel2 = new Model<VertexXYZUV>();
	pModel2->Decl = VertexDecl::GetDecl(VertexType_XYZUV);
	pModel2->Fill = new ShaderFill(ss);

	//Texture* ttt = new Texture(pRender);
	//ttt->LoadFromFile("face.tga");
	pModel2->Fill->SetTexture(0, pRendertargetTexture);

	pModel2->AddVertex(VertexXYZUV(0.5f, -1.0f, 0.0f, 0.0f, 0.0f));
	pModel2->AddVertex(VertexXYZUV(2.5f, -1.0f, 0.0f, 1.0f, 0.0f));
	pModel2->AddVertex(VertexXYZUV(0.5f, 1.0f, 0.0f, 0.0f, 1.0f));
	pModel2->AddVertex(VertexXYZUV(2.5f, 1.0f, 0.0f, 1.0f, 1.0f));

	pModel2->AddVertex(VertexXYZUV(-1.0f, -1.5f, -1.0f, 0.0f, 0.0f));
	pModel2->AddVertex(VertexXYZUV(1.0f, -1.5f, -1.0f, 1.0f, 0.0f));
	pModel2->AddVertex(VertexXYZUV(-1.0f, -1.5f, 1.0f, 0.0f, 1.0f));
	pModel2->AddVertex(VertexXYZUV(1.0f, -1.5f, 1.0f, 1.0f, 1.0f));

	pModel2->AddTriangle(0, 1, 2);
	pModel2->AddTriangle(2, 1, 3);
	pModel2->AddTriangle(4, 5, 6);
	pModel2->AddTriangle(6, 5, 7);

	pScene = new Scene;
	pScene->World.Add(pModel2);

    return (0);
}
Esempio n. 5
0
	void MaterialInstance::createForConfiguration (const std::string& configuration)
	{
		bool res = mMaterial->createConfiguration(configuration);
		if (!res)
			return; // listener was false positive

		if (mListener)
			mListener->requestedConfiguration (this, configuration);

		mFactory->setActiveConfiguration (configuration);

		bool allowFixedFunction = true;
		if (!mShadersEnabled && hasProperty("allow_fixed_function"))
		{
			allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
		}

		// get passes of the top-most parent
		PassVector passes = getPasses();
		for (PassVector::iterator it = passes.begin(); it != passes.end(); ++it)
		{
			boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration);
			it->copyAll (pass.get(), this);

			// texture samplers used in the shaders
			std::vector<std::string> usedTextureSamplersVertex;
			std::vector<std::string> usedTextureSamplersFragment;

			PropertySetGet* context = this;

			// create or retrieve shaders
			if (mShadersEnabled || !allowFixedFunction)
			{
				it->setContext(context);
				it->mShaderProperties.setContext(context);
				if (it->hasProperty("vertex_program"))
				{
					ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
					ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
					if (v)
					{
						pass->assignProgram (GPT_Vertex, v->getName());
						v->setUniformParameters (pass, &it->mShaderProperties);

						std::vector<std::string> sharedParams = v->getSharedParameters ();
						for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
						{
							pass->addSharedParameter (GPT_Vertex, *it);
						}

						std::vector<std::string> vector = v->getUsedSamplers ();
						usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
					}
				}
				if (it->hasProperty("fragment_program"))
				{
					ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
					ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
					if (f)
					{
						pass->assignProgram (GPT_Fragment, f->getName());
						f->setUniformParameters (pass, &it->mShaderProperties);

						std::vector<std::string> sharedParams = f->getSharedParameters ();
						for (std::vector<std::string>::iterator it = sharedParams.begin(); it != sharedParams.end(); ++it)
						{
							pass->addSharedParameter (GPT_Fragment, *it);
						}

						std::vector<std::string> vector = f->getUsedSamplers ();
						usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
					}
				}
			}

			// create texture units
			std::vector<MaterialInstanceTextureUnit> texUnits = it->getTexUnits();
			int i=0;
			for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits.begin(); texIt  != texUnits.end(); ++texIt )
			{
				// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
				bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
				bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
				if (  (foundVertex || foundFragment)
						|| ((!mShadersEnabled && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
				{
					boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState ();
					texIt->copyAll (texUnit.get(), context);

					mTexUnits.push_back(texUnit);

					// set texture unit indices (required by GLSL)
					if (mShadersEnabled && mFactory->getCurrentLanguage () == Language_GLSL)
					{
						pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);

						++i;
					}
				}
			}
		}
	}
Esempio n. 6
0
	bool MaterialInstance::createForConfiguration (const std::string& configuration, unsigned short lodIndex)
	{
		if (mFailedToCreate)
			return false;
		try{
			mMaterial->ensureLoaded();
			bool res = mMaterial->createConfiguration(configuration, lodIndex);
			if (!res)
				return false; // listener was false positive

			if (mListener)
				mListener->requestedConfiguration (this, configuration);

			mFactory->setActiveConfiguration (configuration);
			mFactory->setActiveLodLevel (lodIndex);

			bool allowFixedFunction = true;
			if (!mShadersEnabled && hasProperty("allow_fixed_function"))
			{
				allowFixedFunction = retrieveValue<BooleanValue>(getProperty("allow_fixed_function"), NULL).get();
			}

			bool useShaders = mShadersEnabled || !allowFixedFunction;

			// get passes of the top-most parent
			PassVector* passes = getParentPasses();
			if (passes->empty())
				throw std::runtime_error ("material \"" + mName + "\" does not have any passes");

			for (PassVector::iterator it = passes->begin(); it != passes->end(); ++it)
			{
				boost::shared_ptr<Pass> pass = mMaterial->createPass (configuration, lodIndex);
				it->copyAll (pass.get(), this);

				// texture samplers used in the shaders
				std::vector<std::string> usedTextureSamplersVertex;
				std::vector<std::string> usedTextureSamplersFragment;

				PropertySetGet* context = this;

				// create or retrieve shaders
				bool hasVertex = it->hasProperty("vertex_program")
						&& !retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get().empty();
				bool hasFragment = it->hasProperty("fragment_program")
						&& !retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get().empty();
				if (useShaders)
				{
					it->setContext(context);
					it->mShaderProperties.setContext(context);
					if (hasVertex)
					{
						ShaderSet* vertex = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("vertex_program"), context).get());
						ShaderInstance* v = vertex->getInstance(&it->mShaderProperties);
						if (v)
						{
							pass->assignProgram (GPT_Vertex, v->getName());
							v->setUniformParameters (pass, &it->mShaderProperties);

							std::vector<std::string> sharedParams = v->getSharedParameters ();
							for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
							{
								pass->addSharedParameter (GPT_Vertex, *it2);
							}

							std::vector<std::string> vector = v->getUsedSamplers ();
							usedTextureSamplersVertex.insert(usedTextureSamplersVertex.end(), vector.begin(), vector.end());
						}
					}
					if (hasFragment)
					{
						ShaderSet* fragment = mFactory->getShaderSet(retrieveValue<StringValue>(it->getProperty("fragment_program"), context).get());
						ShaderInstance* f = fragment->getInstance(&it->mShaderProperties);
						if (f)
						{
							pass->assignProgram (GPT_Fragment, f->getName());
							f->setUniformParameters (pass, &it->mShaderProperties);

							std::vector<std::string> sharedParams = f->getSharedParameters ();
							for (std::vector<std::string>::iterator it2 = sharedParams.begin(); it2 != sharedParams.end(); ++it2)
							{
								pass->addSharedParameter (GPT_Fragment, *it2);
							}

							std::vector<std::string> vector = f->getUsedSamplers ();
							usedTextureSamplersFragment.insert(usedTextureSamplersFragment.end(), vector.begin(), vector.end());
						}
					}
				}

				// create texture units
				std::vector<MaterialInstanceTextureUnit>* texUnits = &it->mTexUnits;
				int i=0;
				for (std::vector<MaterialInstanceTextureUnit>::iterator texIt = texUnits->begin(); texIt  != texUnits->end(); ++texIt )
				{
					// only create those that are needed by the shader, OR those marked to be created in fixed function pipeline if shaders are disabled
					bool foundVertex = std::find(usedTextureSamplersVertex.begin(), usedTextureSamplersVertex.end(), texIt->getName()) != usedTextureSamplersVertex.end();
					bool foundFragment = std::find(usedTextureSamplersFragment.begin(), usedTextureSamplersFragment.end(), texIt->getName()) != usedTextureSamplersFragment.end();
					if (  (foundVertex || foundFragment)
							|| (((!useShaders || (!hasVertex || !hasFragment)) && allowFixedFunction) && texIt->hasProperty("create_in_ffp") && retrieveValue<BooleanValue>(texIt->getProperty("create_in_ffp"), this).get()))
					{
						boost::shared_ptr<TextureUnitState> texUnit = pass->createTextureUnitState (texIt->getName());
						texIt->copyAll (texUnit.get(), context);

						mTexUnits.push_back(texUnit);

						// set texture unit indices (required by GLSL)
						if (useShaders && ((hasVertex && foundVertex) || (hasFragment && foundFragment)) && mFactory->getCurrentLanguage () == Language_GLSL)
						{
							pass->setTextureUnitIndex (foundVertex ? GPT_Vertex : GPT_Fragment, texIt->getName(), i);

							++i;
						}
					}
				}
			}

			if (mListener)
				mListener->createdConfiguration (this, configuration);
			return true;

		} catch (std::runtime_error& e)
		{
			destroyAll();
			mFailedToCreate = true;
			std::stringstream msg;
			msg << "Error while creating material " << mName << ": " << e.what();
			std::cerr << msg.str() << std::endl;
			mFactory->logError(msg.str());
			return false;
		}
	}